diff --git a/DEPS b/DEPS
index 7e57e33c..91a39b1 100644
--- a/DEPS
+++ b/DEPS
@@ -200,11 +200,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': '96826732868890b5f715ca6025440f5a39053d69',
+  'skia_revision': '77b68e8599f03a4bcf8311841a4fdc38ea9f2f39',
   # 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': '8d791670ba247239ef6ce9091183f11f8c5f0825',
+  'v8_revision': '732b1bcfdb8b23b7714bb840927ea2492a52a3c7',
   # 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.
@@ -212,7 +212,7 @@
   # 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': '59aa1ef1975ae2d263da864f111eaaa7cdb4f9f2',
+  'angle_revision': '3d061021c920ada75c5d9ab2424ca5a037607212',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -267,7 +267,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': '759827265102502cc7f814572675b9685c351908',
+  'catapult_revision': '146912bb62b7ca0f77478424a23c611a613480f2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -275,7 +275,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': '37a7420d1afbff8d43980292858846af9405cfe2',
+  'devtools_frontend_revision': '75aeca4eb9f8aad41919ba1ac10a7c60035ce549',
   # 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.
@@ -899,7 +899,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' + '@' + '34d74e1ebe96ea0136e999f661edf266519a9e68',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9ed30bc3ed292b02d85fde89c64207484b7a3aa4',
       'condition': 'checkout_chromeos',
   },
 
@@ -1589,7 +1589,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': '7OAln1cRnDCb00TBld5dPAV-X6ezVIxW3xzBDZW9CCkC',
+          'version': 'qmz8kJxTUN_Mt51qpFOU1gn2Es-tf5fUQbm_dwWR4WsC',
         },
       ],
       'dep_type': 'cipd',
@@ -1599,7 +1599,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': 'yZ7VbaW1KAIyuzwfeFwPomNFownHQYrrzEEe9ZdOpZsC',
+          'version': 'VR4k806B8ASaIGHP_wz13-mO3s-X-NxvU7dSULraOMEC',
         },
       ],
       'dep_type': 'cipd',
@@ -1623,7 +1623,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@bb305e324c105ec5ee79e138d49c5e8ac1dd8e2a',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c2f6edd90e95c4e9995aafd628fda64cb12ab730',
     'condition': 'checkout_src_internal',
   },
 
@@ -1642,7 +1642,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'QLcUbwkt8a45zusATb281jmlNK1me6mIaZYUL8O7bCgC',
+        'version': 'lG_a4dmzvUVz2tG1lGjqFDf82D7njOF8sDwKc4SdWYwC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/system/accessibility/switch_access_menu_button.cc b/ash/system/accessibility/switch_access_menu_button.cc
index 312f65de..421c982 100644
--- a/ash/system/accessibility/switch_access_menu_button.cc
+++ b/ash/system/accessibility/switch_access_menu_button.cc
@@ -12,6 +12,7 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/vector_icon_types.h"
+#include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
@@ -45,6 +46,7 @@
   SkColor label_color = AshColorProvider::Get()->GetContentLayerColor(
       AshColorProvider::ContentLayerType::kTextColorPrimary);
 
+  base::string16 label_text = l10n_util::GetStringUTF16(label_text_id);
   views::Builder<SwitchAccessMenuButton>(this)
       .SetFocusBehavior(views::View::FocusBehavior::ACCESSIBLE_ONLY)
       .AddChildren(
@@ -53,7 +55,7 @@
                .SetImage(gfx::CreateVectorIcon(icon, kIconSizeDip, icon_color)),
            views::Builder<views::Label>()
                .CopyAddressTo(&label_)
-               .SetText(l10n_util::GetStringUTF16(label_text_id))
+               .SetText(label_text)
                .SetTextContext(views::style::CONTEXT_BUTTON)
                .SetAutoColorReadabilityEnabled(false)
                .SetEnabledColor(label_color)
@@ -80,6 +82,9 @@
       gfx::Insets(kButtonTopPaddingDip, left_padding_dip, bottom_padding_dip,
                   right_padding_dip));
   SetLayoutManager(std::move(layout));
+
+  GetViewAccessibility().OverrideName(label_text);
+  GetViewAccessibility().OverrideIsLeaf(true);
 }
 
 void SwitchAccessMenuButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
diff --git a/base/allocator/allocator_shim.h b/base/allocator/allocator_shim.h
index 1646ae46..f7a68d0 100644
--- a/base/allocator/allocator_shim.h
+++ b/base/allocator/allocator_shim.h
@@ -156,6 +156,7 @@
 #endif
 
 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
+BASE_EXPORT void EnablePCScan();
 BASE_EXPORT void EnablePCScanIfNeeded();
 #endif
 
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 a296ab9..0a9fdb23 100644
--- a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
+++ b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -237,11 +237,15 @@
       AlignedAllocator());
 }
 
+void EnablePCScan() {
+  Allocator()->EnablePCScan();
+  AlignedAllocator()->EnablePCScan();
+}
+
 void EnablePCScanIfNeeded() {
   if (!features::IsPartitionAllocPCScanEnabled())
     return;
-  Allocator()->EnablePCScan();
-  AlignedAllocator()->EnablePCScan();
+  EnablePCScan();
 }
 
 }  // namespace allocator
diff --git a/base/allocator/partition_allocator/OWNERS b/base/allocator/partition_allocator/OWNERS
index 54db26c..ecb23bd0 100644
--- a/base/allocator/partition_allocator/OWNERS
+++ b/base/allocator/partition_allocator/OWNERS
@@ -3,3 +3,9 @@
 haraken@chromium.org
 lizeb@chromium.org
 palmer@chromium.org
+
+# For PCScan specific changes:
+per-file pcscan*=bikineev@chromium.org
+per-file pcscan*=mlippautz@chromium.org
+per-file object_bitmap*=bikineev@chromium.org
+per-file object_bitmap*=mlippautz@chromium.org
diff --git a/base/allocator/partition_allocator/partition_alloc_features.h b/base/allocator/partition_allocator/partition_alloc_features.h
index 1aedf81..f0beeece 100644
--- a/base/allocator/partition_allocator/partition_alloc_features.h
+++ b/base/allocator/partition_allocator/partition_alloc_features.h
@@ -64,8 +64,6 @@
 #if !defined(PA_HAS_64_BITS_POINTERS)
   return false;
 #endif  // !PA_HAS_64_BITS_POINTERS
-  // TODO(bikineev): Calling this function can allocate which can cause
-  // reentrancy for the 'PA as malloc' configuration.
   return FeatureList::IsEnabled(kPartitionAllocPCScan);
 }
 
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 18730e5..efd5e79d 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20201128.3.1
+0.20201129.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 18730e5..efd5e79d 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20201128.3.1
+0.20201129.3.1
diff --git a/chrome/VERSION b/chrome/VERSION
index cd07a24..9c0dda2 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=89
 MINOR=0
-BUILD=4341
+BUILD=4342
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 23137891..96284c9 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -299,6 +299,7 @@
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/banners/android:java",
     "//chrome/browser/browser_controls/android:java",
+    "//chrome/browser/consent_auditor/android:java",
     "//chrome/browser/contextmenu:java",
     "//chrome/browser/device:java",
     "//chrome/browser/download/android:factory_java",
@@ -550,7 +551,6 @@
     "//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",
-    "//components/consent_auditor:consent_auditor_java",
     "//components/data_reduction_proxy/core/browser:data_reduction_proxy_savings_cleared_enum_java",
     "//components/dom_distiller/core:distiller_type_java",
     "//components/ntp_tiles:ntp_tiles_enums_java",
@@ -3217,7 +3217,6 @@
     "java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java",
     "java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java",
     "java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java",
-    "java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java",
     "java/src/org/chromium/chrome/browser/content/ContentUtils.java",
     "java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java",
     "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index bd65735a..c9ca94e 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -347,7 +347,6 @@
   "java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java",
   "java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java",
   "java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java",
-  "java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java",
   "java/src/org/chromium/chrome/browser/contacts_picker/ChromePickerAdapter.java",
   "java/src/org/chromium/chrome/browser/content/ContentUtils.java",
   "java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java",
@@ -1282,7 +1281,6 @@
   "java/src/org/chromium/chrome/browser/signin/SigninView.java",
   "java/src/org/chromium/chrome/browser/signin/SyncPromoView.java",
   "java/src/org/chromium/chrome/browser/signin/UnifiedConsentServiceBridge.java",
-  "java/src/org/chromium/chrome/browser/signin/account_picker/AccountConsistencyPromoAction.java",
   "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java",
   "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java",
   "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/consent_auditor/DIR_METADATA b/chrome/android/java/src/org/chromium/chrome/browser/consent_auditor/DIR_METADATA
deleted file mode 100644
index 7a2580a..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/consent_auditor/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-os: ANDROID
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/consent_auditor/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/consent_auditor/OWNERS
deleted file mode 100644
index e147eaf..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/consent_auditor/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/consent_auditor/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
index 7d426bc..3aca0e9c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.signin.account_picker.AccountConsistencyPromoAction;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegate;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegateImpl;
@@ -35,6 +34,7 @@
 import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.GAIAServiceType;
+import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.ui.base.WindowAndroid;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountConsistencyPromoAction.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountConsistencyPromoAction.java
deleted file mode 100644
index ed51376..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountConsistencyPromoAction.java
+++ /dev/null
@@ -1,125 +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.
-
-package org.chromium.chrome.browser.signin.account_picker;
-
-import androidx.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * This class is used to record user action that was taken after receiving the header
- * from Gaia in the web sign-in flow.
- *
- * These values are persisted to logs. Entries should not be renumbered and
- * numeric values should never be reused.
- */
-@IntDef({
-        AccountConsistencyPromoAction.SUPPRESSED_NO_ACCOUNTS,
-        AccountConsistencyPromoAction.DISMISSED_BACK,
-        AccountConsistencyPromoAction.ADD_ACCOUNT_STARTED,
-        AccountConsistencyPromoAction.STARTED_INCOGNITO_SESSION,
-        AccountConsistencyPromoAction.SIGNED_IN_WITH_DEFAULT_ACCOUNT,
-        AccountConsistencyPromoAction.SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT,
-        AccountConsistencyPromoAction.SHOWN,
-        AccountConsistencyPromoAction.SUPPRESSED_SIGNIN_NOT_ALLOWED,
-        AccountConsistencyPromoAction.SIGNED_IN_WITH_ADDED_ACCOUNT,
-        AccountConsistencyPromoAction.DISMISSED_SCRIM,
-        AccountConsistencyPromoAction.DISMISSED_SWIPE_DOWN,
-        AccountConsistencyPromoAction.DISMISSED_OTHER,
-        AccountConsistencyPromoAction.AUTH_ERROR_SHOWN,
-        AccountConsistencyPromoAction.GENERIC_ERROR_SHOWN,
-        AccountConsistencyPromoAction.DISMISSED_BUTTON,
-        AccountConsistencyPromoAction.ADD_ACCOUNT_COMPLETED,
-})
-@Retention(RetentionPolicy.SOURCE)
-public @interface AccountConsistencyPromoAction {
-    /**
-     * Promo is not shown as there are no accounts on device.
-     */
-    int SUPPRESSED_NO_ACCOUNTS = 0;
-
-    /**
-     * User has dismissed the promo by tapping back button.
-     */
-    int DISMISSED_BACK = 1;
-
-    /**
-     * User has tapped |Add account to device| from expanded account list.
-     */
-    int ADD_ACCOUNT_STARTED = 2;
-
-    /**
-     * User tapped the button from the expanded account list to open the incognito interstitial
-     * then confirmed opening the page in the incognito tab by tapping |Continue| in the incognito
-     * interstitial.
-     */
-    int STARTED_INCOGNITO_SESSION = 3;
-
-    /**
-     * User has selected the default account and signed in with it.
-     */
-    int SIGNED_IN_WITH_DEFAULT_ACCOUNT = 4;
-
-    /**
-     * User has selected one of the non default accounts and signed in with it.
-     */
-    int SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT = 5;
-
-    /**
-     * The promo was shown to user.
-     */
-    int SHOWN = 6;
-
-    /**
-     * Promo is not shown due to sign-in being disallowed either by an enterprise policy
-     * or by |Allow Chrome sign-in| toggle.
-     */
-    int SUPPRESSED_SIGNIN_NOT_ALLOWED = 7;
-
-    /**
-     * User has added an account and signed in with this account.
-     * When this metric is recorded, we won't record SIGNED_IN_WITH_DEFAULT_ACCOUNT or
-     * SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT.
-     */
-    int SIGNED_IN_WITH_ADDED_ACCOUNT = 8;
-
-    /**
-     * User has dismissed the promo by tapping on the scrim above the bottom sheet.
-     */
-    int DISMISSED_SCRIM = 9;
-
-    /**
-     * User has dismissed the promo by swiping down the bottom sheet.
-     */
-    int DISMISSED_SWIPE_DOWN = 10;
-
-    /**
-     * User has dismissed the promo by other means.
-     */
-    int DISMISSED_OTHER = 11;
-
-    /**
-     * The auth error screen was shown to the user.
-     */
-    int AUTH_ERROR_SHOWN = 12;
-
-    /**
-     * The generic error screen was shown to the user.
-     */
-    int GENERIC_ERROR_SHOWN = 13;
-
-    /**
-     * User has dismissed the promo by tapping on the dismissal button in the bottom sheet.
-     */
-    int DISMISSED_BUTTON = 14;
-
-    /**
-     * User has completed the account addition flow triggered from the bottom sheet.
-     */
-    int ADD_ACCOUNT_COMPLETED = 15;
-
-    int MAX = 16;
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
index 4519d33..2bfd501 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
@@ -19,6 +19,7 @@
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
 import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
+import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
index 3abd75a..f756095 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
@@ -23,6 +23,7 @@
 import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.base.GoogleServiceAuthError;
 import org.chromium.components.signin.base.GoogleServiceAuthError.State;
+import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 import org.chromium.ui.modelutil.PropertyModel;
 
 import java.util.Collections;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
index d66fe70..8f2e154 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
@@ -8,6 +8,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.base.GoogleServiceAuthError;
+import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 
 /**
  * This interface is used in web sign-in flow for the account picker bottom sheet.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
index 1d82711..61fc8e2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
@@ -54,7 +54,6 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.incognito.interstitial.IncognitoInterstitialDelegate;
-import org.chromium.chrome.browser.signin.account_picker.AccountConsistencyPromoAction;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegate;
 import org.chromium.chrome.browser.tabmodel.TabCreator;
@@ -70,6 +69,7 @@
 import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.base.GoogleServiceAuthError;
 import org.chromium.components.signin.base.GoogleServiceAuthError.State;
+import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 import org.chromium.components.signin.test.util.FakeAccountManagerFacade;
 import org.chromium.components.signin.test.util.FakeProfileDataSource;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninUtilsAccountPickerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninUtilsAccountPickerTest.java
index ee51dbdc..638894b 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninUtilsAccountPickerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninUtilsAccountPickerTest.java
@@ -20,9 +20,9 @@
 import org.chromium.base.metrics.UmaRecorderHolder;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.signin.account_picker.AccountConsistencyPromoAction;
 import org.chromium.chrome.browser.signin.services.SigninManager;
 import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
+import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 import org.chromium.ui.base.WindowAndroid;
 
 /**
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index e6d5b17..523e361 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -8622,9 +8622,16 @@
       <message name="IDS_NOTIFICATION_REPLY_PLACEHOLDER" desc="Placeholder text shown in the text box before any text is entered when replying directly to a notification.">
         Send message
       </message>
-      <message name="IDS_NOTIFICATION_MUTED_MESSAGE" desc="Informative message describing that notification content is currently hidden while the screen is being shared. Shown as the body of a notification.">
-        Details are hidden while you share your screen
-      </message>
+      <if expr="not chromeos">
+        <message name="IDS_NOTIFICATION_MUTED_MESSAGE" desc="Informative message describing that notification content is currently hidden while the screen is being shared. Shown as the body of a notification." meaning="Not on Chrome OS.">
+          Details are hidden while you share your screen
+        </message>
+      </if>
+      <if expr="chromeos">
+        <message name="IDS_NOTIFICATION_MUTED_MESSAGE" desc="Informative message describing that notification content is currently hidden while the screen is being shared. Shown as the body of a notification." meaning="On Chrome OS only.">
+          Details are hidden while you share your screen
+        </message>
+      </if>
       <if expr="not use_titlecase">
         <message name="IDS_NOTIFICATION_MUTED_TITLE" desc="Title of a notification showing how many new notifications are currently hidden. The number is always greater than zero.">
           {MUTED_NOTIFICATIONS_COUNT, plural,
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 0a4b3ed..a3e684e 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3215,6 +3215,7 @@
       "//chrome/android/modules/extra_icu/provider:native",
       "//chrome/browser/android/webapk:proto",
       "//chrome/browser/banners/android:jni_headers",
+      "//chrome/browser/consent_auditor/android:jni_headers",
       "//chrome/browser/download/internal/android",
       "//chrome/browser/endpoint_fetcher:jni_headers",
       "//chrome/browser/feedback/android",
diff --git a/chrome/browser/android/consent_auditor/consent_auditor_bridge.cc b/chrome/browser/android/consent_auditor/consent_auditor_bridge.cc
index ace93ee0..200d0f7 100644
--- a/chrome/browser/android/consent_auditor/consent_auditor_bridge.cc
+++ b/chrome/browser/android/consent_auditor/consent_auditor_bridge.cc
@@ -10,7 +10,7 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
-#include "chrome/android/chrome_jni_headers/ConsentAuditorBridge_jni.h"
+#include "chrome/browser/consent_auditor/android/jni_headers/ConsentAuditorBridge_jni.h"
 #include "chrome/browser/consent_auditor/consent_auditor_factory.h"
 #include "chrome/browser/profiles/profile_android.h"
 #include "components/consent_auditor/consent_auditor.h"
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc
index 897d9a72..742bcd7 100644
--- a/chrome/browser/apps/app_service/arc_apps.cc
+++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -55,6 +55,9 @@
 
 namespace {
 
+constexpr char kIntentExtraText[] = "android.intent.extra.TEXT";
+constexpr char kIntentExtraSubject[] = "android.intent.extra.SUBJECT";
+
 void CompleteWithCompressed(apps::mojom::Publisher::LoadIconCallback callback,
                             std::vector<uint8_t> data) {
   if (data.empty()) {
@@ -232,10 +235,16 @@
   if (intent->url.has_value()) {
     arc_intent->data = intent->url->spec();
   }
-  if (intent->share_text.has_value()) {
+  if (intent->share_text.has_value() || intent->share_title.has_value()) {
     arc_intent->extras = base::flat_map<std::string, std::string>();
-    arc_intent->extras.value().insert(std::make_pair(
-        "android.intent.extra.TEXT", intent->share_text.value()));
+  }
+  if (intent->share_text.has_value()) {
+    arc_intent->extras.value().insert(
+        std::make_pair(kIntentExtraText, intent->share_text.value()));
+  }
+  if (intent->share_title.has_value()) {
+    arc_intent->extras.value().insert(
+        std::make_pair(kIntentExtraSubject, intent->share_title.value()));
   }
   return arc_intent;
 }
diff --git a/chrome/browser/apps/app_service/extension_apps_chromeos.cc b/chrome/browser/apps/app_service/extension_apps_chromeos.cc
index d202561..fef56d44 100644
--- a/chrome/browser/apps/app_service/extension_apps_chromeos.cc
+++ b/chrome/browser/apps/app_service/extension_apps_chromeos.cc
@@ -499,8 +499,9 @@
     return;
   }
 
-  bool is_disabled = base::Contains(*disabled_system_features_pref,
-                                    base::Value(policy::SystemFeature::CAMERA));
+  bool is_disabled =
+      base::Contains(*disabled_system_features_pref,
+                     base::Value(policy::SystemFeature::kCamera));
   auto* app_id = extension_misc::kCameraAppId;
 
   // Sometimes the policy is updated before the app is installed, so this way
diff --git a/chrome/browser/apps/app_service/intent_util.cc b/chrome/browser/apps/app_service/intent_util.cc
index facfd21..99114c9 100644
--- a/chrome/browser/apps/app_service/intent_util.cc
+++ b/chrome/browser/apps/app_service/intent_util.cc
@@ -19,4 +19,15 @@
   return CreateShareIntentFromFiles(file_urls, mime_types);
 }
 
+apps::mojom::IntentPtr CreateShareIntentFromFiles(
+    Profile* profile,
+    const std::vector<base::FilePath>& file_paths,
+    const std::vector<std::string>& mime_types,
+    const std::string& share_text,
+    const std::string& share_title) {
+  auto file_urls = apps::GetFileUrls(profile, file_paths);
+  return CreateShareIntentFromFiles(file_urls, mime_types, share_text,
+                                    share_title);
+}
+
 }  // namespace apps_util
diff --git a/chrome/browser/apps/app_service/intent_util.h b/chrome/browser/apps/app_service/intent_util.h
index 1f50b06..c927c83 100644
--- a/chrome/browser/apps/app_service/intent_util.h
+++ b/chrome/browser/apps/app_service/intent_util.h
@@ -24,6 +24,17 @@
     Profile* profile,
     const std::vector<base::FilePath>& file_paths,
     const std::vector<std::string>& mime_types);
+
+// Create an intent struct from the file paths, mime types
+// of a list of files, and the share text and title.
+// This util has to live under chrome/ because it uses fileapis
+// and cannot be inlucded in components/.
+apps::mojom::IntentPtr CreateShareIntentFromFiles(
+    Profile* profile,
+    const std::vector<base::FilePath>& file_paths,
+    const std::vector<std::string>& mime_types,
+    const std::string& share_text,
+    const std::string& share_title);
 }  // namespace apps_util
 
 #endif  // CHROME_BROWSER_APPS_APP_SERVICE_INTENT_UTIL_H_
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 2b457739..5363b278 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -4584,17 +4584,17 @@
   // installation complete successfully.
   if (url.DomainIs(chrome::kChromeUIOSSettingsHost) &&
       url.path() != "/pwa.html" &&
-      IsSystemFeatureDisabled(policy::SystemFeature::OS_SETTINGS)) {
+      IsSystemFeatureDisabled(policy::SystemFeature::kOsSettings)) {
     return true;
   }
 
   if (url.DomainIs(chrome::kChromeUISettingsHost) &&
-      IsSystemFeatureDisabled(policy::SystemFeature::BROWSER_SETTINGS)) {
+      IsSystemFeatureDisabled(policy::SystemFeature::kBrowserSettings)) {
     return true;
   }
 
   if (url.DomainIs(chromeos::kChromeUIScanningAppHost) &&
-      IsSystemFeatureDisabled(policy::SystemFeature::SCANNING)) {
+      IsSystemFeatureDisabled(policy::SystemFeature::kScanning)) {
     return true;
   }
 
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc
index 31141a9e..71603361 100644
--- a/chrome/browser/chrome_content_browser_client_unittest.cc
+++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -802,7 +802,7 @@
   EXPECT_EQ(os_settings_url, dest_url);
 
   base::Value list(base::Value::Type::LIST);
-  list.Append(policy::SystemFeature::OS_SETTINGS);
+  list.Append(policy::SystemFeature::kOsSettings);
   testing_local_state_.Get()->Set(
       policy::policy_prefs::kSystemFeaturesDisableList, std::move(list));
 
@@ -825,7 +825,7 @@
   EXPECT_EQ(settings_url, dest_url);
 
   base::Value list(base::Value::Type::LIST);
-  list.Append(policy::SystemFeature::BROWSER_SETTINGS);
+  list.Append(policy::SystemFeature::kBrowserSettings);
   testing_local_state_.Get()->Set(
       policy::policy_prefs::kSystemFeaturesDisableList, std::move(list));
 
@@ -842,7 +842,7 @@
   EXPECT_EQ(scanning_app_url, dest_url);
 
   base::Value list(base::Value::Type::LIST);
-  list.Append(policy::SystemFeature::SCANNING);
+  list.Append(policy::SystemFeature::kScanning);
   testing_local_state_.Get()->Set(
       policy::policy_prefs::kSystemFeaturesDisableList, std::move(list));
 
diff --git a/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc b/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc
index 7b2d094..f435fa3 100644
--- a/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc
@@ -182,4 +182,54 @@
   WaitForFocusRing("primary", "button", "Southeast");
 }
 
+IN_PROC_BROWSER_TEST_F(SwitchAccessTest, NavigateButtonsInTextFieldMenu) {
+  EnableSwitchAccess({'1', 'A'} /* select */, {'2', 'B'} /* next */,
+                     {'3', 'C'} /* previous */);
+
+  // Load a webpage with a text box.
+  ui_test_utils::NavigateToURL(
+      browser(),
+      GURL("data:text/html,<input autofocus aria-label=MyTextField>"));
+
+  // Wait for switch access to focus on the text field.
+  WaitForFocusRing("primary", "textField", "MyTextField");
+
+  // Send "select", which opens the switch access menu.
+  SendVirtualKeyPress(ui::KeyboardCode::VKEY_1);
+
+  // Wait for the switch access menu to appear and for focus to land on
+  // the first item, the "keyboard" button.
+  //
+  // Note that we don't try to also call WaitForSwitchAccessMenuAndGetActions
+  // here because by the time it returns, we may have already received the focus
+  // ring for the menu and so the following WaitForFocusRing would fail / loop
+  // forever.
+  WaitForFocusRing("primary", "button", "Keyboard");
+
+  // Send "next".
+  SendVirtualKeyPress(ui::KeyboardCode::VKEY_2);
+
+  // The next menu item is the "dictation" button.
+  WaitForFocusRing("primary", "button", "Dictation");
+
+  // Send "next".
+  SendVirtualKeyPress(ui::KeyboardCode::VKEY_2);
+
+  // The next menu item is the "settings" button.
+  WaitForFocusRing("primary", "button", "Settings");
+
+  // Send "next".
+  SendVirtualKeyPress(ui::KeyboardCode::VKEY_2);
+
+  // Finally is the back button. Note that it has a role of "back" so we
+  // can tell it's the special Switch Access back button.
+  WaitForFocusRing("primary", "back", "");
+
+  // Send "next".
+  SendVirtualKeyPress(ui::KeyboardCode::VKEY_2);
+
+  // Wrap back around to the "keyboard" button.
+  WaitForFocusRing("primary", "button", "Keyboard");
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
index e840778..60c5c73 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
@@ -53,6 +53,8 @@
   }
 }
 
+constexpr int kFailedMountRetries = 3;
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -138,7 +140,8 @@
     : account_id_(app_account_id),
       app_type_(app_type),
       use_guest_mount_(use_guest_mount),
-      delegate_(delegate) {}
+      delegate_(delegate),
+      failed_mount_attempts_(0) {}
 
 KioskProfileLoader::~KioskProfileLoader() {}
 
@@ -181,6 +184,8 @@
   login_performer_->set_delegate(NULL);
   ignore_result(login_performer_.release());
 
+  failed_mount_attempts_ = 0;
+
   // If we are launching a demo session, we need to start MountGuest with the
   // guest username; this is because there are several places in the cros code
   // which rely on the username sent to cryptohome to be $guest. Back in Chrome
@@ -197,6 +202,17 @@
 }
 
 void KioskProfileLoader::OnAuthFailure(const AuthFailure& error) {
+  failed_mount_attempts_++;
+  if (error.reason() == AuthFailure::UNRECOVERABLE_CRYPTOHOME &&
+      failed_mount_attempts_ < kFailedMountRetries) {
+    // If the cryptohome mount failed due to corruption of the on disk state -
+    // try again: we always ask to "create" cryptohome and the corrupted one
+    // was deleted under the hood.
+    LoginAsKioskAccount();
+    return;
+  }
+  failed_mount_attempts_ = 0;
+
   SYSLOG(ERROR) << "Kiosk auth failure: error=" << error.GetErrorString();
   KioskAppLaunchError::SaveCryptohomeFailure(error);
   ReportLaunchResult(LoginFailureToKioskAppLaunchError(error));
diff --git a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h
index a1df8359..385b6b2 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h
@@ -69,6 +69,7 @@
   const KioskAppType app_type_;
   bool use_guest_mount_;
   Delegate* delegate_;
+  int failed_mount_attempts_;
   std::unique_ptr<CryptohomedChecker> cryptohomed_checker_;
   std::unique_ptr<LoginPerformer> login_performer_;
 
diff --git a/chrome/browser/chromeos/borealis/borealis_util.cc b/chrome/browser/chromeos/borealis/borealis_util.cc
index 8a368857..0504737 100644
--- a/chrome/browser/chromeos/borealis/borealis_util.cc
+++ b/chrome/browser/chromeos/borealis/borealis_util.cc
@@ -4,9 +4,18 @@
 
 #include "chrome/browser/chromeos/borealis/borealis_util.h"
 
+#include "third_party/re2/src/re2/re2.h"
+
 namespace borealis {
 
 const char kBorealisAppId[] = "dkecggknbdokeipkgnhifhiokailichf";
 const char kBorealisDlcName[] = "borealis-dlc";
+// TODO(b/174282035): Potentially update regex when other strings
+// are updated.
+const char kBorealisAppIdRegex[] = "([^/]+\\d+)";
+
+bool GetBorealisAppId(std::string exec, int& app_id) {
+  return RE2::PartialMatch(exec, kBorealisAppIdRegex, &app_id);
+}
 
 }  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_util.h b/chrome/browser/chromeos/borealis/borealis_util.h
index 7dc6fe41..36b45ff 100644
--- a/chrome/browser/chromeos/borealis/borealis_util.h
+++ b/chrome/browser/chromeos/borealis/borealis_util.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_UTIL_H_
 #define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_UTIL_H_
 
+#include <string>
+
 class Profile;
 
 namespace borealis {
@@ -14,10 +16,18 @@
 extern const char kBorealisAppId[];
 // This is used to install the Borealis DLC component.
 extern const char kBorealisDlcName[];
+// The regex used for extracing the Borealis app id of an application.
+extern const char kBorealisAppIdRegex[];
 
 // Shows the Borealis installer (borealis_installer_view).
 void ShowBorealisInstallerView(Profile* profile);
 
+// Extracts the borealis app id from |exec| and puts it into |app_id|,
+// returns true if successful.
+// TODO(b/173547790): This should probably be moved when we've decided
+// the details of how/where it will be used.
+bool GetBorealisAppId(std::string exec, int& app_id);
+
 }  // namespace borealis
 
 #endif  // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_UTIL_H_
diff --git a/chrome/browser/chromeos/guest_os/guest_os_pref_names.cc b/chrome/browser/chromeos/guest_os/guest_os_pref_names.cc
index 4b5d0855..01f0c47c 100644
--- a/chrome/browser/chromeos/guest_os/guest_os_pref_names.cc
+++ b/chrome/browser/chromeos/guest_os/guest_os_pref_names.cc
@@ -23,6 +23,7 @@
 const char kAppExtensionsKey[] = "extensions";
 const char kAppMimeTypesKey[] = "mime_types";
 const char kAppKeywordsKey[] = "keywords";
+const char kAppExecKey[] = "exec";
 const char kAppExecutableFileNameKey[] = "executable_file_name";
 const char kAppNameKey[] = "name";
 const char kAppNoDisplayKey[] = "no_display";
diff --git a/chrome/browser/chromeos/guest_os/guest_os_pref_names.h b/chrome/browser/chromeos/guest_os/guest_os_pref_names.h
index b67b75d9..87357fd 100644
--- a/chrome/browser/chromeos/guest_os/guest_os_pref_names.h
+++ b/chrome/browser/chromeos/guest_os/guest_os_pref_names.h
@@ -22,6 +22,7 @@
 extern const char kAppExtensionsKey[];
 extern const char kAppMimeTypesKey[];
 extern const char kAppKeywordsKey[];
+extern const char kAppExecKey[];
 extern const char kAppExecutableFileNameKey[];
 extern const char kAppNameKey[];
 extern const char kAppNoDisplayKey[];
diff --git a/chrome/browser/chromeos/guest_os/guest_os_registry_service.cc b/chrome/browser/chromeos/guest_os/guest_os_registry_service.cc
index 694a0434..e342cef 100644
--- a/chrome/browser/chromeos/guest_os/guest_os_registry_service.cc
+++ b/chrome/browser/chromeos/guest_os/guest_os_registry_service.cc
@@ -125,6 +125,8 @@
   pref_registration.SetKey(guest_os::prefs::kAppNameKey, std::move(name));
   pref_registration.SetKey(guest_os::prefs::kAppCommentKey,
                            ProtoToDictionary(app.comment()));
+  pref_registration.SetKey(guest_os::prefs::kAppExecKey,
+                           base::Value(app.exec()));
   pref_registration.SetKey(guest_os::prefs::kAppExecutableFileNameKey,
                            base::Value(app.executable_file_name()));
   pref_registration.SetKey(guest_os::prefs::kAppExtensionsKey,
@@ -255,6 +257,7 @@
          ", startup_wm_class: " + ToString(app.startup_wm_class()) +
          ", startup_notify: " + ToString(app.startup_notify()) +
          ", keywords: " + ToString(app.keywords()) +
+         ", exec: " + ToString(app.exec()) +
          ", executable_file_name: " + ToString(app.executable_file_name()) +
          ", package_id: " + ToString(app.package_id()) +
          ", extensions: " + ToString(app.extensions()) + "}";
@@ -387,6 +390,12 @@
   return LocalizedString(guest_os::prefs::kAppCommentKey);
 }
 
+std::string GuestOsRegistryService::Registration::Exec() const {
+  return pref_
+      .FindKeyOfType(guest_os::prefs::kAppExecKey, base::Value::Type::STRING)
+      ->GetString();
+}
+
 std::string GuestOsRegistryService::Registration::ExecutableFileName() const {
   if (pref_.is_none())
     return std::string();
diff --git a/chrome/browser/chromeos/guest_os/guest_os_registry_service.h b/chrome/browser/chromeos/guest_os/guest_os_registry_service.h
index 5b57ba1b..7128dd5 100644
--- a/chrome/browser/chromeos/guest_os/guest_os_registry_service.h
+++ b/chrome/browser/chromeos/guest_os/guest_os_registry_service.h
@@ -86,6 +86,7 @@
 
     std::string Name() const;
     std::string Comment() const;
+    std::string Exec() const;
     std::string ExecutableFileName() const;
     std::set<std::string> Extensions() const;
     std::set<std::string> MimeTypes() const;
diff --git a/chrome/browser/chromeos/guest_os/guest_os_registry_service_unittest.cc b/chrome/browser/chromeos/guest_os/guest_os_registry_service_unittest.cc
index 6db4ec287..0dd4648 100644
--- a/chrome/browser/chromeos/guest_os/guest_os_registry_service_unittest.cc
+++ b/chrome/browser/chromeos/guest_os/guest_os_registry_service_unittest.cc
@@ -102,6 +102,7 @@
       {"", {"very", "awesome"}}};
   std::set<std::string> mime_types = {"text/plain", "text/x-python"};
   bool no_display = true;
+  std::string exec = "execName --extra-arg=true";
   std::string executable_file_name = "execName";
   std::string package_id =
       "vim;2:8.0.0197-4+deb9u1;amd64;installed:debian-stable";
@@ -118,6 +119,7 @@
   App* app = app_list.add_apps();
   app->set_desktop_file_id(desktop_file_id);
   app->set_no_display(no_display);
+  app->set_exec(exec);
   app->set_executable_file_name(executable_file_name);
   app->set_package_id(package_id);
 
@@ -160,6 +162,7 @@
   EXPECT_EQ(result->Keywords(), keywords[""]);
   EXPECT_EQ(result->MimeTypes(), mime_types);
   EXPECT_EQ(result->NoDisplay(), no_display);
+  EXPECT_EQ(result->Exec(), exec);
   EXPECT_EQ(result->ExecutableFileName(), executable_file_name);
   EXPECT_EQ(result->PackageId(), package_id);
 }
@@ -488,6 +491,27 @@
   EXPECT_EQ(result->Keywords(), keywords["te"]);
 }
 
+TEST_F(GuestOsRegistryServiceTest, SetAndGetRegistrationExec) {
+  std::string exec = "execName --extra-arg=true";
+  std::string app_id_valid_exec =
+      crostini::CrostiniTestHelper::GenerateAppId("app", "vm", "container");
+  std::string app_id_no_exec =
+      crostini::CrostiniTestHelper::GenerateAppId("noExec", "vm", "container");
+  ApplicationList app_list =
+      crostini::CrostiniTestHelper::BasicAppList("app", "vm", "container");
+  *app_list.add_apps() = crostini::CrostiniTestHelper::BasicApp("noExec");
+
+  app_list.mutable_apps(0)->set_exec(exec);
+  service()->UpdateApplicationList(app_list);
+
+  base::Optional<GuestOsRegistryService::Registration> result_valid_exec =
+      service()->GetRegistration(app_id_valid_exec);
+  base::Optional<GuestOsRegistryService::Registration> result_no_exec =
+      service()->GetRegistration(app_id_no_exec);
+  EXPECT_EQ(result_valid_exec->Exec(), exec);
+  EXPECT_EQ(result_no_exec->Exec(), "");
+}
+
 TEST_F(GuestOsRegistryServiceTest, SetAndGetRegistrationExecutableFileName) {
   std::string executable_file_name = "myExec";
   std::string app_id_valid_exec =
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
index cc51d21d..e35aaa9 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -138,11 +138,12 @@
   void SetUp() override {
     ui::InitializeInputMethodForTesting();
 
-    InitImeList();
+    std::vector<ComponentExtensionIME> ime_list;
+    InitImeList(ime_list);
 
     auto mock_delegate =
         std::make_unique<MockComponentExtensionIMEManagerDelegate>();
-    mock_delegate->set_ime_list(ime_list_);
+    mock_delegate->set_ime_list(ime_list);
 
     manager_ = std::make_unique<InputMethodManagerImpl>(
         std::make_unique<FakeInputMethodDelegate>(), std::move(mock_delegate),
@@ -191,8 +192,9 @@
     manager_.reset();
   }
 
-  void InitImeList() {
-    ime_list_.clear();
+ private:
+  static void InitImeList(std::vector<ComponentExtensionIME>& ime_list) {
+    ime_list.clear();
 
     ComponentExtensionIME ext_xkb;
     ext_xkb.id = extension_ime_util::kXkbExtensionId;
@@ -290,7 +292,7 @@
     ext_xkb_engine_hu.layouts.emplace_back("hu");
     ext_xkb.engines.push_back(ext_xkb_engine_hu);
 
-    ime_list_.push_back(ext_xkb);
+    ime_list.push_back(ext_xkb);
 
     ComponentExtensionIME ext1;
     ext1.id = extension_ime_util::kMozcExtensionId;
@@ -311,7 +313,7 @@
     ext1_engine2.layouts.emplace_back("jp");
     ext1.engines.push_back(ext1_engine2);
 
-    ime_list_.push_back(ext1);
+    ime_list.push_back(ext1);
 
     ComponentExtensionIME ext2;
     ext2.id = extension_ime_util::kT13nExtensionId;
@@ -332,7 +334,7 @@
     ext2_engine2.layouts.emplace_back("us(dvorak)");
     ext2.engines.push_back(ext2_engine2);
 
-    ime_list_.push_back(ext2);
+    ime_list.push_back(ext2);
   }
 
  protected:
@@ -342,7 +344,6 @@
   MockCandidateWindowController* candidate_window_controller_ = nullptr;
   std::unique_ptr<MockInputMethodEngine> mock_engine_handler_;
   FakeImeKeyboard* keyboard_ = nullptr;
-  std::vector<ComponentExtensionIME> ime_list_;
   ui::ime::InputMethodMenuManager* menu_manager_;
 
  private:
@@ -1181,8 +1182,7 @@
 
 TEST_F(InputMethodManagerImplTest, ChangeInputMethodComponentExtensionOneIME) {
   const std::string ext_id = extension_ime_util::GetComponentInputMethodID(
-      ime_list_[1].id,
-      ime_list_[1].engines[0].engine_id);
+      extension_ime_util::kMozcExtensionId, "nacl_mozc_us");
   std::vector<std::string> ids;
   ids.push_back(ext_id);
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
@@ -1193,11 +1193,9 @@
 
 TEST_F(InputMethodManagerImplTest, ChangeInputMethodComponentExtensionTwoIME) {
   const std::string ext_id1 = extension_ime_util::GetComponentInputMethodID(
-      ime_list_[1].id,
-      ime_list_[1].engines[0].engine_id);
+      extension_ime_util::kMozcExtensionId, "nacl_mozc_us");
   const std::string ext_id2 = extension_ime_util::GetComponentInputMethodID(
-      ime_list_[2].id,
-      ime_list_[2].engines[0].engine_id);
+      extension_ime_util::kT13nExtensionId, kExt2Engine1Id);
   std::vector<std::string> ids;
   ids.push_back(ext_id1);
   ids.push_back(ext_id2);
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
index 16828185..e688102a 100644
--- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
@@ -765,6 +765,18 @@
   RunResolve(auth_.get());
 }
 
+TEST_F(CryptohomeAuthenticatorTest, ResolveOfflineMountUnrecoverable) {
+  // Set up state as though a cryptohome mount attempt has occurred
+  // and has been rejected because the vault is unrecoverable.
+  state_->PresetCryptohomeStatus(cryptohome::MOUNT_ERROR_VAULT_UNRECOVERABLE);
+
+  EXPECT_EQ(CryptohomeAuthenticator::OFFLINE_MOUNT_UNRECOVERABLE,
+            SetAndResolveState(auth_.get(), state_.release()));
+
+  ExpectLoginFailure(AuthFailure(AuthFailure::UNRECOVERABLE_CRYPTOHOME));
+  RunResolve(auth_.get());
+}
+
 TEST_F(CryptohomeAuthenticatorTest, ResolveCreateNew) {
   // Set up state as though a cryptohome mount attempt has occurred
   // and been rejected because the user doesn't exist; additionally,
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index d274825..94c6e498 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -935,6 +935,15 @@
     ForceOnlineLoginForAccountId(last_login_attempt_account_id_);
     RecordReauthReason(last_login_attempt_account_id_,
                        ReauthReason::MISSING_CRYPTOHOME);
+  } else if (is_known_user &&
+             failure.reason() == AuthFailure::UNRECOVERABLE_CRYPTOHOME) {
+    // TODO(chromium:1140868, dlunev): for now we route unrecoverable the same
+    // way as missing because it is removed under the hood in cryptohomed when
+    // the condition met. We should surface that up and deal with it on the
+    // chromium level, including making the decision user-driven.
+    ForceOnlineLoginForAccountId(last_login_attempt_account_id_);
+    RecordReauthReason(last_login_attempt_account_id_,
+                       ReauthReason::UNRECOVERABLE_CRYPTOHOME);
   } else {
     // Check networking after trying to login in case user is
     // cached locally or the local admin account.
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
index 977ac21..31dca1e 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -1243,6 +1243,21 @@
   EXPECT_TRUE(user->force_online_signin());
 }
 
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerAuthFailureTest,
+                       CryptohomeUnrecoverable) {
+  SetUpStubAuthenticatorAndAttemptLogin(AuthFailure::UNRECOVERABLE_CRYPTOHOME);
+
+  WaitForGaiaPageLoad();
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsOobeDialogVisible());
+  EXPECT_EQ(fake_gaia_.fake_gaia()->prefilled_email(),
+            test_user_.account_id.GetUserEmail());
+
+  const user_manager::User* user =
+      user_manager::UserManager::Get()->FindUser(test_user_.account_id);
+  ASSERT_TRUE(user);
+  EXPECT_TRUE(user->force_online_signin());
+}
+
 IN_PROC_BROWSER_TEST_F(ExistingUserControllerAuthFailureTest, TpmError) {
   SetUpStubAuthenticatorAndAttemptLogin(AuthFailure::TPM_ERROR);
 
diff --git a/chrome/browser/chromeos/login/reauth_stats.h b/chrome/browser/chromeos/login/reauth_stats.h
index 917f0b6b..70a3265c 100644
--- a/chrome/browser/chromeos/login/reauth_stats.h
+++ b/chrome/browser/chromeos/login/reauth_stats.h
@@ -52,6 +52,9 @@
   // SAML password sync token validation failed.
   SAML_PASSWORD_SYNC_TOKEN_VALIDATION_FAILED = 9,
 
+  // Corrupted cryptohome
+  UNRECOVERABLE_CRYPTOHOME = 10,
+
   // Must be the last value in this list.
   NUM_REAUTH_FLOW_REASONS,
 };
diff --git a/chrome/browser/chromeos/login/screens/eula_screen.cc b/chrome/browser/chromeos/login/screens/eula_screen.cc
index 070e623..6961243c 100644
--- a/chrome/browser/chromeos/login/screens/eula_screen.cc
+++ b/chrome/browser/chromeos/login/screens/eula_screen.cc
@@ -14,9 +14,10 @@
 #include "chrome/browser/chromeos/login/wizard_context.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h"
-#include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 
 namespace chromeos {
 namespace {
@@ -121,7 +122,8 @@
 
 void EulaScreen::ShowImpl() {
   // Command to own the TPM.
-  CryptohomeClient::Get()->TpmCanAttemptOwnership(base::DoNothing());
+  TpmManagerClient::Get()->TakeOwnership(::tpm_manager::TakeOwnershipRequest(),
+                                         base::DoNothing());
   if (WizardController::UsingHandsOffEnrollment())
     OnUserAction(kUserActionAcceptButtonClicked);
   else if (view_)
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
index 9b2ad53..09ad672 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
@@ -620,17 +620,22 @@
     } else {
       NOTREACHED();
     }
-  } else if (path == kStartUpFlags) {
-    em::StartUpFlagsProto* flags_proto = settings.mutable_start_up_flags();
-    flags_proto->Clear();
-    const base::ListValue* flags;
-    if (value.GetAsList(&flags)) {
-      for (base::ListValue::const_iterator i = flags->begin();
-           i != flags->end();
-           ++i) {
-        std::string flag;
-        if (i->GetAsString(&flag))
-          flags_proto->add_flags(flag);
+  } else if (path == kStartUpFlagsDeprecated) {
+    em::FeatureFlagsProto* feature_flags = settings.mutable_feature_flags();
+    feature_flags->Clear();
+    if (value.is_list()) {
+      for (const auto& flag : value.GetList()) {
+        if (flag.is_string())
+          feature_flags->add_switches(flag.GetString());
+      }
+    }
+  } else if (path == kFeatureFlags) {
+    em::FeatureFlagsProto* feature_flags = settings.mutable_feature_flags();
+    feature_flags->Clear();
+    if (value.is_list()) {
+      for (const auto& flag : value.GetList()) {
+        if (flag.is_string())
+          feature_flags->add_feature_flags(flag.GetString());
       }
     }
   } else if (path == kSystemUse24HourClock) {
diff --git a/chrome/browser/chromeos/policy/affiliation_mixin.cc b/chrome/browser/chromeos/policy/affiliation_mixin.cc
new file mode 100644
index 0000000..3a06b9b
--- /dev/null
+++ b/chrome/browser/chromeos/policy/affiliation_mixin.cc
@@ -0,0 +1,97 @@
+// 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/chromeos/policy/affiliation_mixin.h"
+
+#include <set>
+#include <string>
+
+#include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
+#include "chrome/browser/chromeos/policy/device_policy_builder.h"
+#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
+#include "chromeos/dbus/authpolicy/authpolicy_client.h"
+#include "chromeos/dbus/authpolicy/fake_authpolicy_client.h"
+#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
+#include "components/account_id/account_id.h"
+#include "components/policy/core/common/cloud/device_management_service.h"
+#include "components/policy/core/common/cloud/policy_builder.h"
+
+namespace policy {
+
+namespace {
+
+// If running with `affiliated==true`, the test will use the same
+// `kAffiliationID` as user and device affiliation ID, which makes the user
+// affiliated (affiliation IDs overlap).
+// If running with `affiliated==false`, the test will use `kAffiliationID` as
+// device and `kAnotherAffiliationID` as user affiliation ID, which makes the
+// user non-affiliated (affiliation IDs don't overlap).
+constexpr char kAffiliationID[] = "some-affiliation-id";
+constexpr char kAnotherAffiliationID[] = "another-affiliation-id";
+
+constexpr char kAffiliatedUserEmail[] = "affiliateduser@example.com";
+constexpr char kAffiliatedUserGaiaId[] = "1029384756";
+constexpr char kAffiliatedUserObjGuid[] =
+    "{11111111-1111-1111-1111-111111111111}";
+
+}  // namespace
+
+AffiliationMixin::AffiliationMixin(
+    InProcessBrowserTestMixinHost* host,
+    DevicePolicyCrosTestHelper* device_policy_cros_test_helper)
+    : InProcessBrowserTestMixin(host),
+      policy_test_helper_(device_policy_cros_test_helper),
+      account_id_(AccountId::FromUserEmailGaiaId(kAffiliatedUserEmail,
+                                                 kAffiliatedUserGaiaId)),
+      user_policy_(std::make_unique<UserPolicyBuilder>()) {}
+
+AffiliationMixin::~AffiliationMixin() = default;
+
+void AffiliationMixin::SetUpInProcessBrowserTestFixture() {
+  AffiliationTestHelper affiliation_helper = GetAffiliationTestHelper();
+  std::set<std::string> device_affiliation_ids;
+  device_affiliation_ids.insert(kAffiliationID);
+  ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
+      policy_test_helper_, device_affiliation_ids));
+  policy_test_helper_->InstallOwnerKey();
+
+  std::set<std::string> user_affiliation_ids;
+  if (affiliated_) {
+    user_affiliation_ids.insert(kAffiliationID);
+  } else {
+    user_affiliation_ids.insert(kAnotherAffiliationID);
+  }
+  ASSERT_TRUE(user_policy_.get());
+  ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetUserAffiliationIDs(
+      user_policy_.get(), account_id_, user_affiliation_ids));
+}
+
+void AffiliationMixin::SetIsForActiveDirectory(bool is_for_active_directory) {
+  if (is_for_active_directory == is_for_active_directory_)
+    return;
+
+  is_for_active_directory_ = is_for_active_directory;
+  if (is_for_active_directory) {
+    account_id_ = AccountId::AdFromUserEmailObjGuid(kAffiliatedUserEmail,
+                                                    kAffiliatedUserObjGuid);
+  } else {
+    account_id_ = AccountId::FromUserEmailGaiaId(kAffiliatedUserEmail,
+                                                 kAffiliatedUserGaiaId);
+  }
+}
+
+AffiliationTestHelper AffiliationMixin::GetAffiliationTestHelper() const {
+  auto* session_manager_client = chromeos::FakeSessionManagerClient::Get();
+  CHECK(session_manager_client);
+  if (is_for_active_directory_) {
+    auto* fake_auth_policy_client = chromeos::FakeAuthPolicyClient::Get();
+    CHECK(fake_auth_policy_client);
+    return AffiliationTestHelper::CreateForActiveDirectory(
+        session_manager_client, fake_auth_policy_client);
+  }
+  return AffiliationTestHelper::CreateForCloud(session_manager_client);
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/affiliation_mixin.h b/chrome/browser/chromeos/policy/affiliation_mixin.h
new file mode 100644
index 0000000..b30131d
--- /dev/null
+++ b/chrome/browser/chromeos/policy/affiliation_mixin.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_CHROMEOS_POLICY_AFFILIATION_MIXIN_H_
+#define CHROME_BROWSER_CHROMEOS_POLICY_AFFILIATION_MIXIN_H_
+
+#include <memory>
+#include <utility>
+
+#include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
+#include "chrome/browser/chromeos/policy/device_policy_builder.h"
+#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
+#include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "components/account_id/account_id.h"
+#include "components/policy/core/common/cloud/policy_builder.h"
+
+namespace policy {
+
+// Mixin to set up device and user affiliation ids. By default, device and user
+// affiliation ids will be identical, and the user will be affiliated.
+// `set_affiliated(false)` can be used to change this behavior.
+// This mixin relies on an available `chromeos::FakeSessionManagerClient` during
+// `SetUpInProcessBrowserTestFixture()`. Users of this mixin can run
+// `chromeos::SessionManagerClient::InitializeFakeInMemory();` to ensure this is
+// the case.
+class AffiliationMixin final : public InProcessBrowserTestMixin {
+ public:
+  explicit AffiliationMixin(
+      InProcessBrowserTestMixinHost* host,
+      DevicePolicyCrosTestHelper* device_policy_cros_test_helper);
+  AffiliationMixin(const AffiliationMixin&) = delete;
+  AffiliationMixin& operator=(const AffiliationMixin&) = delete;
+  ~AffiliationMixin() override;
+
+  // InProcessBrowserTestMixin:
+  void SetUpInProcessBrowserTestFixture() override;
+
+  // Returns the account id of the user.
+  AccountId account_id() const { return account_id_; }
+
+  // Sets if the user is an Active Directory user. False by default. Needs to be
+  // called before SetUp to have an effect (e.g., directly after mixin
+  // construction).
+  void SetIsForActiveDirectory(bool is_for_active_directory);
+
+  // Sets if the user is affiliated with the device. True by default. Needs to
+  // be called before SetUp to have an effect (e.g., directly after mixin
+  // construction).
+  void set_affiliated(bool affiliated) { affiliated_ = affiliated; }
+
+  // Returns the user policies of the user. Needs to be used to change the
+  // user's policies. Can only be used after setup is complete.
+  std::unique_ptr<UserPolicyBuilder> TakeUserPolicy() {
+    return std::move(user_policy_);
+  }
+
+ private:
+  AffiliationTestHelper GetAffiliationTestHelper() const;
+
+  DevicePolicyCrosTestHelper* const policy_test_helper_;
+  bool affiliated_ = true;
+  bool is_for_active_directory_ = false;
+  AccountId account_id_;
+  std::unique_ptr<UserPolicyBuilder> user_policy_;
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_CHROMEOS_POLICY_AFFILIATION_MIXIN_H_
diff --git a/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.cc b/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.cc
index a23ccc8..25eca10 100644
--- a/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.cc
+++ b/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.cc
@@ -53,7 +53,7 @@
   for (const auto& element : filtered_list.GetList()) {
     SystemFeature feature = ConvertToEnum(element.GetString());
     enums_list.Append(feature);
-    if (feature == SystemFeature::OS_SETTINGS)
+    if (feature == SystemFeature::kOsSettings)
       os_settings_enabled = false;
 
     if (!old_list ||
@@ -71,16 +71,16 @@
 SystemFeature SystemFeaturesDisableListPolicyHandler::ConvertToEnum(
     const std::string& system_feature) {
   if (system_feature == kCameraFeature)
-    return SystemFeature::CAMERA;
+    return SystemFeature::kCamera;
   if (system_feature == kOsSettingsFeature)
-    return SystemFeature::OS_SETTINGS;
+    return SystemFeature::kOsSettings;
   if (system_feature == kBrowserSettingsFeature)
-    return SystemFeature::BROWSER_SETTINGS;
+    return SystemFeature::kBrowserSettings;
   if (system_feature == kScanningFeature)
-    return SystemFeature::SCANNING;
+    return SystemFeature::kScanning;
 
   LOG(ERROR) << "Unsupported system feature: " << system_feature;
-  return UNKNOWN_SYSTEM_FEATURE;
+  return kUnknownSystemFeature;
 }
 
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h b/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h
index 601eace4..2d3070c 100644
--- a/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h
+++ b/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h
@@ -19,12 +19,12 @@
 // These values are persisted to logs. Entries should not be renumbered and
 // numeric values should never be reused.
 enum SystemFeature {
-  UNKNOWN_SYSTEM_FEATURE = 0,
-  CAMERA = 1,            // The camera chrome app on Chrome OS.
-  BROWSER_SETTINGS = 2,  // Browser settings.
-  OS_SETTINGS = 3,       // The settings feature on Chrome OS.
-  SCANNING = 4,          // The scan SWA on Chrome OS.
-  kMaxValue = SCANNING
+  kUnknownSystemFeature = 0,
+  kCamera = 1,           // The camera chrome app on Chrome OS.
+  kBrowserSettings = 2,  // Browser settings.
+  kOsSettings = 3,       // The settings feature on Chrome OS.
+  kScanning = 4,         // The scan SWA on Chrome OS.
+  kMaxValue = kScanning
 };
 
 // A disabling mode that decides the user experience when a system feature is
diff --git a/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler_unittest.cc b/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler_unittest.cc
index 8f2b81e..ecaa003 100644
--- a/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler_unittest.cc
+++ b/chrome/browser/chromeos/policy/system_features_disable_list_policy_handler_unittest.cc
@@ -45,27 +45,27 @@
   EXPECT_TRUE(value->GetBool());
 
   base::Value expected_list(base::Value::Type::LIST);
-  expected_list.Append(SystemFeature::CAMERA);
-  expected_list.Append(SystemFeature::BROWSER_SETTINGS);
+  expected_list.Append(SystemFeature::kCamera);
+  expected_list.Append(SystemFeature::kBrowserSettings);
 
   EXPECT_TRUE(prefs.GetValue(policy_prefs::kSystemFeaturesDisableList, &value));
   EXPECT_EQ(expected_list, *value);
 
   histogram_tester_.ExpectTotalCount(kSystemFeaturesDisableListHistogram, 2);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::CAMERA,
+                                      SystemFeature::kCamera,
                                       /*amount*/ 1);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::BROWSER_SETTINGS,
+                                      SystemFeature::kBrowserSettings,
                                       /*amount*/ 1);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::OS_SETTINGS,
+                                      SystemFeature::kOsSettings,
                                       /*amount*/ 0);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::SCANNING,
+                                      SystemFeature::kScanning,
                                       /*amount*/ 0);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::UNKNOWN_SYSTEM_FEATURE,
+                                      SystemFeature::kUnknownSystemFeature,
                                       /*amount*/ 0);
 
   features_list.ClearList();
@@ -84,29 +84,29 @@
   EXPECT_FALSE(value->GetBool());
 
   expected_list.ClearList();
-  expected_list.Append(SystemFeature::CAMERA);
-  expected_list.Append(SystemFeature::OS_SETTINGS);
-  expected_list.Append(SystemFeature::SCANNING);
-  expected_list.Append(SystemFeature::UNKNOWN_SYSTEM_FEATURE);
+  expected_list.Append(SystemFeature::kCamera);
+  expected_list.Append(SystemFeature::kOsSettings);
+  expected_list.Append(SystemFeature::kScanning);
+  expected_list.Append(SystemFeature::kUnknownSystemFeature);
 
   EXPECT_TRUE(prefs.GetValue(policy_prefs::kSystemFeaturesDisableList, &value));
   EXPECT_EQ(expected_list, *value);
 
   histogram_tester_.ExpectTotalCount(kSystemFeaturesDisableListHistogram, 5);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::CAMERA,
+                                      SystemFeature::kCamera,
                                       /*amount*/ 1);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::BROWSER_SETTINGS,
+                                      SystemFeature::kBrowserSettings,
                                       /*amount*/ 1);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::OS_SETTINGS,
+                                      SystemFeature::kOsSettings,
                                       /*amount*/ 1);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::SCANNING,
+                                      SystemFeature::kScanning,
                                       /*amount*/ 1);
   histogram_tester_.ExpectBucketCount(kSystemFeaturesDisableListHistogram,
-                                      SystemFeature::UNKNOWN_SYSTEM_FEATURE,
+                                      SystemFeature::kUnknownSystemFeature,
                                       /*amount*/ 1);
 }
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/unaffiliated_arc_allowed_browsertest.cc b/chrome/browser/chromeos/policy/unaffiliated_arc_allowed_browsertest.cc
index a98f085..0cf2bc1 100644
--- a/chrome/browser/chromeos/policy/unaffiliated_arc_allowed_browsertest.cc
+++ b/chrome/browser/chromeos/policy/unaffiliated_arc_allowed_browsertest.cc
@@ -12,8 +12,8 @@
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
+#include "chrome/browser/chromeos/policy/affiliation_mixin.h"
 #include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
-#include "chrome/browser/chromeos/policy/device_policy_builder.h"
 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -31,11 +31,6 @@
 
 namespace {
 
-constexpr char kAffiliatedUserEmail[] = "affiliated-user@example.com";
-constexpr char kAffiliatedUserGaiaId[] = "affiliated-user_example.com";
-constexpr char kAffiliationID[] = "some-affiliation-id";
-constexpr char kAnotherAffiliationID[] = "another-affiliation-id";
-
 struct Params {
   explicit Params(bool _affiliated) : affiliated(_affiliated) {}
   bool affiliated;
@@ -47,11 +42,9 @@
     : public DevicePolicyCrosBrowserTest,
       public ::testing::WithParamInterface<Params> {
  public:
-  UnaffiliatedArcAllowedTest()
-      : affiliated_account_id_(
-            AccountId::FromUserEmailGaiaId(kAffiliatedUserEmail,
-                                           kAffiliatedUserGaiaId)) {
+  UnaffiliatedArcAllowedTest() {
     set_exit_when_last_browser_closes(false);
+    affiliation_mixin_.set_affiliated(GetParam().affiliated);
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -61,24 +54,6 @@
         command_line);
   }
 
-  void SetUpInProcessBrowserTestFixture() override {
-    DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
-
-    UserPolicyBuilder user_policy;
-    DevicePolicyCrosTestHelper test_helper;
-
-    const std::set<std::string> device_affiliation_ids = {kAffiliationID};
-    const std::set<std::string> user_affiliation_ids = {
-        GetParam().affiliated ? kAffiliationID : kAnotherAffiliationID};
-
-    AffiliationTestHelper affiliation_helper =
-        AffiliationTestHelper::CreateForCloud(session_manager_client());
-    ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
-        &test_helper, device_affiliation_ids));
-    ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetUserAffiliationIDs(
-        &user_policy, affiliated_account_id_, user_affiliation_ids));
-  }
-
   void TearDownOnMainThread() override {
     // If the login display is still showing, exit gracefully.
     if (chromeos::LoginDisplayHost::default_host()) {
@@ -107,20 +82,20 @@
     run_loop.Run();
   }
 
-  const AccountId affiliated_account_id_;
+  AffiliationMixin affiliation_mixin_{&mixin_host_, policy_helper()};
 
  private:
   DISALLOW_COPY_AND_ASSIGN(UnaffiliatedArcAllowedTest);
 };
 
 IN_PROC_BROWSER_TEST_P(UnaffiliatedArcAllowedTest, PRE_ProfileTest) {
-  AffiliationTestHelper::PreLoginUser(affiliated_account_id_);
+  AffiliationTestHelper::PreLoginUser(affiliation_mixin_.account_id());
 }
 
 IN_PROC_BROWSER_TEST_P(UnaffiliatedArcAllowedTest, ProfileTest) {
-  AffiliationTestHelper::LoginUser(affiliated_account_id_);
-  const user_manager::User* user =
-      user_manager::UserManager::Get()->FindUser(affiliated_account_id_);
+  AffiliationTestHelper::LoginUser(affiliation_mixin_.account_id());
+  const user_manager::User* user = user_manager::UserManager::Get()->FindUser(
+      affiliation_mixin_.account_id());
   const Profile* profile =
       chromeos::ProfileHelper::Get()->GetProfileByUser(user);
   const bool affiliated = GetParam().affiliated;
diff --git a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
index 37dc557..3a3d9447 100644
--- a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
+++ b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
@@ -11,8 +11,9 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/login/test/device_state_mixin.h"
+#include "chrome/browser/chromeos/policy/affiliation_mixin.h"
 #include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
-#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
 #include "chrome/browser/net/nss_context.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -22,8 +23,6 @@
 #include "chromeos/dbus/authpolicy/fake_authpolicy_client.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "components/account_id/account_id.h"
@@ -48,13 +47,6 @@
 
 namespace {
 
-constexpr char kAffiliatedUser[] = "affiliated-user@example.com";
-constexpr char kAffiliatedUserGaiaId[] = "1234567890";
-constexpr char kAffiliatedUserObjGuid[] =
-    "{11111111-1111-1111-1111-111111111111}";
-constexpr char kAffiliationID[] = "some-affiliation-id";
-constexpr char kAnotherAffiliationID[] = "another-affiliation-id";
-
 struct Params {
   Params(bool affiliated, bool active_directory)
       : affiliated(affiliated), active_directory(active_directory) {}
@@ -124,14 +116,8 @@
  public:
   UserAffiliationBrowserTest() {
     set_exit_when_last_browser_closes(false);
-
-    if (GetParam().active_directory) {
-      account_id_ = AccountId::AdFromUserEmailObjGuid(kAffiliatedUser,
-                                                      kAffiliatedUserObjGuid);
-    } else {
-      account_id_ = AccountId::FromUserEmailGaiaId(kAffiliatedUser,
-                                                   kAffiliatedUserGaiaId);
-    }
+    affiliation_mixin_.SetIsForActiveDirectory(GetParam().active_directory);
+    affiliation_mixin_.set_affiliated(GetParam().affiliated);
   }
 
  protected:
@@ -143,7 +129,8 @@
           command_line);
     } else {
       const cryptohome::AccountIdentifier cryptohome_id =
-          cryptohome::CreateAccountIdentifierFromAccountId(account_id_);
+          cryptohome::CreateAccountIdentifierFromAccountId(
+              affiliation_mixin_.account_id());
       command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
                                       cryptohome_id.account_id());
       command_line->AppendSwitchASCII(
@@ -159,32 +146,11 @@
     // shutdown in ChromeBrowserMain.
     chromeos::SessionManagerClient::InitializeFakeInMemory();
     chromeos::UpstartClient::InitializeFake();
-    chromeos::FakeAuthPolicyClient* fake_authpolicy_client = nullptr;
     if (GetParam().active_directory) {
       chromeos::AuthPolicyClient::InitializeFake();
-      fake_authpolicy_client = chromeos::FakeAuthPolicyClient::Get();
-      fake_authpolicy_client->DisableOperationDelayForTesting();
+      chromeos::FakeAuthPolicyClient::Get()->DisableOperationDelayForTesting();
     }
 
-    DevicePolicyCrosTestHelper test_helper;
-    UserPolicyBuilder user_policy;
-    const std::set<std::string> device_affiliation_ids = {kAffiliationID};
-    const std::set<std::string> user_affiliation_ids = {
-        GetParam().affiliated ? kAffiliationID : kAnotherAffiliationID};
-
-    auto* session_manager_client = chromeos::FakeSessionManagerClient::Get();
-    AffiliationTestHelper affiliation_helper =
-        GetParam().active_directory
-            ? AffiliationTestHelper::CreateForActiveDirectory(
-                  session_manager_client, fake_authpolicy_client)
-            : AffiliationTestHelper::CreateForCloud(session_manager_client);
-
-    ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
-        &test_helper, device_affiliation_ids));
-
-    ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetUserAffiliationIDs(
-        &user_policy, account_id_, user_affiliation_ids));
-
     // Set retry delay to prevent timeouts.
     policy::DeviceManagementService::SetRetryDelayForTesting(0);
   }
@@ -216,8 +182,6 @@
     TearDownTestSystemSlot();
   }
 
-  AccountId account_id_;
-
   void SetUpTestSystemSlot() {
     bool system_slot_constructed_successfully = false;
     base::RunLoop loop;
@@ -232,9 +196,10 @@
   }
 
   void VerifyAffiliationExpectations() {
-    EXPECT_EQ(GetParam().affiliated, user_manager::UserManager::Get()
-                                         ->FindUser(account_id_)
-                                         ->IsAffiliated());
+    EXPECT_EQ(GetParam().affiliated,
+              user_manager::UserManager::Get()
+                  ->FindUser(affiliation_mixin_.account_id())
+                  ->IsAffiliated());
 
     // Also test system slot availability, which is tied to user affiliation.
     // This gives us additional information, because for the system slot to be
@@ -245,6 +210,9 @@
               IsSystemSlotAvailable(ProfileManager::GetPrimaryUserProfile()));
   }
 
+  DevicePolicyCrosTestHelper test_helper_;
+  AffiliationMixin affiliation_mixin_{&mixin_host_, &test_helper_};
+
  private:
   void SetUpTestSystemSlotOnIO(bool* out_system_slot_constructed_successfully) {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -284,12 +252,12 @@
 };
 
 IN_PROC_BROWSER_TEST_P(UserAffiliationBrowserTest, PRE_PRE_TestAffiliation) {
-  AffiliationTestHelper::PreLoginUser(account_id_);
+  AffiliationTestHelper::PreLoginUser(affiliation_mixin_.account_id());
 }
 
 // This part of the test performs a regular sign-in through the login manager.
 IN_PROC_BROWSER_TEST_P(UserAffiliationBrowserTest, PRE_TestAffiliation) {
-  AffiliationTestHelper::LoginUser(account_id_);
+  AffiliationTestHelper::LoginUser(affiliation_mixin_.account_id());
   ASSERT_NO_FATAL_FAILURE(VerifyAffiliationExpectations());
 }
 
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index b235ad3..f52b1dee 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -105,6 +105,7 @@
     kDeviceWilcoDtcAllowed,
     kDisplayRotationDefault,
     kExtensionCacheSize,
+    kFeatureFlags,
     kHeartbeatEnabled,
     kHeartbeatFrequency,
     kLoginAuthenticationBehavior,
@@ -145,7 +146,7 @@
     kSamlLoginAuthenticationType,
     kServiceAccountIdentity,
     kSignedDataRoamingEnabled,
-    kStartUpFlags,
+    kStartUpFlagsDeprecated,
     kStatsReportingPref,
     kSystemLogUploadEnabled,
     kSystemProxySettings,
@@ -374,14 +375,24 @@
       kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
       policy.device_local_accounts().prompt_for_network_when_offline());
 
-  if (policy.has_start_up_flags()) {
-    std::vector<base::Value> list;
-    const em::StartUpFlagsProto& flags_proto = policy.start_up_flags();
-    const RepeatedPtrField<std::string>& flags = flags_proto.flags();
-    for (const std::string& entry : flags) {
-      list.push_back(base::Value(entry));
+  if (policy.has_feature_flags()) {
+    std::vector<base::Value> switches_list;
+    for (const std::string& entry : policy.feature_flags().switches()) {
+      switches_list.push_back(base::Value(entry));
     }
-    new_values_cache->SetValue(kStartUpFlags, base::Value(std::move(list)));
+    if (!switches_list.empty()) {
+      new_values_cache->SetValue(kStartUpFlagsDeprecated,
+                                 base::Value(std::move(switches_list)));
+    }
+
+    std::vector<base::Value> feature_flags_list;
+    for (const std::string& entry : policy.feature_flags().feature_flags()) {
+      feature_flags_list.push_back(base::Value(entry));
+    }
+    if (!feature_flags_list.empty()) {
+      new_values_cache->SetValue(kFeatureFlags,
+                                 base::Value(std::move(feature_flags_list)));
+    }
   }
 
   if (policy.has_saml_settings()) {
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
index 7d740d1..40807fc 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -1228,4 +1228,26 @@
             *provider_->Get(kAccountsPrefFamilyLinkAccountsAllowed));
 }
 
+TEST_F(DeviceSettingsProviderTest, StartUpFlagsDeprecated) {
+  EXPECT_EQ(nullptr, provider_->Get(kStartUpFlagsDeprecated));
+
+  device_policy_->payload().mutable_feature_flags()->add_switches("--foo");
+  BuildAndInstallDevicePolicy();
+
+  base::ListValue expected_switches;
+  expected_switches.Append(base::Value("--foo"));
+  EXPECT_EQ(expected_switches, *provider_->Get(kStartUpFlagsDeprecated));
+}
+
+TEST_F(DeviceSettingsProviderTest, FeatureFlags) {
+  EXPECT_EQ(nullptr, provider_->Get(kFeatureFlags));
+
+  device_policy_->payload().mutable_feature_flags()->add_feature_flags("foo");
+  BuildAndInstallDevicePolicy();
+
+  base::ListValue expected_feature_flags;
+  expected_feature_flags.Append(base::Value("foo"));
+  EXPECT_EQ(expected_feature_flags, *provider_->Get(kFeatureFlags));
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/settings/owner_flags_storage.cc b/chrome/browser/chromeos/settings/owner_flags_storage.cc
index c47abf9..63a94f09 100644
--- a/chrome/browser/chromeos/settings/owner_flags_storage.cc
+++ b/chrome/browser/chromeos/settings/owner_flags_storage.cc
@@ -38,7 +38,7 @@
        it != switches.end(); ++it) {
     experiments_list.AppendString(*it);
   }
-  owner_settings_service_->Set(kStartUpFlags, experiments_list);
+  owner_settings_service_->Set(kStartUpFlagsDeprecated, experiments_list);
 
   return true;
 }
diff --git a/chrome/browser/chromeos/system_token_cert_db_initializer.cc b/chrome/browser/chromeos/system_token_cert_db_initializer.cc
index 9fe9dc3..605426c 100644
--- a/chrome/browser/chromeos/system_token_cert_db_initializer.cc
+++ b/chrome/browser/chromeos/system_token_cert_db_initializer.cc
@@ -18,6 +18,8 @@
 #include "build/buildflag.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
+#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/tpm/tpm_token_loader.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -199,7 +201,8 @@
       // have been lost if initialization was interrupted.
       // We don't care about the result, and don't block waiting for it.
       LOG(WARNING) << "Request attempting TPM ownership.";
-      CryptohomeClient::Get()->TpmCanAttemptOwnership(base::DoNothing());
+      TpmManagerClient::Get()->TakeOwnership(
+          ::tpm_manager::TakeOwnershipRequest(), base::DoNothing());
     }
 
     return;
diff --git a/chrome/browser/chromeos/web_applications/scanning_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/scanning_app_integration_browsertest.cc
index 86a18480..96b97e2 100644
--- a/chrome/browser/chromeos/web_applications/scanning_app_integration_browsertest.cc
+++ b/chrome/browser/chromeos/web_applications/scanning_app_integration_browsertest.cc
@@ -47,7 +47,7 @@
     ListPrefUpdate update(TestingBrowserProcess::GetGlobal()->local_state(),
                           policy::policy_prefs::kSystemFeaturesDisableList);
     base::ListValue* list = update.Get();
-    list->Append(policy::SystemFeature::SCANNING);
+    list->Append(policy::SystemFeature::kScanning);
   }
 
   ASSERT_FALSE(GetManager()
diff --git a/chrome/browser/chromeos/web_applications/settings_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/settings_app_integration_browsertest.cc
index 90444c36..1a80215 100644
--- a/chrome/browser/chromeos/web_applications/settings_app_integration_browsertest.cc
+++ b/chrome/browser/chromeos/web_applications/settings_app_integration_browsertest.cc
@@ -30,7 +30,7 @@
     ListPrefUpdate update(TestingBrowserProcess::GetGlobal()->local_state(),
                           policy::policy_prefs::kSystemFeaturesDisableList);
     base::ListValue* list = update.Get();
-    list->Append(policy::SystemFeature::OS_SETTINGS);
+    list->Append(policy::SystemFeature::kOsSettings);
   }
 
   ASSERT_FALSE(GetManager()
diff --git a/chrome/browser/consent_auditor/android/BUILD.gn b/chrome/browser/consent_auditor/android/BUILD.gn
new file mode 100644
index 0000000..77ca70f5
--- /dev/null
+++ b/chrome/browser/consent_auditor/android/BUILD.gn
@@ -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("//build/config/android/rules.gni")
+
+generate_jni("jni_headers") {
+  sources = [ "java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java" ]
+}
+
+android_library("java") {
+  sources = [ "java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java" ]
+  deps = [
+    "//base:base_java",
+    "//base:jni_java",
+    "//chrome/browser/profiles/android:java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
+  ]
+  srcjar_deps = [ "//components/consent_auditor:consent_auditor_java" ]
+  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java b/chrome/browser/consent_auditor/android/java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java
rename to chrome/browser/consent_auditor/android/java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 3480976e..af9110c 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -322,8 +322,9 @@
 
   // Otherwise, proceed as normal and check for a separate reservation with the
   // same target path. If such a reservation exists, cancel this reservation.
+  const base::FilePath target_path = target_info->target_path;
   DownloadPathReservationTracker::CheckDownloadPathForExistingDownload(
-      target_info->target_path, download_item,
+      target_path, download_item,
       base::BindOnce(&OnCheckExistingDownloadPathDone, std::move(target_info),
                      std::move(callback)));
 }
diff --git a/chrome/browser/endpoint_fetcher/endpoint_fetcher.cc b/chrome/browser/endpoint_fetcher/endpoint_fetcher.cc
index a2d4abb..ddfb75cd 100644
--- a/chrome/browser/endpoint_fetcher/endpoint_fetcher.cc
+++ b/chrome/browser/endpoint_fetcher/endpoint_fetcher.cc
@@ -294,7 +294,8 @@
       // TODO(crbug.com/995852) Create a traffic annotation tag and configure it
       // as part of the EndpointFetcher call over JNI.
       NO_TRAFFIC_ANNOTATION_YET);
-  endpoint_fetcher->Fetch(
+  auto* const endpoint_fetcher_ptr = endpoint_fetcher.get();
+  endpoint_fetcher_ptr->Fetch(
       base::BindOnce(&OnEndpointFetcherComplete,
                      base::android::ScopedJavaGlobalRef<jobject>(jcallback),
                      // unique_ptr endpoint_fetcher is passed until the callback
@@ -321,7 +322,8 @@
       base::android::ConvertJavaStringToUTF8(env, jcontent_type), jtimeout,
       base::android::ConvertJavaStringToUTF8(env, jpost_data), headers,
       NO_TRAFFIC_ANNOTATION_YET);
-  endpoint_fetcher->PerformRequest(
+  auto* const endpoint_fetcher_ptr = endpoint_fetcher.get();
+  endpoint_fetcher_ptr->PerformRequest(
       base::BindOnce(&OnEndpointFetcherComplete,
                      base::android::ScopedJavaGlobalRef<jobject>(jcallback),
                      // unique_ptr endpoint_fetcher is passed until the callback
@@ -339,7 +341,8 @@
       ProfileAndroid::FromProfileAndroid(jprofile),
       GURL(base::android::ConvertJavaStringToUTF8(env, jurl)),
       NO_TRAFFIC_ANNOTATION_YET);
-  endpoint_fetcher->PerformRequest(
+  auto* const endpoint_fetcher_ptr = endpoint_fetcher.get();
+  endpoint_fetcher_ptr->PerformRequest(
       base::BindOnce(&OnEndpointFetcherComplete,
                      base::android::ScopedJavaGlobalRef<jobject>(jcallback),
                      // unique_ptr endpoint_fetcher is passed until the callback
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc b/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc
index d6f92a0..5d9594e 100644
--- a/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc
+++ b/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc
@@ -79,6 +79,9 @@
   for (const auto* entry : g_browser_process->profile_manager()
                                ->GetProfileAttributesStorage()
                                .GetAllProfilesAttributes()) {
+    // Exclude Guest profiles.
+    if (entry->IsGuest())
+      continue;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     // Skip sign-in and lock screen app profile on Chrome OS.
     if (!chromeos::ProfileHelper::IsRegularProfilePath(
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc b/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc
index 4d966b9a..ba3ef81 100644
--- a/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc
@@ -48,11 +48,15 @@
 
 }  // namespace
 
-class BrowserReportGeneratorTest : public ::testing::Test {
+class BrowserReportGeneratorTest : public ::testing::Test,
+                                   public ::testing::WithParamInterface<bool> {
  public:
   BrowserReportGeneratorTest()
       : profile_manager_(TestingBrowserProcess::GetGlobal()),
-        generator_(&delegate_factory_) {}
+        generator_(&delegate_factory_) {
+    TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
+        scoped_feature_list_, GetParam());
+  }
   ~BrowserReportGeneratorTest() override = default;
 
   void SetUp() override {
@@ -192,11 +196,12 @@
   TestingProfileManager profile_manager_;
   BrowserReportGenerator generator_;
   ScopedExtensionRequestReportThrottler throttler_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserReportGeneratorTest);
 };
 
-TEST_F(BrowserReportGeneratorTest, GenerateBasicReport) {
+TEST_P(BrowserReportGeneratorTest, GenerateBasicReport) {
   InitializeProfile();
   InitializeIrregularProfiles();
   InitializePlugin();
@@ -204,7 +209,7 @@
 }
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-TEST_F(BrowserReportGeneratorTest, GenerateBasicReportWithUpdate) {
+TEST_P(BrowserReportGeneratorTest, GenerateBasicReportWithUpdate) {
   InitializeUpdate();
   InitializeProfile();
   InitializeIrregularProfiles();
@@ -213,7 +218,7 @@
 }
 #endif
 
-TEST_F(BrowserReportGeneratorTest, ExtensionRequestOnly) {
+TEST_P(BrowserReportGeneratorTest, ExtensionRequestOnly) {
   InitializeUpdate();
   InitializeProfile();
   InitializeIrregularProfiles();
@@ -227,7 +232,7 @@
 
 // It's possible that the extension request report is delayed and by the time
 // report is generated, the extension request report throttler is disabled.
-TEST_F(BrowserReportGeneratorTest, ExtensionRequestOnlyWithoutThrottler) {
+TEST_P(BrowserReportGeneratorTest, ExtensionRequestOnlyWithoutThrottler) {
   InitializeUpdate();
   InitializeProfile();
   InitializeIrregularProfiles();
@@ -237,4 +242,8 @@
   GenerateExtensinRequestReportAndVerify({});
 }
 
+INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
+                         BrowserReportGeneratorTest,
+                         /*is_ephemeral=*/testing::Bool());
+
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/extension_request/extension_request_observer_factory.cc b/chrome/browser/enterprise/reporting/extension_request/extension_request_observer_factory.cc
index 1182a3c..ae85d2e2 100644
--- a/chrome/browser/enterprise/reporting/extension_request/extension_request_observer_factory.cc
+++ b/chrome/browser/enterprise/reporting/extension_request/extension_request_observer_factory.cc
@@ -37,7 +37,7 @@
 
 void ExtensionRequestObserverFactory::OnProfileAdded(Profile* profile) {
   if (profile->IsSystemProfile() || profile->IsGuestSession() ||
-      profile->IsOffTheRecord()) {
+      profile->IsEphemeralGuestProfile() || profile->IsOffTheRecord()) {
     return;
   }
 
diff --git a/chrome/browser/enterprise/reporting/extension_request/extension_request_observer_factory_unittest.cc b/chrome/browser/enterprise/reporting/extension_request/extension_request_observer_factory_unittest.cc
index 6b4a8eb..857f087 100644
--- a/chrome/browser/enterprise/reporting/extension_request/extension_request_observer_factory_unittest.cc
+++ b/chrome/browser/enterprise/reporting/extension_request/extension_request_observer_factory_unittest.cc
@@ -119,7 +119,20 @@
   EXPECT_EQ(2, factory_.GetNumberOfObserversForTesting());
 }
 
-TEST_F(ExtensionRequestObserverFactoryTest,
+class GuestExtensionRequestObserverFactoryTest
+    : public ExtensionRequestObserverFactoryTest,
+      public ::testing::WithParamInterface<bool> {
+ public:
+  GuestExtensionRequestObserverFactoryTest() {
+    TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
+        scoped_feature_list_, GetParam());
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_P(GuestExtensionRequestObserverFactoryTest,
        NoObserverForSystemAndGuestProfile) {
   ExtensionRequestObserverFactory factory_;
   EXPECT_EQ(0, factory_.GetNumberOfObserversForTesting());
@@ -133,4 +146,8 @@
   EXPECT_EQ(0, factory_.GetNumberOfObserversForTesting());
 }
 
+INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
+                         GuestExtensionRequestObserverFactoryTest,
+                         /*is_ephemeral=*/testing::Bool());
+
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/report_generator_unittest.cc b/chrome/browser/enterprise/reporting/report_generator_unittest.cc
index 5e7b546..525a612 100644
--- a/chrome/browser/enterprise/reporting/report_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/report_generator_unittest.cc
@@ -135,13 +135,17 @@
 
 }  // namespace
 
-class ReportGeneratorTest : public ::testing::Test {
+class ReportGeneratorTest : public ::testing::Test,
+                            public ::testing::WithParamInterface<bool> {
  public:
   using ReportRequest = definition::ReportRequest;
 
   ReportGeneratorTest()
       : generator_(&delegate_factory_),
-        profile_manager_(TestingBrowserProcess::GetGlobal()) {}
+        profile_manager_(TestingBrowserProcess::GetGlobal()) {
+    TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
+        scoped_feature_list_, GetParam());
+  }
   ~ReportGeneratorTest() override = default;
 
   void SetUp() override {
@@ -287,11 +291,12 @@
   content::BrowserTaskEnvironment task_environment_;
   TestingProfileManager profile_manager_;
   std::unique_ptr<base::HistogramTester> histogram_tester_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(ReportGeneratorTest);
 };
 
-TEST_F(ReportGeneratorTest, GenerateBasicReport) {
+TEST_P(ReportGeneratorTest, GenerateBasicReport) {
   auto profile_names = CreateProfiles(/*number*/ 2, kIdle);
   CreatePlugin();
 
@@ -346,7 +351,7 @@
                       profile_names, browser_report);
 }
 
-TEST_F(ReportGeneratorTest, GenerateWithoutProfiles) {
+TEST_P(ReportGeneratorTest, GenerateWithoutProfiles) {
   auto profile_names = CreateProfiles(/*number*/ 2, kActive);
   CreatePlugin();
 
@@ -396,7 +401,7 @@
                       profile_names, browser_report);
 }
 
-TEST_F(ReportGeneratorTest, ExtensionRequestOnly) {
+TEST_P(ReportGeneratorTest, ExtensionRequestOnly) {
   auto profile_names = CreateProfiles(/*number*/ 2, kActive);
   CreatePlugin();
 
@@ -422,7 +427,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 
-TEST_F(ReportGeneratorTest, ReportArcAppInChromeOS) {
+TEST_P(ReportGeneratorTest, ReportArcAppInChromeOS) {
   ArcAppTest arc_app_test;
   TestingProfile primary_profile;
   arc_app_test.SetUp(&primary_profile);
@@ -462,7 +467,7 @@
   arc_app_test.TearDown();
 }
 
-TEST_F(ReportGeneratorTest, ArcPlayStoreDisabled) {
+TEST_P(ReportGeneratorTest, ArcPlayStoreDisabled) {
   ArcAppTest arc_app_test;
   TestingProfile primary_profile;
   arc_app_test.SetUp(&primary_profile);
@@ -489,4 +494,8 @@
 
 #endif
 
+INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
+                         ReportGeneratorTest,
+                         /*is_ephemeral=*/testing::Bool());
+
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc b/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc
index 33d0038..01a549bf 100644
--- a/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc
@@ -42,14 +42,19 @@
 
 // TODO(crbug.com/1103732): Get rid of chrome/browser dependencies and then
 // move this file to components/enterprise/browser.
-class ReportRequestQueueGeneratorTest : public ::testing::Test {
+class ReportRequestQueueGeneratorTest
+    : public ::testing::Test,
+      public ::testing::WithParamInterface<bool> {
  public:
   using ReportRequest = definition::ReportRequest;
 
   ReportRequestQueueGeneratorTest()
       : profile_manager_(TestingBrowserProcess::GetGlobal()),
         browser_report_generator_(&reporting_delegate_factory_),
-        report_request_queue_generator_(&reporting_delegate_factory_) {}
+        report_request_queue_generator_(&reporting_delegate_factory_) {
+    TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
+        scoped_feature_list_, GetParam());
+  }
 
   ~ReportRequestQueueGeneratorTest() override = default;
 
@@ -207,11 +212,12 @@
   BrowserReportGenerator browser_report_generator_;
   ReportRequestQueueGenerator report_request_queue_generator_;
   std::unique_ptr<base::HistogramTester> histogram_tester_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(ReportRequestQueueGeneratorTest);
 };
 
-TEST_F(ReportRequestQueueGeneratorTest, GenerateReport) {
+TEST_P(ReportRequestQueueGeneratorTest, GenerateReport) {
   auto idle_profile_names = CreateIdleProfiles();
   auto basic_request = GenerateBasicRequest();
   auto requests = GenerateRequests(*basic_request);
@@ -222,7 +228,7 @@
                                         /*report size floor to KB*/ 0, 1);
 }
 
-TEST_F(ReportRequestQueueGeneratorTest, GenerateActiveProfiles) {
+TEST_P(ReportRequestQueueGeneratorTest, GenerateActiveProfiles) {
   auto idle_profile_names = CreateIdleProfiles();
   auto active_profile_names = CreateActiveProfiles();
   auto basic_request = GenerateBasicRequest();
@@ -235,7 +241,7 @@
                                         /*report size floor to KB*/ 0, 1);
 }
 
-TEST_F(ReportRequestQueueGeneratorTest, BasicReportIsTooBig) {
+TEST_P(ReportRequestQueueGeneratorTest, BasicReportIsTooBig) {
   // Set a super small limitation.
   SetAndVerifyMaximumRequestSize(5);
 
@@ -249,7 +255,7 @@
                                        0);
 }
 
-TEST_F(ReportRequestQueueGeneratorTest, ReportSeparation) {
+TEST_P(ReportRequestQueueGeneratorTest, ReportSeparation) {
   CreateActiveProfilesWithContent();
   auto basic_request = GenerateBasicRequest();
   auto requests = GenerateRequests(*basic_request);
@@ -271,7 +277,7 @@
                                         /*report size floor to KB*/ 0, 2);
 }
 
-TEST_F(ReportRequestQueueGeneratorTest, ProfileReportIsTooBig) {
+TEST_P(ReportRequestQueueGeneratorTest, ProfileReportIsTooBig) {
   CreateActiveProfileWithContent(kActiveProfileName1);
   auto basic_request = GenerateBasicRequest();
   auto requests = GenerateRequests(*basic_request);
@@ -294,7 +300,7 @@
                                         /*report size floor to KB*/ 0, 2);
 }
 
-TEST_F(ReportRequestQueueGeneratorTest, ChromePoliciesCollection) {
+TEST_P(ReportRequestQueueGeneratorTest, ChromePoliciesCollection) {
   auto policy_service = std::make_unique<policy::MockPolicyService>();
   policy::PolicyMap policy_map;
 
@@ -331,4 +337,8 @@
 #endif
 }
 
+INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
+                         ReportRequestQueueGeneratorTest,
+                         /*is_ephemeral=*/testing::Bool());
+
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc b/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
index 2f5978d..49d6c2d1 100644
--- a/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
+++ b/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
@@ -5,6 +5,7 @@
 #include "base/files/file_path.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/policy/affiliation_mixin.h"
 #include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
 #include "chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h"
@@ -90,13 +91,13 @@
 };
 
 IN_PROC_BROWSER_TEST_P(EnterpriseDeviceAttributesTest, PRE_Success) {
-  policy::AffiliationTestHelper::PreLoginUser(affiliated_account_id_);
+  policy::AffiliationTestHelper::PreLoginUser(affiliation_mixin_.account_id());
 }
 
 IN_PROC_BROWSER_TEST_P(EnterpriseDeviceAttributesTest, Success) {
   const bool is_affiliated = GetParam();
   EXPECT_EQ(is_affiliated, user_manager::UserManager::Get()
-                               ->FindUser(affiliated_account_id_)
+                               ->FindUser(affiliation_mixin_.account_id())
                                ->IsAffiliated());
 
   const Extension* extension =
diff --git a/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_apitest.cc b/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_apitest.cc
index 99ab581..5dcbdb4 100644
--- a/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_apitest.cc
+++ b/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_apitest.cc
@@ -149,13 +149,13 @@
 
 IN_PROC_BROWSER_TEST_P(EnterpriseNetworkingAttributesTest,
                        PRE_GetNetworkDetails) {
-  policy::AffiliationTestHelper::PreLoginUser(affiliated_account_id_);
+  policy::AffiliationTestHelper::PreLoginUser(affiliation_mixin_.account_id());
 }
 
 IN_PROC_BROWSER_TEST_P(EnterpriseNetworkingAttributesTest, GetNetworkDetails) {
   const bool is_affiliated = GetParam();
   EXPECT_EQ(is_affiliated, user_manager::UserManager::Get()
-                               ->FindUser(affiliated_account_id_)
+                               ->FindUser(affiliation_mixin_.account_id())
                                ->IsAffiliated());
 
   const Extension* extension =
diff --git a/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc b/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc
index d01b415f..93e23af 100644
--- a/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc
+++ b/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc
@@ -22,18 +22,6 @@
 
 namespace {
 
-// If running with |is_affiliated|==true, the test will use the same
-// |kAffiliationID| as user and device affiliation ID, which makes the user
-// affiliated (affiliation IDs overlap).
-// If running with |is_affiliated|==false, the test will use |kAffiliationID| as
-// device and |kAnotherAffiliationID| as user affiliation ID, which makes the
-// user non-affiliated (affiliation IDs don't overlap).
-constexpr char kAffiliationID[] = "some-affiliation-id";
-constexpr char kAnotherAffiliationID[] = "another-affiliation-id";
-
-constexpr char kAffiliatedUserEmail[] = "user@example.com";
-constexpr char kAffiliatedUserGaiaId[] = "1029384756";
-
 base::FilePath GetTestDataDir() {
   return base::PathService::CheckedGet(chrome::DIR_TEST_DATA);
 }
@@ -44,15 +32,12 @@
 
 ForceInstalledAffiliatedExtensionApiTest::
     ForceInstalledAffiliatedExtensionApiTest(bool is_affiliated)
-    : is_affiliated_(is_affiliated),
-      affiliated_account_id_(
-          AccountId::FromUserEmailGaiaId(kAffiliatedUserEmail,
-                                         kAffiliatedUserGaiaId)),
-      test_install_attributes_(
+    : test_install_attributes_(
           chromeos::StubInstallAttributes::CreateCloudManaged("fake-domain",
                                                               "fake-id")) {
   set_exit_when_last_browser_closes(false);
   set_chromeos_user_ = false;
+  affiliation_mixin_.set_affiliated(is_affiliated);
 }
 
 ForceInstalledAffiliatedExtensionApiTest::
@@ -70,26 +55,6 @@
   // Initialize clients here so they are available during setup. They will be
   // shutdown in ChromeBrowserMain.
   chromeos::SessionManagerClient::InitializeFakeInMemory();
-  policy::AffiliationTestHelper affiliation_helper =
-      policy::AffiliationTestHelper::CreateForCloud(
-          chromeos::FakeSessionManagerClient::Get());
-
-  std::set<std::string> device_affiliation_ids;
-  device_affiliation_ids.insert(kAffiliationID);
-  ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
-      &test_helper_, device_affiliation_ids));
-  test_helper_.InstallOwnerKey();
-
-  std::set<std::string> user_affiliation_ids;
-  if (is_affiliated_) {
-    user_affiliation_ids.insert(kAffiliationID);
-  } else {
-    user_affiliation_ids.insert(kAnotherAffiliationID);
-  }
-  policy::UserPolicyBuilder user_policy;
-  ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetUserAffiliationIDs(
-      &user_policy, affiliated_account_id_, user_affiliation_ids));
-  test_helper_.InstallOwnerKey();
 
   // Init the user policy provider.
   EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
@@ -112,7 +77,7 @@
   const base::ListValue* users =
       g_browser_process->local_state()->GetList("LoggedInUsers");
   if (!users->empty()) {
-    policy::AffiliationTestHelper::LoginUser(affiliated_account_id_);
+    policy::AffiliationTestHelper::LoginUser(affiliation_mixin_.account_id());
   }
 
   force_install_mixin_.InitWithMockPolicyProvider(profile(), &policy_provider_);
diff --git a/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h b/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h
index 5f327a57..b58b325 100644
--- a/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h
+++ b/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include "base/values.h"
+#include "chrome/browser/chromeos/policy/affiliation_mixin.h"
 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
 #include "chrome/browser/extensions/mixin_based_extension_apitest.h"
 #include "chrome/browser/policy/extension_force_install_mixin.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/tpm/stub_install_attributes.h"
-#include "components/account_id/account_id.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "extensions/common/extension_id.h"
 #include "url/gurl.h"
@@ -28,9 +28,6 @@
 
 class Extension;
 
-// TODO(https://crbug.com/1082195) Create user affiliation test mixin to use in
-// this class.
-
 // Helper class to test force-installed extensions in a
 // affiliated/non-affiliated user profile.
 class ForceInstalledAffiliatedExtensionApiTest
@@ -55,14 +52,10 @@
                      const GURL& page_url,
                      const base::Value& custom_arg_value);
 
-  // Whether the user should be affiliated (= user and device affiliation IDs
-  // overlap).
-  const bool is_affiliated_;
-
-  const AccountId affiliated_account_id_;
   policy::MockConfigurationPolicyProvider policy_provider_;
   chromeos::ScopedStubInstallAttributes test_install_attributes_;
   policy::DevicePolicyCrosTestHelper test_helper_;
+  policy::AffiliationMixin affiliation_mixin_{&mixin_host_, &test_helper_};
   ExtensionForceInstallMixin force_install_mixin_{&mixin_host_};
 };
 
diff --git a/chrome/browser/profiles/guest_mode_policy_handler_unittest.cc b/chrome/browser/profiles/guest_mode_policy_handler_unittest.cc
index f9691847..44df237f 100644
--- a/chrome/browser/profiles/guest_mode_policy_handler_unittest.cc
+++ b/chrome/browser/profiles/guest_mode_policy_handler_unittest.cc
@@ -4,9 +4,11 @@
 
 #include "chrome/browser/profiles/guest_mode_policy_handler.h"
 
+#include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "chrome/browser/policy/browser_signin_policy_handler.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
@@ -14,7 +16,14 @@
 
 namespace policy {
 
-class GuestModePolicyHandlerTest : public ::testing::Test {
+class GuestModePolicyHandlerTest : public ::testing::Test,
+                                   public ::testing::WithParamInterface<bool> {
+ public:
+  GuestModePolicyHandlerTest() {
+    TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
+        scoped_feature_list_, GetParam());
+  }
+
  public:
   void SetUp() override {
     prefs_.Clear();
@@ -35,14 +44,17 @@
   PolicyMap policies_;
   PrefValueMap prefs_;
   GuestModePolicyHandler handler_;
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-TEST_F(GuestModePolicyHandlerTest, ForceSigninNotSet) {
+TEST_P(GuestModePolicyHandlerTest, ForceSigninNotSet) {
   handler_.ApplyPolicySettings(policies_, &prefs_);
   EXPECT_FALSE(prefs_.GetValue(prefs::kBrowserGuestModeEnabled, nullptr));
 }
 
-TEST_F(GuestModePolicyHandlerTest, ForceSigninDisabled) {
+TEST_P(GuestModePolicyHandlerTest, ForceSigninDisabled) {
   SetUpPolicy(key::kForceBrowserSignin, false);
   handler_.ApplyPolicySettings(policies_, &prefs_);
   EXPECT_FALSE(prefs_.GetValue(prefs::kBrowserGuestModeEnabled, nullptr));
@@ -52,7 +64,7 @@
   EXPECT_FALSE(prefs_.GetValue(prefs::kBrowserGuestModeEnabled, nullptr));
 }
 
-TEST_F(GuestModePolicyHandlerTest, GuestModeDisabledByDefault) {
+TEST_P(GuestModePolicyHandlerTest, GuestModeDisabledByDefault) {
   bool value;
   SetUpPolicy(key::kForceBrowserSignin, true);
   handler_.ApplyPolicySettings(policies_, &prefs_);
@@ -60,7 +72,7 @@
   EXPECT_FALSE(value);
 }
 
-TEST_F(GuestModePolicyHandlerTest,
+TEST_P(GuestModePolicyHandlerTest,
        GuestModeDisabledByDefaultWithInvalidFormat) {
   bool value;
   SetUpPolicy(key::kForceBrowserSignin, true);
@@ -70,7 +82,7 @@
   EXPECT_FALSE(value);
 }
 
-TEST_F(GuestModePolicyHandlerTest, GuestModeSet) {
+TEST_P(GuestModePolicyHandlerTest, GuestModeSet) {
   bool value;
   SetUpPolicy(key::kForceBrowserSignin, true);
   SetUpPolicy(key::kBrowserGuestModeEnabled, true);
@@ -84,7 +96,7 @@
   EXPECT_FALSE(value);
 }
 
-TEST_F(GuestModePolicyHandlerTest, GuestModeDisabledWhenBrowserSigninIsForced) {
+TEST_P(GuestModePolicyHandlerTest, GuestModeDisabledWhenBrowserSigninIsForced) {
   SetUpPolicy(key::kBrowserSignin,
               static_cast<int>(BrowserSigninMode::kForced));
   handler_.ApplyPolicySettings(policies_, &prefs_);
@@ -93,7 +105,7 @@
   EXPECT_FALSE(value);
 }
 
-TEST_F(GuestModePolicyHandlerTest,
+TEST_P(GuestModePolicyHandlerTest,
        GuestModeIsNotSetWhenBrowserSigninIsNotForced) {
   bool value = false;
   SetUpPolicy(key::kBrowserSignin,
@@ -119,4 +131,8 @@
   EXPECT_FALSE(prefs_.GetBoolean(prefs::kBrowserGuestModeEnabled, &value));
 }
 
+INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
+                         GuestModePolicyHandlerTest,
+                         /*is_ephemeral=*/testing::Bool());
+
 }  // namespace policy
diff --git a/chrome/browser/resources/chromeos/login/security_token_pin.html b/chrome/browser/resources/chromeos/login/security_token_pin.html
index d2a923e..f88d0ef 100644
--- a/chrome/browser/resources/chromeos/login/security_token_pin.html
+++ b/chrome/browser/resources/chromeos/login/security_token_pin.html
@@ -32,7 +32,7 @@
       </paper-progress>
       <div slot="footer">
         <div id="pinKeyboardContainer" hidden="[[processingCompletion_]]">
-          <pin-keyboard id="pinKeyboard" enable-letters
+          <pin-keyboard id="pinKeyboard" enable-letters allow-non-digit
               has-error="[[isErrorLabelVisible_(errorLabelId_, userEdited_)]]"
               aria-label="[[getLabel_(locale, parameters, errorLabelId_,
                                       userEdited_)]]"
diff --git a/chrome/browser/resources/chromeos/login/security_token_pin_browsertest.js b/chrome/browser/resources/chromeos/login/security_token_pin_browsertest.js
index 97e0423..e437adc 100644
--- a/chrome/browser/resources/chromeos/login/security_token_pin_browsertest.js
+++ b/chrome/browser/resources/chromeos/login/security_token_pin_browsertest.js
@@ -122,6 +122,17 @@
     expectEquals(completedEventDetail, SECOND_PIN);
   });
 
+  // Test that the input field accepts non-digit PIN.
+  test('non-digit PIN input validity', () => {
+    const NON_DIGIT_PIN = '+Aa';
+
+    // The user enters a non-digit pin.
+    pinInput.value = NON_DIGIT_PIN;
+
+    expectEquals(pinInput.value, NON_DIGIT_PIN);
+    expectEquals(inputField.value, NON_DIGIT_PIN);
+  });
+
   // Test that the 'cancel' event is fired when the user aborts the dialog.
   test('completion events in cancellation flow', () => {
     let cancelEventCount = 0;
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc
index 2f7ccdc..5144a67 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -18,12 +18,10 @@
 #include "ash/public/cpp/app_list/internal_app_id_constants.h"
 #include "base/bind.h"
 #include "base/callback_list.h"
-#include "base/containers/flat_set.h"
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -116,16 +114,15 @@
 }
 
 // Checks if current locale is non Latin locales.
-bool IsNonLatinLocale(const std::string& locale) {
+bool IsNonLatinLocale(base::StringPiece locale) {
   // A set of of non Latin locales. This set is used to select appropriate
   // algorithm for app search.
-  static const base::NoDestructor<base::flat_set<std::string>>
-      non_latin_locales({"am", "ar", "be", "bg",    "bn",    "el",   "fa",
-                         "gu", "hi", "hy", "iw",    "ja",    "ka",   "kk",
-                         "km", "kn", "ko", "ky",    "lo",    "mk",   "ml",
-                         "mn", "mr", "my", "pa",    "ru",    "sr",   "ta",
-                         "te", "th", "uk", "zh-CN", "zh-HK", "zh-TW"});
-  return base::Contains(*non_latin_locales, locale);
+  static constexpr char kNonLatinLocales[][6] = {
+      "am", "ar", "be", "bg", "bn",    "el",    "fa",   "gu", "hi",
+      "hy", "iw", "ja", "ka", "kk",    "km",    "kn",   "ko", "ky",
+      "lo", "mk", "ml", "mn", "mr",    "my",    "pa",   "ru", "sr",
+      "ta", "te", "th", "uk", "zh-CN", "zh-HK", "zh-TW"};
+  return base::Contains(kNonLatinLocales, locale);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 4aa93919..9d03fab 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -993,7 +993,7 @@
 
   bool is_enabled = !system_features_disable_list_pref ||
                     system_features_disable_list_pref->Find(
-                        base::Value(policy::SystemFeature::BROWSER_SETTINGS)) ==
+                        base::Value(policy::SystemFeature::kBrowserSettings)) ==
                         system_features_disable_list_pref->end();
 
   int index = GetIndexOfCommandId(IDC_OPTIONS);
diff --git a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
index da961d1..c14242ca5 100644
--- a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
@@ -237,7 +237,7 @@
     ListPrefUpdate update(TestingBrowserProcess::GetGlobal()->local_state(),
                           policy::policy_prefs::kSystemFeaturesDisableList);
     base::ListValue* list = update.Get();
-    list->Append(policy::SystemFeature::BROWSER_SETTINGS);
+    list->Append(policy::SystemFeature::kBrowserSettings);
   }
   EXPECT_FALSE(model.IsEnabledAt(index));
 
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc
index 09f68ce..2a7ff73 100644
--- a/chrome/browser/web_applications/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -302,13 +302,13 @@
 
   for (const auto& entry : *disabled_system_features_pref) {
     switch (entry.GetInt()) {
-      case policy::SystemFeature::CAMERA:
+      case policy::SystemFeature::kCamera:
         disabled_system_apps.insert(SystemAppType::CAMERA);
         break;
-      case policy::SystemFeature::OS_SETTINGS:
+      case policy::SystemFeature::kOsSettings:
         disabled_system_apps.insert(SystemAppType::SETTINGS);
         break;
-      case policy::SystemFeature::SCANNING:
+      case policy::SystemFeature::kScanning:
         disabled_system_apps.insert(SystemAppType::SCANNING);
         break;
     }
diff --git a/chrome/browser/web_applications/system_web_app_manager_browsertest.cc b/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
index 360d1211..efb094b0 100644
--- a/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
@@ -1456,7 +1456,7 @@
     ListPrefUpdate update(TestingBrowserProcess::GetGlobal()->local_state(),
                           policy::policy_prefs::kSystemFeaturesDisableList);
     base::ListValue* list = update.Get();
-    list->Append(policy::SystemFeature::OS_SETTINGS);
+    list->Append(policy::SystemFeature::kOsSettings);
   }
   WaitForTestSystemAppInstall();
   base::Optional<AppId> settings_id =
@@ -1494,7 +1494,7 @@
     ListPrefUpdate update(TestingBrowserProcess::GetGlobal()->local_state(),
                           policy::policy_prefs::kSystemFeaturesDisableList);
     base::ListValue* list = update.Get();
-    list->Append(policy::SystemFeature::OS_SETTINGS);
+    list->Append(policy::SystemFeature::kOsSettings);
   }
 
   apps::AppServiceProxy* proxy = GetAppServiceProxy(browser()->profile());
diff --git a/chrome/browser/webshare/chromeos/prepare_directory_task.cc b/chrome/browser/webshare/chromeos/prepare_directory_task.cc
index b8b463f..055eec5 100644
--- a/chrome/browser/webshare/chromeos/prepare_directory_task.cc
+++ b/chrome/browser/webshare/chromeos/prepare_directory_task.cc
@@ -4,10 +4,13 @@
 
 #include "chrome/browser/webshare/chromeos/prepare_directory_task.h"
 
+#include "base/files/file.h"
+#include "base/system/sys_info.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "content/public/browser/browser_thread.h"
+#include "third_party/cros_system_api/constants/cryptohome.h"
 
 using content::BrowserThread;
 
@@ -15,8 +18,11 @@
 
 PrepareDirectoryTask::PrepareDirectoryTask(
     base::FilePath directory,
+    uint64_t required_space,
     blink::mojom::ShareService::ShareCallback callback)
-    : directory_(std::move(directory)), callback_(std::move(callback)) {}
+    : directory_(std::move(directory)),
+      required_space_(required_space),
+      callback_(std::move(callback)) {}
 
 PrepareDirectoryTask::~PrepareDirectoryTask() = default;
 
@@ -24,20 +30,30 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
-      base::BindOnce(&PrepareDirectoryTask::PrepareDirectory, directory_),
+      base::BindOnce(&PrepareDirectoryTask::PrepareDirectory, directory_,
+                     required_space_),
       base::BindOnce(&PrepareDirectoryTask::OnPrepareDirectory,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
 // static
 base::File::Error PrepareDirectoryTask::PrepareDirectory(
-    base::FilePath directory) {
+    base::FilePath directory,
+    uint64_t required_space) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::WILL_BLOCK);
 
   base::File::Error result = base::File::FILE_OK;
-  if (!base::CreateDirectoryAndGetError(directory, &result)) {
+  if (base::CreateDirectoryAndGetError(directory, &result)) {
+    if (base::SysInfo::AmountOfFreeDiskSpace(directory) <
+        static_cast<int64_t>(cryptohome::kMinFreeSpaceInBytes +
+                             required_space)) {
+      result = base::File::FILE_ERROR_NO_SPACE;
+      VLOG(1) << "Insufficient space for sharing files";
+    }
+  } else {
     DCHECK(result != base::File::FILE_OK);
+    VLOG(1) << "Could not create directory for shared files";
   }
 
   // TODO(crbug.com/1110119): Delete any old files in directory.
@@ -47,8 +63,6 @@
 
 void PrepareDirectoryTask::OnPrepareDirectory(base::File::Error result) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (result != base::File::FILE_OK)
-    VLOG(1) << "Could not create directory for shared files";
   std::move(callback_).Run((result == base::File::FILE_OK)
                                ? blink::mojom::ShareError::OK
                                : blink::mojom::ShareError::PERMISSION_DENIED);
diff --git a/chrome/browser/webshare/chromeos/prepare_directory_task.h b/chrome/browser/webshare/chromeos/prepare_directory_task.h
index 02653fe0..44f4e4b 100644
--- a/chrome/browser/webshare/chromeos/prepare_directory_task.h
+++ b/chrome/browser/webshare/chromeos/prepare_directory_task.h
@@ -16,6 +16,7 @@
 class PrepareDirectoryTask {
  public:
   PrepareDirectoryTask(base::FilePath directory,
+                       uint64_t required_space,
                        blink::mojom::ShareService::ShareCallback callback);
   PrepareDirectoryTask(const PrepareDirectoryTask&) = delete;
   PrepareDirectoryTask& operator=(const PrepareDirectoryTask&) = delete;
@@ -27,11 +28,13 @@
 
  private:
   // Runs on a thread where blocking is permitted.
-  static base::File::Error PrepareDirectory(base::FilePath directory);
+  static base::File::Error PrepareDirectory(base::FilePath directory,
+                                            uint64_t required_space);
 
   void OnPrepareDirectory(base::File::Error result);
 
   const base::FilePath directory_;
+  const uint64_t required_space_;
   blink::mojom::ShareService::ShareCallback callback_;
 
   base::WeakPtrFactory<PrepareDirectoryTask> weak_ptr_factory_{this};
diff --git a/chrome/browser/webshare/chromeos/sharesheet_client.cc b/chrome/browser/webshare/chromeos/sharesheet_client.cc
index 52f5f860e..c2cdffb 100644
--- a/chrome/browser/webshare/chromeos/sharesheet_client.cc
+++ b/chrome/browser/webshare/chromeos/sharesheet_client.cc
@@ -106,7 +106,7 @@
 
   current_share_->prepare_directory_task =
       std::make_unique<PrepareDirectoryTask>(
-          current_share_->directory,
+          current_share_->directory, kMaxSharedFileBytes,
           base::BindOnce(&SharesheetClient::OnPrepareDirectory,
                          weak_ptr_factory_.GetWeakPtr()));
   current_share_->prepare_directory_task->Start();
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 6945d0556..f30b72c 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1606625552-afc99e02f6627cb60c322aac342a59aa984da01f.profdata
+chrome-linux-master-1606715277-5a5c0b93116eb4ed5bae16849c10b7071f9da60f.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 148f749..55e3cacb 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1606625552-b5a7a65d1b224a057cc7d35779ce0f69d79bcefc.profdata
+chrome-mac-master-1606715277-7cd8080ef7943d789d7f3f75a67090679d493829.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 92a66b79..b97906a0 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1606551753-197452eaff218342626be756057e9b24b253257e.profdata
+chrome-win32-master-1606649289-a1ddd7e3579fd6803de4501ea269c51715a31009.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index df80e6d..659f700 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1606616692-df77728b15a3e48bc410a5af3ed38500d40bc4b4.profdata
+chrome-win64-master-1606715277-9385c299327136363de38f40b28eb44b3b85ec7c.profdata
diff --git a/chrome/renderer/extensions/extension_localization_peer.cc b/chrome/renderer/extensions/extension_localization_peer.cc
index f307e21..6db4324 100644
--- a/chrome/renderer/extensions/extension_localization_peer.cc
+++ b/chrome/renderer/extensions/extension_localization_peer.cc
@@ -72,6 +72,8 @@
   response_head_ = std::move(head);
 }
 
+void ExtensionLocalizationPeer::EvictFromBackForwardCache() {}
+
 void ExtensionLocalizationPeer::OnStartLoadingResponseBody(
     mojo::ScopedDataPipeConsumerHandle body) {
   data_pipe_state_.body_state_ = DataPipeState::BodyState::kReadingBody;
diff --git a/chrome/renderer/extensions/extension_localization_peer.h b/chrome/renderer/extensions/extension_localization_peer.h
index fc85808..139d0b037 100644
--- a/chrome/renderer/extensions/extension_localization_peer.h
+++ b/chrome/renderer/extensions/extension_localization_peer.h
@@ -64,6 +64,7 @@
   void OnTransferSizeUpdated(int transfer_size_diff) override;
   void OnCompletedRequest(
       const network::URLLoaderCompletionStatus& status) override;
+  void EvictFromBackForwardCache() override;
 
  private:
   friend class ExtensionLocalizationPeerTest;
diff --git a/chrome/renderer/extensions/extension_localization_peer_unittest.cc b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
index 10102ec..0bce856 100644
--- a/chrome/renderer/extensions/extension_localization_peer_unittest.cc
+++ b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
@@ -89,6 +89,7 @@
   MOCK_METHOD1(OnTransferSizeUpdated, void(int transfer_size_diff));
   MOCK_METHOD1(OnCompletedRequest,
                void(const network::URLLoaderCompletionStatus& status));
+  MOCK_METHOD0(EvictFromBackForwardCache, void());
 
   void RunUntilBodyBecomesReady() {
     base::RunLoop loop;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 569cddb..94d4eab 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2661,6 +2661,8 @@
         "../browser/chromeos/platform_keys/platform_keys_service_test_util.cc",
         "../browser/chromeos/platform_keys/platform_keys_service_test_util.h",
         "../browser/chromeos/plugin_vm/plugin_vm_test_helper.cc",
+        "../browser/chromeos/policy/affiliation_mixin.cc",
+        "../browser/chromeos/policy/affiliation_mixin.h",
         "../browser/chromeos/policy/affiliation_test_helper.cc",
         "../browser/chromeos/policy/affiliation_test_helper.h",
         "../browser/chromeos/policy/blocking_login_browsertest.cc",
diff --git a/chromecast/media/audio/audio_clock_simulator.cc b/chromecast/media/audio/audio_clock_simulator.cc
index 6d3a65b..e197079 100644
--- a/chromecast/media/audio/audio_clock_simulator.cc
+++ b/chromecast/media/audio/audio_clock_simulator.cc
@@ -76,6 +76,7 @@
       auto result =
           FillDataLengthen(num_frames, playout_timestamp, channel_data, filled);
       filled += result.filled;
+      output_frames_ += result.filled;
       if (!result.complete) {
         break;
       }
@@ -86,6 +87,7 @@
       auto result =
           FillDataShorten(num_frames, playout_timestamp, channel_data, filled);
       filled += result.filled;
+      output_frames_ += result.filled;
       if (!result.complete) {
         break;
       }
@@ -93,8 +95,9 @@
     }
 
     int64_t end_input_frames = input_frames_ + kInterpolateWindow;
-    int64_t end_output_frames = output_frames_ + filled + kInterpolateWindow;
+    int64_t end_output_frames = output_frames_ + kInterpolateWindow;
     int64_t desired_output_frames = std::round(end_input_frames / clock_rate_);
+
     if (end_output_frames > desired_output_frames) {
       state_ = State::kShortening;
       continue;
@@ -112,6 +115,7 @@
     int desired = std::min(num_frames - filled, kInterpolateWindow);
     int provided = provider_->FillFrames(desired, timestamp, channels);
     input_frames_ += provided;
+    output_frames_ += provided;
     filled += provided;
 
     if (provided < desired) {
@@ -119,7 +123,6 @@
     }
   }
 
-  output_frames_ += filled;
   return filled;
 }
 
diff --git a/chromecast/media/cma/backend/video/av_sync_video.cc b/chromecast/media/cma/backend/video/av_sync_video.cc
index f11c135..ba40299f 100644
--- a/chromecast/media/cma/backend/video/av_sync_video.cc
+++ b/chromecast/media/cma/backend/video/av_sync_video.cc
@@ -53,7 +53,7 @@
 // Maximum A/V sync offset that we allow without correction. Note that we still
 // correct the audio playback rate to match video (to prevent the offset from
 // growing) even when the offset is lower than this value.
-const int64_t kMaxIgnoredOffset = 1000;
+const int64_t kMaxIgnoredOffset = 500;
 
 }  // namespace
 
@@ -235,24 +235,30 @@
     apts_error_ = std::make_unique<WeightedMovingLinearRegression>(
         kLinearRegressionWindow.InMicroseconds());
     clock_rate_start_timestamp_ = timestamp;
-    clock_rate_error_base_ = 0;
+    clock_rate_error_base_ = 0.0;
     apts_error_start_timestamp_ = timestamp;
   }
 
   int64_t x = timestamp - apts_error_start_timestamp_;
 
   // Error is positive if audio is playing out too late.
-  // We play out |current_audio_clock_rate_| seconds of audio per second of
-  // actual time. In the last N seconds, if the clock rate was 1.0 we would have
-  // played (1.0 - clock_rate) * N more seconds of audio, so the current
-  // buffer would have played out that much sooner (reducing its error by that
-  // amount). We also need to take into account any existing error when we
-  // last changed the clock rate.
+  // We play out |current_clock_rate_| seconds of audio per second of actual
+  // time. We want to run a linear regression on how the error is changing over
+  // time, if we ignore the effects of any previous clock rate changes. To do
+  // this, we correct the error value to what it would have been if we had never
+  // adjusted the clock rate.
+  // In the last N seconds, if the clock rate was 1.0 we would have played
+  // (1.0 - clock_rate) * N more seconds of audio, so the current buffer would
+  // have played out that much sooner (reducing its error by that amount). We
+  // also need to take into account the previous "expected error" (due to clock
+  // rate changes) at the point when we last changed the clock rate. The
+  // expected error now is the previous expected error, plus the change due to
+  // the clock rate of (1.0 - clock_rate) * N seconds.
   int64_t time_at_current_clock_rate = timestamp - clock_rate_start_timestamp_;
-  int64_t correction =
-      clock_rate_error_base_ -
+  double correction =
+      clock_rate_error_base_ +
       (1.0 - current_audio_clock_rate_) * time_at_current_clock_rate;
-  int64_t corrected_error = error + correction;
+  int64_t corrected_error = error - correction;
   apts_error_->AddSample(x, corrected_error, 1.0);
 
   if (time_at_current_clock_rate < kRateChangeInterval.InMicroseconds()) {
@@ -268,7 +274,9 @@
     return;
   }
 
-  int64_t smoothed_error = error + (offset - corrected_error);
+  // Get the smoothed error (linear regression estimate) at the current frame,
+  // translated back into actual error.
+  int64_t smoothed_error = offset + correction;
 
   // If slope is positive, a clock rate of 1.0 is too slow (audio is playing
   // progressively later than desired). We wanted to play slope*N seconds more
@@ -277,25 +285,28 @@
   // However, we also want to correct for any existing offset. We correct so
   // that the error should reduce to 0 by the next rate change interval;
   // however the rate change is capped to prevent very fast slewing.
-  double offset_correction = 0.0;
-  if (std::abs(smoothed_error) >= kMaxIgnoredOffset) {
-    offset_correction = static_cast<double>(smoothed_error) /
-                        kRateChangeInterval.InMicroseconds();
-    offset_correction = base::ClampToRange(
-        offset_correction, -kMaxOffsetCorrection, kMaxOffsetCorrection);
+  double offset_correction = static_cast<double>(smoothed_error) /
+                             kRateChangeInterval.InMicroseconds();
+  if (std::abs(smoothed_error) < kMaxIgnoredOffset) {
+    // Offset is small enough that we can ignore it, but still correct a little
+    // bit to avoid bouncing in and out of the ignored region.
+    offset_correction = offset_correction / 4;
   }
+  offset_correction = base::ClampToRange(
+      offset_correction, -kMaxOffsetCorrection, kMaxOffsetCorrection);
   double new_rate = (1.0 + slope) + offset_correction;
 
-  double effective_new_rate =
-      backend_->audio_decoder()->SetAvSyncPlaybackRate(new_rate);
-  if (effective_new_rate != current_audio_clock_rate_) {
+  // Only change the clock rate if the desired rate is > 30 ppm different.
+  // Reasoning: 30 ppm means that leaving the clock rate unchanged will add at
+  // most 30 microseconds of additional error before the next clock rate check.
+  if (fabs(new_rate - current_audio_clock_rate_) > 3e-5) {
+    double effective_new_rate =
+        backend_->audio_decoder()->SetAvSyncPlaybackRate(new_rate);
     current_audio_clock_rate_ = effective_new_rate;
     LOG(INFO) << "Update audio clock rate to " << effective_new_rate
-              << "; wanted " << new_rate << ", error slope = " << slope;
-    LOG(INFO) << "Offset = " << offset
+              << "; wanted " << new_rate << ", error slope = " << slope
               << ", smoothed error = " << smoothed_error
-              << ", base rate = " << (1.0 + slope)
-              << ", offset correction = " << offset_correction;
+              << ", correction = " << correction;
 
     double vpts_slope;
     if (video_pts_->EstimateSlope(&vpts_slope, &e)) {
diff --git a/chromecast/media/cma/backend/video/av_sync_video.h b/chromecast/media/cma/backend/video/av_sync_video.h
index a92e6e0..c51b158 100644
--- a/chromecast/media/cma/backend/video/av_sync_video.h
+++ b/chromecast/media/cma/backend/video/av_sync_video.h
@@ -67,7 +67,7 @@
   int64_t last_apts_timestamp_ = INT64_MIN;
 
   int64_t clock_rate_start_timestamp_ = INT64_MIN;
-  int64_t clock_rate_error_base_ = INT64_MIN;
+  double clock_rate_error_base_ = 0.0;
   int64_t apts_error_start_timestamp_ = INT64_MIN;
 
   DISALLOW_COPY_AND_ASSIGN(AvSyncVideo);
diff --git a/chromeos/components/camera_app_ui/resources/BUILD.gn b/chromeos/components/camera_app_ui/resources/BUILD.gn
index fc5e630b..df61bc4 100644
--- a/chromeos/components/camera_app_ui/resources/BUILD.gn
+++ b/chromeos/components/camera_app_ui/resources/BUILD.gn
@@ -50,7 +50,10 @@
 import("images/images.gni")
 
 copy("chrome_camera_app_images") {
-  sources = []
+  sources = [
+    "images/camera_app_icons_128.png",
+    "images/camera_app_icons_48.png",
+  ]
   foreach(asset, in_app_assets) {
     sources += [ "images/$asset" ]
   }
@@ -133,8 +136,11 @@
 
 copy("chrome_camera_app_js_models") {
   sources = [
+    "js/models/async_interval.js",
     "js/models/async_writer.js",
     "js/models/barcode.js",
+    "js/models/barcode_worker.js",
+    "js/models/barcode_worker_interface.js",
     "js/models/chrome_file_system_entry.js",
     "js/models/file_namer.js",
     "js/models/file_system.js",
diff --git a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
index 03dc3841..5d97b9d5 100644
--- a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
+++ b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
@@ -14,11 +14,14 @@
     <structures>
       <structure name="IDR_CAMERA_ANALYTICS_JS" file="js/lib/analytics.js" type="chrome_html" />
       <structure name="IDR_CAMERA_APP_WINDOW_JS" file="js/app_window.js" type="chrome_html" />
+      <structure name="IDR_CAMERA_ASYNC_INTERVAL_JS" file="js/models/async_interval.js" type="chrome_html" />
       <structure name="IDR_CAMERA_ASYNC_JOB_QUEUE_JS" file="js/async_job_queue.js" type="chrome_html" />
       <structure name="IDR_CAMERA_ASYNC_WRITER_JS" file="js/models/async_writer.js" type="chrome_html" />
       <structure name="IDR_CAMERA_BACKGROUND_JS" file="js/background.js" type="chrome_html" />
       <structure name="IDR_CAMERA_BACKGROUND_OPS_JS" file="js/background_ops.js" type="chrome_html" />
       <structure name="IDR_CAMERA_BARCODE_JS" file="js/models/barcode.js" type="chrome_html" />
+      <structure name="IDR_CAMERA_BARCODE_WORKER_JS" file="js/models/barcode_worker.js" type="chrome_html" />
+      <structure name="IDR_CAMERA_BARCODE_WORKER_INTERFACE_JS" file="js/models/barcode_worker_interface.js" type="chrome_html" />
       <structure name="IDR_CAMERA_BROWSER_PROXY_INTERFACE_JS" file="js/browser_proxy/browser_proxy_interface.js" type="chrome_html" />
       <structure name="IDR_CAMERA_CAMERA3_DEVICE_INFO_JS" file="js/device/camera3_device_info.js" type="chrome_html" />
       <structure name="IDR_CAMERA_CAMERA_INTENT_JS" file="js/views/camera_intent.js" type="chrome_html" />
diff --git a/chromeos/components/camera_app_ui/resources/js/BUILD.gn b/chromeos/components/camera_app_ui/resources/js/BUILD.gn
index a1d2bf18..f2e1e1d 100644
--- a/chromeos/components/camera_app_ui/resources/js/BUILD.gn
+++ b/chromeos/components/camera_app_ui/resources/js/BUILD.gn
@@ -71,8 +71,11 @@
     "lib/ffmpeg.js",
     "main.js",
     "metrics.js",
+    "models/async_interval.js",
     "models/async_writer.js",
     "models/barcode.js",
+    "models/barcode_worker.js",
+    "models/barcode_worker_interface.js",
     "models/chrome_file_system_entry.js",
     "models/file_namer.js",
     "models/file_system.js",
diff --git a/chromeos/components/camera_app_ui/resources/js/models/async_interval.js b/chromeos/components/camera_app_ui/resources/js/models/async_interval.js
new file mode 100644
index 0000000..392278f
--- /dev/null
+++ b/chromeos/components/camera_app_ui/resources/js/models/async_interval.js
@@ -0,0 +1,117 @@
+// 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 {WaitableEvent} from '../waitable_event.js';
+
+/**
+ * Sleeps |delay| millisecond.
+ * @param {number} delay
+ * @return {!Promise} Resolved after |delay| is passed.
+ */
+function sleep(delay) {
+  return new Promise((resolve) => {
+    setTimeout(resolve, delay);
+  });
+}
+
+/**
+ * A helper class for setAsyncInterval().
+ */
+class AsyncIntervalRunner {
+  /**
+   * @param {function(): !Promise} handler
+   * @param {number} delay
+   */
+  constructor(handler, delay) {
+    /**
+     * @type {function(): !Promise}
+     * @private
+     */
+    this.handler_ = handler;
+
+    /**
+     * @type {number}
+     * @private
+     */
+    this.delay_ = delay;
+
+    /**
+     * @type {!WaitableEvent}
+     * @private
+     */
+    this.stopped_ = new WaitableEvent();
+
+    /**
+     * @type {!Promise}
+     * @private
+     */
+    this.runningPromise_ = this.loop_();
+  }
+
+
+  /**
+   * Stops the loop and wait for the |handler| if it's running.
+   * @return {!Promise}
+   */
+  async stop() {
+    this.stopped_.signal();
+    await this.runningPromise_;
+  }
+
+  /**
+   * The main loop for running handler repeatedly.
+   * @return {!Promise}
+   */
+  async loop_() {
+    while (!this.stopped_.isSignaled()) {
+      // Wait until |delay| passed or the runner is stopped.
+      await Promise.race([sleep(this.delay_), this.stopped_.wait()]);
+      if (this.stopped_.isSignaled()) {
+        break;
+      }
+      await this.handler_();
+    }
+  }
+}
+
+
+/**
+ * A counter of runner, which is used as the identifier in setAsyncInterval().
+ * @type {number}
+ */
+let runnerCount = 0;
+
+/**
+ * A map from the async interval id to the corresponding runner.
+ * @type {!Map<number, !AsyncIntervalRunner>}
+ */
+const runnerMap = new Map();
+
+/**
+ * Repeatedly calls the async function |handler| and waits until it's resolved,
+ * with a fixed delay between the next call and the previous completion time.
+ * @param {function(): !Promise} handler
+ * @param {number} delay
+ * @return {number} A numeric, non-zero value which identifies the timer.
+ */
+export function setAsyncInterval(handler, delay) {
+  const runner = new AsyncIntervalRunner(handler, delay);
+  const id = ++runnerCount;
+  runnerMap.set(id, runner);
+  return id;
+}
+
+/**
+ * Cancels a timed, repeating async action by |id|, which was returned by the
+ * corresponding call of setAsyncInterval().
+ * @param {number} id
+ * @return {!Promise} Resolved when the last action is finished.
+ */
+export async function clearAsyncInterval(id) {
+  const runner = runnerMap.get(id);
+  if (runner === undefined) {
+    return;
+  }
+  await runner.stop();
+}
diff --git a/chromeos/components/camera_app_ui/resources/js/models/barcode.js b/chromeos/components/camera_app_ui/resources/js/models/barcode.js
index 0b49c046f..62b550a 100644
--- a/chromeos/components/camera_app_ui/resources/js/models/barcode.js
+++ b/chromeos/components/camera_app_ui/resources/js/models/barcode.js
@@ -2,6 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import * as Comlink from '../lib/comlink.js';
+
+import {clearAsyncInterval, setAsyncInterval} from './async_interval.js';
+// eslint-disable-next-line no-unused-vars
+import {BarcodeWorkerInterface} from './barcode_worker_interface.js';
+
 // TODO(b/172879638): Get some performance data and tune the scan interval.
 const SCAN_INTERVAL = 1000;
 
@@ -27,10 +33,11 @@
     this.callback_ = callback;
 
     /**
-     * @type {!BarcodeDetector}
+     * @type {!BarcodeWorkerInterface}
      * @private
      */
-    this.detector_ = new BarcodeDetector({formats: ['qr_code']});
+    this.worker_ = Comlink.wrap(
+        new Worker('/js/models/barcode_worker.js', {type: 'module'}));
 
     /**
      * The current running interval id.
@@ -48,9 +55,7 @@
       return;
     }
     let prevCode = null;
-    // TODO(b/172879638): Add a setIntervalAsync() helper to avoid two
-    // detections running at the same time.
-    this.intervalId_ = setInterval(async () => {
+    this.intervalId_ = setAsyncInterval(async () => {
       const code = await this.scan_();
       if (code !== null && code !== prevCode) {
         prevCode = code;
@@ -66,7 +71,7 @@
     if (this.intervalId_ === null) {
       return;
     }
-    clearInterval(this.intervalId_);
+    clearAsyncInterval(this.intervalId_);
     this.intervalId_ = null;
   }
 
@@ -78,13 +83,9 @@
    */
   async scan_() {
     // TODO(b/172879638): Down scale the frame if the resolution is too high.
-    // TODO(b/172879638): Run this on a Web Worker.
-    const codes = await this.detector_.detect(this.video_);
+    const bitmap = await createImageBitmap(this.video_);
 
-    if (codes.length === 0) {
-      return null;
-    }
-    // TODO(b/172879638): Handle multiple barcodes.
-    return codes[0].rawValue;
+    const value = await this.worker_.detect(Comlink.transfer(bitmap, [bitmap]));
+    return value;
   }
 }
diff --git a/chromeos/components/camera_app_ui/resources/js/models/barcode_worker.js b/chromeos/components/camera_app_ui/resources/js/models/barcode_worker.js
new file mode 100644
index 0000000..df141d3
--- /dev/null
+++ b/chromeos/components/camera_app_ui/resources/js/models/barcode_worker.js
@@ -0,0 +1,41 @@
+// 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 * as Comlink from '../lib/comlink.js';
+
+// eslint-disable-next-line no-unused-vars
+import {BarcodeWorkerInterface} from './barcode_worker_interface.js';
+
+/**
+ * A barcode worker to detect barcode from images.
+ * @implements {BarcodeWorkerInterface}
+ */
+class BarcodeWorker {
+  /**
+   * @public
+   */
+  constructor() {
+    /**
+     * @type {!BarcodeDetector}
+     * @private
+     */
+    this.detector_ = new BarcodeDetector({formats: ['qr_code']});
+  }
+
+  /**
+   * @override
+   */
+  async detect(bitmap) {
+    const codes = await this.detector_.detect(bitmap);
+
+    if (codes.length === 0) {
+      return null;
+    }
+
+    // TODO(b/172879638): Handle multiple barcodes.
+    return codes[0].rawValue;
+  }
+}
+
+Comlink.expose(new BarcodeWorker());
diff --git a/chromeos/components/camera_app_ui/resources/js/models/barcode_worker_interface.js b/chromeos/components/camera_app_ui/resources/js/models/barcode_worker_interface.js
new file mode 100644
index 0000000..34885d4
--- /dev/null
+++ b/chromeos/components/camera_app_ui/resources/js/models/barcode_worker_interface.js
@@ -0,0 +1,19 @@
+// 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.
+
+/**
+ * The interface for a barcode worker. All methods are marked as async since
+ * it will be used with Comlink and Web Workers.
+ * @interface
+ */
+export class BarcodeWorkerInterface {
+  /**
+   * Detects barcodes from an image bitmap.
+   * @param {!ImageBitmap} bitmap
+   * @return {!Promise<?string>} The detected barcode value, or null if no
+   *     barcode is detected.
+   * @abstract
+   */
+  async detect(bitmap) {}
+}
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index e92e3ff1..8b088025a 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -88,8 +88,8 @@
     "ArcManagedAdbSideloadingSupport", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Controls whether to enable support for View.onKeyPreIme() of ARC apps.
-const base::Feature kArcPreImeKeyEventSupport{"ArcPreImeKeyEventSupport",
-                                              base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kArcPreImeKeyEventSupport{
+    "ArcPreImeKeyEventSupport", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enables or disables auto screen-brightness adjustment when ambient light
 // changes.
diff --git a/chromeos/cryptohome/cryptohome_util.cc b/chromeos/cryptohome/cryptohome_util.cc
index 9544307..908bbba 100644
--- a/chromeos/cryptohome/cryptohome_util.cc
+++ b/chromeos/cryptohome/cryptohome_util.cc
@@ -369,6 +369,8 @@
       return MOUNT_ERROR_REMOVE_FAILED;
     case CRYPTOHOME_ERROR_TPM_UPDATE_REQUIRED:
       return MOUNT_ERROR_TPM_UPDATE_REQUIRED;
+    case CRYPTOHOME_ERROR_VAULT_UNRECOVERABLE:
+      return MOUNT_ERROR_VAULT_UNRECOVERABLE;
     // TODO(crbug.com/797563): Split the error space and/or handle everything.
     case CRYPTOHOME_ERROR_LOCKBOX_SIGNATURE_INVALID:
     case CRYPTOHOME_ERROR_LOCKBOX_CANNOT_SIGN:
diff --git a/chromeos/login/auth/auth_status_consumer.h b/chromeos/login/auth/auth_status_consumer.h
index 5c23a47..d01a208 100644
--- a/chromeos/login/auth/auth_status_consumer.h
+++ b/chromeos/login/auth/auth_status_consumer.h
@@ -43,6 +43,7 @@
     MISSING_CRYPTOHOME = 13,          // cryptohome missing from disk.
     AUTH_DISABLED = 14,               // Authentication disabled for user.
     TPM_UPDATE_REQUIRED = 15,         // TPM firmware update is required.
+    UNRECOVERABLE_CRYPTOHOME = 16,    // cryptohome is corrupted.
     NUM_FAILURE_REASONS,              // This has to be the last item.
   };
 
@@ -101,6 +102,8 @@
         return "Critical TPM error encountered.";
       case TPM_UPDATE_REQUIRED:
         return "TPM firmware update required.";
+      case UNRECOVERABLE_CRYPTOHOME:
+        return "Cryptohome is corrupted.";
       default:
         NOTREACHED();
         return std::string();
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc
index 6d3abb8b..d86d41c 100644
--- a/chromeos/login/auth/cryptohome_authenticator.cc
+++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -133,6 +133,8 @@
       return "OFFLINE_NO_MOUNT";
     case CryptohomeAuthenticator::TPM_UPDATE_REQUIRED:
       return "TPM_UPDATE_REQUIRED";
+    case CryptohomeAuthenticator::OFFLINE_MOUNT_UNRECOVERABLE:
+      return "OFFLINE_MOUNT_UNRECOVERABLE";
   }
   return "UNKNOWN";
 }
@@ -996,6 +998,12 @@
           base::BindOnce(&CryptohomeAuthenticator::OnAuthFailure, this,
                          AuthFailure(AuthFailure::TPM_UPDATE_REQUIRED)));
       break;
+    case OFFLINE_MOUNT_UNRECOVERABLE:
+      task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&CryptohomeAuthenticator::OnAuthFailure, this,
+                         AuthFailure(AuthFailure::UNRECOVERABLE_CRYPTOHOME)));
+      break;
     default:
       NOTREACHED();
       break;
@@ -1078,6 +1086,13 @@
     return TPM_UPDATE_REQUIRED;
   }
 
+  if (current_state_->cryptohome_code() ==
+      cryptohome::MOUNT_ERROR_VAULT_UNRECOVERABLE) {
+    // Surface up if the mount attempt failed because the vault is
+    // unrecoverable.
+    return OFFLINE_MOUNT_UNRECOVERABLE;
+  }
+
   // Return intermediate states in the following case:
   // when there is an online result to use;
   // This is the case after user finishes Gaia login;
diff --git a/chromeos/login/auth/cryptohome_authenticator.h b/chromeos/login/auth/cryptohome_authenticator.h
index c89a791..d32fbde 100644
--- a/chromeos/login/auth/cryptohome_authenticator.h
+++ b/chromeos/login/auth/cryptohome_authenticator.h
@@ -98,7 +98,9 @@
                                                 // partially encrypted in old
                                                 // format.
     OFFLINE_NO_MOUNT = 26,  // Offline login failed due to missing cryptohome.
-    TPM_UPDATE_REQUIRED = 27,  // TPM firmware update is required.
+    TPM_UPDATE_REQUIRED = 27,          // TPM firmware update is required.
+    OFFLINE_MOUNT_UNRECOVERABLE = 28,  // Offline login failed due to corrupted
+                                       // cryptohome.
   };
 
   CryptohomeAuthenticator(scoped_refptr<base::SequencedTaskRunner> task_runner,
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc
index 73816ca..8c4e3eb48 100644
--- a/chromeos/settings/cros_settings_names.cc
+++ b/chromeos/settings/cros_settings_names.cc
@@ -233,9 +233,14 @@
 const char kAllowRedeemChromeOsRegistrationOffers[] =
     "cros.echo.allow_redeem_chrome_os_registration_offers";
 
+// A list pref storing the feature flags (in the chrome://flags sense) that
+// should to be applied at the login screen.
+const char kFeatureFlags[] = "cros.feature_flags";
+
 // A list pref storing the flags that need to be applied to the browser upon
-// start-up.
-const char kStartUpFlags[] = "cros.startup_flags";
+// start-up. This lists raw flags, which isn't ideal since Chrome can't easily
+// tie this back to feature flags. Deprecated in favor of kFeatureFlags.
+const char kStartUpFlagsDeprecated[] = "cros.startup_flags";
 
 // A string pref for the restrict parameter to be appended to the Variations URL
 // when pinging the Variations server.
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h
index 64d3576..b88a211 100644
--- a/chromeos/settings/cros_settings_names.h
+++ b/chromeos/settings/cros_settings_names.h
@@ -133,7 +133,8 @@
 COMPONENT_EXPORT(CHROMEOS_SETTINGS)
 extern const char kAllowRedeemChromeOsRegistrationOffers[];
 
-COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kStartUpFlags[];
+COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kFeatureFlags[];
+COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kStartUpFlagsDeprecated[];
 
 COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kKioskAppSettingsPrefix[];
 COMPONENT_EXPORT(CHROMEOS_SETTINGS)
diff --git a/components/account_manager_core/account.h b/components/account_manager_core/account.h
index 6a0d248..938b8b0 100644
--- a/components/account_manager_core/account.h
+++ b/components/account_manager_core/account.h
@@ -14,7 +14,7 @@
 
 // Type of an account, based on the authentication backend of the account.
 // Loosely based on //chromeos/components/account_manager/tokens.proto
-enum class COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE) AccountType : int {
+enum class AccountType : int {
   // Gaia account (aka Google account) - including enterprise and consumer
   // accounts.
   kGaia = 1,
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 105d3ff..e812c2f5 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -394,6 +394,7 @@
     "//base",
     "//base:i18n",
     "//build:branding_buildflags",
+    "//build:chromeos_buildflags",
     "//components/google/core/common",
     "//components/history/core/browser",
     "//components/infobars/core",
@@ -735,6 +736,7 @@
     ":unit_tests_bundle_data",
     "//base",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//components/autofill/core/common",
     "//components/infobars/core:feature_flags",
     "//components/leveldb_proto",
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 593c8b7..d0dc0dbf9 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -41,6 +41,7 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/autofill/core/browser/autocomplete_history_manager.h"
 #include "components/autofill/core/browser/autofill_browser_util.h"
 #include "components/autofill/core/browser/autofill_client.h"
@@ -1152,7 +1153,7 @@
 
   ProcessPendingFormForUpload();
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // There is no way of determining whether ChromeVox is in use, so assume it's
   // being used.
   external_delegate_->OnAutofillAvailabilityEvent(
@@ -1172,7 +1173,7 @@
   // are suggestions to present. Ignore if a screen reader is not present. If
   // the platform is ChromeOS, then assume ChromeVox is in use as there is no
   // way of determining whether it's being used from this point in the code.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   if (!external_delegate_->HasActiveScreenReader())
     return;
 #endif
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index a2bc8c1..6b16cbc 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -30,6 +30,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/autofill/core/browser/autocomplete_history_manager.h"
 #include "components/autofill/core/browser/autofill_download_manager.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
@@ -8894,7 +8895,7 @@
   }
 
   void CheckSuggestionsAvailableIfScreenReaderRunning() {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     // The only existing functions for determining whether ChromeVox is in use
     // are in the src/chrome directory, which cannot be included in components.
     // Thus, if the platform is ChromeOS, we assume that ChromeVox is in use at
@@ -8904,7 +8905,7 @@
 #else
     EXPECT_EQ(has_active_screen_reader_,
               external_delegate_->has_suggestions_available_on_field_focus());
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
 
   void CheckNoSuggestionsAvailableOnFieldFocus() {
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index 11d891b..dfb65176 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -26,6 +26,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_download_manager.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
@@ -1957,7 +1958,9 @@
 
 bool PersonalDataManager::ShouldShowCardsFromAccountOption() const {
 // The feature is only for Linux, Windows and Mac.
-#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_WIN) || \
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || defined(OS_WIN) || \
     defined(OS_APPLE)
   // This option should only be shown for users that have not enabled the Sync
   // Feature and that have server credit cards available.
@@ -1981,8 +1984,8 @@
   return !is_opted_in;
 #else
   return false;
-#endif  // #if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_WIN) || \
-       //     defined(OS_APPLE)
+#endif  // #if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) ||
+        // defined(OS_WIN) || defined(OS_APPLE)
 }
 
 void PersonalDataManager::OnUserAcceptedCardsFromAccountOption() {
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 50fcc72..f759c4f 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -31,6 +31,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
@@ -449,7 +450,9 @@
 
 // Cards are automatically remasked on Linux since full server cards are not
 // supported.
-#if !defined(OS_LINUX) || defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if !(defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
     personal_data_->ResetFullServerCard(
         personal_data_->GetCreditCards()[0]->guid());
 #endif
@@ -580,7 +583,7 @@
  public:
   PersonalDataManagerMigrationTest()
       : PersonalDataManagerHelper(
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
             { ::switches::kAccountIdMigration }
 #endif
         ) {
@@ -1410,7 +1413,7 @@
       /*disabled_features=*/{});
 
 // ClearPrimaryAccount is not supported on CrOS.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Sign out.
   identity_test_env_.ClearPrimaryAccount();
   EXPECT_EQ(AutofillSyncSigninState::kSignedOut,
@@ -6634,7 +6637,9 @@
 
 // These tests are not applicable on Linux since it does not support full server
 // cards.
-#if !defined(OS_LINUX) || defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if !(defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 // Test that calling OnSyncServiceInitialized with a null sync service remasks
 // full server cards.
 TEST_F(PersonalDataManagerTest, OnSyncServiceInitialized_NoSyncService) {
@@ -6683,7 +6688,7 @@
   // OnSyncServiceInitialized.
   personal_data_->OnSyncShutdown(&sync_service);
 }
-#endif  // !defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif  // !(defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
 
 #if !defined(OS_ANDROID)
 TEST_F(PersonalDataManagerTest, ExcludeServerSideCards) {
@@ -6765,8 +6770,8 @@
   EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
   EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
 }
-#endif  // defined(OS_WIN) || defined(OS_MAC) ||
-        // defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif  // defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) ||
+        // defined(OS_CHROMEOS)
 
 // Tests that all the non settings origins of autofill profiles are cleared but
 // that the settings origins are untouched.
@@ -7490,7 +7495,7 @@
 }
 #endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !defined(OS_IOS) && !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) {
   // The method should return false if one of these is not respected:
   //   * The sync_service is not null
@@ -7603,7 +7608,8 @@
     histogram_tester.ExpectTotalCount(kHistogramName, 0);
   }
 }
-#else   // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+#else   // !defined(OS_ANDROID) && !defined(OS_IOS) &&
+        // !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) {
   // The method should return false if one of these is not respected:
   //   * The sync_service is not null
@@ -7677,7 +7683,8 @@
   personal_data_->SetSyncServiceForTest(nullptr);
   EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
 }
-#endif  // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS) &&
+        // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(PersonalDataManagerTest, GetSyncSigninState) {
   // Make a non-primary account available with both a refresh token and cookie
@@ -7726,7 +7733,7 @@
   }
 
 // ClearPrimaryAccount is not supported on CrOS.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // Check that the sync state is |SignedOut| when the account info is empty.
   {
     identity_test_env_.ClearPrimaryAccount();
@@ -7741,7 +7748,7 @@
   sync_service_.SetAuthenticatedAccountInfo(primary_account_info);
   sync_service_.SetIsAuthenticatedAccountPrimary(true);
 // MakePrimaryAccountAvailable is not supported on CrOS.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   identity_test_env_.MakePrimaryAccountAvailable(primary_account_info.email);
 #endif
 
@@ -7784,7 +7791,7 @@
 
   // Account wallet storage only makes sense together with support for
   // unconsented primary accounts, i.e. on Win/Mac/Linux.
-#if !defined(OS_CHROMEOS)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   {
     base::test::ScopedFeatureList scoped_features;
     scoped_features.InitAndEnableFeature(
@@ -7843,7 +7850,7 @@
     EXPECT_FALSE(prefs::IsUserOptedInWalletSyncTransport(
         prefs_.get(), active_info.account_id));
   }
-#endif  // !defined(OS_CHROMEOS)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   ///////////////////////////////////////////////////////////
   // kSignedInAndSyncFeature
diff --git a/components/autofill/core/common/BUILD.gn b/components/autofill/core/common/BUILD.gn
index 97d08395..319e579b 100644
--- a/components/autofill/core/common/BUILD.gn
+++ b/components/autofill/core/common/BUILD.gn
@@ -59,6 +59,7 @@
   deps = [
     "//base",
     "//base:i18n",
+    "//build:chromeos_buildflags",
 
     # Note: Can't use mojom:mojo_types here, as that already depends on :common.
     "//components/autofill/core/common/mojom:mojo_types_shared",
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 1899168..534e61c 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/prefs/pref_service.h"
@@ -67,7 +68,7 @@
 // account-based storage when sync the transport is enabled.
 const base::Feature kAutofillEnableAccountWalletStorage {
   "AutofillEnableAccountWalletStorage",
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_IOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID) || defined(OS_IOS)
       // Wallet transport is only currently available on Win/Mac/Linux.
       // (Somehow, swapping this check makes iOS unhappy?)
       base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index 6e896042..e790357 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/prefs/pref_service.h"
@@ -128,8 +129,10 @@
     "AutofillUpstreamAllowAllEmailDomains", base::FEATURE_DISABLED_BY_DEFAULT};
 
 bool ShouldShowImprovedUserConsentForCreditCardSave() {
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
 #if defined(OS_WIN) || defined(OS_APPLE) || \
-    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+    (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
   // The new user consent UI is fully launched on MacOS, Windows and Linux.
   return true;
 #else
diff --git a/components/bookmarks/browser/BUILD.gn b/components/bookmarks/browser/BUILD.gn
index 9d1193a6..ba1575b 100644
--- a/components/bookmarks/browser/BUILD.gn
+++ b/components/bookmarks/browser/BUILD.gn
@@ -146,6 +146,7 @@
     ":browser",
     ":unit_tests_bundle_data",
     "//base/test:test_support",
+    "//build:chromeos_buildflags",
     "//components/bookmarks/common",
     "//components/bookmarks/test",
     "//components/favicon_base",
diff --git a/components/bookmarks/browser/bookmark_node_data_unittest.cc b/components/bookmarks/browser/bookmark_node_data_unittest.cc
index e01879b..2c512294 100644
--- a/components/bookmarks/browser/bookmark_node_data_unittest.cc
+++ b/components/bookmarks/browser/bookmark_node_data_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
 #include "components/bookmarks/test/test_bookmark_client.h"
diff --git a/components/feedback/feedback_common.cc b/components/feedback/feedback_common.cc
index e3e5bb8..d067bcd6 100644
--- a/components/feedback/feedback_common.cc
+++ b/components/feedback/feedback_common.cc
@@ -18,7 +18,7 @@
 
 namespace {
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 constexpr int kChromeOSProductId = 208;
 #else
 constexpr int kChromeBrowserProductId = 237;
@@ -124,7 +124,7 @@
 
   // Set whether we're reporting from ChromeOS or Chrome on another platform.
   userfeedback::ChromeData chrome_data;
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
   const userfeedback::ChromeData_ChromePlatform chrome_platform =
       userfeedback::ChromeData_ChromePlatform_CHROME_OS;
   const int default_product_id = kChromeOSProductId;
@@ -140,7 +140,7 @@
   chrome_browser_data.set_category(
       userfeedback::ChromeBrowserData_ChromeBrowserCategory_OTHER);
   *(chrome_data.mutable_chrome_browser_data()) = chrome_browser_data;
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
   chrome_data.set_chrome_platform(chrome_platform);
   *(feedback_data->mutable_chrome_data()) = chrome_data;
 
diff --git a/components/feedback/feedback_common_unittest.cc b/components/feedback/feedback_common_unittest.cc
index d77f959..35b991b1 100644
--- a/components/feedback/feedback_common_unittest.cc
+++ b/components/feedback/feedback_common_unittest.cc
@@ -23,11 +23,11 @@
 constexpr char kLogsAttachmentName[] = "system_logs.zip";
 constexpr int kTestProductId = 3490;
 
-#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 constexpr int kDefaultProductId = 208;  // ChromeOS & Lacros default product ID.
 #else
 constexpr int kDefaultProductId = 237;  // Chrome default product ID.
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 }  // namespace
 
 class FeedbackCommonTest : public testing::Test {
diff --git a/components/feedback/redaction_tool.cc b/components/feedback/redaction_tool.cc
index 7561037..4531776 100644
--- a/components/feedback/redaction_tool.cc
+++ b/components/feedback/redaction_tool.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_restrictions.h"
+#include "build/chromeos_buildflags.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/ip_address.h"
 #include "third_party/re2/src/re2/re2.h"
@@ -564,7 +565,7 @@
   // We only use this on Chrome OS and there's differences in the API for
   // FilePath on Windows which prevents this from compiling, so only enable this
   // code for Chrome OS.
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::string result;
   result.reserve(input.size());
 
@@ -612,7 +613,7 @@
   return result;
 #else
   return input;
-#endif  //  defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 std::string RedactionTool::RedactCustomPatterns(std::string input) {
diff --git a/components/feedback/redaction_tool_unittest.cc b/components/feedback/redaction_tool_unittest.cc
index 531bf335..e1e08be03 100644
--- a/components/feedback/redaction_tool_unittest.cc
+++ b/components/feedback/redaction_tool_unittest.cc
@@ -7,6 +7,7 @@
 #include <gtest/gtest.h>
 
 #include "base/strings/string_util.h"
+#include "build/chromeos_buildflags.h"
 
 namespace feedback {
 
@@ -434,14 +435,14 @@
      "<URL: 3>"},  // Potentially PII in parameter.
     {"/root/27540283740a0897ab7c8de0f809add2bacde78f/foo",
      "/root/<HASH:2754 1>/foo"},  // Hash string.
-#if defined(OS_CHROMEOS)          // We only redact Android paths on Chrome OS.
+#if BUILDFLAG(IS_CHROMEOS_ASH)    // We only redact Android paths on Chrome OS.
     // Allowed android storage path.
     {"112K\t/home/root/deadbeef1234/android-data/data/system_de",
      "112K\t/home/root/deadbeef1234/android-data/data/system_de"},
     // Redacted app-specific storage path.
     {"8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/de",
      "8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/d_"},
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   };
   std::string redaction_input;
   std::string redaction_output;
@@ -452,7 +453,7 @@
   EXPECT_EQ(redaction_output, redactor_.Redact(redaction_input));
 }
 
-#if defined(OS_CHROMEOS)  // We only redact Android paths on Chrome OS.
+#if BUILDFLAG(IS_CHROMEOS_ASH)  // We only redact Android paths on Chrome OS.
 TEST_F(RedactionToolTest, RedactAndroidAppStoragePaths) {
   EXPECT_EQ("", RedactAndroidAppStoragePaths(""));
   EXPECT_EQ("foo\nbar\n", RedactAndroidAppStoragePaths("foo\nbar\n"));
@@ -499,7 +500,7 @@
       "78M\t/home/root/deadbeef1234/android-data/data/data\n";
   EXPECT_EQ(kDuOutputRedacted, RedactAndroidAppStoragePaths(kDuOutput));
 }
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(RedactionToolTest, RedactBlockDevices) {
   // Test cases in the form {input, output}.
diff --git a/components/nacl/browser/BUILD.gn b/components/nacl/browser/BUILD.gn
index d9b9976..ebd6417 100644
--- a/components/nacl/browser/BUILD.gn
+++ b/components/nacl/browser/BUILD.gn
@@ -29,6 +29,7 @@
   deps = [
     "//base",
     "//base/third_party/dynamic_annotations",
+    "//build:chromeos_buildflags",
     "//components/nacl/common",
     "//components/nacl/common:buildflags",
     "//components/nacl/common:debug_exception_handler",
diff --git a/components/nacl/browser/nacl_host_message_filter.cc b/components/nacl/browser/nacl_host_message_filter.cc
index a4cbdfc4..c4524ad 100644
--- a/components/nacl/browser/nacl_host_message_filter.cc
+++ b/components/nacl/browser/nacl_host_message_filter.cc
@@ -12,6 +12,7 @@
 #include "base/system/sys_info.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/nacl/browser/bad_message.h"
 #include "components/nacl/browser/nacl_browser.h"
 #include "components/nacl/browser/nacl_file_host.h"
@@ -134,7 +135,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   bool nonsfi_mode_allowed = false;
-#if defined(OS_CHROMEOS) && \
+#if BUILDFLAG(IS_CHROMEOS_ASH) && \
     (defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL))
   nonsfi_mode_allowed = NaClBrowser::GetDelegate()->IsNonSfiModeAllowed(
       profile_directory_, GURL(launch_params.manifest_url));
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index a3bc2a3..38edb501 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -34,6 +34,7 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/nacl/browser/nacl_browser.h"
 #include "components/nacl/browser/nacl_browser_delegate.h"
 #include "components/nacl/browser/nacl_host_message_filter.h"
@@ -315,7 +316,9 @@
 void NaClProcessHost::EarlyStartup() {
   NaClBrowser::GetInstance()->EarlyStartup();
   // Inform NaClBrowser that we exist and will have a debug port at some point.
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+// of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
   // Open the IRT file early to make sure that it isn't replaced out from
   // under us by autoupdate.
   NaClBrowser::GetInstance()->EnsureIrtAvailable();
diff --git a/components/nacl/common/BUILD.gn b/components/nacl/common/BUILD.gn
index 4755bdb..c39d5ed7 100644
--- a/components/nacl/common/BUILD.gn
+++ b/components/nacl/common/BUILD.gn
@@ -77,6 +77,7 @@
 
     deps = [
       "//base",
+      "//build:chromeos_buildflags",
       "//content/public/common",
       "//url",
     ]
diff --git a/components/nacl/common/nacl_nonsfi_util.cc b/components/nacl/common/nacl_nonsfi_util.cc
index f042010..488a9b4 100644
--- a/components/nacl/common/nacl_nonsfi_util.cc
+++ b/components/nacl/common/nacl_nonsfi_util.cc
@@ -6,12 +6,13 @@
 
 #include "base/command_line.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/nacl/common/nacl_switches.h"
 
 namespace nacl {
 
 bool IsNonSFIModeEnabled() {
-#if defined(OS_CHROMEOS) && \
+#if BUILDFLAG(IS_CHROMEOS_ASH) && \
     (defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL))
   return true;
 #elif defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/components/nacl/loader/BUILD.gn b/components/nacl/loader/BUILD.gn
index f1f943c3..34b43f9 100644
--- a/components/nacl/loader/BUILD.gn
+++ b/components/nacl/loader/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/c++/c++.gni")
+import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/nacl/config.gni")
 import("//components/nacl/features.gni")
@@ -139,7 +140,7 @@
       "//url/ipc:url_ipc",
     ]
 
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       # NaCl is not working with compiler-rt in ChromeOS.
       # Force libgcc as a workaround. See https://crbug.com/761103
       ldflags = [
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.cc b/components/password_manager/core/browser/sync/password_sync_bridge.cc
index 9592d28a..35dd2d8 100644
--- a/components/password_manager/core/browser/sync/password_sync_bridge.cc
+++ b/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -756,7 +756,7 @@
   auto batch = std::make_unique<syncer::MutableDataBatch>();
   for (const auto& pair : key_to_form_map) {
     PasswordForm form = *pair.second;
-    form.password_value = base::UTF8ToUTF16("hidden");
+    form.password_value = base::UTF8ToUTF16("<redacted>");
     batch->Put(base::NumberToString(pair.first), CreateEntityData(form));
   }
   std::move(callback).Run(std::move(batch));
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
index 52ce582..31a6f3b 100644
--- a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
+++ b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -794,7 +794,8 @@
   EXPECT_FALSE(error);
 }
 
-TEST_F(PasswordSyncBridgeTest, ShouldGetAllDataForDebuggingWithHiddenPassword) {
+TEST_F(PasswordSyncBridgeTest,
+       ShouldGetAllDataForDebuggingWithRedactedPassword) {
   const int kPrimaryKey1 = 1000;
   const int kPrimaryKey2 = 1001;
   PasswordForm form1 = MakePasswordForm(kSignonRealm1);
@@ -814,9 +815,9 @@
   EXPECT_TRUE(batch->HasNext());
   while (batch->HasNext()) {
     const syncer::KeyAndData& data_pair = batch->Next();
-    EXPECT_EQ("hidden", data_pair.second->specifics.password()
-                            .client_only_encrypted_data()
-                            .password_value());
+    EXPECT_EQ("<redacted>", data_pair.second->specifics.password()
+                                .client_only_encrypted_data()
+                                .password_value());
   }
 }
 
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index 1715e441..c901111d 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -552,11 +552,25 @@
   optional bool allow_redeem_offers = 1 [default = true];
 }
 
-message StartUpFlagsProto {
-  // Specifies the flags that should be applied to Google Chrome when it starts.
-  // The specified flags are applied on the login screen only. Flags set via
-  // this policy do not propagate into user sessions.
-  repeated string flags = 1;
+message FeatureFlagsProto {
+  // Specifies switches that should be passed to Google Chrome when it starts.
+  // The specified switches are applied on the login screen only. Switches set
+  // via this policy do not propagate into user sessions.
+  // This is deprecated because it turned out that storing raw switches is
+  // problematic since Chrome can't easily tie switches back to feature flags to
+  // validate them. The |feature_flags| field below works in terms of feature
+  // flag names (i.e. chrome://flags items) instead and supersedes |switches|.
+  repeated string switches = 1 [deprecated = true];
+
+  // Specifies feature flags (i.e. chrome://flags items) that should be enabled
+  // when Chrome starts. The format of the individual entries matches the format
+  // chrome://flags uses for internal bookkeeping, i.e. either the flag name as
+  // listed on chrome://flags (for flags that only have a single choice besides
+  // the default) or the flag name followed by the index of the chosen option,
+  // separated by an '@' character (for flags with multiple choices). The
+  // specified feature flags are applied on the login screen only and don't
+  // propagate into the user session.
+  repeated string feature_flags = 2;
 }
 
 message UptimeLimitProto {
@@ -1763,7 +1777,7 @@
   optional SystemTimezoneProto system_timezone = 20;
   optional DeviceLocalAccountsProto device_local_accounts = 21;
   optional AllowRedeemChromeOsRegistrationOffersProto allow_redeem_offers = 22;
-  optional StartUpFlagsProto start_up_flags = 23;
+  optional FeatureFlagsProto feature_flags = 23;
   optional UptimeLimitProto uptime_limit = 24;
   optional VariationsParameterProto variations_parameter = 25;
   optional AttestationSettingsProto attestation_settings = 26;
diff --git a/components/services/app_service/public/cpp/intent_util.cc b/components/services/app_service/public/cpp/intent_util.cc
index 005baf6..29fd9a65 100644
--- a/components/services/app_service/public/cpp/intent_util.cc
+++ b/components/services/app_service/public/cpp/intent_util.cc
@@ -153,6 +153,17 @@
   return intent;
 }
 
+apps::mojom::IntentPtr CreateShareIntentFromFiles(
+    const std::vector<GURL>& filesystem_urls,
+    const std::vector<std::string>& mime_types,
+    const std::string& share_text,
+    const std::string& share_title) {
+  auto intent = CreateShareIntentFromFiles(filesystem_urls, mime_types);
+  intent->share_text = share_text;
+  intent->share_title = share_title;
+  return intent;
+}
+
 apps::mojom::IntentPtr CreateShareIntentFromDriveFile(
     const GURL& filesystem_url,
     const std::string& mime_type,
diff --git a/components/services/app_service/public/cpp/intent_util.h b/components/services/app_service/public/cpp/intent_util.h
index eebb78e..4ba575f 100644
--- a/components/services/app_service/public/cpp/intent_util.h
+++ b/components/services/app_service/public/cpp/intent_util.h
@@ -28,6 +28,14 @@
     const std::vector<GURL>& filesystem_urls,
     const std::vector<std::string>& mime_types);
 
+// Create an intent struct from the filesystem urls, mime types
+// of a list of files, and the share text and title.
+apps::mojom::IntentPtr CreateShareIntentFromFiles(
+    const std::vector<GURL>& filesystem_urls,
+    const std::vector<std::string>& mime_types,
+    const std::string& share_text,
+    const std::string& share_title);
+
 // Create an intent struct from the filesystem url, mime type
 // and the drive share url for a Google Drive file.
 apps::mojom::IntentPtr CreateShareIntentFromDriveFile(
diff --git a/components/services/app_service/public/mojom/types.mojom b/components/services/app_service/public/mojom/types.mojom
index b3acba6..26923d28 100644
--- a/components/services/app_service/public/mojom/types.mojom
+++ b/components/services/app_service/public/mojom/types.mojom
@@ -330,6 +330,7 @@
   // from Google Drive.
   url.mojom.Url? drive_share_url;
   string? share_text; // Text to share. e.g. Share link to other app.
+  string? share_title; // Title for the share.
 };
 
 // Represents a group of |app_ids| that is no longer preferred app of their
diff --git a/components/services/storage/public/mojom/service_worker_storage_control.mojom b/components/services/storage/public/mojom/service_worker_storage_control.mojom
index f45a3714..86223dd61 100644
--- a/components/services/storage/public/mojom/service_worker_storage_control.mojom
+++ b/components/services/storage/public/mojom/service_worker_storage_control.mojom
@@ -125,8 +125,9 @@
 // Currently this is consumed and implemented in the browser process, but the
 // implementation will eventually live in the Storage Service.
 interface ServiceWorkerStorageControl {
-  // Disables the storage.
-  Disable();
+  // Disables the storage. The callback is invoked after the storage is
+  // disabled.
+  Disable() => ();
 
   // Deletes the whole storage.
   Delete() => (ServiceWorkerDatabaseStatus status);
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
index 426f92c..80d1e99b 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
@@ -135,11 +135,6 @@
 // static
 void ProfileOAuth2TokenService::RegisterProfilePrefs(
     PrefRegistrySimple* registry) {
-#if defined(OS_IOS)
-  registry->RegisterBooleanPref(prefs::kTokenServiceExcludeAllSecondaryAccounts,
-                                false);
-  registry->RegisterListPref(prefs::kTokenServiceExcludedSecondaryAccounts);
-#endif
   registry->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId,
                                std::string());
 }
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h
index f820916..25ccdd84 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h
@@ -93,9 +93,6 @@
   // removed.
   void ReloadCredentials();
 
-  // Clears exclude secondary accounts preferences.
-  void ClearExcludedSecondaryAccounts();
-
   // Info about the existing accounts.
   AccountStatusMap accounts_;
 
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm
index afa151d..377a482a 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm
@@ -14,11 +14,8 @@
 #include "base/stl_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/values.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
 #include "components/signin/public/base/signin_client.h"
-#include "components/signin/public/base/signin_pref_names.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/ios/device_accounts_provider.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
@@ -187,9 +184,6 @@
   set_load_credentials_state(
       signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS);
 
-  // Clean-up stale data from prefs.
-  ClearExcludedSecondaryAccounts();
-
   if (primary_account_id.empty()) {
     // On startup, always fire refresh token loaded even if there is nothing
     // to load (not authenticated).
@@ -267,7 +261,6 @@
     RemoveAccount(accountStatus.first);
 
   DCHECK_EQ(0u, accounts_.size());
-  ClearExcludedSecondaryAccounts();
 }
 
 void ProfileOAuth2TokenServiceIOSDelegate::ReloadAllAccountsFromSystem() {
@@ -370,9 +363,3 @@
     FireRefreshTokenRevoked(account_id);
   }
 }
-
-void ProfileOAuth2TokenServiceIOSDelegate::ClearExcludedSecondaryAccounts() {
-  client_->GetPrefs()->ClearPref(
-      prefs::kTokenServiceExcludeAllSecondaryAccounts);
-  client_->GetPrefs()->ClearPref(prefs::kTokenServiceExcludedSecondaryAccounts);
-}
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm
index cc1995de..9516d54 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm
@@ -7,11 +7,9 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
-#include "components/signin/public/base/signin_pref_names.h"
 #include "components/signin/public/base/test_signin_client.h"
 #include "components/signin/public/identity_manager/ios/fake_device_accounts_provider.h"
 #include "google_apis/gaia/gaia_urls.h"
@@ -46,11 +44,6 @@
     AccountTrackerService::RegisterPrefs(prefs_.registry());
     account_tracker_.Initialize(&prefs_, base::FilePath());
 
-    prefs_.registry()->RegisterBooleanPref(
-        prefs::kTokenServiceExcludeAllSecondaryAccounts, false);
-    prefs_.registry()->RegisterListPref(
-        prefs::kTokenServiceExcludedSecondaryAccounts);
-
     fake_provider_ = new FakeDeviceAccountsProvider();
     oauth2_delegate_.reset(new ProfileOAuth2TokenServiceIOSDelegate(
         &client_, base::WrapUnique(fake_provider_), &account_tracker_));
diff --git a/components/signin/public/base/signin_metrics.h b/components/signin/public/base/signin_metrics.h
index 37c25d6..88793956 100644
--- a/components/signin/public/base/signin_metrics.h
+++ b/components/signin/public/base/signin_metrics.h
@@ -8,6 +8,7 @@
 #include <limits.h>
 
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 
 namespace signin_metrics {
@@ -207,6 +208,61 @@
   PROMO_ACTION_NEW_ACCOUNT_EXISTING_ACCOUNT
 };
 
+#if defined(OS_ANDROID)
+// This class is used to record user action that was taken after
+// receiving the header from Gaia in the web sign-in flow.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.signin.metrics
+// GENERATED_JAVA_CLASS_NAME_OVERRIDE: AccountConsistencyPromoAction
+enum class AccountConsistencyPromoAction : int {
+  // Promo is not shown as there are no accounts on device.
+  SUPPRESSED_NO_ACCOUNTS = 0,
+  // User has dismissed the promo by tapping back button.
+  DISMISSED_BACK,
+  // User has tapped |Add account to device| from expanded account list.
+  ADD_ACCOUNT_STARTED,
+  // User tapped the button from the expanded account list to open the incognito
+  // interstitial
+  // then confirmed opening the page in the incognito tab by tapping |Continue|
+  // in the incognito
+  // interstitial.
+  STARTED_INCOGNITO_SESSION,
+  // User has selected the default account and signed in with it
+  SIGNED_IN_WITH_DEFAULT_ACCOUNT,
+  // User has selected one of the non default accounts and signed in with it.
+  SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT,
+  // The promo was shown to user.
+  SHOWN,
+  // Promo is not shown due to sign-in being disallowed either by an enterprise
+  // policy
+  // or by |Allow Chrome sign-in| toggle.
+  SUPPRESSED_SIGNIN_NOT_ALLOWED,
+  // User has added an account and signed in with this account.
+  // When this metric is recorded, we won't record
+  // SIGNED_IN_WITH_DEFAULT_ACCOUNT or
+  // SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT.
+  SIGNED_IN_WITH_ADDED_ACCOUNT,
+  // User has dismissed the promo by tapping on the scrim above the bottom
+  // sheet.
+  DISMISSED_SCRIM,
+  // User has dismissed the promo by swiping down the bottom sheet.
+  DISMISSED_SWIPE_DOWN,
+  // User has dismissed the promo by other means.
+  DISMISSED_OTHER,
+  // The auth error screen was shown to the user.
+  AUTH_ERROR_SHOWN,
+  // The generic error screen was shown to the user.
+  GENERIC_ERROR_SHOWN,
+  // User has dismissed the promo by tapping on the dismissal button in the
+  // bottom sheet.
+  DISMISSED_BUTTON,
+  // User has completed the account addition flow triggered from the bottom
+  // sheet.
+  ADD_ACCOUNT_COMPLETED,
+
+  MAX,
+};
+#endif  // defined(OS_ANDROID)
+
 // Enum values which enumerates all reasons to start sign in process.
 // A Java counterpart will be generated for this enum.
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.signin.metrics
diff --git a/components/signin/public/base/signin_pref_names.cc b/components/signin/public/base/signin_pref_names.cc
index 4b79d6de..3860caf 100644
--- a/components/signin/public/base/signin_pref_names.cc
+++ b/components/signin/public/base/signin_pref_names.cc
@@ -92,16 +92,6 @@
 // True if the token service has been prepared for Dice migration.
 const char kTokenServiceDiceCompatible[] = "token_service.dice_compatible";
 
-// Boolean which stores if the ProfileOAuth2TokenService should ignore secondary
-// accounts.
-const char kTokenServiceExcludeAllSecondaryAccounts[] =
-    "token_service.exclude_all_secondary_accounts";
-
-// List that identifies the account id that should be ignored by the token
-// service.
-const char kTokenServiceExcludedSecondaryAccounts[] =
-    "token_service.excluded_secondary_accounts";
-
 // Contains last |ListAccounts| data which corresponds to Gaia cookies.
 const char kGaiaCookieLastListAccountsData[] =
     "gaia_cookie.last_list_accounts_data";
diff --git a/components/signin/public/base/signin_pref_names.h b/components/signin/public/base/signin_pref_names.h
index 849a94e..59015f7 100644
--- a/components/signin/public/base/signin_pref_names.h
+++ b/components/signin/public/base/signin_pref_names.h
@@ -29,8 +29,6 @@
 extern const char kSignedInWithCredentialProvider[];
 extern const char kSigninAllowed[];
 extern const char kTokenServiceDiceCompatible[];
-extern const char kTokenServiceExcludeAllSecondaryAccounts[];
-extern const char kTokenServiceExcludedSecondaryAccounts[];
 extern const char kGaiaCookieLastListAccountsData[];
 
 }  // namespace prefs
diff --git a/components/storage_monitor/BUILD.gn b/components/storage_monitor/BUILD.gn
index 33bcb82..28c1453f 100644
--- a/components/storage_monitor/BUILD.gn
+++ b/components/storage_monitor/BUILD.gn
@@ -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/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 
 static_library("storage_monitor") {
@@ -21,6 +22,7 @@
 
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//content/public/browser",
     "//mojo/public/cpp/bindings",
     "//services/service_manager/public/cpp",
@@ -50,7 +52,7 @@
       "Foundation.framework",
       "ImageCaptureCore.framework",
     ]
-  } else if (is_chromeos) {
+  } else if (is_chromeos_ash) {
     # For Chrome OS, |is_linux| is also true. Put this in an else-if block above
     # the |is_linux| else-if block, so they do not clash.
     sources += [
@@ -68,7 +70,7 @@
       ]
       deps += [ "//services/device/public/mojom" ]
     }
-  } else if (is_linux) {
+  } else if (is_linux || is_chromeos_lacros) {
     if (use_udev) {
       sources += [
         "mtab_watcher_linux.cc",
@@ -111,13 +113,15 @@
     "//content/public/browser",
   ]
 
-  if (is_chromeos) {
+  deps = [ "//build:chromeos_buildflags" ]
+
+  if (is_chromeos_ash) {
     sources += [
       "test_media_transfer_protocol_manager_chromeos.cc",
       "test_media_transfer_protocol_manager_chromeos.h",
     ]
     if (use_dbus) {
-      deps = [ "//services/device/public/mojom" ]
+      deps += [ "//services/device/public/mojom" ]
     }
   }
 
@@ -130,7 +134,7 @@
       "test_volume_mount_watcher_win.cc",
       "test_volume_mount_watcher_win.h",
     ]
-    deps = [ "//testing/gtest" ]
+    deps += [ "//testing/gtest" ]
   }
 }
 
@@ -161,7 +165,7 @@
   }
 
   if (use_dbus) {
-    if (is_chromeos) {
+    if (is_chromeos_ash) {
       deps += [
         "//services/device/public/mojom",
         "//testing/gmock",
@@ -170,11 +174,11 @@
         "mtp_manager_client_chromeos_unittest.cc",
         "storage_monitor_chromeos_unittest.cc",
       ]
-    } else if (is_linux) {
+    } else if (is_linux || is_chromeos_lacros) {
       sources += [ "storage_monitor_linux_unittest.cc" ]
     }
   }
-  if (is_chromeos) {
+  if (is_chromeos_ash) {
     deps += [ "//chromeos/disks:test_support" ]
   }
 }
diff --git a/components/storage_monitor/mtab_watcher_linux.h b/components/storage_monitor/mtab_watcher_linux.h
index bd7ef28..2f048d3e 100644
--- a/components/storage_monitor/mtab_watcher_linux.h
+++ b/components/storage_monitor/mtab_watcher_linux.h
@@ -5,7 +5,9 @@
 #ifndef COMPONENTS_STORAGE_MONITOR_MTAB_WATCHER_LINUX_H_
 #define COMPONENTS_STORAGE_MONITOR_MTAB_WATCHER_LINUX_H_
 
-#if defined(OS_CHROMEOS)
+#include "build/chromeos_buildflags.h"
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #error "ChromeOS does not use MtabWatcherLinux."
 #endif
 
diff --git a/components/storage_monitor/storage_monitor.h b/components/storage_monitor/storage_monitor.h
index 8200c65..28a3ef3 100644
--- a/components/storage_monitor/storage_monitor.h
+++ b/components/storage_monitor/storage_monitor.h
@@ -17,9 +17,10 @@
 #include "base/strings/string16.h"
 #include "base/synchronization/lock.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/storage_monitor/storage_info.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "services/device/public/mojom/mtp_manager.mojom-forward.h"
 #endif
 
@@ -120,7 +121,7 @@
       base::string16* storage_object_id) const = 0;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   virtual device::mojom::MtpManager* media_transfer_protocol_manager() = 0;
 #endif
 
diff --git a/components/storage_monitor/storage_monitor_chromeos.h b/components/storage_monitor/storage_monitor_chromeos.h
index 93049a4..482337e 100644
--- a/components/storage_monitor/storage_monitor_chromeos.h
+++ b/components/storage_monitor/storage_monitor_chromeos.h
@@ -9,7 +9,9 @@
 #ifndef COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_CHROMEOS_H_
 #define COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_CHROMEOS_H_
 
-#if !defined(OS_CHROMEOS)
+#include "build/chromeos_buildflags.h"
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 #error "Should only be used on ChromeOS."
 #endif
 
diff --git a/components/storage_monitor/storage_monitor_linux.h b/components/storage_monitor/storage_monitor_linux.h
index 02ac626..1e91e62e 100644
--- a/components/storage_monitor/storage_monitor_linux.h
+++ b/components/storage_monitor/storage_monitor_linux.h
@@ -10,7 +10,9 @@
 #ifndef COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_LINUX_H_
 #define COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_LINUX_H_
 
-#if defined(OS_CHROMEOS)
+#include "build/chromeos_buildflags.h"
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #error "Use the ChromeOS-specific implementation instead."
 #endif
 
diff --git a/components/storage_monitor/test_storage_monitor.cc b/components/storage_monitor/test_storage_monitor.cc
index 1a03b2d..5b9c855 100644
--- a/components/storage_monitor/test_storage_monitor.cc
+++ b/components/storage_monitor/test_storage_monitor.cc
@@ -10,16 +10,17 @@
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/storage_monitor/storage_info.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h"
 #endif
 
 namespace storage_monitor {
 
 TestStorageMonitor::TestStorageMonitor() : init_called_(false) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   auto* fake_mtp_manager =
       TestMediaTransferProtocolManagerChromeOS::GetFakeMtpManager();
   fake_mtp_manager->AddReceiver(
@@ -115,7 +116,7 @@
 }
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 device::mojom::MtpManager*
 TestStorageMonitor::media_transfer_protocol_manager() {
   return media_transfer_protocol_manager_.get();
diff --git a/components/storage_monitor/test_storage_monitor.h b/components/storage_monitor/test_storage_monitor.h
index d68b412..fb2a8396 100644
--- a/components/storage_monitor/test_storage_monitor.h
+++ b/components/storage_monitor/test_storage_monitor.h
@@ -10,9 +10,10 @@
 #include <vector>
 
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/storage_monitor/storage_monitor.h"
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/mtp_manager.mojom.h"
 #endif
@@ -52,7 +53,7 @@
       base::string16* storage_object_id) const override;
 #endif
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   device::mojom::MtpManager* media_transfer_protocol_manager() override;
 #endif
 
@@ -78,7 +79,7 @@
   // Paths considered for testing purposes to be on removable storage.
   std::vector<base::FilePath> removable_paths_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   mojo::Remote<device::mojom::MtpManager> media_transfer_protocol_manager_;
 #endif
 };
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index 92a9384..79329f6 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -646,8 +646,6 @@
 
   ModelTypeSet types_to_associate;
   if (group == READY_AT_CONFIG) {
-    association_types_queue_.front().ready_association_request_time =
-        base::Time::Now();
     types_to_associate = association_types_queue_.front().ready_types;
   } else {
     DCHECK_EQ(UNREADY_AT_CONFIG, group);
@@ -655,8 +653,6 @@
     // downloading.
     if (association_types_queue_.front().download_ready_time.is_null())
       return;
-    association_types_queue_.front().full_association_request_time =
-        base::Time::Now();
     // We request the full set of types here for completeness sake. All types
     // within the READY_AT_CONFIG set will already be started and should be
     // no-ops.
@@ -737,13 +733,6 @@
       configuration_stats_[type].download_time =
           info.download_ready_time - info.download_start_time;
     }
-    if (info.ready_types.Has(type)) {
-      configuration_stats_[type].association_wait_time_for_high_priority =
-          info.ready_association_request_time - info.download_start_time;
-    } else {
-      configuration_stats_[type].association_wait_time_for_high_priority =
-          info.full_association_request_time - info.download_ready_time;
-    }
     configuration_stats_[type].high_priority_types_configured_before =
         info.high_priority_types_before;
     configuration_stats_[type].same_priority_types_configured_before =
diff --git a/components/sync/driver/data_type_manager_impl.h b/components/sync/driver/data_type_manager_impl.h
index 9decce50..ef9ff21 100644
--- a/components/sync/driver/data_type_manager_impl.h
+++ b/components/sync/driver/data_type_manager_impl.h
@@ -241,11 +241,6 @@
     base::Time download_start_time;
     // Time at which |types| finished downloading.
     base::Time download_ready_time;
-    // Time at which the association for |read_types| began.
-    base::Time ready_association_request_time;
-    // Time at which the association for |types| began (not relevant to
-    // |ready_types|.
-    base::Time full_association_request_time;
     // The set of types that are higher priority (and were therefore blocking)
     // the association of |types|.
     ModelTypeSet high_priority_types_before;
diff --git a/components/sync/engine/data_type_debug_info_listener.h b/components/sync/engine/data_type_debug_info_listener.h
index 9c12bb9..cad7f21 100644
--- a/components/sync/engine/data_type_debug_info_listener.h
+++ b/components/sync/engine/data_type_debug_info_listener.h
@@ -26,10 +26,6 @@
   // Time spent on downloading data for first-sync data types.
   base::TimeDelta download_time;
 
-  // TODO(crbug.com/1102837): The concept of "association" doesn't exist
-  // anymore, and this is effectively always zero now. Get rid of it.
-  base::TimeDelta association_wait_time_for_high_priority;
-
   // Types configured before this type.
   ModelTypeSet high_priority_types_configured_before;
   ModelTypeSet same_priority_types_configured_before;
diff --git a/components/sync/engine_impl/debug_info_event_listener.cc b/components/sync/engine_impl/debug_info_event_listener.cc
index dd9e6cf..290d8110 100644
--- a/components/sync/engine_impl/debug_info_event_listener.cc
+++ b/components/sync/engine_impl/debug_info_event_listener.cc
@@ -180,9 +180,6 @@
         configuration_stats[i].download_wait_time.InMicroseconds());
     datatype_stats->set_download_time_us(
         configuration_stats[i].download_time.InMicroseconds());
-    datatype_stats->set_association_wait_time_for_high_priority_us(
-        configuration_stats[i]
-            .association_wait_time_for_high_priority.InMicroseconds());
 
     for (ModelType type :
          configuration_stats[i].high_priority_types_configured_before) {
diff --git a/components/sync/protocol/client_debug_info.proto b/components/sync/protocol/client_debug_info.proto
index 2b9d801..472c22380 100644
--- a/components/sync/protocol/client_debug_info.proto
+++ b/components/sync/protocol/client_debug_info.proto
@@ -78,12 +78,6 @@
   //       |data_type_id| instead of just one data type.
   optional int64 download_time_us = 13;
 
-  // Waiting time for higher priority types to finish association. This
-  // measures the time between finishing downloading data to requesting
-  // association manager to associate this batch of types. High priority types
-  // have near zero waiting time.
-  optional int64 association_wait_time_for_high_priority_us = 16;
-
   // Higher priority type that's configured before this type.
   repeated int32 high_priority_type_configured_before = 18;
 
@@ -114,6 +108,8 @@
   reserved 12;
   reserved "association_wait_time_for_same_priority_us";
   reserved 14;
+  reserved "association_wait_time_for_high_priority_us";
+  reserved 16;
   reserved "association_time_us";
   reserved 17;
   reserved "local_version_pre_association";
diff --git a/components/sync/protocol/proto_value_conversions.cc b/components/sync/protocol/proto_value_conversions.cc
index bfd453e..7316c0c 100644
--- a/components/sync/protocol/proto_value_conversions.cc
+++ b/components/sync/protocol/proto_value_conversions.cc
@@ -188,22 +188,6 @@
     // Obsolete, don't visit
   }
 
-  // PasswordSpecifics
-  std::unique_ptr<base::DictionaryValue> ToValue(
-      const sync_pb::PasswordSpecifics& proto) const {
-    auto value = ToValueImpl(proto);
-    value->Remove("client_only_encrypted_data", nullptr);
-    return value;
-  }
-
-  // PasswordSpecificsData
-  std::unique_ptr<base::DictionaryValue> ToValue(
-      const sync_pb::PasswordSpecificsData& proto) const {
-    auto value = ToValueImpl(proto);
-    value->SetString("password_value", "<redacted>");
-    return value;
-  }
-
   // AutofillWalletSpecifics
   std::unique_ptr<base::DictionaryValue> ToValue(
       const sync_pb::AutofillWalletSpecifics& proto) const {
diff --git a/components/sync/protocol/proto_value_conversions_unittest.cc b/components/sync/protocol/proto_value_conversions_unittest.cc
index 2b3a382..bc68bb2 100644
--- a/components/sync/protocol/proto_value_conversions_unittest.cc
+++ b/components/sync/protocol/proto_value_conversions_unittest.cc
@@ -104,24 +104,6 @@
 DEFINE_SPECIFICS_TO_VALUE_TEST(web_app)
 DEFINE_SPECIFICS_TO_VALUE_TEST(wifi_configuration)
 
-TEST(ProtoValueConversionsTest, PasswordSpecifics) {
-  sync_pb::PasswordSpecifics specifics;
-  specifics.mutable_client_only_encrypted_data();
-  auto value = PasswordSpecificsToValue(specifics);
-  EXPECT_FALSE(value->Get("client_only_encrypted_data", nullptr));
-}
-
-TEST(ProtoValueConversionsTest, PasswordSpecificsData) {
-  sync_pb::PasswordSpecificsData specifics;
-  specifics.set_password_value("secret");
-  std::unique_ptr<base::DictionaryValue> value(
-      PasswordSpecificsDataToValue(specifics));
-  EXPECT_FALSE(value->empty());
-  std::string password_value;
-  EXPECT_TRUE(value->GetString("password_value", &password_value));
-  EXPECT_EQ("<redacted>", password_value);
-}
-
 TEST(ProtoValueConversionsTest, AppSettingSpecificsToValue) {
   sync_pb::AppNotificationSettings specifics;
   specifics.set_disabled(true);
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index e1c30126..ac2f67b 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -347,7 +347,6 @@
   VISIT(data_type_id);
   VISIT(download_wait_time_us);
   VISIT(download_time_us);
-  VISIT(association_wait_time_for_high_priority_us);
   VISIT_REP(high_priority_type_configured_before);
   VISIT_REP(same_priority_type_configured_before);
 }
diff --git a/components/sync_device_info/device_info_sync_bridge.cc b/components/sync_device_info/device_info_sync_bridge.cc
index a576dbf..de1454a 100644
--- a/components/sync_device_info/device_info_sync_bridge.cc
+++ b/components/sync_device_info/device_info_sync_bridge.cc
@@ -558,7 +558,8 @@
   // dropped. In that case, MergeSyncData() will eventually follow.
   if (!change_processor()->IsTrackingMetadata()) {
     // In this scenario, ApplyStopSyncChanges() should have been exercised.
-    DCHECK(local_cache_guid_.empty());
+    // However OnSyncStarting() must have been called during ModelReadyToSync().
+    DCHECK(!local_cache_guid_.empty());
     DCHECK(all_data_.empty());
     return;
   }
diff --git a/components/sync_device_info/device_info_sync_bridge_unittest.cc b/components/sync_device_info/device_info_sync_bridge_unittest.cc
index a38f2095..028b64c 100644
--- a/components/sync_device_info/device_info_sync_bridge_unittest.cc
+++ b/components/sync_device_info/device_info_sync_bridge_unittest.cc
@@ -42,6 +42,7 @@
 using testing::_;
 using testing::AllOf;
 using testing::IsEmpty;
+using testing::IsNull;
 using testing::Matcher;
 using testing::NotNull;
 using testing::Pair;
@@ -1312,6 +1313,110 @@
                              EntityChangeList());
 }
 
+// This test mimics the case when OnSyncStarting is called before the metadata
+// is loaded from the storage.
+TEST_F(DeviceInfoSyncBridgeTest,
+       ShouldCleanUpMetadataOnInvalidCacheGuidAfterReadMetadata) {
+  const std::string kInvalidCacheGuid = "invalid_cache_guid";
+
+  DeviceInfoSpecifics specifics = CreateLocalDeviceSpecifics();
+  specifics.set_cache_guid(kInvalidCacheGuid);
+
+  ModelTypeState model_type_state = StateWithEncryption("ekn");
+  model_type_state.set_cache_guid(kInvalidCacheGuid);
+
+  WriteToStoreWithMetadata({specifics}, model_type_state);
+
+  InitializeBridge();
+  ASSERT_FALSE(
+      bridge()->IsRecentLocalCacheGuid(CacheGuidForSuffix(kLocalSuffix)));
+  ASSERT_FALSE(bridge()->IsRecentLocalCacheGuid(kInvalidCacheGuid));
+
+  EXPECT_CALL(*processor(), IsTrackingMetadata).WillRepeatedly(Return(false));
+  bridge()->OnSyncStarting(TestDataTypeActivationRequest(SyncMode::kFull));
+
+  EXPECT_TRUE(
+      bridge()->IsRecentLocalCacheGuid(CacheGuidForSuffix(kLocalSuffix)));
+  EXPECT_FALSE(bridge()->IsRecentLocalCacheGuid(kInvalidCacheGuid));
+  EXPECT_THAT(bridge()->GetLocalDeviceInfoProvider()->GetLocalDeviceInfo(),
+              IsNull());
+
+  base::RunLoop run_loop;
+  EXPECT_CALL(*processor(), ModelReadyToSync)
+      .WillOnce([this, &run_loop](std::unique_ptr<MetadataBatch> batch) {
+        // Mimic CTBMTP behaviour on invalid cache GUID.
+        std::unique_ptr<MetadataChangeList> change_list =
+            bridge()->CreateMetadataChangeList();
+        change_list->ClearMetadata(CacheGuidForSuffix(kLocalSuffix));
+        change_list->ClearModelTypeState();
+        bridge()->ApplyStopSyncChanges(std::move(change_list));
+
+        bridge()->OnSyncStarting(
+            TestDataTypeActivationRequest(SyncMode::kFull));
+
+        run_loop.Quit();
+      });
+  run_loop.Run();
+
+  EXPECT_TRUE(
+      bridge()->IsRecentLocalCacheGuid(CacheGuidForSuffix(kLocalSuffix)));
+  EXPECT_FALSE(bridge()->IsRecentLocalCacheGuid(kInvalidCacheGuid));
+  EXPECT_THAT(bridge()->GetLocalDeviceInfoProvider()->GetLocalDeviceInfo(),
+              IsNull());
+}
+
+// This test mimics the opposite case when OnSyncStarting is called after the
+// metadata is loaded from the storage.
+TEST_F(DeviceInfoSyncBridgeTest,
+       ShouldCleanUpMetadataOnInvalidCacheGuidAfterSyncStarting) {
+  const std::string kInvalidCacheGuid = "invalid_cache_guid";
+
+  DeviceInfoSpecifics specifics = CreateLocalDeviceSpecifics();
+  specifics.set_cache_guid(kInvalidCacheGuid);
+
+  ModelTypeState model_type_state = StateWithEncryption("ekn");
+  model_type_state.set_cache_guid(kInvalidCacheGuid);
+
+  WriteToStoreWithMetadata({specifics}, model_type_state);
+  InitializeBridge();
+  ASSERT_FALSE(
+      bridge()->IsRecentLocalCacheGuid(CacheGuidForSuffix(kLocalSuffix)));
+  ASSERT_FALSE(bridge()->IsRecentLocalCacheGuid(kInvalidCacheGuid));
+
+  // Wait until the metadata is loaded.
+  base::RunLoop run_loop;
+  EXPECT_CALL(*processor(), IsTrackingMetadata).WillOnce(Return(true));
+  EXPECT_CALL(*processor(), ModelReadyToSync)
+      .WillOnce([&run_loop](std::unique_ptr<MetadataBatch> batch) {
+        run_loop.Quit();
+      });
+  run_loop.Run();
+
+  EXPECT_FALSE(
+      bridge()->IsRecentLocalCacheGuid(CacheGuidForSuffix(kLocalSuffix)));
+  EXPECT_TRUE(bridge()->IsRecentLocalCacheGuid(kInvalidCacheGuid));
+  EXPECT_THAT(bridge()->GetLocalDeviceInfoProvider()->GetLocalDeviceInfo(),
+              NotNull());
+
+  // Mimic CTBMTP behaviour on invalid cache GUID.
+  EXPECT_CALL(*processor(), IsTrackingMetadata).WillRepeatedly(Return(false));
+  bridge()->OnSyncStarting(TestDataTypeActivationRequest(SyncMode::kFull));
+
+  std::unique_ptr<MetadataChangeList> change_list =
+      bridge()->CreateMetadataChangeList();
+  change_list->ClearMetadata(CacheGuidForSuffix(kLocalSuffix));
+  change_list->ClearModelTypeState();
+  bridge()->ApplyStopSyncChanges(std::move(change_list));
+
+  bridge()->OnSyncStarting(TestDataTypeActivationRequest(SyncMode::kFull));
+
+  // Check that the cache GUID is in recent devices.
+  EXPECT_TRUE(
+      bridge()->IsRecentLocalCacheGuid(CacheGuidForSuffix(kLocalSuffix)));
+  EXPECT_THAT(bridge()->GetLocalDeviceInfoProvider()->GetLocalDeviceInfo(),
+              IsNull());
+}
+
 }  // namespace
 
 }  // namespace syncer
diff --git a/components/translate/core/browser/BUILD.gn b/components/translate/core/browser/BUILD.gn
index a9c4a78..bd5a4476 100644
--- a/components/translate/core/browser/BUILD.gn
+++ b/components/translate/core/browser/BUILD.gn
@@ -51,6 +51,7 @@
     "//base",
     "//base:i18n",
     "//base/util/values:values_util",
+    "//build:chromeos_buildflags",
     "//components/assist_ranker",
     "//components/assist_ranker/proto",
     "//components/keyed_service/core",
@@ -113,6 +114,7 @@
     ":browser",
     ":test_support",
     "//base",
+    "//build:chromeos_buildflags",
     "//components/assist_ranker",
     "//components/assist_ranker/proto",
     "//components/infobars/core",
@@ -149,6 +151,7 @@
   ]
   deps = [
     "//base",
+    "//build:chromeos_buildflags",
     "//components/infobars/core",
     "//components/language/core/browser",
     "//components/sync_preferences",
diff --git a/components/translate/core/browser/mock_translate_client.cc b/components/translate/core/browser/mock_translate_client.cc
index 031ba04..f92a29e 100644
--- a/components/translate/core/browser/mock_translate_client.cc
+++ b/components/translate/core/browser/mock_translate_client.cc
@@ -4,6 +4,7 @@
 
 #include <memory>
 
+#include "build/chromeos_buildflags.h"
 #include "components/translate/core/browser/mock_translate_client.h"
 #include "components/translate/core/browser/translate_prefs.h"
 
@@ -11,7 +12,7 @@
 
 namespace testing {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const char* preferred_languages_prefs = "settings.language.preferred_languages";
 #else
 const char* preferred_languages_prefs = nullptr;
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index e940915..b7d06ee 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/infobars/core/infobar.h"
 #include "components/language/core/browser/language_model.h"
 #include "components/language/core/browser/language_prefs.h"
@@ -116,7 +117,7 @@
   ProfilePrefRegistration(sync_preferences::TestingPrefServiceSyncable* prefs) {
     language::LanguagePrefs::RegisterProfilePrefs(prefs->registry());
     prefs->SetString(accept_languages_prefs, std::string());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     prefs->SetString(preferred_languages_prefs, std::string());
 #endif
     TranslatePrefs::RegisterProfilePrefs(prefs->registry());
diff --git a/components/translate/core/browser/translate_prefs.cc b/components/translate/core/browser/translate_prefs.cc
index 4e7c9a5..63cf2e3 100644
--- a/components/translate/core/browser/translate_prefs.cc
+++ b/components/translate/core/browser/translate_prefs.cc
@@ -22,6 +22,7 @@
 #include "base/util/values/values_util.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/language/core/browser/language_prefs.h"
 #include "components/language/core/common/language_experiments.h"
 #include "components/language/core/common/language_util.h"
@@ -195,7 +196,7 @@
     : accept_languages_pref_(accept_languages_pref),
       prefs_(user_prefs),
       language_prefs_(std::make_unique<language::LanguagePrefs>(user_prefs)) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   preferred_languages_pref_ = preferred_languages_pref;
 #else
   DCHECK(!preferred_languages_pref);
@@ -737,7 +738,7 @@
   DCHECK(languages);
   DCHECK(languages->empty());
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   const std::string& key = preferred_languages_pref_;
 #else
   const std::string& key = accept_languages_pref_;
@@ -751,7 +752,7 @@
     const std::vector<std::string>& languages) {
   std::string languages_str = base::JoinString(languages, ",");
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   prefs_->SetString(preferred_languages_pref_, languages_str);
 #endif
 
diff --git a/components/translate/core/browser/translate_prefs.h b/components/translate/core/browser/translate_prefs.h
index c9ab155..a17058eb 100644
--- a/components/translate/core/browser/translate_prefs.h
+++ b/components/translate/core/browser/translate_prefs.h
@@ -17,6 +17,7 @@
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "url/gurl.h"
 
@@ -367,7 +368,7 @@
 
   // Path to the preference storing the accept languages.
   const std::string accept_languages_pref_;
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Path to the preference storing the preferred languages.
   // Only used on ChromeOS.
   std::string preferred_languages_pref_;
diff --git a/components/translate/core/browser/translate_prefs_unittest.cc b/components/translate/core/browser/translate_prefs_unittest.cc
index d7866d1..421b379 100644
--- a/components/translate/core/browser/translate_prefs_unittest.cc
+++ b/components/translate/core/browser/translate_prefs_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/test/test_timeouts.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/language/core/browser/language_prefs.h"
 #include "components/language/core/common/language_experiments.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -36,7 +37,7 @@
 
 const char kTestLanguage[] = "en";
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 const char kPreferredLanguagesPref[] = "settings.language.preferred_languages";
 #else
 const char* kPreferredLanguagesPref = nullptr;
@@ -77,7 +78,7 @@
 
   void SetUp() override {
     prefs_.SetString(kAcceptLanguagesPref, std::string());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     prefs_.SetString(kPreferredLanguagesPref, std::string());
 #endif
     prefs_.registry()->RegisterBooleanPref(
@@ -104,7 +105,7 @@
     } else {
       EXPECT_EQ(expected, prefs_.GetString(kAcceptLanguagesPref));
     }
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     if (expected_chromeos.empty()) {
       EXPECT_TRUE(prefs_.GetString(kPreferredLanguagesPref).empty());
     } else {
diff --git a/components/translate/core/browser/translate_ui_delegate_unittest.cc b/components/translate/core/browser/translate_ui_delegate_unittest.cc
index 0ab6792..8fafd8f6 100644
--- a/components/translate/core/browser/translate_ui_delegate_unittest.cc
+++ b/components/translate/core/browser/translate_ui_delegate_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/infobars/core/infobar.h"
 #include "components/language/core/browser/language_model.h"
 #include "components/language/core/browser/language_prefs.h"
@@ -54,7 +55,7 @@
         std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
     language::LanguagePrefs::RegisterProfilePrefs(pref_service_->registry());
     pref_service_->SetString(language::prefs::kAcceptLanguages, std::string());
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     pref_service_->SetString(language::prefs::kPreferredLanguages,
                              std::string());
 #endif
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn
index 4aab9385..7e370ab 100644
--- a/components/variations/BUILD.gn
+++ b/components/variations/BUILD.gn
@@ -111,6 +111,7 @@
     ":variations_mojom",
     "proto",
     "//base",
+    "//build:chromeos_buildflags",
     "//components/crash/core/common:crash_key",
     "//components/prefs",
     "//crypto",
diff --git a/components/variations/client_filterable_state.cc b/components/variations/client_filterable_state.cc
index 42c57b4c..7aa50e147 100644
--- a/components/variations/client_filterable_state.cc
+++ b/components/variations/client_filterable_state.cc
@@ -8,6 +8,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 
 namespace variations {
 
@@ -19,13 +20,14 @@
   return Study::PLATFORM_IOS;
 #elif defined(OS_APPLE)
   return Study::PLATFORM_MAC;
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   return Study::PLATFORM_CHROMEOS;
 #elif defined(OS_ANDROID)
   return Study::PLATFORM_ANDROID;
 #elif defined(OS_FUCHSIA)
   return Study::PLATFORM_FUCHSIA;
-#elif defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
+#elif (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
+    defined(OS_BSD) || defined(OS_SOLARIS)
   // Default BSD and SOLARIS to Linux to not break those builds, although these
   // platforms are not officially supported by Chrome.
   return Study::PLATFORM_LINUX;
diff --git a/components/variations/proto/BUILD.gn b/components/variations/proto/BUILD.gn
index c0ad4c24..8f8c395 100644
--- a/components/variations/proto/BUILD.gn
+++ b/components/variations/proto/BUILD.gn
@@ -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/chromeos/ui_mode.gni")
 import("//third_party/protobuf/proto_library.gni")
 
 if (is_android) {
@@ -33,7 +34,7 @@
 # Some of the Windows builders do not support Java, which is a required
 # dependency for this build target. This target is only built manually, so it's
 # fine to limit it to Linux.
-if (is_linux || is_mac) {
+if (is_linux || is_chromeos_lacros || is_mac) {
   group("devtools") {
     deps = [ "devtools" ]
   }
diff --git a/components/variations/proto/devtools/BUILD.gn b/components/variations/proto/devtools/BUILD.gn
index b94fc18..1308c20a 100644
--- a/components/variations/proto/devtools/BUILD.gn
+++ b/components/variations/proto/devtools/BUILD.gn
@@ -2,13 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/closure_compiler/closure_args.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 
 # Some of the Windows builders do not support Java, which is a required
 # dependency for these build targets. These targets are only built manually, so
 # it's fine to limit them to Linux.
-if (is_linux || is_mac) {
+if (is_linux || is_chromeos_lacros || is_mac) {
   # Build this target to generate a small, self-contained utility for parsing a
   # serialized ClientVariations proto from the X-Client-Data header.
   #
diff --git a/components/variations/service/BUILD.gn b/components/variations/service/BUILD.gn
index fb0dc78..963203db 100644
--- a/components/variations/service/BUILD.gn
+++ b/components/variations/service/BUILD.gn
@@ -40,6 +40,7 @@
     ":buildflags",
     "//base",
     "//build:branding_buildflags",
+    "//build:chromeos_buildflags",
     "//components/encrypted_messages",
     "//components/language/core/browser",
     "//components/metrics",
diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc
index 25e5661..3847513 100644
--- a/components/variations/service/variations_field_trial_creator.cc
+++ b/components/variations/service/variations_field_trial_creator.cc
@@ -26,6 +26,7 @@
 #include "base/trace_event/trace_event.h"
 #include "base/version.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/language/core/browser/locale_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/variations/field_trial_config/field_trial_util.h"
@@ -240,7 +241,7 @@
   state->form_factor = GetCurrentFormFactor();
   state->platform = GetPlatform();
   // TODO(crbug/1111131): Expand to other platforms.
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_ANDROID)
   state->hardware_class = base::SysInfo::HardwareModelName();
 #endif
 #if defined(OS_ANDROID)
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc
index 9c77226..ea7ba04 100644
--- a/components/variations/service/variations_service.cc
+++ b/components/variations/service/variations_service.cc
@@ -32,6 +32,7 @@
 #include "base/version.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "components/encrypted_messages/encrypted_message.pb.h"
 #include "components/encrypted_messages/message_encrypter.h"
 #include "components/metrics/clean_exit_beacon.h"
@@ -105,13 +106,14 @@
   return "ios";
 #elif defined(OS_APPLE)
   return "mac";
-#elif defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
   return "chromeos";
 #elif defined(OS_ANDROID)
   return "android";
 #elif defined(OS_FUCHSIA)
   return "fuchsia";
-#elif defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
+#elif (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
+    defined(OS_BSD) || defined(OS_SOLARIS)
   // Default BSD and SOLARIS to Linux to not break those builds, although these
   // platforms are not officially supported by Chrome.
   return "linux";
@@ -262,7 +264,7 @@
 
 }  // namespace
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // This is a utility which syncs the policy-managed value of
 // |prefs::kDeviceVariationsRestrictionsByPolicy| into
 // |prefs::kVariationsRestrictionsByPolicy|.
@@ -339,7 +341,7 @@
   base::WeakPtrFactory<DeviceVariationsRestrictionByPolicyApplicator>
       weak_ptr_factory_{this};
 };
-#endif  // defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 VariationsService::VariationsService(
     std::unique_ptr<VariationsServiceClient> client,
@@ -368,7 +370,7 @@
   DCHECK(client_);
   DCHECK(resource_request_allowed_notifier_);
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   device_variations_restrictions_by_policy_applicator_ =
       std::make_unique<DeviceVariationsRestrictionByPolicyApplicator>(
           policy_pref_service_);
@@ -495,7 +497,7 @@
 }
 
 void VariationsService::EnsureLocaleEquals(const std::string& locale) {
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Chrome OS may switch language on the fly.
   DCHECK_EQ(locale, field_trial_creator_.application_locale());
 #else
diff --git a/components/variations/service/variations_service.h b/components/variations/service/variations_service.h
index af944964..66250dc 100644
--- a/components/variations/service/variations_service.h
+++ b/components/variations/service/variations_service.h
@@ -16,6 +16,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
+#include "build/chromeos_buildflags.h"
 #include "components/variations/client_filterable_state.h"
 #include "components/variations/service/safe_seed_manager.h"
 #include "components/variations/service/ui_string_overrider.h"
@@ -56,7 +57,7 @@
 
 namespace variations {
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 class DeviceVariationsRestrictionByPolicyApplicator;
 #endif
 
@@ -431,7 +432,7 @@
   // server url.
   std::string osname_server_param_override_;
 
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<DeviceVariationsRestrictionByPolicyApplicator>
       device_variations_restrictions_by_policy_applicator_;
 #endif
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index ada3a3a..aa611448 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -241,6 +241,18 @@
 #endif
 }
 
+void EnablePCScanForMallocPartitionsInBrowserProcessIfNeeded() {
+  static const base::Feature kPartitionAllocPCScanBrowserOnly{
+      "PartitionAllocPCScanBrowserOnly", base::FEATURE_DISABLED_BY_DEFAULT};
+  (void)kPartitionAllocPCScanBrowserOnly;
+#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
+  CHECK(base::FeatureList::GetInstance());
+  if (base::FeatureList::IsEnabled(kPartitionAllocPCScanBrowserOnly)) {
+    base::allocator::EnablePCScan();
+  }
+#endif
+}
+
 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
 pid_t LaunchZygoteHelper(base::CommandLine* cmd_line,
                          base::ScopedFD* control_fd) {
@@ -517,6 +529,7 @@
   int exit_code = delegate->RunProcess("", main_function_params);
   if (exit_code >= 0)
     return exit_code;
+  EnablePCScanForMallocPartitionsInBrowserProcessIfNeeded();
   return BrowserMain(main_function_params);
 }
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index fc624473..cc7fbcf 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1237,8 +1237,6 @@
     "quota/quota_context.h",
     "quota/quota_manager_host.cc",
     "quota/quota_manager_host.h",
-    "renderer_host/agent_metrics_collector.cc",
-    "renderer_host/agent_metrics_collector.h",
     "renderer_host/agent_scheduling_group_host.cc",
     "renderer_host/agent_scheduling_group_host.h",
     "renderer_host/ancestor_throttle.cc",
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index c52e259..4a4a631 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -259,8 +259,15 @@
   RunEventTest(FILE_PATH_LITERAL("aria-busy-changed.html"));
 }
 
-IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
-                       AccessibilityEventsAriaButtonExpand) {
+#if defined(OS_LINUX) && \
+    (defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER))
+#define DISABLED_ON_LINUX_TSAN_MSAN(name) DISABLED_##name
+#else
+#define DISABLED_ON_LINUX_TSAN_MSAN(name) name
+#endif
+IN_PROC_BROWSER_TEST_P(
+    DumpAccessibilityEventsTest,
+    DISABLED_ON_LINUX_TSAN_MSAN(AccessibilityEventsAriaButtonExpand)) {
   RunEventTest(FILE_PATH_LITERAL("aria-button-expand.html"));
 }
 
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index ac7e9af68..b39d68d9 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -3911,7 +3911,7 @@
 // Tests the case when the header was received before the page is frozen,
 // but parts of the response body is received when the page is frozen.
 IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithUnfreezableLoading,
-                       KeepFetchingBodyInCache) {
+                       PageWithDrainedDatapipeRequestsShouldBeEvicted) {
   net::test_server::ControllableHttpResponse fetch_response(
       embedded_test_server(), "/fetch");
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -3933,26 +3933,18 @@
   // Send response header and a piece of the body before navigating away.
   fetch_response.WaitForRequest();
   fetch_response.Send(net::HTTP_OK, "text/plain");
-  fetch_response.Send("bo");
+  fetch_response.Send("body");
 
   // 2) Navigate to B.
   EXPECT_TRUE(NavigateToURL(shell(), url_b));
 
-  EXPECT_TRUE(rfh_a->IsInBackForwardCache());
-  EXPECT_FALSE(delete_observer_rfh_a.deleted());
-
-  // Send the response body while A is in the back-forward cache.
-  fetch_response.Send("dy");
-  fetch_response.Done();
+  delete_observer_rfh_a.WaitUntilDeleted();
 
   // 3) Go back to A.
   web_contents()->GetController().GoBack();
   EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kRestored,
+  ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kNotRestored,
                 FROM_HERE);
-
-  // A should get the correct response body.
-  EXPECT_EQ("body", EvalJs(rfh_a, "fetch_response_promise"));
 }
 
 // Disabled on Android, since we have problems starting up the websocket test
diff --git a/content/browser/renderer_host/agent_metrics_collector.cc b/content/browser/renderer_host/agent_metrics_collector.cc
deleted file mode 100644
index a95aad2..0000000
--- a/content/browser/renderer_host/agent_metrics_collector.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/agent_metrics_collector.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
-#include "base/time/time.h"
-#include "content/public/browser/render_process_host.h"
-
-namespace content {
-
-namespace {
-
-const char kAgentsByTimeHistogram[] = "PerformanceManager.AgentsByTime";
-const char kAgentsUniqueByTimeHistogram[] =
-    "PerformanceManager.AgentsUniqueByTime";
-
-constexpr base::TimeDelta kReportingInterval = base::TimeDelta::FromMinutes(5);
-
-// This object is allocated statically and serves to combine and store all the
-// per-process counts.
-class Aggregator {
- public:
-  Aggregator() { time_last_reported_ = base::TimeTicks::Now(); }
-
-  void ComputeAndReport() {
-    int total = 0;
-    int unique = 0;
-    std::set<std::string> sites;
-    for (auto const& pair : process_to_agent_sites_) {
-      auto& sites_vector = pair.second;
-      total += sites_vector.size();
-      for (auto& agent : sites_vector) {
-        if (agent.empty()) {
-          // An empty string indicates non-tuple origins; don't consolidate
-          // those.
-          ++unique;
-          continue;
-        }
-        sites.insert(agent);
-      }
-    }
-
-    unique += sites.size();
-
-    // This computation and reporting is based on the one in:
-    // chrome/browser/performance_manager/observers/isolation_context_metrics.cc
-    base::TimeTicks now = base::TimeTicks::Now();
-    base::TimeDelta elapsed = now - time_last_reported_;
-
-    // Account for edge cases like hibernate/sleep. See
-    // GetSecondsSinceLastReportAndUpdate in isolation_context_metrics.cc. This
-    // might lose some data just before a sleep but that's probably ok.
-    if (elapsed >= 2 * kReportingInterval) {
-      time_last_reported_ = now;
-      return;
-    }
-
-    int seconds = static_cast<int>(std::round(elapsed.InSecondsF()));
-    if (seconds <= 0)
-      return;
-
-    // Note: renderers report their metrics by pushing sending them over every 5
-    // minutes so we don't need to setup our own timer here, we can just rely on
-    // those updates reaching here.
-
-    STATIC_HISTOGRAM_POINTER_BLOCK(
-        kAgentsByTimeHistogram, AddCount(total, seconds),
-        base::Histogram::FactoryGet(
-            kAgentsByTimeHistogram, 1, 100, 101,
-            base::HistogramBase::kUmaTargetedHistogramFlag));
-
-    STATIC_HISTOGRAM_POINTER_BLOCK(
-        kAgentsUniqueByTimeHistogram, AddCount(unique, seconds),
-        base::Histogram::FactoryGet(
-            kAgentsUniqueByTimeHistogram, 1, 100, 101,
-            base::HistogramBase::kUmaTargetedHistogramFlag));
-
-    time_last_reported_ = now;
-  }
-
-  void AddPerRendererData(int process_id,
-                          blink::mojom::AgentMetricsDataPtr data) {
-    ComputeAndReport();
-    process_to_agent_sites_[process_id] = std::move(data->agents);
-  }
-
-  void RemovePerRendererData(int process_id) {
-    auto itr = process_to_agent_sites_.find(process_id);
-    if (itr == process_to_agent_sites_.end())
-      return;
-
-    ComputeAndReport();
-    process_to_agent_sites_.erase(itr);
-  }
-
- private:
-  // A map from each renderer process' id to a collection of agent strings
-  // hosted in that renderer. The string will be the security origin's
-  // |protocol| + "://" + |registrable domain|. If the agent was opaque or
-  // otherwise not associated with a domain (e.g. file://) then it will be
-  // added as an empty string. These agents should not be coalesced.
-  using ProcessToAgentsMapType = std::map<int, std::vector<std::string>>;
-  ProcessToAgentsMapType process_to_agent_sites_;
-
-  base::TimeTicks time_last_reported_;
-};
-
-Aggregator& GetAggregator() {
-  static base::NoDestructor<Aggregator> a;
-  return *a;
-}
-
-}  // namespace
-
-AgentMetricsCollectorHost::AgentMetricsCollectorHost(
-    int id,
-    mojo::PendingReceiver<blink::mojom::AgentMetricsCollectorHost> receiver)
-    : process_id_(id), receiver_(this, std::move(receiver)) {}
-
-AgentMetricsCollectorHost::~AgentMetricsCollectorHost() {}
-
-void AgentMetricsCollectorHost::ReportRendererMetrics(
-    blink::mojom::AgentMetricsDataPtr data) {
-  GetAggregator().AddPerRendererData(process_id_, std::move(data));
-}
-
-void AgentMetricsCollectorHost::RemoveRendererData() {
-  GetAggregator().RemovePerRendererData(process_id_);
-}
-
-void AgentMetricsCollectorHost::RenderProcessExited(
-    RenderProcessHost* host,
-    const ChildProcessTerminationInfo& info) {
-  RemoveRendererData();
-  host->RemoveObserver(this);
-}
-
-void AgentMetricsCollectorHost::RenderProcessHostDestroyed(
-    RenderProcessHost* host) {
-  RemoveRendererData();
-}
-
-}  // namespace content
diff --git a/content/browser/renderer_host/agent_metrics_collector.h b/content/browser/renderer_host/agent_metrics_collector.h
deleted file mode 100644
index f987089f..0000000
--- a/content/browser/renderer_host/agent_metrics_collector.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_AGENT_METRICS_COLLECTOR_H_
-#define CONTENT_BROWSER_RENDERER_HOST_AGENT_METRICS_COLLECTOR_H_
-
-#include "content/common/renderer_host.mojom.h"
-#include "content/public/browser/render_process_host_observer.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "third_party/blink/public/mojom/agents/agent_metrics.mojom.h"
-
-namespace content {
-
-// Collects and reports metrics about the number of agents being hosted in the
-// various renderer processes. This is the browser-side of the Blink-based
-// execution_context/agent_metrics_collector.
-class CONTENT_EXPORT AgentMetricsCollectorHost
-    : public blink::mojom::AgentMetricsCollectorHost,
-      public RenderProcessHostObserver {
- public:
-  AgentMetricsCollectorHost(
-      int id,
-      mojo::PendingReceiver<blink::mojom::AgentMetricsCollectorHost> receiver);
-  ~AgentMetricsCollectorHost() override;
-
-  void ReportRendererMetrics(blink::mojom::AgentMetricsDataPtr data) override;
-  void RemoveRendererData();
-
-  // RenderProcessHostObserver implementation
-  void RenderProcessExited(RenderProcessHost* host,
-                           const ChildProcessTerminationInfo& info) override;
-  void RenderProcessHostDestroyed(RenderProcessHost* host) override;
-
- private:
-  int process_id_;
-
-  mojo::Receiver<blink::mojom::AgentMetricsCollectorHost> receiver_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_RENDERER_HOST_AGENT_METRICS_COLLECTOR_H_
diff --git a/content/browser/renderer_host/frame_navigation_entry.cc b/content/browser/renderer_host/frame_navigation_entry.cc
index 6f4e955a0..a3c6f09 100644
--- a/content/browser/renderer_host/frame_navigation_entry.cc
+++ b/content/browser/renderer_host/frame_navigation_entry.cc
@@ -31,7 +31,8 @@
     const std::string& method,
     int64_t post_id,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info)
+    std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info,
+    std::unique_ptr<PolicyContainerHost::DocumentPolicies> document_policies)
     : frame_unique_name_(frame_unique_name),
       item_sequence_number_(item_sequence_number),
       document_sequence_number_(document_sequence_number),
@@ -46,7 +47,8 @@
       method_(method),
       post_id_(post_id),
       blob_url_loader_factory_(std::move(blob_url_loader_factory)),
-      web_bundle_navigation_info_(std::move(web_bundle_navigation_info)) {
+      web_bundle_navigation_info_(std::move(web_bundle_navigation_info)),
+      document_policies_(std::move(document_policies)) {
   if (origin)
     committed_origin_ = *origin;
 }
@@ -57,12 +59,16 @@
   auto copy = base::MakeRefCounted<FrameNavigationEntry>();
 
   // Omit any fields cleared at commit time.
-  copy->UpdateEntry(frame_unique_name_, item_sequence_number_,
-                    document_sequence_number_, site_instance_.get(), nullptr,
-                    url_, committed_origin_, referrer_, initiator_origin_,
-                    redirect_chain_, page_state_, method_, post_id_,
-                    nullptr /* blob_url_loader_factory */,
-                    nullptr /* web_bundle_navigation_info */);
+  copy->UpdateEntry(
+      frame_unique_name_, item_sequence_number_, document_sequence_number_,
+      site_instance_.get(), nullptr, url_, committed_origin_, referrer_,
+      initiator_origin_, redirect_chain_, page_state_, method_, post_id_,
+      nullptr /* blob_url_loader_factory */,
+      nullptr /* web_bundle_navigation_info */,
+      document_policies_
+          ? std::make_unique<PolicyContainerHost::DocumentPolicies>(
+                *document_policies_)
+          : nullptr);
   // |bindings_| gets only updated through the SetBindings API, not through
   // UpdateEntry, so make a copy of it explicitly here as part of cloning.
   copy->bindings_ = bindings_;
@@ -84,7 +90,8 @@
     const std::string& method,
     int64_t post_id,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info) {
+    std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info,
+    std::unique_ptr<PolicyContainerHost::DocumentPolicies> document_policies) {
   frame_unique_name_ = frame_unique_name;
   item_sequence_number_ = item_sequence_number;
   document_sequence_number_ = document_sequence_number;
@@ -100,6 +107,7 @@
   post_id_ = post_id;
   blob_url_loader_factory_ = std::move(blob_url_loader_factory);
   web_bundle_navigation_info_ = std::move(web_bundle_navigation_info);
+  document_policies_ = std::move(document_policies);
 }
 
 void FrameNavigationEntry::set_item_sequence_number(
diff --git a/content/browser/renderer_host/frame_navigation_entry.h b/content/browser/renderer_host/frame_navigation_entry.h
index 635a2bbc3..f42125c7 100644
--- a/content/browser/renderer_host/frame_navigation_entry.h
+++ b/content/browser/renderer_host/frame_navigation_entry.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
+#include "content/browser/renderer_host/policy_container_host.h"
 #include "content/browser/site_instance_impl.h"
 #include "content/public/common/referrer.h"
 #include "services/network/public/cpp/resource_request_body.h"
@@ -55,7 +56,8 @@
       const std::string& method,
       int64_t post_id,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info);
+      std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info,
+      std::unique_ptr<PolicyContainerHost::DocumentPolicies> document_policies);
 
   // Creates a copy of this FrameNavigationEntry that can be modified
   // independently from the original.
@@ -77,7 +79,8 @@
       const std::string& method,
       int64_t post_id,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info);
+      std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info,
+      std::unique_ptr<PolicyContainerHost::DocumentPolicies> document_policies);
 
   // The unique name of the frame this entry is for.  This is a stable name for
   // the frame based on its position in the tree and relation to other named
@@ -186,6 +189,19 @@
   scoped_refptr<network::ResourceRequestBody> GetPostData(
       std::string* content_type) const;
 
+  // The document policies for this entry. This is needed for local schemes,
+  // since for them the policy container was inherited by the creator, while for
+  // network schemes we can reconstruct the policy container by parsing the
+  // network response.
+  void set_document_policies(
+      std::unique_ptr<PolicyContainerHost::DocumentPolicies>
+          document_policies) {
+    document_policies_ = std::move(document_policies);
+  }
+  const PolicyContainerHost::DocumentPolicies* document_policies() const {
+    return document_policies_.get();
+  }
+
   // Optional URLLoaderFactory to facilitate blob URL loading.
   scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory()
       const {
@@ -244,6 +260,9 @@
   // TODO(995177): Support Session/Tab restore.
   std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info_;
 
+  // TODO(https://crbug.com/1140393): Persist the document policies.
+  std::unique_ptr<PolicyContainerHost::DocumentPolicies> document_policies_;
+
   DISALLOW_COPY_AND_ASSIGN(FrameNavigationEntry);
 };
 
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 429eca7..ec86c29 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -451,6 +451,21 @@
   return true;
 }
 
+bool ShouldStoreDocumentPoliciesInFrameNavigationEntry(
+    const NavigationRequest* request) {
+  // For local schemes we need to store the policy container in the
+  // FrameNavigationEntry, so that we can reload it in case of history
+  // navigation.
+  //
+  // TODO(https://crbug.com/1146361 and https://crbug.com/1146362): blob: and
+  // filesystem: should be removed from this list when we have properly
+  // implemented storing their policy container in the respective store.
+  return (request->common_params().url.SchemeIs(url::kAboutScheme) ||
+          request->common_params().url.SchemeIs(url::kDataScheme) ||
+          request->common_params().url.SchemeIsBlob() ||
+          request->common_params().url.SchemeIsFileSystem());
+}
+
 }  // namespace
 
 // NavigationControllerImpl::PendingEntryRef------------------------------------
@@ -1142,7 +1157,8 @@
           previous_document_was_activated, navigation_request);
       break;
     case NAVIGATION_TYPE_AUTO_SUBFRAME:
-      if (!RendererDidNavigateAutoSubframe(rfh, params, navigation_request)) {
+      if (!RendererDidNavigateAutoSubframe(
+              rfh, params, details->is_same_document, navigation_request)) {
         // We don't send a notification about auto-subframe PageState during
         // UpdateStateForFrame, since it looks like nothing has changed.  Send
         // it here at commit time instead.
@@ -1434,7 +1450,9 @@
         Referrer(*params.referrer), initiator_origin, params.redirects,
         params.page_state, params.method, params.post_id,
         nullptr /* blob_url_loader_factory */,
-        nullptr /* web_bundle_navigation_info */);
+        nullptr /* web_bundle_navigation_info */,
+        // We will set the document policies later in this function.
+        nullptr /* document_policies */);
 
     new_entry = GetLastCommittedEntry()->CloneAndReplace(
         frame_entry, true, rfh->frame_tree_node(),
@@ -1554,6 +1572,9 @@
   frame_entry->SetPageState(params.page_state);
   frame_entry->set_method(params.method);
   frame_entry->set_post_id(params.post_id);
+  frame_entry->set_document_policies(
+      ComputeDocumentPoliciesForFrameEntry(rfh, is_same_document, request));
+
   if (!params.url_is_unreachable)
     frame_entry->set_committed_origin(params.origin);
   if (request->web_bundle_navigation_info()) {
@@ -1753,7 +1774,8 @@
       nullptr /* blob_url_loader_factory */,
       request->web_bundle_navigation_info()
           ? request->web_bundle_navigation_info()->Clone()
-          : nullptr);
+          : nullptr,
+      ComputeDocumentPoliciesForFrameEntry(rfh, is_same_document, request));
 
   // The redirected to page should not inherit the favicon from the previous
   // page.
@@ -1834,7 +1856,8 @@
       nullptr /* blob_url_loader_factory */,
       request->web_bundle_navigation_info()
           ? request->web_bundle_navigation_info()->Clone()
-          : nullptr);
+          : nullptr,
+      ComputeDocumentPoliciesForFrameEntry(rfh, is_same_document, request));
 
   DiscardNonCommittedEntries();
 }
@@ -1875,7 +1898,8 @@
       nullptr /* blob_url_loader_factory */,
       request->web_bundle_navigation_info()
           ? request->web_bundle_navigation_info()->Clone()
-          : nullptr);
+          : nullptr,
+      ComputeDocumentPoliciesForFrameEntry(rfh, is_same_document, request));
 
   std::unique_ptr<NavigationEntryImpl> new_entry =
       GetLastCommittedEntry()->CloneAndReplace(
@@ -1897,6 +1921,7 @@
 bool NavigationControllerImpl::RendererDidNavigateAutoSubframe(
     RenderFrameHostImpl* rfh,
     const mojom::DidCommitProvisionalLoadParams& params,
+    bool is_same_document,
     NavigationRequest* request) {
   DCHECK(ui::PageTransitionCoreTypeIs(params.transition,
                                       ui::PAGE_TRANSITION_AUTO_SUBFRAME));
@@ -1957,7 +1982,8 @@
       nullptr /* blob_url_loader_factory */,
       request->web_bundle_navigation_info()
           ? request->web_bundle_navigation_info()->Clone()
-          : nullptr);
+          : nullptr,
+      ComputeDocumentPoliciesForFrameEntry(rfh, is_same_document, request));
 
   return send_commit_notification;
 }
@@ -2357,12 +2383,23 @@
       // CreateNavigationEntry() may have changed the transition type.
       page_transition = entry->GetTransitionType();
     }
+    std::unique_ptr<PolicyContainerHost::DocumentPolicies> document_policies;
+    if (GetLastCommittedEntry()) {
+      FrameNavigationEntry* previous_frame_entry =
+          GetLastCommittedEntry()->GetFrameEntry(node);
+      if (previous_frame_entry && previous_frame_entry->document_policies()) {
+        document_policies =
+            std::make_unique<PolicyContainerHost::DocumentPolicies>(
+                *previous_frame_entry->document_policies());
+      }
+    }
     entry->AddOrUpdateFrameEntry(
         node, -1, -1, nullptr,
         static_cast<SiteInstanceImpl*>(source_site_instance), url,
         base::nullopt /* commit_origin */, referrer, initiator_origin,
         std::vector<GURL>(), blink::PageState(), method, -1,
-        blob_url_loader_factory, nullptr /* web_bundle_navigation_info */);
+        blob_url_loader_factory, nullptr /* web_bundle_navigation_info */,
+        std::move(document_policies));
   } else {
     // Main frame case.
     entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
@@ -2397,7 +2434,8 @@
         static_cast<SiteInstanceImpl*>(source_site_instance), url,
         nullptr /* origin */, referrer, initiator_origin, std::vector<GURL>(),
         blink::PageState(), method, -1, blob_url_loader_factory,
-        nullptr /* web_bundle_navigation_info */);
+        nullptr /* web_bundle_navigation_info */,
+        nullptr /* document_policies */);
   }
 
   LoadURLParams params(url);
@@ -3051,6 +3089,8 @@
     return;
   }
 
+  DCHECK(pending_entry_);
+
   // Convert navigations to the current URL to a reload.
   // TODO(clamy): We should be using FrameTreeNode::IsMainFrame here instead of
   // relying on the frame tree node id from LoadURLParams. Unfortunately,
@@ -3068,12 +3108,44 @@
           false /* is_reload */, false /* is_navigation_to_existing_entry */,
           GetLastCommittedEntry())) {
     reload_type = ReloadType::NORMAL;
+
+    // If this is a reload of an existing FrameNavigationEntry and we had a
+    // policy container for it, then we should copy it into the pending entry,
+    // so that it is copied to the navigation request in
+    // CreateNavigationRequestFromLoadParams later.
+    if (GetLastCommittedEntry()) {
+      FrameNavigationEntry* previous_frame_entry =
+          GetLastCommittedEntry()->GetFrameEntry(node);
+      if (previous_frame_entry && previous_frame_entry->document_policies()) {
+        pending_entry_->GetFrameEntry(node)->set_document_policies(
+            std::make_unique<PolicyContainerHost::DocumentPolicies>(
+                *previous_frame_entry->document_policies()));
+      }
+    }
+  }
+
+  // If this navigation is an "Enter-in-omnibox" with the initial about:blank
+  // document (so no last commit), then we should copy the document polices from
+  // RenderFrameHost's PolicyContainerHost. The NavigationRequest will create a
+  // new PolicyContainerHost with the document policies from the
+  // |pending_entry_|, and that PolicyContainerHost will be put in the final
+  // RenderFrameHost for the navigation. This way, we ensure that we keep
+  // enforcing the right policies on the initial empty document after the
+  // reload.
+  if (!GetLastCommittedEntry() && params.url.IsAboutBlank()) {
+    if (node->current_frame_host() &&
+        node->current_frame_host()->policy_container_host()) {
+      pending_entry_->GetFrameEntry(node)->set_document_policies(
+          std::make_unique<PolicyContainerHost::DocumentPolicies>(
+              node->current_frame_host()
+                  ->policy_container_host()
+                  ->document_policies()));
+    }
   }
 
   // navigation_ui_data should only be present for main frame navigations.
   DCHECK(node->IsMainFrame() || !params.navigation_ui_data);
 
-  DCHECK(pending_entry_);
   std::unique_ptr<NavigationRequest> request =
       CreateNavigationRequestFromLoadParams(
           node, params, override_user_agent, should_replace_current_entry,
@@ -3175,7 +3247,11 @@
         static_cast<SiteInstanceImpl*>(params.source_site_instance.get()),
         params.url, base::nullopt, params.referrer, params.initiator_origin,
         params.redirect_chain, blink::PageState(), "GET", -1,
-        blob_url_loader_factory, nullptr /* web_bundle_navigation_info */);
+        blob_url_loader_factory, nullptr /* web_bundle_navigation_info */,
+        // If in NavigateWithoutEntry we later determine that this navigation is
+        // a SAME_PAGE conversion of a new navigation into a reload, we will set
+        // the right document policies there.
+        nullptr /* document_policies */);
   } else {
     // Otherwise, create a pending entry for the main frame.
     entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
@@ -3792,4 +3868,47 @@
   delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
 }
 
+std::unique_ptr<PolicyContainerHost::DocumentPolicies>
+NavigationControllerImpl::ComputeDocumentPoliciesForFrameEntry(
+    RenderFrameHostImpl* rfh,
+    bool is_same_document,
+    NavigationRequest* request) {
+  if (!ShouldStoreDocumentPoliciesInFrameNavigationEntry(request))
+    return nullptr;
+
+  if (is_same_document) {
+    FrameNavigationEntry* previous_frame_entry =
+        GetLastCommittedEntry()->GetFrameEntry(rfh->frame_tree_node());
+
+    // TODO(https://crbug.com/608402): Remove this nullptr check when we can
+    // ensure we always have a FrameNavigationEntry here.
+    if (!previous_frame_entry)
+      return nullptr;
+
+    const PolicyContainerHost::DocumentPolicies* previous_document_policies =
+        previous_frame_entry->document_policies();
+
+    if (!previous_document_policies)
+      return nullptr;
+
+    // Make a copy of the policy container for the new FrameNavigationEntry.
+    return std::make_unique<PolicyContainerHost::DocumentPolicies>(
+        *previous_document_policies);
+  }
+
+  if (!request->IsWaitingToCommit()) {
+    // This is the initial, "fake" navigation to about:blank. The
+    // NavigationRequest contains a dummy policy container, while the
+    // RenderFrameHost already inherited the policy container from the
+    // creator, so let's take the policies from there.
+    return std::make_unique<PolicyContainerHost::DocumentPolicies>(
+        rfh->policy_container_host()->document_policies());
+  }
+
+  // Take the policy container from the request since we did not move it
+  // into the RFH yet.
+  return std::make_unique<PolicyContainerHost::DocumentPolicies>(
+      request->policy_container_host()->document_policies());
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/navigation_controller_impl.h b/content/browser/renderer_host/navigation_controller_impl.h
index 97bf101ba..6f7964c 100644
--- a/content/browser/renderer_host/navigation_controller_impl.h
+++ b/content/browser/renderer_host/navigation_controller_impl.h
@@ -522,6 +522,7 @@
   bool RendererDidNavigateAutoSubframe(
       RenderFrameHostImpl* rfh,
       const mojom::DidCommitProvisionalLoadParams& params,
+      bool is_same_document,
       NavigationRequest* request);
 
   // Allows the derived class to issue notifications that a load has been
@@ -598,6 +599,13 @@
   // pending NavigationEntry.
   void PendingEntryRefDeleted(PendingEntryRef* ref);
 
+  // Compute the document policies to be stored in the FrameNavigationEntry by
+  // RendererDidNavigate.
+  std::unique_ptr<PolicyContainerHost::DocumentPolicies>
+  ComputeDocumentPoliciesForFrameEntry(RenderFrameHostImpl* rfh,
+                                       bool is_same_document,
+                                       NavigationRequest* request);
+
   // ---------------------------------------------------------------------------
 
   // The user browser context associated with this controller.
diff --git a/content/browser/renderer_host/navigation_entry_impl.cc b/content/browser/renderer_host/navigation_entry_impl.cc
index 80b3f25..5b3dc0ce 100644
--- a/content/browser/renderer_host/navigation_entry_impl.cc
+++ b/content/browser/renderer_host/navigation_entry_impl.cc
@@ -81,7 +81,10 @@
       state.initiator_origin, std::vector<GURL>(),
       blink::PageState::CreateFromEncodedData(data), "GET", -1,
       nullptr /* blob_url_loader_factory */,
-      nullptr /* web_bundle_navigation_info */);
+      nullptr /* web_bundle_navigation_info */,
+      // TODO(https://crbug.com/1140393): We should restore the policy
+      // container.
+      nullptr /* document_policies */);
 
   // Don't pass the file list to subframes, since that would result in multiple
   // copies of it ending up in the combined list in GetPageState (via
@@ -335,7 +338,8 @@
               "GET",
               -1,
               std::move(blob_url_loader_factory),
-              nullptr /* web_bundle_navigation_info */))),
+              nullptr /* web_bundle_navigation_info */,
+              nullptr /* document_policies */))),
       unique_id_(CreateUniqueEntryID()),
       page_type_(PAGE_TYPE_NORMAL),
       update_virtual_url_with_url_(false),
@@ -852,7 +856,8 @@
     const std::string& method,
     int64_t post_id,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info) {
+    std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info,
+    std::unique_ptr<PolicyContainerHost::DocumentPolicies> document_policies) {
   // If this is called for the main frame, the FrameNavigationEntry is
   // guaranteed to exist, so just update it directly and return.
   if (frame_tree_node->IsMainFrame()) {
@@ -868,7 +873,7 @@
         std::move(source_site_instance), url, origin, referrer,
         initiator_origin, redirect_chain, page_state, method, post_id,
         std::move(blob_url_loader_factory),
-        std::move(web_bundle_navigation_info));
+        std::move(web_bundle_navigation_info), std::move(document_policies));
     return;
   }
 
@@ -898,7 +903,7 @@
           site_instance, std::move(source_site_instance), url, origin, referrer,
           initiator_origin, redirect_chain, page_state, method, post_id,
           std::move(blob_url_loader_factory),
-          std::move(web_bundle_navigation_info));
+          std::move(web_bundle_navigation_info), std::move(document_policies));
       return;
     }
   }
@@ -911,8 +916,8 @@
       site_instance, std::move(source_site_instance), url,
       base::OptionalOrNullptr(origin), referrer, initiator_origin,
       redirect_chain, page_state, method, post_id,
-      std::move(blob_url_loader_factory),
-      std::move(web_bundle_navigation_info));
+      std::move(blob_url_loader_factory), std::move(web_bundle_navigation_info),
+      std::move(document_policies));
   parent_node->children.push_back(
       std::make_unique<NavigationEntryImpl::TreeNode>(parent_node,
                                                       std::move(frame_entry)));
diff --git a/content/browser/renderer_host/navigation_entry_impl.h b/content/browser/renderer_host/navigation_entry_impl.h
index ef1e96e..76615cf 100644
--- a/content/browser/renderer_host/navigation_entry_impl.h
+++ b/content/browser/renderer_host/navigation_entry_impl.h
@@ -233,7 +233,8 @@
       const std::string& method,
       int64_t post_id,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info);
+      std::unique_ptr<WebBundleNavigationInfo> web_bundle_navigation_info,
+      std::unique_ptr<PolicyContainerHost::DocumentPolicies> document_policies);
 
   // Returns the FrameNavigationEntry corresponding to |frame_tree_node|, if
   // there is one in this NavigationEntry.
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 41c0075..7495862d 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -1072,16 +1072,22 @@
 
   policy_container_host_ = std::make_unique<PolicyContainerHost>();
 
-  // Local schemes inherit the policy container  from the initiator.
-  //
-  // TODO(antoniosartori): Fill up the PolicyContainerHost and/or replace it
-  // with a new one whenever needed (e.g. blob: or filesystem: URLs should get
-  // the policy container from the document which created them and not from the
-  // initiator of the navigation).
-  if (common_params_->url.SchemeIs(url::kAboutScheme) ||
-      common_params_->url.SchemeIs(url::kDataScheme) ||
-      common_params_->url.SchemeIs(url::kBlobScheme) ||
-      common_params_->url.SchemeIs(url::kFileSystemScheme)) {
+  // If there is a history entry with some document policies, initialize the
+  // PolicyContainerHost with them, so that they will get applied to the
+  // document created by the navigation.
+  if (frame_entry && frame_entry->document_policies()) {
+    policy_container_host_ = std::make_unique<PolicyContainerHost>(
+        *frame_entry->document_policies());
+    // Local schemes inherit the policy container  from the initiator.
+    //
+    // TODO(antoniosartori): Fill up the PolicyContainerHost and/or replace it
+    // with a new one whenever needed (e.g. blob: or filesystem: URLs should get
+    // the policy container from the document which created them and not from
+    // the initiator of the navigation).
+  } else if (common_params_->url.SchemeIs(url::kAboutScheme) ||
+             common_params_->url.SchemeIs(url::kDataScheme) ||
+             common_params_->url.SchemeIs(url::kBlobScheme) ||
+             common_params_->url.SchemeIs(url::kFileSystemScheme)) {
     if (GetInitiatorRoutingId()) {
       RenderFrameHostImpl* initiator_rfh = static_cast<RenderFrameHostImpl*>(
           RenderFrameHost::FromID(GetInitiatorRoutingId()));
@@ -2518,6 +2524,10 @@
           frame_entry->post_id(), frame_entry->blob_url_loader_factory(),
           frame_entry->web_bundle_navigation_info()
               ? frame_entry->web_bundle_navigation_info()->Clone()
+              : nullptr,
+          frame_entry->document_policies()
+              ? std::make_unique<PolicyContainerHost::DocumentPolicies>(
+                    *frame_entry->document_policies())
               : nullptr);
     }
   }
diff --git a/content/browser/renderer_host/policy_container_host_browsertest.cc b/content/browser/renderer_host/policy_container_host_browsertest.cc
index a91d303..e7bc238 100644
--- a/content/browser/renderer_host/policy_container_host_browsertest.cc
+++ b/content/browser/renderer_host/policy_container_host_browsertest.cc
@@ -9,7 +9,9 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
 #include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/blink/public/common/features.h"
@@ -341,4 +343,349 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_F(PolicyContainerHostBrowserTest, HistoryForMainFrame) {
+  NavigationControllerImpl& controller = web_contents()->GetController();
+  GURL no_referrer_url(embedded_test_server()->GetURL(
+      "/set-header?Referrer-Policy: no-referrer"));
+  GURL always_referrer_url(embedded_test_server()->GetURL(
+      "/set-header?Referrer-Policy: unsafe-url"));
+
+  // Navigate to a page setting Referrer-Policy: no-referrer.
+  ASSERT_TRUE(NavigateToURL(shell(), no_referrer_url));
+  ASSERT_EQ(1, controller.GetEntryCount());
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever,
+            current_frame_host()->policy_container_host()->referrer_policy());
+
+  // Now navigate to a local scheme.
+  ASSERT_TRUE(ExecJs(current_frame_host(), "window.location = 'about:blank'"));
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever,
+            current_frame_host()->policy_container_host()->referrer_policy());
+
+  ASSERT_EQ(2, controller.GetEntryCount());
+  NavigationEntryImpl* entry2 = controller.GetEntryAtIndex(1);
+
+  // Check that RendererDidNavigateToNewPage stored the correct policy container
+  // in the FrameNavigationEntry.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever, entry2->root_node()
+                                                        ->frame_entry.get()
+                                                        ->document_policies()
+                                                        ->referrer_policy);
+
+  // Same document navigation.
+  ASSERT_TRUE(ExecJs(current_frame_host(), "window.location.href = '#top'"));
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever,
+            current_frame_host()->policy_container_host()->referrer_policy());
+
+  ASSERT_EQ(3, controller.GetEntryCount());
+  NavigationEntryImpl* entry3 = controller.GetEntryAtIndex(2);
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever, entry3->root_node()
+                                                        ->frame_entry.get()
+                                                        ->document_policies()
+                                                        ->referrer_policy);
+
+  // Navigate to a third page.
+  ASSERT_TRUE(NavigateToURL(shell(), always_referrer_url));
+  ASSERT_EQ(4, controller.GetEntryCount());
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kAlways,
+            current_frame_host()->policy_container_host()->referrer_policy());
+
+  // Go back to "about:blank#top"
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  // The correct referrer policy should be restored from history.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever,
+            current_frame_host()->policy_container_host()->referrer_policy());
+
+  // The function RendererDidNavigateToExistingPage should not have changed
+  // anything.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever, entry3->root_node()
+                                                        ->frame_entry.get()
+                                                        ->document_policies()
+                                                        ->referrer_policy);
+
+  // Go back to "about:blank".
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  // The correct referrer policy should be restored from history.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever,
+            current_frame_host()->policy_container_host()->referrer_policy());
+
+  // The function RendererDidNavigateToExistingPage should not have changed
+  // anything.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever, entry2->root_node()
+                                                        ->frame_entry.get()
+                                                        ->document_policies()
+                                                        ->referrer_policy);
+
+  // Same page navigation.
+  ASSERT_TRUE(NavigateFrameToURL(current_frame_host()->frame_tree_node(),
+                                 GURL("about:blank")));
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever,
+            current_frame_host()->policy_container_host()->referrer_policy());
+
+  ASSERT_EQ(4, controller.GetEntryCount());
+
+  // Check that after RendererDidNavigateToSamePage the policy container in the
+  // FrameNavigationEntry is still correct.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kNever, entry2->root_node()
+                                                        ->frame_entry.get()
+                                                        ->document_policies()
+                                                        ->referrer_policy);
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyContainerHostBrowserTest, HistoryForChildFrame) {
+  NavigationControllerImpl& controller = web_contents()->GetController();
+  GURL always_referrer_url(embedded_test_server()->GetURL(
+      "/set-header?Referrer-Policy: unsafe-url"));
+  GURL strict_origin_when_cross_origin_referrer_url(
+      embedded_test_server()->GetURL(
+          "/set-header?Referrer-Policy: strict-origin-when-cross-origin"));
+
+  GURL main_url(embedded_test_server()->GetURL("/page_with_blank_iframe.html"));
+  FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+  ASSERT_TRUE(NavigateToURL(shell(), main_url));
+
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  ASSERT_NE(nullptr, child);
+  ASSERT_EQ(1, controller.GetEntryCount());
+
+  // The child has default referrer policy (same as the parent).
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kDefault,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+  NavigationEntryImpl* entry1 = controller.GetEntryAtIndex(0);
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kDefault,
+            entry1->GetFrameEntry(child)->document_policies()->referrer_policy);
+
+  // Change referrer policy of the main frame.
+  ASSERT_TRUE(ExecJs(current_frame_host(),
+                     "var meta = document.createElement('meta');"
+                     "meta.name = 'referrer';"
+                     "meta.content = 'same-origin';"
+                     "document.head.appendChild(meta);"));
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kSameOrigin,
+            current_frame_host()->policy_container_host()->referrer_policy());
+
+  // 1) Navigate the child frame to a local scheme url.
+  ASSERT_TRUE(ExecJs(current_frame_host(),
+                     "window.open('data:text/html,Hello', 'test_iframe');"));
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  // The new document inherits from the navigation initiator.
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kSameOrigin,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+
+  // The new page replaces the initial about:blank page in the subframe, so no
+  // new navigation entry is created.
+  ASSERT_EQ(1, controller.GetEntryCount());
+
+  // The policy container of the FrameNavigationEntry should have been
+  // updated. Test that the function RendererDidNavigateAutoSubframe updates the
+  // FrameNavigationEntry properly.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kSameOrigin,
+            entry1->GetFrameEntry(child)->document_policies()->referrer_policy);
+
+  // 2) Same document navigation.
+  ASSERT_TRUE(
+      ExecJs(child->current_frame_host(), "window.location.href = '#top';"));
+  ASSERT_TRUE(WaitForLoadStop(web_contents()));
+
+  // The policy container has not changed.
+  EXPECT_EQ(
+      network::mojom::ReferrerPolicy::kSameOrigin,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+  ASSERT_EQ(2, controller.GetEntryCount());
+  NavigationEntryImpl* entry2 = controller.GetEntryAtIndex(1);
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kSameOrigin,
+            entry2->GetFrameEntry(child)->document_policies()->referrer_policy);
+
+  // 3) Navigate the child frame to a network scheme url.
+  ASSERT_TRUE(NavigateFrameToURL(child, always_referrer_url));
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+  ASSERT_EQ(3, controller.GetEntryCount());
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kAlways,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+
+  // 4) Navigate the child frame to another local scheme url.
+  ASSERT_TRUE(ExecJs(child->current_frame_host(),
+                     "window.location = 'data:text/html,Hello2';"));
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  // The new document inherits from the navigation initiator.
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kAlways,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+
+  // Now test that the function RendererDidNavigateNewSubframe properly stored
+  // the policy container in the FrameNavigationEntry.
+  ASSERT_EQ(4, controller.GetEntryCount());
+  NavigationEntryImpl* entry4 = controller.GetEntryAtIndex(3);
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kAlways,
+            entry4->GetFrameEntry(child)->document_policies()->referrer_policy);
+
+  // 5) Navigate the child frame to another network scheme url.
+  ASSERT_TRUE(
+      NavigateFrameToURL(child, strict_origin_when_cross_origin_referrer_url));
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+  ASSERT_EQ(5, controller.GetEntryCount());
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+
+  // 6) Navigate the main frame cross-document to destroy the subframes.
+  GURL foo_url(embedded_test_server()->GetURL(
+      "foo.com", "/navigation_controller/simple_page_1.html"));
+  ASSERT_TRUE(NavigateToURL(shell(), foo_url));
+
+  // 7) Navigate all the way back and check that we properly reload the policy
+  // container from history.
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  child = web_contents()->GetFrameTree()->root()->child_at(0);
+  ASSERT_NE(nullptr, child);
+
+  // The correct referrer policy should be restored from history.
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kAlways,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+
+  // The frame entry should not have changed.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kAlways,
+            entry4->GetFrameEntry(child)->document_policies()->referrer_policy);
+
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  // The correct referrer policy should be restored from history.
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kSameOrigin,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+
+  // The frame entry should not have changed.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kSameOrigin,
+            entry2->GetFrameEntry(child)->document_policies()->referrer_policy);
+
+  controller.GoBack();
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  // The correct referrer policy should be restored from history.
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kSameOrigin,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+
+  // The frame entry should not have changed.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kSameOrigin,
+            entry1->GetFrameEntry(child)->document_policies()->referrer_policy);
+}
+
+// Check that the FrameNavigationEntry for the initial empty document is
+// correctly populated, both for main frames and for subframes.
+IN_PROC_BROWSER_TEST_F(PolicyContainerHostBrowserTest,
+                       HistoryForInitialEmptyDocument) {
+  GURL origin_referrer_page = embedded_test_server()->GetURL(
+      "a.com", "/set-header?Referrer-Policy: origin");
+  ASSERT_TRUE(NavigateToURL(shell(), origin_referrer_page));
+
+  {
+    // Open a subframe
+    ASSERT_TRUE(ExecJs(current_frame_host(),
+                       "var frame = document.createElement('iframe');"
+                       "frame.name = 'test_iframe';"
+                       "document.body.appendChild(frame);"));
+
+    FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+    ASSERT_EQ(1U, root->child_count());
+    FrameTreeNode* child = root->child_at(0);
+    ASSERT_NE(nullptr, child);
+    // The child inherits from the parent.
+    ASSERT_EQ(network::mojom::ReferrerPolicy::kOrigin,
+              child->current_frame_host()
+                  ->policy_container_host()
+                  ->referrer_policy());
+
+    // The right policy is stored in the FrameNavigationEntry.
+    NavigationControllerImpl& controller = web_contents()->GetController();
+    ASSERT_EQ(1, controller.GetEntryCount());
+    NavigationEntryImpl* entry1 = controller.GetEntryAtIndex(0);
+    ASSERT_EQ(
+        network::mojom::ReferrerPolicy::kOrigin,
+        entry1->GetFrameEntry(child)->document_policies()->referrer_policy);
+  }
+
+  {
+    // Open a popup.
+    ShellAddedObserver shell_observer;
+    ASSERT_TRUE(ExecJs(current_frame_host(), "window.open('about:blank');"));
+    WebContentsImpl* popup_webcontents = static_cast<WebContentsImpl*>(
+        shell_observer.GetShell()->web_contents());
+    RenderFrameHostImpl* popup_frame =
+        popup_webcontents->GetFrameTree()->root()->current_frame_host();
+
+    // The popup inherits from the creator.
+    EXPECT_EQ(network::mojom::ReferrerPolicy::kOrigin,
+              popup_frame->policy_container_host()->referrer_policy());
+
+    // The right policy is stored in the FrameNavigationEntry.
+    NavigationEntryImpl* entry1 =
+        popup_webcontents->GetController().GetEntryAtIndex(0);
+    ASSERT_EQ(network::mojom::ReferrerPolicy::kOrigin, entry1->root_node()
+                                                           ->frame_entry.get()
+                                                           ->document_policies()
+                                                           ->referrer_policy);
+  }
+}
+
+// This test ensures that the document policies what we store in the
+// FrameNavigationEntry are a snapshot of the document policies at
+// CommitNavigation time, and do not include updates triggered by Blink.
+IN_PROC_BROWSER_TEST_F(PolicyContainerHostBrowserTest,
+                       BlinkModificationsDoNotAffectPolicyContainer) {
+  NavigationControllerImpl& controller = web_contents()->GetController();
+
+  GURL always_referrer_url(embedded_test_server()->GetURL(
+      "/set-header?Referrer-Policy: unsafe-url"));
+  ASSERT_TRUE(NavigateToURL(shell(), always_referrer_url));
+
+  FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+  // Create child frame
+  ASSERT_TRUE(ExecJs(current_frame_host(), R"(
+    let frame = document.createElement('iframe');
+    let content = '<head><meta name="referrer" content="no-referrer"></head>';
+    frame.src = 'data:text/html,' + content;
+    document.body.appendChild(frame);
+  )"));
+  EXPECT_TRUE(WaitForLoadStop(web_contents()));
+
+  FrameTreeNode* child = root->child_at(0);
+  ASSERT_NE(nullptr, child);
+
+  // Blink should have parsed Referrer-Policy from the meta tag and the
+  // information should have propagated to the PolicyContainerHost.
+  ASSERT_EQ(
+      network::mojom::ReferrerPolicy::kNever,
+      child->current_frame_host()->policy_container_host()->referrer_policy());
+  ASSERT_EQ(1, controller.GetEntryCount());
+  NavigationEntryImpl* entry1 = controller.GetEntryAtIndex(0);
+
+  // Policies should be stored in the FrameNavigationEntry before any
+  // modification coming from blink.
+  ASSERT_EQ(network::mojom::ReferrerPolicy::kAlways,
+            entry1->GetFrameEntry(child)->document_policies()->referrer_policy);
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 2399cc32..9147b8637 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -113,7 +113,6 @@
 #include "content/browser/permissions/permission_service_impl.h"
 #include "content/browser/push_messaging/push_messaging_manager.h"
 #include "content/browser/quota/quota_context.h"
-#include "content/browser/renderer_host/agent_metrics_collector.h"
 #include "content/browser/renderer_host/code_cache_host_impl.h"
 #include "content/browser/renderer_host/embedded_frame_sink_provider_impl.h"
 #include "content/browser/renderer_host/file_utilities_host_impl.h"
@@ -2375,12 +2374,6 @@
       &MediaStreamTrackMetricsHost::BindReceiver,
       base::Unretained(media_stream_track_metrics_host_.get())));
 
-  AddUIThreadInterface(
-      registry.get(),
-      base::BindRepeating(
-          &RenderProcessHostImpl::CreateAgentMetricsCollectorHost,
-          weak_factory_.GetWeakPtr()));
-
   registry->AddInterface(
       base::BindRepeating(&metrics::CreateSingleSampleMetricsProvider));
 
@@ -4970,16 +4963,6 @@
   return nullptr;
 }
 
-void RenderProcessHostImpl::CreateAgentMetricsCollectorHost(
-    mojo::PendingReceiver<blink::mojom::AgentMetricsCollectorHost> receiver) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!agent_metrics_collector_host_) {
-    agent_metrics_collector_host_.reset(
-        new AgentMetricsCollectorHost(this->GetID(), std::move(receiver)));
-    AddObserver(agent_metrics_collector_host_.get());
-  }
-}
-
 void RenderProcessHostImpl::BindPeerConnectionTrackerHost(
     mojo::PendingReceiver<blink::mojom::PeerConnectionTrackerHost> receiver) {
   GetPeerConnectionTrackerHost()->BindReceiver(std::move(receiver));
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 1f2f101e..0679c731 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -72,7 +72,6 @@
 #include "services/viz/public/mojom/compositing/compositing_mode_watcher.mojom.h"
 #include "services/viz/public/mojom/gpu.mojom.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
-#include "third_party/blink/public/mojom/agents/agent_metrics.mojom.h"
 #include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h"
 #include "third_party/blink/public/mojom/background_sync/background_sync.mojom-forward.h"
 #include "third_party/blink/public/mojom/broadcastchannel/broadcast_channel.mojom.h"
@@ -107,7 +106,6 @@
 }
 
 namespace content {
-class AgentMetricsCollectorHost;
 class AgentSchedulingGroupHost;
 class CodeCacheHostImpl;
 class FileSystemManagerImpl;
@@ -866,9 +864,6 @@
   static RenderProcessHost* FindReusableProcessHostForSiteInstance(
       SiteInstanceImpl* site_instance);
 
-  void CreateAgentMetricsCollectorHost(
-      mojo::PendingReceiver<blink::mojom::AgentMetricsCollectorHost> receiver);
-
   void BindPeerConnectionTrackerHost(
       mojo::PendingReceiver<blink::mojom::PeerConnectionTrackerHost> receiver);
 
@@ -1107,8 +1102,6 @@
   std::unique_ptr<MediaStreamTrackMetricsHost, BrowserThread::DeleteOnIOThread>
       media_stream_track_metrics_host_;
 
-  std::unique_ptr<AgentMetricsCollectorHost> agent_metrics_collector_host_;
-
   std::unique_ptr<FramelessMediaInterfaceProxy> media_interface_proxy_;
 
   // Forwards messages between WebRTCInternals in the browser process
diff --git a/content/browser/service_worker/service_worker_context_core_unittest.cc b/content/browser/service_worker/service_worker_context_core_unittest.cc
index e94a17a..538a382 100644
--- a/content/browser/service_worker/service_worker_context_core_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_core_unittest.cc
@@ -308,7 +308,7 @@
                   }));
   // Disable storage before it finishes. This causes the Unregister job to
   // complete with an error.
-  context()->GetStorageControl()->Disable();
+  context()->registry()->DisableStorageForTesting(base::DoNothing());
   loop.Run();
 
   // The operation should still complete.
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index f496db93..4032b42 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -225,7 +225,7 @@
   base::HistogramTester histogram_tester;
 
   // Disabling the storage makes looking up the registration return an error.
-  context()->GetStorageControl()->Disable();
+  context()->registry()->DisableStorageForTesting(base::DoNothing());
 
   histogram_tester.ExpectTotalCount(
       "ServiceWorker.LookupRegistration.MainResource.Time.Error", 0);
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
index 9e814b47a..408aca6 100644
--- a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
+++ b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
@@ -700,8 +700,9 @@
         info.second.WriteToDiskCache(context()->GetStorageControl()));
   version()->script_cache_map()->SetResources(records);
 
-  registry()->GetRemoteStorageControl()->Disable();
-  registry()->GetRemoteStorageControl().FlushForTesting();
+  base::RunLoop loop;
+  registry()->DisableStorageForTesting(loop.QuitClosure());
+  loop.Run();
 
   auto sender =
       std::make_unique<ServiceWorkerInstalledScriptsSender>(version());
diff --git a/content/browser/service_worker/service_worker_registry.cc b/content/browser/service_worker/service_worker_registry.cc
index 0196d04..5e66b4f 100644
--- a/content/browser/service_worker/service_worker_registry.cc
+++ b/content/browser/service_worker/service_worker_registry.cc
@@ -190,6 +190,9 @@
               old_registry->user_data_directory_,
               old_registry->database_task_runner_,
               old_registry->quota_manager_proxy_.get()))),
+      user_data_directory_(old_registry->user_data_directory_),
+      database_task_runner_(old_registry->database_task_runner_),
+      quota_manager_proxy_(old_registry->quota_manager_proxy_),
       special_storage_policy_(old_registry->special_storage_policy_) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   DCHECK(context_);
@@ -665,18 +668,27 @@
 void ServiceWorkerRegistry::GetRegisteredOrigins(
     GetRegisteredOriginsCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  GetRemoteStorageControl()->GetRegisteredOrigins(std::move(callback));
+  CreateInvokerAndStartRemoteCall(
+      &storage::mojom::ServiceWorkerStorageControl::GetRegisteredOrigins,
+      base::BindRepeating(&ServiceWorkerRegistry::DidGetRegisteredOrigins,
+                          weak_factory_.GetWeakPtr(), base::Passed(&callback)));
 }
 
 void ServiceWorkerRegistry::PerformStorageCleanup(base::OnceClosure callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  GetRemoteStorageControl()->PerformStorageCleanup(std::move(callback));
+  CreateInvokerAndStartRemoteCall(
+      &storage::mojom::ServiceWorkerStorageControl::PerformStorageCleanup,
+      base::BindRepeating(&ServiceWorkerRegistry::DidPerformStorageCleanup,
+                          weak_factory_.GetWeakPtr(), base::Passed(&callback)));
 }
 
 void ServiceWorkerRegistry::PrepareForDeleteAndStartOver() {
   should_schedule_delete_and_start_over_ = false;
-  GetRemoteStorageControl()->Disable();
   is_storage_disabled_ = true;
+  CreateInvokerAndStartRemoteCall(
+      &storage::mojom::ServiceWorkerStorageControl::Disable,
+      base::BindRepeating(&ServiceWorkerRegistry::DidDisable,
+                          weak_factory_.GetWeakPtr()));
 }
 
 void ServiceWorkerRegistry::DeleteAndStartOver(StatusCallback callback) {
@@ -687,6 +699,11 @@
                           weak_factory_.GetWeakPtr(), base::Passed(&callback)));
 }
 
+void ServiceWorkerRegistry::DisableStorageForTesting(
+    base::OnceClosure callback) {
+  GetRemoteStorageControl()->Disable(std::move(callback));
+}
+
 void ServiceWorkerRegistry::SimulateStorageRestartForTesting() {
   storage_control_ = std::make_unique<ServiceWorkerStorageControlImpl>(
       ServiceWorkerStorage::Create(user_data_directory_, database_task_runner_,
@@ -701,7 +718,7 @@
         weak_factory_.GetWeakPtr(),
         base::WrapRefCounted(special_storage_policy_.get()));
 
-    GetRemoteStorageControl()->GetRegisteredOrigins(
+    GetRegisteredOrigins(
         base::BindOnce(&ServiceWorkerRegistry::DidGetRegisteredOriginsOnStartup,
                        weak_factory_.GetWeakPtr()));
   }
@@ -1369,6 +1386,27 @@
   std::move(callback).Run(DatabaseStatusToStatusCode(status));
 }
 
+void ServiceWorkerRegistry::DidGetRegisteredOrigins(
+    GetRegisteredOriginsCallback callback,
+    uint64_t call_id,
+    const std::vector<url::Origin>& origins) {
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+  FinishRemoteCall(call_id);
+  std::move(callback).Run(origins);
+}
+
+void ServiceWorkerRegistry::DidPerformStorageCleanup(base::OnceClosure callback,
+                                                     uint64_t call_id) {
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+  FinishRemoteCall(call_id);
+  std::move(callback).Run();
+}
+
+void ServiceWorkerRegistry::DidDisable(uint64_t call_id) {
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+  FinishRemoteCall(call_id);
+}
+
 void ServiceWorkerRegistry::DidGetRegisteredOriginsOnStartup(
     const std::vector<url::Origin>& origins) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
diff --git a/content/browser/service_worker/service_worker_registry.h b/content/browser/service_worker/service_worker_registry.h
index 372d48e1..c10a3508 100644
--- a/content/browser/service_worker/service_worker_registry.h
+++ b/content/browser/service_worker/service_worker_registry.h
@@ -244,6 +244,10 @@
   mojo::Remote<storage::mojom::ServiceWorkerStorageControl>&
   GetRemoteStorageControl();
 
+  // Call storage::mojom::ServiceWorkerStorageControl::Disable() immediately.
+  // This method sends an IPC message without using the queuing mechanism.
+  void DisableStorageForTesting(base::OnceClosure callback);
+
   void SimulateStorageRestartForTesting();
 
  private:
@@ -376,6 +380,12 @@
       uint64_t call_id,
       storage::mojom::ServiceWorkerDatabaseStatus status);
 
+  void DidGetRegisteredOrigins(GetRegisteredOriginsCallback callback,
+                               uint64_t call_id,
+                               const std::vector<url::Origin>& origins);
+  void DidPerformStorageCleanup(base::OnceClosure callback, uint64_t call_id);
+  void DidDisable(uint64_t call_id);
+
   // TODO(bashi): Consider introducing a helper class that handles the below.
   // These are almost the same as DOMStorageContextWrapper.
   void DidGetRegisteredOriginsOnStartup(
diff --git a/content/browser/service_worker/service_worker_registry_unittest.cc b/content/browser/service_worker/service_worker_registry_unittest.cc
index 4830ff33b..8213f50 100644
--- a/content/browser/service_worker/service_worker_registry_unittest.cc
+++ b/content/browser/service_worker/service_worker_registry_unittest.cc
@@ -1283,15 +1283,17 @@
 // Tests that inflight remote calls are retried after the remote storage is
 // restarted.
 TEST_F(ServiceWorkerRegistryTest, RetryInflightCalls) {
-  const GURL kScope1("http://www.example.com/scope/");
-  const GURL kScriptUrl1("http://www.example.com/script.js");
+  EnsureRemoteCallsAreExecuted();
+
+  const GURL kScope1("https://www.example.com/scope/");
+  const GURL kScriptUrl1("https://www.example.com/script.js");
   const auto kOrigin1(url::Origin::Create(kScope1));
   scoped_refptr<ServiceWorkerRegistration> registration1 =
       CreateServiceWorkerRegistrationAndVersion(context(), kScope1, kScriptUrl1,
                                                 /*resource_id=*/1);
 
-  const GURL kScope2("http://www.example.com/scope/foo");
-  const GURL kScriptUrl2("http://www.example.com/fooscript.js");
+  const GURL kScope2("https://www2.example.com/scope/foo");
+  const GURL kScriptUrl2("https://www2.example.com/foo/script.js");
   const auto kOrigin2(url::Origin::Create(kScope2));
   scoped_refptr<ServiceWorkerRegistration> registration2 =
       CreateServiceWorkerRegistrationAndVersion(context(), kScope2, kScriptUrl2,
@@ -1327,6 +1329,23 @@
     EXPECT_EQ(inflight_call_count(), 0U);
   }
 
+  // Get registered origins
+  {
+    base::RunLoop loop;
+    registry()->GetRegisteredOrigins(base::BindLambdaForTesting(
+        [&](const std::vector<url::Origin>& origins) {
+          EXPECT_THAT(origins,
+                      testing::UnorderedElementsAreArray({kOrigin1, kOrigin2}));
+          loop.Quit();
+        }));
+
+    EXPECT_EQ(inflight_call_count(), 1U);
+    registry()->SimulateStorageRestartForTesting();
+
+    loop.Run();
+    EXPECT_EQ(inflight_call_count(), 0U);
+  }
+
   // Finding registrations stored in the previous block.
   {
     base::RunLoop loop1;
@@ -1369,7 +1388,7 @@
                 const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
                     registrations) {
               EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk);
-              EXPECT_EQ(registrations.size(), 2U);
+              EXPECT_EQ(registrations.size(), 1U);
               loop1.Quit();
             }));
 
@@ -1515,6 +1534,8 @@
 
 TEST_F(ServiceWorkerRegistryTest,
        RetryInflightCalls_CreateNewRegistrationAndVersion) {
+  EnsureRemoteCallsAreExecuted();
+
   const GURL kScope("http://www.example.com/scope/");
   const GURL kScriptUrl("http://www.example.com/script.js");
 
@@ -1560,6 +1581,8 @@
 }
 
 TEST_F(ServiceWorkerRegistryTest, RetryInflightCalls_DeleteAndStartOver) {
+  EnsureRemoteCallsAreExecuted();
+
   base::RunLoop loop;
   registry()->DeleteAndStartOver(
       base::BindLambdaForTesting([&](blink::ServiceWorkerStatusCode status) {
@@ -1580,6 +1603,45 @@
       kExpectedRetryCountForRecovery, kExpectedSampleCount);
 }
 
+TEST_F(ServiceWorkerRegistryTest, RetryInflightCalls_PerformStorageCleanup) {
+  EnsureRemoteCallsAreExecuted();
+
+  base::RunLoop loop;
+  registry()->PerformStorageCleanup(
+      base::BindLambdaForTesting([&]() { loop.Quit(); }));
+
+  EXPECT_EQ(inflight_call_count(), 1U);
+  registry()->SimulateStorageRestartForTesting();
+
+  base::HistogramTester histogram_tester;
+  loop.Run();
+  EXPECT_EQ(inflight_call_count(), 0U);
+  const size_t kExpectedRetryCountForRecovery = 0;
+  const size_t kExpectedSampleCount = 1;
+  histogram_tester.ExpectUniqueSample(
+      "ServiceWorker.Storage.RetryCountForRecovery",
+      kExpectedRetryCountForRecovery, kExpectedSampleCount);
+}
+
+TEST_F(ServiceWorkerRegistryTest, RetryInflightCalls_Disable) {
+  EnsureRemoteCallsAreExecuted();
+
+  // This schedules a Disable() remote call.
+  registry()->PrepareForDeleteAndStartOver();
+
+  EXPECT_EQ(inflight_call_count(), 1U);
+  registry()->SimulateStorageRestartForTesting();
+
+  base::HistogramTester histogram_tester;
+  EnsureRemoteCallsAreExecuted();
+  EXPECT_EQ(inflight_call_count(), 0U);
+  const size_t kExpectedRetryCountForRecovery = 0;
+  const size_t kExpectedSampleCount = 1;
+  histogram_tester.ExpectUniqueSample(
+      "ServiceWorker.Storage.RetryCountForRecovery",
+      kExpectedRetryCountForRecovery, kExpectedSampleCount);
+}
+
 class ServiceWorkerRegistryOriginTrialsTest : public ServiceWorkerRegistryTest {
  public:
   ServiceWorkerRegistryOriginTrialsTest() {
diff --git a/content/browser/service_worker/service_worker_storage_control_impl.cc b/content/browser/service_worker/service_worker_storage_control_impl.cc
index e821d8b..362328b 100644
--- a/content/browser/service_worker/service_worker_storage_control_impl.cc
+++ b/content/browser/service_worker/service_worker_storage_control_impl.cc
@@ -104,8 +104,9 @@
   storage_->LazyInitializeForTest();
 }
 
-void ServiceWorkerStorageControlImpl::Disable() {
+void ServiceWorkerStorageControlImpl::Disable(DisableCallback callback) {
   storage_->Disable();
+  std::move(callback).Run();
 }
 
 void ServiceWorkerStorageControlImpl::Delete(DeleteCallback 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 3fb8538..fe5e558 100644
--- a/content/browser/service_worker/service_worker_storage_control_impl.h
+++ b/content/browser/service_worker/service_worker_storage_control_impl.h
@@ -45,7 +45,7 @@
 
  private:
   // storage::mojom::ServiceWorkerStorageControl implementations:
-  void Disable() override;
+  void Disable(DisableCallback callback) override;
   void Delete(DeleteCallback callback) override;
   void Recover(
       std::vector<storage::mojom::ServiceWorkerLiveVersionInfoPtr> versions,
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc
index 5f1962d..b3239d0 100644
--- a/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -1462,8 +1462,9 @@
 TEST_F(ServiceWorkerVersionTest, WriteMetadata_StorageDisabled) {
   const std::string kMetadata("Test metadata");
 
-  helper_->context()->registry()->GetRemoteStorageControl()->Disable();
-  helper_->context()->registry()->GetRemoteStorageControl().FlushForTesting();
+  base::RunLoop loop;
+  helper_->context()->registry()->DisableStorageForTesting(loop.QuitClosure());
+  loop.Run();
 
   net::TestCompletionCallback completion;
   version_->script_cache_map()->WriteMetadata(
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc
index d4b52b1..1b2ff5d 100644
--- a/content/renderer/loader/resource_dispatcher.cc
+++ b/content/renderer/loader/resource_dispatcher.cc
@@ -409,6 +409,14 @@
       ->NotifyResourceTransferSizeUpdated(transfer_size_diff);
 }
 
+void ResourceDispatcher::EvictFromBackForwardCache(int request_id) {
+  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
+  if (!request_info)
+    return;
+
+  return request_info->peer->EvictFromBackForwardCache();
+}
+
 void ResourceDispatcher::SetCorsExemptHeaderList(
     const std::vector<std::string>& list) {
   cors_exempt_header_list_ = list;
diff --git a/content/renderer/loader/resource_dispatcher.h b/content/renderer/loader/resource_dispatcher.h
index 1eaf54d..c2b2738 100644
--- a/content/renderer/loader/resource_dispatcher.h
+++ b/content/renderer/loader/resource_dispatcher.h
@@ -162,6 +162,8 @@
 
   void OnTransferSizeUpdated(int request_id, int32_t transfer_size_diff);
 
+  void EvictFromBackForwardCache(int request_id);
+
   // Sets the CORS exempt header list for sanity checking.
   void SetCorsExemptHeaderList(const std::vector<std::string>& list);
 
diff --git a/content/renderer/loader/resource_dispatcher_unittest.cc b/content/renderer/loader/resource_dispatcher_unittest.cc
index 6cff3509..6ae90ec 100644
--- a/content/renderer/loader/resource_dispatcher_unittest.cc
+++ b/content/renderer/loader/resource_dispatcher_unittest.cc
@@ -227,6 +227,8 @@
       original_peer_->OnCompletedRequest(status);
     }
 
+    void EvictFromBackForwardCache() override {}
+
    private:
     std::unique_ptr<blink::WebRequestPeer> original_peer_;
     network::mojom::URLResponseHeadPtr response_head_;
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc
index 5fe479b..c1123a1 100644
--- a/content/renderer/loader/sync_load_context.cc
+++ b/content/renderer/loader/sync_load_context.cc
@@ -179,6 +179,10 @@
   return true;
 }
 
+void SyncLoadContext::EvictFromBackForwardCache() {
+  return;
+}
+
 void SyncLoadContext::FollowRedirect() {
   if (!signals_->RestartAfterRedirect()) {
     CancelRedirect();
diff --git a/content/renderer/loader/sync_load_context.h b/content/renderer/loader/sync_load_context.h
index 6bb9f19..410a4574 100644
--- a/content/renderer/loader/sync_load_context.h
+++ b/content/renderer/loader/sync_load_context.h
@@ -108,6 +108,7 @@
   void OnTransferSizeUpdated(int transfer_size_diff) override;
   void OnCompletedRequest(
       const network::URLLoaderCompletionStatus& status) override;
+  void EvictFromBackForwardCache() override;
 
   void OnFinishCreatingBlob(blink::mojom::SerializedBlobPtr blob);
 
diff --git a/content/renderer/loader/test_request_peer.cc b/content/renderer/loader/test_request_peer.cc
index c45406f..075cfaf 100644
--- a/content/renderer/loader/test_request_peer.cc
+++ b/content/renderer/loader/test_request_peer.cc
@@ -89,6 +89,10 @@
   context_->completion_status = status;
 }
 
+void TestRequestPeer::EvictFromBackForwardCache() {
+  return;
+}
+
 TestRequestPeer::Context::Context() = default;
 TestRequestPeer::Context::~Context() = default;
 
diff --git a/content/renderer/loader/test_request_peer.h b/content/renderer/loader/test_request_peer.h
index 5e0a68b..2b0bb9c 100644
--- a/content/renderer/loader/test_request_peer.h
+++ b/content/renderer/loader/test_request_peer.h
@@ -42,6 +42,7 @@
   void OnReceivedCachedMetadata(mojo_base::BigBuffer data) override;
   void OnCompletedRequest(
       const network::URLLoaderCompletionStatus& status) override;
+  void EvictFromBackForwardCache() override;
 
   struct Context final {
     Context();
diff --git a/content/renderer/loader/url_loader_client_impl.cc b/content/renderer/loader/url_loader_client_impl.cc
index 4185c3b..f8778c2 100644
--- a/content/renderer/loader/url_loader_client_impl.cc
+++ b/content/renderer/loader/url_loader_client_impl.cc
@@ -376,8 +376,8 @@
   DCHECK(!has_received_response_head_);
   if (deferred_state_ ==
       blink::WebURLLoader::DeferType::kDeferredWithBackForwardCache) {
-    // TODO(yuzus): Evict here.
-    // Close the connections and disptach and OnComplete message.
+    resource_dispatcher_->EvictFromBackForwardCache(request_id_);
+    // Close the connections and dispatch and OnComplete message.
     url_loader_.reset();
     url_loader_client_receiver_.reset();
     OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index a3a0c20..32354af 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -410,6 +410,7 @@
   void OnTransferSizeUpdated(int transfer_size_diff);
   void OnReceivedCachedMetadata(mojo_base::BigBuffer data);
   void OnCompletedRequest(const network::URLLoaderCompletionStatus& status);
+  void EvictFromBackForwardCache();
 
  private:
   friend class base::RefCounted<Context>;
@@ -484,6 +485,7 @@
   void OnReceivedCachedMetadata(mojo_base::BigBuffer data) override;
   void OnCompletedRequest(
       const network::URLLoaderCompletionStatus& status) override;
+  void EvictFromBackForwardCache() override;
 
  private:
   scoped_refptr<Context> context_;
@@ -831,6 +833,10 @@
   context_->OnCompletedRequest(status);
 }
 
+void WebURLLoaderImpl::RequestPeerImpl::EvictFromBackForwardCache() {
+  context_->EvictFromBackForwardCache();
+}
+
 // WebURLLoaderImpl -----------------------------------------------------------
 
 WebURLLoaderImpl::WebURLLoaderImpl(
@@ -1243,4 +1249,8 @@
   VariationsRenderThreadObserver::AppendThrottleIfNeeded(origin, throttles);
 }
 
+void WebURLLoaderImpl::Context::EvictFromBackForwardCache() {
+  client()->EvictFromBackForwardCache();
+}
+
 }  // namespace content
diff --git a/content/test/data/page_with_blank_iframe.html b/content/test/data/page_with_blank_iframe.html
index f3d1538..ee6d7217 100644
--- a/content/test/data/page_with_blank_iframe.html
+++ b/content/test/data/page_with_blank_iframe.html
@@ -2,6 +2,6 @@
 <head></head>
 <body>
   <p>This page has blank iframe. Yay for iframes!
-  <p><iframe id="test_iframe"></iframe>
+  <p><iframe id="test_iframe" name="test_iframe"></iframe>
 </body>
 </html>
diff --git a/docs/clang_sheriffing.md b/docs/clang_sheriffing.md
index 1936a0eb..ad9b905b 100644
--- a/docs/clang_sheriffing.md
+++ b/docs/clang_sheriffing.md
@@ -206,7 +206,7 @@
 
 1. Copy the link command that ninja prints, `cd out/gn`, paste it, and manually
    append `-Wl,--reproduce,repro.tar`. With `lld-link`, instead append
-   `/linkrepro:repro.tar`. (`ld.lld` is invoked through the `clang` driver, so
+   `/reproduce:repro.tar`. (`ld.lld` is invoked through the `clang` driver, so
    it needs `-Wl` to pass the flag through to the linker. `lld-link` is called
    directly, so the flag needs no prefix.)
 
diff --git a/extensions/renderer/resources/automation/automation_node.js b/extensions/renderer/resources/automation/automation_node.js
index e91074f..d024c0b 100644
--- a/extensions/renderer/resources/automation/automation_node.js
+++ b/extensions/renderer/resources/automation/automation_node.js
@@ -831,7 +831,7 @@
   },
 
   get tableCellRowHeaders() {
-    var id = GetTableCellRowHeaders(this.treeID, this.id);
+    var ids = GetTableCellRowHeaders(this.treeID, this.id);
     if (ids && this.rootImpl) {
       var result = [];
       for (var i = 0; i < ids.length; i++)
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 3a23887..642e22f 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -5032,6 +5032,7 @@
     DCHECK(!_ntpCoordinatorsForWebStates[webState]);
     NewTabPageCoordinator* newTabPageCoordinator =
         [[NewTabPageCoordinator alloc] initWithBrowser:self.browser];
+    newTabPageCoordinator.panGestureHandler = self.thumbStripPanHandler;
     newTabPageCoordinator.toolbarDelegate = self.toolbarInterface;
     newTabPageCoordinator.webState = webState;
     _ntpCoordinatorsForWebStates[webState] = newTabPageCoordinator;
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index 71bf20a..b48639b5 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -165,6 +165,7 @@
     "//ios/chrome/browser/ui/content_suggestions/cells:cells_ui",
     "//ios/chrome/browser/ui/content_suggestions/identifier",
     "//ios/chrome/browser/ui/elements",
+    "//ios/chrome/browser/ui/gestures",
     "//ios/chrome/browser/ui/list_model",
     "//ios/chrome/browser/ui/ntp",
     "//ios/chrome/browser/ui/ntp_tile_views",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h
index d4a87c0c..46fbebc5 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h
@@ -13,6 +13,7 @@
 
 @class ContentSuggestionsHeaderViewController;
 @protocol NewTabPageControllerDelegate;
+@class ViewRevealingVerticalPanHandler;
 
 // Coordinator to manage the Suggestions UI via a
 // ContentSuggestionsViewController.
@@ -32,6 +33,9 @@
 @property(nonatomic, strong, readonly)
     UICollectionViewController* viewController;
 
+// The pan gesture handler for the view controller.
+@property(nonatomic, weak) ViewRevealingVerticalPanHandler* panGestureHandler;
+
 // Dismisses all modals owned by the NTP mediator.
 - (void)dismissModals;
 
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
index 34d67db..b638c30 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -284,6 +284,7 @@
   self.suggestionsViewController.discoverFeedMenuHandler = self;
   self.suggestionsViewController.discoverFeedMetricsRecorder =
       self.discoverFeedMetricsRecorder;
+  self.suggestionsViewController.panGestureHandler = self.panGestureHandler;
 
   self.discoverFeedHeaderDelegate =
       self.suggestionsViewController.discoverFeedHeaderDelegate;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h
index a238ad0..df076449a 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h
@@ -26,6 +26,7 @@
 @protocol SnackbarCommands;
 @protocol SuggestedContent;
 @protocol ThemeChangeDelegate;
+@class ViewRevealingVerticalPanHandler;
 
 extern NSString* const
     kContentSuggestionsMostVisitedAccessibilityIdentifierPrefix;
@@ -74,6 +75,9 @@
 @property(nonatomic, strong)
     DiscoverFeedMetricsRecorder* discoverFeedMetricsRecorder;
 
+// The pan gesture handler for the hider view controller.
+@property(nonatomic, weak) ViewRevealingVerticalPanHandler* panGestureHandler;
+
 - (void)setDataSource:(id<ContentSuggestionsDataSource>)dataSource;
 - (void)setDispatcher:(id<SnackbarCommands>)dispatcher;
 
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 b12fa0c..433b834b 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
@@ -31,6 +31,7 @@
 #import "ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h"
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
 #import "ios/chrome/browser/ui/content_suggestions/theme_change_delegate.h"
+#import "ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
 #import "ios/chrome/browser/ui/ntp_tile_views/ntp_tile_layout_util.h"
 #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
@@ -709,6 +710,7 @@
 
 - (void)scrollViewDidScroll:(UIScrollView*)scrollView {
   [super scrollViewDidScroll:scrollView];
+  [self.panGestureHandler scrollViewDidScroll:scrollView];
   [self.overscrollActionsController scrollViewDidScroll:scrollView];
   [self.headerSynchronizer updateFakeOmniboxOnCollectionScroll];
   self.scrolledToTop =
@@ -737,6 +739,7 @@
 
 - (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView {
   [self.overscrollActionsController scrollViewWillBeginDragging:scrollView];
+  [self.panGestureHandler scrollViewWillBeginDragging:scrollView];
   self.scrollStartPosition = scrollView.contentOffset.y;
 }
 
@@ -745,6 +748,8 @@
   [super scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
   [self.overscrollActionsController scrollViewDidEndDragging:scrollView
                                               willDecelerate:decelerate];
+  [self.panGestureHandler scrollViewDidEndDragging:scrollView
+                                    willDecelerate:decelerate];
   [self.discoverFeedMetricsRecorder
       recordFeedScrolled:scrollView.contentOffset.y - self.scrollStartPosition];
 }
@@ -759,6 +764,9 @@
       scrollViewWillEndDragging:scrollView
                    withVelocity:velocity
             targetContentOffset:targetContentOffset];
+  [self.panGestureHandler scrollViewWillEndDragging:scrollView
+                                       withVelocity:velocity
+                                targetContentOffset:targetContentOffset];
 }
 
 #pragma mark - UIGestureRecognizerDelegate
diff --git a/ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h b/ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h
index 195c03e4..24536a2 100644
--- a/ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h
+++ b/ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h
@@ -12,10 +12,16 @@
 
 // Responsible for handling vertical pan gestures to reveal/hide a view behind
 // another.
+// When passed UIScrollViewDelegate calls, this object will handle those calls
+// to reveal/hide a view with some specific behaviors:
+//   1. The view will only reveal when the scrollView scroll starts from the
+//      top of the scroll view.
+//   2. When the view is peeked, scrolling down (moving the finger up) will
+//      cause the view to become hidden.
 // TODO(crbug.com/1123512): Add support for going straight from a Hidden state
 // to a revealed state (and vice-versa) if the gesture's translation and
 // velocity are enough to trigger such transition.
-@interface ViewRevealingVerticalPanHandler : NSObject
+@interface ViewRevealingVerticalPanHandler : NSObject <UIScrollViewDelegate>
 
 // |peekedHeight| is the height of the view when peeked (partially revealed).
 // |revealedCoverHeight| is the height of the cover view that remains visible
diff --git a/ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.mm b/ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.mm
index c62a039..21348f2 100644
--- a/ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.mm
+++ b/ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h"
 
+#import "base/notreached.h"
 #include "base/numerics/ranges.h"
 #import "ios/chrome/browser/ui/gestures/layout_switcher.h"
 
@@ -55,6 +56,12 @@
 // Whether new pan gestures should be handled. Set to NO when a pan gesture ends
 // and set to YES when a pan gesture starts while layoutInTransition is NO.
 @property(nonatomic, assign) BOOL gesturesEnabled;
+
+// The contentOffset during the previous call to -scrollViewDidScroll:. Used to
+// keep the contentOffset the same during successive calls to
+// -scrollViewDidScroll:.
+@property(nonatomic, assign) CGPoint lastScrollOffset;
+
 @end
 
 @implementation ViewRevealingVerticalPanHandler
@@ -356,4 +363,75 @@
   }
 }
 
+#pragma mark - UIScrollViewDelegate
+
+- (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView {
+  switch (self.currentState) {
+    case ViewRevealState::Hidden:
+      // The transition out of hidden state can only start if the scroll view
+      // starts dragging from the top.
+      if (!self.animator.isRunning && scrollView.contentOffset.y != 0) {
+        return;
+      }
+      break;
+    case ViewRevealState::Peeked:
+      break;
+    case ViewRevealState::Revealed:
+      // The scroll views should be covered in Revealed state, so should not
+      // be able to be scrolled.
+      NOTREACHED();
+      break;
+  }
+  [self panGestureBegan];
+  self.lastScrollOffset = scrollView.contentOffset;
+}
+
+- (void)scrollViewDidScroll:(UIScrollView*)scrollView {
+  // These delegate methods are approximating the pan gesture handling from
+  // above, so only change things if the user is actively scrolling.
+  if (!scrollView.isDragging) {
+    return;
+  }
+  UIPanGestureRecognizer* gesture = scrollView.panGestureRecognizer;
+  CGFloat translationY = [gesture translationInView:gesture.view.superview].y;
+  // When in Peeked state, scrolling can only transition to Hidden state.
+  if (self.currentState == ViewRevealState::Peeked && translationY > 0) {
+    translationY = 0;
+  }
+  [self panGestureChangedWithTranslation:translationY];
+  // During the transition, the ViewRevealingAnimatees should be moving, not the
+  // scroll view.
+  if (self.animator.fractionComplete > 0 &&
+      self.animator.fractionComplete < 1) {
+    CGPoint currentScrollOffset = scrollView.contentOffset;
+    currentScrollOffset.y = std::max(self.lastScrollOffset.y, 0.0);
+    scrollView.contentOffset = currentScrollOffset;
+  }
+  self.lastScrollOffset = scrollView.contentOffset;
+}
+
+- (void)scrollViewWillEndDragging:(UIScrollView*)scrollView
+                     withVelocity:(CGPoint)velocity
+              targetContentOffset:(inout CGPoint*)targetContentOffset {
+  if (self.currentState == ViewRevealState::Hidden &&
+      self.animator.state != UIViewAnimatingStateActive) {
+    return;
+  }
+  UIPanGestureRecognizer* gesture = scrollView.panGestureRecognizer;
+  CGFloat translationY = [gesture translationInView:gesture.view.superview].y;
+  CGFloat velocityY = [gesture velocityInView:gesture.view.superview].y;
+  // When in Peeked state, scrolling can only transition to Hidden state.
+  if (self.currentState == ViewRevealState::Peeked && translationY > 0) {
+    translationY = 0;
+    velocityY = 0;
+  }
+
+  [self panGestureEndedWithTranslation:translationY velocity:velocityY];
+}
+
+- (void)scrollViewDidEndDragging:(UIScrollView*)scrollView
+                  willDecelerate:(BOOL)decelerate {
+  // No-op.
+}
+
 @end
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h
index 7fe63fe..856894e 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h
@@ -14,6 +14,7 @@
 }
 
 @protocol NewTabPageControllerDelegate;
+@class ViewRevealingVerticalPanHandler;
 
 // Coordinator handling the NTP.
 @interface NewTabPageCoordinator
@@ -37,6 +38,9 @@
 // Returns |YES| if the coordinator is started.
 @property(nonatomic, assign, getter=isStarted) BOOL started;
 
+// The pan gesture handler for the view controller.
+@property(nonatomic, weak) ViewRevealingVerticalPanHandler* panGestureHandler;
+
 // Dismisses all modals owned by the NTP.
 - (void)dismissModals;
 
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
index ed461a0..c1ebaac2 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -79,6 +79,8 @@
                            browser:self.browser];
     self.contentSuggestionsCoordinator.webState = self.webState;
     self.contentSuggestionsCoordinator.toolbarDelegate = self.toolbarDelegate;
+    self.contentSuggestionsCoordinator.panGestureHandler =
+        self.panGestureHandler;
 
     [self.contentSuggestionsCoordinator start];
     base::RecordAction(base::UserMetricsAction("MobileNTPShowMostVisited"));
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 8bcecea..c8fef6a 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -453,6 +453,7 @@
     ":constants",
     ":eg_test_support+eg2",
     "//components/content_settings/core/common",
+    "//components/omnibox/common",
     "//components/strings",
     "//components/url_formatter",
     "//components/version_info:version_info",
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm
index a7fc2551..e1785a8 100644
--- a/ios/chrome/browser/web/cache_egtest.mm
+++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -6,6 +6,7 @@
 
 #include "base/ios/ios_util.h"
 #include "base/strings/stringprintf.h"
+#include "components/omnibox/common/omnibox_features.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
@@ -110,6 +111,25 @@
 
 @implementation CacheTestCase
 
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config;
+
+  // Features are enabled or disabled based on the name of the test that is
+  // running. This is done because it is inefficient to use
+  // ensureAppLaunchedWithConfiguration for each test.
+  if ([self isRunningTest:@selector
+            (testCachingBehaviorOnSelectOmniboxSuggestion)]) {
+    // Explicitly disable delay for feature OnDeviceHeadProviderNonIncognito,
+    // which will otherwise cause flakiness for this test in build iphone-device
+    // (crbug.com/1153136).
+    config.additional_args.push_back(
+        std::string("--enable-features=") +
+        std::string(omnibox::kOnDeviceHeadProviderNonIncognito.name) +
+        std::string(":DelayOnDeviceHeadSuggestRequestMs/0"));
+  }
+  return config;
+}
+
 // Tests caching behavior on navigate back and page reload. Navigate back should
 // use the cached page. Page reload should use cache-control in the request
 // header and show updated page.
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn
index 968274f..25c888e 100644
--- a/ios/third_party/material_components_ios/BUILD.gn
+++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -1542,6 +1542,13 @@
   ]
 }
 
+# TODO(crbug.com/1153275): MDCTabBarViewItemView.h has incomplete nullability
+# specification, causing compilation to fail. Disable the warning until this
+# is fixed in MDC. Remove this once fixed.
+config("disable_nullability_completeness") {
+  cflags = [ "-Wno-nullability-completeness" ]
+}
+
 ios_framework_bundle("material_components_ios") {
   sources = _mdc_sources
 
@@ -1579,6 +1586,11 @@
     # material_components_ios internally uses deprecated methods.
     # Disable the warning about deprecation usage.
     ":disable_deprecated_errors",
+
+    # TODO(crbug.com/1153275): MDCTabBarViewItemView.h has incomplete
+    # nullability specification, causing compilation to fail. Disable
+    # the warning until this is fixed in MDC. Remove this once fixed.
+    ":disable_nullability_completeness",
   ]
 }
 
diff --git a/media/gpu/test/video_encoder/video_encoder_client.cc b/media/gpu/test/video_encoder/video_encoder_client.cc
index e0d91b8..deec69a7 100644
--- a/media/gpu/test/video_encoder/video_encoder_client.cc
+++ b/media/gpu/test/video_encoder/video_encoder_client.cc
@@ -500,6 +500,15 @@
 
   num_encodes_requested_++;
   num_outstanding_encode_requests_++;
+  if (encoder_client_config_.encode_interval) {
+    // Schedules the next encode here if we're encoding at a fixed ratio.
+    // Otherwise the next encode will be scheduled immediately when the previous
+    // operation is done in EncodeDoneTask().
+    encoder_client_task_runner_->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&VideoEncoderClient::EncodeNextFrameTask, weak_this_),
+        *encoder_client_config_.encode_interval);
+  }
 }
 
 void VideoEncoderClient::FlushTask() {
@@ -543,10 +552,12 @@
   num_outstanding_encode_requests_--;
   FlushDoneTaskIfNeeded();
 
-  // Queue the next frame to be encoded.
-  encoder_client_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&VideoEncoderClient::EncodeNextFrameTask, weak_this_));
+  if (!encoder_client_config_.encode_interval) {
+    // Queue the next frame to be encoded.
+    encoder_client_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&VideoEncoderClient::EncodeNextFrameTask, weak_this_));
+  }
 }
 
 void VideoEncoderClient::FlushDoneTask(bool success) {
diff --git a/media/gpu/test/video_encoder/video_encoder_client.h b/media/gpu/test/video_encoder/video_encoder_client.h
index 092a768b..3e55441f 100644
--- a/media/gpu/test/video_encoder/video_encoder_client.h
+++ b/media/gpu/test/video_encoder/video_encoder_client.h
@@ -54,6 +54,10 @@
   uint32_t bitrate = kDefaultBitrate;
   // The desired framerate in frames/second.
   uint32_t framerate = 30.0;
+  // The interval of calling VideoEncodeAccelerator::Encode(). If this is
+  // base::nullopt, Encode() is called once VideoEncodeAccelerator consumes
+  // the previous VideoFrames.
+  base::Optional<base::TimeDelta> encode_interval = base::nullopt;
   // The number of frames to be encoded. This can be more than the number of
   // frames in the video, and in which case the VideoEncoderClient loops the
   // video during encoding.
diff --git a/media/gpu/video_encode_accelerator_perf_tests.cc b/media/gpu/video_encode_accelerator_perf_tests.cc
index f8e9e3a..c21abca 100644
--- a/media/gpu/video_encode_accelerator_perf_tests.cc
+++ b/media/gpu/video_encode_accelerator_perf_tests.cc
@@ -59,6 +59,8 @@
 
 media::test::VideoEncoderTestEnvironment* g_env;
 
+constexpr size_t kNumFramesToEncodeForPerformance = 300;
+
 // Default output folder used to store performance metrics.
 constexpr const base::FilePath::CharType* kDefaultOutputFolder =
     FILE_PATH_LITERAL("perf_metrics");
@@ -272,7 +274,8 @@
   // Create a new video encoder instance.
   std::unique_ptr<VideoEncoder> CreateVideoEncoder(const Video* video,
                                                    VideoCodecProfile profile,
-                                                   uint32_t bitrate) {
+                                                   uint32_t bitrate,
+                                                   uint32_t encoder_rate = 0) {
     LOG_ASSERT(video);
 
     std::vector<std::unique_ptr<BitstreamProcessor>> bitstream_processors;
@@ -283,6 +286,10 @@
     constexpr size_t kNumTemporalLayers = 1u;
     VideoEncoderClientConfig config(video, profile, kNumTemporalLayers,
                                     bitrate);
+    config.num_frames_to_encode = kNumFramesToEncodeForPerformance;
+    if (encoder_rate != 0)
+      config.encode_interval =
+          base::TimeDelta::FromSeconds(/*secs=*/1u) / encoder_rate;
     auto video_encoder =
         VideoEncoder::Create(config, g_env->GetGpuMemoryBufferFactory(),
                              std::move(bitstream_processors));
@@ -297,9 +304,9 @@
 
 }  // namespace
 
-// Encode video from start to end while measuring uncapped performance. This
-// test will encode a video as fast as possible, and gives an idea about the
-// maximum output of the encoder.
+// Encode |kNumFramesToEncodeForPerformance| frames while measuring uncapped
+// performance. This test will encode a video as fast as possible, and gives an
+// idea about the maximum output of the encoder.
 TEST_F(VideoEncoderTest, MeasureUncappedPerformance) {
   auto encoder =
       CreateVideoEncoder(g_env->Video(), g_env->Profile(), g_env->Bitrate());
@@ -314,9 +321,28 @@
   metrics.WriteToFile();
 
   EXPECT_EQ(encoder->GetFlushDoneCount(), 1u);
-  EXPECT_EQ(encoder->GetFrameReleasedCount(), g_env->Video()->NumFrames());
+  EXPECT_EQ(encoder->GetFrameReleasedCount(), kNumFramesToEncodeForPerformance);
 }
 
+// Encode |kNumFramesToEncodeForPerformance| frames while measuring uncapped
+// performance. This test will encode a video at a fixed ratio, 30fps.
+// This test can be used to measure the cpu metrics during encoding.
+TEST_F(VideoEncoderTest, MeasureCappedPerformance) {
+  const uint32_t kEncodeRate = 30;
+  auto encoder = CreateVideoEncoder(g_env->Video(), g_env->Profile(),
+                                    g_env->Bitrate(), kEncodeRate);
+  performance_evaluator_->StartMeasuring();
+  encoder->Encode();
+  EXPECT_TRUE(encoder->WaitForFlushDone());
+  performance_evaluator_->StopMeasuring();
+
+  auto metrics = performance_evaluator_->Metrics();
+  metrics.WriteToConsole();
+  metrics.WriteToFile();
+
+  EXPECT_EQ(encoder->GetFlushDoneCount(), 1u);
+  EXPECT_EQ(encoder->GetFrameReleasedCount(), kNumFramesToEncodeForPerformance);
+}
 }  // namespace test
 }  // namespace media
 
diff --git a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
index e38f88e..9267af1 100644
--- a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
+++ b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
@@ -78,11 +78,8 @@
                                   v8::NewStringType::kNormal)
               .ToLocalChecked();
 
-      v8::ScriptOrigin origin(
-          name, v8::Local<v8::Integer>(), v8::Local<v8::Integer>(),
-          v8::Local<v8::Boolean>(), v8::Local<v8::Integer>(),
-          v8::Local<v8::Value>(), v8::Local<v8::Boolean>(),
-          v8::Local<v8::Boolean>(), v8::True(isolate));
+      v8::ScriptOrigin origin(name, 0, 0, false, -1, v8::Local<v8::Value>(),
+                              false, false, true);
       v8::ScriptCompiler::Source source(source_v8_string, origin);
       v8::MaybeLocal<v8::Module> module =
           v8::ScriptCompiler::CompileModule(isolate, &source);
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index ec52e07..e43c2f46 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -163,7 +163,6 @@
     "platform/web_audio_device.h",
     "platform/web_audio_latency_hint.h",
     "platform/web_audio_source_provider.h",
-    "platform/web_battery_savings.h",
     "platform/web_blob_info.h",
     "platform/web_cache.h",
     "platform/web_callbacks.h",
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index c08123f..dec840a 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -23,7 +23,6 @@
   generate_java = true
   sources = [
     "ad_tagging/ad_frame.mojom",
-    "agents/agent_metrics.mojom",
     "app_banner/app_banner.mojom",
     "appcache/appcache.mojom",
     "appcache/appcache_info.mojom",
diff --git a/third_party/blink/public/mojom/agents/OWNERS b/third_party/blink/public/mojom/agents/OWNERS
deleted file mode 100644
index 08850f4..0000000
--- a/third_party/blink/public/mojom/agents/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/agents/agent_metrics.mojom b/third_party/blink/public/mojom/agents/agent_metrics.mojom
deleted file mode 100644
index b895d5b..0000000
--- a/third_party/blink/public/mojom/agents/agent_metrics.mojom
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-// Per-process agent data is reported as a list of agent strings. These strings
-// will either be a "site-like" string or the empty string. A site like string
-// will be the Agent's |protocol| + "://" + |registrable domain|. The empty
-// string specifies that the agent is for a non-domain based document (e.g.
-// opaque or local URL).
-struct AgentMetricsData {
-   array<string> agents;
-};
-
-interface AgentMetricsCollectorHost {
-  // Reports Blink agent related metrics to the browser so that we can track
-  // per-process counts.
-  ReportRendererMetrics(AgentMetricsData data);
-};
diff --git a/third_party/blink/public/platform/web_request_peer.h b/third_party/blink/public/platform/web_request_peer.h
index 3c95ddf1..e1e06fde 100644
--- a/third_party/blink/public/platform/web_request_peer.h
+++ b/third_party/blink/public/platform/web_request_peer.h
@@ -72,6 +72,11 @@
   virtual void OnCompletedRequest(
       const network::URLLoaderCompletionStatus& status) = 0;
 
+  // Called when the page is in BackForwardCache, and when the network request
+  // is redirected or the datapipe is already drained. This method evicts the
+  // entry.
+  virtual void EvictFromBackForwardCache() = 0;
+
   virtual ~WebRequestPeer() {}
 };
 
diff --git a/third_party/blink/public/platform/web_url_loader_client.h b/third_party/blink/public/platform/web_url_loader_client.h
index 55be6c1..c1780b2b 100644
--- a/third_party/blink/public/platform/web_url_loader_client.h
+++ b/third_party/blink/public/platform/web_url_loader_client.h
@@ -122,6 +122,12 @@
                        int64_t total_encoded_body_length,
                        int64_t total_decoded_body_length) {}
 
+  // Called when redirect or upload happens when the page is in
+  // BackForwardCache.
+  // TODO(yuzus): ResponseBodyLoader should implement the eviction logic instead
+  // of client. Move the capability to the loader.
+  virtual void EvictFromBackForwardCache() {}
+
   // Value passed to DidFinishLoading when total encoded data length isn't
   // known.
   static const int64_t kUnknownEncodedDataLength = -1;
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.cc b/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.cc
index 77d95d3..a22d5d7 100644
--- a/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.cc
+++ b/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.cc
@@ -203,10 +203,9 @@
   DCHECK_LE(scopes_size, base::size(scopes));
 
   v8::ScriptOrigin origin(
-      V8String(isolate, source_url_),
-      v8::Integer::New(isolate, position_.line_.ZeroBasedInt()),
-      v8::Integer::New(isolate, position_.column_.ZeroBasedInt()),
-      v8::True(isolate));  // True as |SanitizeScriptErrors::kDoNotSanitize|
+      V8String(isolate, source_url_), position_.line_.ZeroBasedInt(),
+      position_.column_.ZeroBasedInt(),
+      true);  // true as |SanitizeScriptErrors::kDoNotSanitize|
   v8::ScriptCompiler::Source source(V8String(isolate, script_body_), origin);
 
   v8::Local<v8::Function> compiled_function;
diff --git a/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc b/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
index b54f028e0..47a74ecd 100644
--- a/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
+++ b/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
@@ -115,26 +115,39 @@
     DVLOG(1) << "ScheduledAction::execute " << this << ": context is empty";
     return;
   }
-  // ExecutionContext::CanExecuteScripts() relies on the current context to
-  // determine if it is allowed. Enter the scope here.
-  ScriptState::Scope scope(script_state_->Get());
-  if (!context->CanExecuteScripts(kAboutToExecuteScript)) {
-    DVLOG(1) << "ScheduledAction::execute " << this
-             << ": window can not execute scripts";
-    return;
-  }
 
-  // https://html.spec.whatwg.org/C/#timer-initialisation-steps
-  if (function_) {
-    DVLOG(1) << "ScheduledAction::execute " << this << ": have function";
-    function_->InvokeAndReportException(context->ToScriptWrappable(),
-                                        arguments_);
-    return;
+  {
+    // ExecutionContext::CanExecuteScripts() relies on the current context to
+    // determine if it is allowed. Enter the scope here.
+    // TODO(crbug.com/1151165): Consider merging CanExecuteScripts() calls,
+    // because once crbug.com/1111134 is done, CanExecuteScripts() will be
+    // always called below inside
+    // - InvokeAndReportException() => V8Function::Invoke() =>
+    //   IsCallbackFunctionRunnable() and
+    // - V8ScriptRunner::CompileAndRunScript().
+    ScriptState::Scope scope(script_state_->Get());
+    if (!context->CanExecuteScripts(kAboutToExecuteScript)) {
+      DVLOG(1) << "ScheduledAction::execute " << this
+               << ": window can not execute scripts";
+      return;
+    }
+
+    // https://html.spec.whatwg.org/C/#timer-initialisation-steps
+    if (function_) {
+      DVLOG(1) << "ScheduledAction::execute " << this << ": have function";
+      function_->InvokeAndReportException(context->ToScriptWrappable(),
+                                          arguments_);
+      return;
+    }
+
+    // We exit the scope here, because we enter v8::Context during the main
+    // evaluation below.
   }
 
   // We use |SanitizeScriptErrors::kDoNotSanitize| because muted errors flag is
   // not set in https://html.spec.whatwg.org/C/#timer-initialisation-steps
   DVLOG(1) << "ScheduledAction::execute " << this << ": executing from source";
+  v8::HandleScope scope(script_state_->GetIsolate());
   if (LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(context)) {
     window->GetScriptController().ExecuteScriptAndReturnValue(
         script_state_->GetContext(),
diff --git a/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
index 7e6af016..48fdc46 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
@@ -286,8 +286,6 @@
   }
   DCHECK_EQ(script_state->GetIsolate(), GetIsolate());
 
-  v8::Context::Scope scope(script_state->GetContext());
-
   return ExecuteScriptAndReturnValue(script_state->GetContext(), source_code,
                                      base_url, sanitize_script_errors,
                                      fetch_options);
@@ -357,8 +355,6 @@
   // WindowProxy() inside ToScriptState() above. Add a helper which makes that
   // obvious?
 
-  v8::Context::Scope scope(script_state->GetContext());
-
   return ExecuteScriptAndReturnValue(script_state->GetContext(), source,
                                      base_url, sanitize_script_errors);
 }
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
index dea409f..ce93815 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
@@ -409,6 +409,9 @@
   readable_stream->Serialize(script_state, local_port, exception_state);
   if (exception_state.HadException())
     return;
+  // The last element is added by the above `AddStreamChannel()` call.
+  streams_.back().readable_optimizer =
+      readable_stream->TakeTransferringOptimizer();
 }
 
 void SerializedScriptValue::TransferWritableStreams(
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
index a0565f4..02d378e1 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
@@ -31,6 +31,7 @@
 #include "third_party/blink/renderer/core/mojo/mojo_handle.h"
 #include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
 #include "third_party/blink/renderer/core/streams/transform_stream.h"
 #include "third_party/blink/renderer/core/streams/writable_stream.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
@@ -567,7 +568,7 @@
       return ReadableStream::Deserialize(
           script_state_,
           CreateEntangledPort(GetScriptState(), streams_[index].channel),
-          exception_state);
+          std::move(streams_[index].readable_optimizer), exception_state);
     }
     case kWritableStreamTransferTag: {
       if (!TransferableStreamsEnabled())
@@ -599,8 +600,9 @@
       // 1. Let readableRecord be !
       //    StructuredDeserializeWithTransfer(dataHolder.[[readable]], the
       //    current Realm).
-      ReadableStream* readable = ReadableStream::Deserialize(
-          script_state_, port_for_readable, exception_state);
+      ReadableStream* readable =
+          ReadableStream::Deserialize(script_state_, port_for_readable,
+                                      /*optimizer=*/nullptr, exception_state);
       if (!readable)
         return nullptr;
 
diff --git a/third_party/blink/renderer/bindings/core/v8/source_location.cc b/third_party/blink/renderer/bindings/core/v8/source_location.cc
index a7dada1..9288c60a 100644
--- a/third_party/blink/renderer/bindings/core/v8/source_location.cc
+++ b/third_party/blink/renderer/bindings/core/v8/source_location.cc
@@ -86,8 +86,7 @@
   if (debugger)
     stack_trace = debugger->GetV8Inspector()->createStackTrace(stack);
 
-  int script_id =
-      static_cast<int>(message->GetScriptOrigin().ScriptID()->Value());
+  int script_id = message->GetScriptOrigin().ScriptId();
   if (!stack.IsEmpty() && stack->GetFrameCount() > 0) {
     int top_script_id = stack->GetFrame(isolate, 0)->GetScriptId();
     if (top_script_id == script_id)
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
index 44c1182..0f995990 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
@@ -321,17 +321,14 @@
   ReferrerScriptInfo referrer_info;
   v8::ScriptOrigin origin(
       V8String(isolate, file_name),
-      v8::Integer::New(isolate, 0),  // line_offset
-      v8::Integer::New(isolate, 0),  // column_offset
-      v8::Boolean::New(
-          isolate,
-          opaque_mode == OpaqueMode::kNotOpaque),  // is_shared_cross_origin
-      v8::Local<v8::Integer>(),                    // script_id
-      V8String(isolate, String("")),               // source_map_url
-      v8::Boolean::New(isolate,
-                       opaque_mode == OpaqueMode::kOpaque),  // is_opaque
-      v8::False(isolate),                                    // is_wasm
-      v8::False(isolate),                                    // is_module
+      0,                                      // line_offset
+      0,                                      // column_offset
+      opaque_mode == OpaqueMode::kNotOpaque,  // is_shared_cross_origin
+      -1,                                     // script_id
+      V8String(isolate, String("")),          // source_map_url
+      opaque_mode == OpaqueMode::kOpaque,     // is_opaque
+      false,                                  // is_wasm
+      false,                                  // is_module
       referrer_info.ToV8HostDefinedOptions(isolate));
   v8::Local<v8::String> code(V8String(isolate, script_string));
   v8::ScriptCompiler::Source source(code, origin);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
index ff68180..46c6559 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -220,16 +220,13 @@
   // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
   // 1, whereas v8 starts at 0.
   v8::ScriptOrigin origin(
-      V8String(isolate, file_name),
-      v8::Integer::New(isolate, script_start_position.line_.ZeroBasedInt()),
-      v8::Integer::New(isolate, script_start_position.column_.ZeroBasedInt()),
-      v8::Boolean::New(isolate, sanitize_script_errors ==
-                                    SanitizeScriptErrors::kDoNotSanitize),
-      v8::Local<v8::Integer>(), V8String(isolate, source.SourceMapUrl()),
-      v8::Boolean::New(
-          isolate, sanitize_script_errors == SanitizeScriptErrors::kSanitize),
-      v8::False(isolate),  // is_wasm
-      v8::False(isolate),  // is_module
+      V8String(isolate, file_name), script_start_position.line_.ZeroBasedInt(),
+      script_start_position.column_.ZeroBasedInt(),
+      sanitize_script_errors == SanitizeScriptErrors::kDoNotSanitize, -1,
+      V8String(isolate, source.SourceMapUrl()),
+      sanitize_script_errors == SanitizeScriptErrors::kSanitize,
+      false,  // is_wasm
+      false,  // is_module
       referrer_info.ToV8HostDefinedOptions(isolate));
 
   if (!*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(kTraceEventCategoryGroup)) {
@@ -263,17 +260,16 @@
 
   // |resource_is_shared_cross_origin| is always true and |resource_is_opaque|
   // is always false because CORS is enforced to module scripts.
-  v8::ScriptOrigin origin(
-      V8String(isolate, file_name),
-      v8::Integer::New(isolate, start_position.line_.ZeroBasedInt()),
-      v8::Integer::New(isolate, start_position.column_.ZeroBasedInt()),
-      v8::Boolean::New(isolate, true),   // resource_is_shared_cross_origin
-      v8::Local<v8::Integer>(),          // script id
-      v8::String::Empty(isolate),        // source_map_url
-      v8::Boolean::New(isolate, false),  // resource_is_opaque
-      v8::False(isolate),                // is_wasm
-      v8::True(isolate),                 // is_module
-      referrer_info.ToV8HostDefinedOptions(isolate));
+  v8::ScriptOrigin origin(V8String(isolate, file_name),
+                          start_position.line_.ZeroBasedInt(),
+                          start_position.column_.ZeroBasedInt(),
+                          true,  // resource_is_shared_cross_origin
+                          -1,    // script id
+                          v8::String::Empty(isolate),  // source_map_url
+                          false,                   // resource_is_opaque
+                          false,                   // is_wasm
+                          true,                    // is_module
+                          referrer_info.ToV8HostDefinedOptions(isolate));
 
   v8::Local<v8::String> code = V8String(isolate, source_text);
 
@@ -380,6 +376,8 @@
     RethrowErrorsOption rethrow_errors) {
   DCHECK_EQ(isolate, script_state->GetIsolate());
 
+  v8::Context::Scope scope(script_state->GetContext());
+
   LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(execution_context);
   LocalFrame* frame = window ? window->GetFrame() : nullptr;
   TRACE_EVENT1("devtools.timeline", "EvaluateScript", "data",
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 9cbbff8..2dbac45b 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1224,7 +1224,6 @@
     "events/pointer_event_util_test.cc",
     "events/touch_event_test.cc",
     "events/web_input_event_conversion_test.cc",
-    "execution_context/agent_metrics_collector_test.cc",
     "execution_context/execution_context_lifecycle_state_observer_test.cc",
     "exported/web_document_subresource_filter_test.cc",
     "exported/web_document_test.cc",
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
index a06274f..42bbe80 100644
--- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
@@ -99,7 +99,7 @@
     if (!active_iterator->second)
       continue;
     const RuleSet& rule_set = *active_iterator->second;
-    author_style_sheets_.push_back(sheet);
+    style_sheets_.push_back(sheet);
     AddKeyframeRules(rule_set);
     AddFontFaceRules(rule_set);
     AddTreeBoundaryCrossingRules(rule_set, sheet, index);
@@ -116,7 +116,7 @@
   features.DeviceDependentMediaQueryResults().AppendVector(
       device_dependent_media_query_results_);
 
-  for (auto sheet : author_style_sheets_) {
+  for (auto sheet : style_sheets_) {
     DCHECK(sheet->ownerNode() || sheet->IsConstructed());
     StyleSheetContents* contents = sheet->Contents();
     if (contents->HasOneClient() ||
@@ -134,8 +134,8 @@
   }
 }
 
-void ScopedStyleResolver::ResetAuthorStyle() {
-  author_style_sheets_.clear();
+void ScopedStyleResolver::ResetStyle() {
+  style_sheets_.clear();
   viewport_dependent_media_query_results_.clear();
   device_dependent_media_query_results_.clear();
   keyframes_rule_map_.clear();
@@ -145,12 +145,12 @@
   needs_append_all_sheets_ = false;
 }
 
-const ActiveStyleSheetVector& ScopedStyleResolver::ActiveAuthorStyleSheets() {
+const ActiveStyleSheetVector& ScopedStyleResolver::ActiveStyleSheets() {
   StyleSheetCollection* collection =
       GetTreeScope().GetDocument().GetStyleEngine().StyleSheetCollectionFor(
           *scope_);
   DCHECK(collection);
-  return collection->ActiveAuthorStyleSheets();
+  return collection->ActiveStyleSheets();
 }
 
 // static
@@ -177,8 +177,8 @@
 StyleRuleKeyframes* ScopedStyleResolver::KeyframeStylesForAnimation(
     const AtomicString& animation_name) {
   if (RuntimeEnabledFeatures::CSSKeyframesMemoryReductionEnabled()) {
-    return KeyframeStylesForAnimationFromActiveSheets(
-        animation_name, ActiveAuthorStyleSheets());
+    return KeyframeStylesForAnimationFromActiveSheets(animation_name,
+                                                      ActiveStyleSheets());
   }
 
   if (keyframes_rule_map_.IsEmpty())
@@ -254,11 +254,11 @@
   tree_scope.GetDocument().Timeline().InvalidateKeyframeEffects(tree_scope);
 }
 
-void ScopedStyleResolver::CollectMatchingAuthorRules(
+void ScopedStyleResolver::CollectMatchingElementScopeRules(
     ElementRuleCollector& collector,
     ShadowV0CascadeOrder cascade_order) {
   wtf_size_t sheet_index = 0;
-  for (auto sheet : author_style_sheets_) {
+  for (auto sheet : style_sheets_) {
     DCHECK(sheet->ownerNode() || sheet->IsConstructed());
     MatchRequest match_request(&sheet->Contents()->GetRuleSet(),
                                &scope_->RootNode(), sheet, sheet_index++);
@@ -270,7 +270,7 @@
     ElementRuleCollector& collector,
     ShadowV0CascadeOrder cascade_order) {
   wtf_size_t sheet_index = 0;
-  for (auto sheet : author_style_sheets_) {
+  for (auto sheet : style_sheets_) {
     DCHECK(sheet->ownerNode() || sheet->IsConstructed());
     MatchRequest match_request(&sheet->Contents()->GetRuleSet(),
                                &scope_->RootNode(), sheet, sheet_index++);
@@ -309,7 +309,7 @@
     PartNames& part_names,
     ShadowV0CascadeOrder cascade_order) {
   wtf_size_t sheet_index = 0;
-  for (auto sheet : author_style_sheets_) {
+  for (auto sheet : style_sheets_) {
     DCHECK(sheet->ownerNode() || sheet->IsConstructed());
     MatchRequest match_request(&sheet->Contents()->GetRuleSet(),
                                &scope_->RootNode(), sheet, sheet_index++);
@@ -319,16 +319,15 @@
 }
 
 void ScopedStyleResolver::MatchPageRules(PageRuleCollector& collector) {
-  // Only consider the global author RuleSet for @page rules, as per the HTML5
-  // spec.
+  // Currently, only @page rules in the document scope apply.
   DCHECK(scope_->RootNode().IsDocumentNode());
-  for (auto sheet : author_style_sheets_)
+  for (auto sheet : style_sheets_)
     collector.MatchPageRules(&sheet->Contents()->GetRuleSet());
 }
 
 void ScopedStyleResolver::Trace(Visitor* visitor) const {
   visitor->Trace(scope_);
-  visitor->Trace(author_style_sheets_);
+  visitor->Trace(style_sheets_);
   visitor->Trace(keyframes_rule_map_);
   visitor->Trace(tree_boundary_crossing_rule_set_);
   visitor->Trace(slotted_rule_set_);
@@ -341,24 +340,22 @@
 }
 
 void ScopedStyleResolver::AddTreeBoundaryCrossingRules(
-    const RuleSet& author_rules,
+    const RuleSet& rules,
     CSSStyleSheet* parent_style_sheet,
     unsigned sheet_index) {
   bool is_document_scope = GetTreeScope().RootNode().IsDocumentNode();
-  if (author_rules.DeepCombinatorOrShadowPseudoRules().IsEmpty() &&
-      (is_document_scope ||
-       (author_rules.ContentPseudoElementRules().IsEmpty())))
+  if (rules.DeepCombinatorOrShadowPseudoRules().IsEmpty() &&
+      (is_document_scope || (rules.ContentPseudoElementRules().IsEmpty())))
     return;
 
-  if (!author_rules.DeepCombinatorOrShadowPseudoRules().IsEmpty())
+  if (!rules.DeepCombinatorOrShadowPseudoRules().IsEmpty())
     has_deep_or_shadow_selector_ = true;
 
   auto* rule_set_for_scope = MakeGarbageCollected<RuleSet>();
-  AddRules(rule_set_for_scope,
-           author_rules.DeepCombinatorOrShadowPseudoRules());
+  AddRules(rule_set_for_scope, rules.DeepCombinatorOrShadowPseudoRules());
 
   if (!is_document_scope)
-    AddRules(rule_set_for_scope, author_rules.ContentPseudoElementRules());
+    AddRules(rule_set_for_scope, rules.ContentPseudoElementRules());
 
   if (!tree_boundary_crossing_rule_set_) {
     tree_boundary_crossing_rule_set_ =
@@ -386,15 +383,15 @@
   slotted_rule_set_ = nullptr;
 }
 
-void ScopedStyleResolver::AddSlottedRules(const RuleSet& author_rules,
+void ScopedStyleResolver::AddSlottedRules(const RuleSet& rules,
                                           CSSStyleSheet* parent_style_sheet,
                                           unsigned sheet_index) {
   bool is_document_scope = GetTreeScope().RootNode().IsDocumentNode();
-  if (is_document_scope || author_rules.SlottedPseudoElementRules().IsEmpty())
+  if (is_document_scope || rules.SlottedPseudoElementRules().IsEmpty())
     return;
 
   auto* slotted_rule_set = MakeGarbageCollected<RuleSet>();
-  AddRules(slotted_rule_set, author_rules.SlottedPseudoElementRules());
+  AddRules(slotted_rule_set, rules.SlottedPseudoElementRules());
 
   // In case ::slotted rule is used in V0/V1 mixed document, put ::slotted
   // rules in tree boundary crossing rules as the pure v1 fast path in
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
index 9460d74..29787ff 100644
--- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
+++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
@@ -63,8 +63,9 @@
       const AtomicString& animation_name);
 
   void AppendActiveStyleSheets(unsigned index, const ActiveStyleSheetVector&);
-  void CollectMatchingAuthorRules(ElementRuleCollector&,
-                                  ShadowV0CascadeOrder = kIgnoreCascadeOrder);
+  void CollectMatchingElementScopeRules(
+      ElementRuleCollector&,
+      ShadowV0CascadeOrder = kIgnoreCascadeOrder);
   void CollectMatchingShadowHostRules(
       ElementRuleCollector&,
       ShadowV0CascadeOrder = kIgnoreCascadeOrder);
@@ -81,7 +82,7 @@
   void CollectFeaturesTo(RuleFeatureSet&,
                          HeapHashSet<Member<const StyleSheetContents>>&
                              visited_shared_style_sheet_contents) const;
-  void ResetAuthorStyle();
+  void ResetStyle();
   bool HasDeepOrShadowSelector() const { return has_deep_or_shadow_selector_; }
   void SetHasUnresolvedKeyframesRule() {
     has_unresolved_keyframes_rule_ = true;
@@ -103,11 +104,11 @@
   void AddFontFaceRules(const RuleSet&);
   void AddKeyframeStyle(StyleRuleKeyframes*);
 
-  const ActiveStyleSheetVector& ActiveAuthorStyleSheets();
+  const ActiveStyleSheetVector& ActiveStyleSheets();
 
   Member<TreeScope> scope_;
 
-  HeapVector<Member<CSSStyleSheet>> author_style_sheets_;
+  HeapVector<Member<CSSStyleSheet>> style_sheets_;
   MediaQueryResultList viewport_dependent_media_query_results_;
   MediaQueryResultList device_dependent_media_query_results_;
 
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 53c5ca1..ed4f80eb 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -44,7 +44,6 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
 #include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
@@ -699,20 +698,6 @@
     AdjustStyleForDisplay(style, layout_parent_style, element,
                           element ? &element->GetDocument() : nullptr);
 
-    // TOOD(crbug.com/1146925): Sticky content in a scrollable FIELDSET triggers
-    // a DHCECK failure in |StickyPositionScrollingConstraints::
-    // AncestorContainingBlockOffset()|. We disable it until the root cause is
-    // fixed.
-    if (style.GetPosition() == EPosition::kSticky && element) {
-      for (const Node& ancestor : FlatTreeTraversal::AncestorsOf(*element)) {
-        if (const auto* fieldset = DynamicTo<HTMLFieldSetElement>(ancestor)) {
-          if (!fieldset->ComputedStyleRef().IsOverflowVisibleAlongBothAxes())
-            style.SetPosition(EPosition::kStatic);
-          break;
-        }
-      }
-    }
-
     // If this is a child of a LayoutNGCustom, we need the name of the parent
     // layout function for invalidation purposes.
     if (layout_parent_style.IsDisplayLayoutCustomBox()) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 671feb9..8d88bf1 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -430,7 +430,7 @@
                                    ElementRuleCollector& collector) {
   if (element_scope_resolver) {
     collector.ClearMatchedRules();
-    element_scope_resolver->CollectMatchingAuthorRules(collector);
+    element_scope_resolver->CollectMatchingElementScopeRules(collector);
     element_scope_resolver->CollectMatchingTreeBoundaryCrossingRules(collector);
     collector.SortAndTransferMatchedRules();
   }
@@ -621,8 +621,8 @@
 
   // Apply normal rules from element scope.
   if (element_scope_resolver) {
-    element_scope_resolver->CollectMatchingAuthorRules(collector,
-                                                       ++cascade_order);
+    element_scope_resolver->CollectMatchingElementScopeRules(collector,
+                                                             ++cascade_order);
   }
 
   // Apply /deep/ and ::shadow rules from outer scopes, and ::content from
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
index c7c44d0..17d0efc0 100644
--- a/third_party/blink/renderer/core/css/style_engine.cc
+++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -426,18 +426,12 @@
                                                   MediaValueChange change) {
   auto* collection = StyleSheetCollectionFor(tree_scope);
   DCHECK(collection);
-  if (MediaQueryAffectingValueChanged(collection->ActiveAuthorStyleSheets(),
+  if (MediaQueryAffectingValueChanged(collection->ActiveStyleSheets(),
                                       change)) {
     SetNeedsActiveStyleUpdate(tree_scope);
   }
 }
 
-void StyleEngine::MediaQueriesChangedInScope(TreeScope& tree_scope) {
-  if (ScopedStyleResolver* resolver = tree_scope.GetScopedStyleResolver())
-    resolver->SetNeedsAppendAllSheets();
-  SetNeedsActiveStyleUpdate(tree_scope);
-}
-
 void StyleEngine::WatchedSelectorsChanged() {
   DCHECK(!IsHTMLImport());
   DCHECK(global_rule_set_);
@@ -621,16 +615,16 @@
     UpdateActiveStyle();
 
   if (active_tree_scopes_.IsEmpty())
-    return GetDocumentStyleSheetCollection().ActiveAuthorStyleSheets();
+    return GetDocumentStyleSheetCollection().ActiveStyleSheets();
 
   ActiveStyleSheetVector active_style_sheets;
 
   active_style_sheets.AppendVector(
-      GetDocumentStyleSheetCollection().ActiveAuthorStyleSheets());
+      GetDocumentStyleSheetCollection().ActiveStyleSheets());
   for (TreeScope* tree_scope : active_tree_scopes_) {
     if (TreeScopeStyleSheetCollection* collection =
             style_sheet_collection_map_.at(tree_scope))
-      active_style_sheets.AppendVector(collection->ActiveAuthorStyleSheets());
+      active_style_sheets.AppendVector(collection->ActiveStyleSheets());
   }
 
   // FIXME: Inspector needs a vector which has all active stylesheets.
@@ -670,7 +664,7 @@
   if (global_rule_set_)
     global_rule_set_->MarkDirty();
   if (tree_scope.RootNode().IsDocumentNode()) {
-    scoped_resolver->ResetAuthorStyle();
+    scoped_resolver->ResetStyle();
     return;
   }
 
@@ -1700,7 +1694,7 @@
     else if (change == kActiveSheetsAppended)
       append_start_index = old_style_sheets.size();
     else
-      scoped_resolver->ResetAuthorStyle();
+      scoped_resolver->ResetStyle();
   }
 
   if (!new_style_sheets.IsEmpty()) {
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
index b7169d2..be5762e 100644
--- a/third_party/blink/renderer/core/css/style_engine.h
+++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -154,7 +154,6 @@
       const HeapVector<Member<CSSStyleSheet>>& new_sheets);
   void AddedCustomElementDefaultStyles(
       const HeapVector<Member<CSSStyleSheet>>& default_styles);
-  void MediaQueriesChangedInScope(TreeScope&);
   void WatchedSelectorsChanged();
   void InitialStyleChanged();
   void ColorSchemeChanged();
diff --git a/third_party/blink/renderer/core/css/style_sheet_collection.cc b/third_party/blink/renderer/core/css/style_sheet_collection.cc
index a06c56b..04507e284 100644
--- a/third_party/blink/renderer/core/css/style_sheet_collection.cc
+++ b/third_party/blink/renderer/core/css/style_sheet_collection.cc
@@ -37,13 +37,13 @@
 
 void StyleSheetCollection::Dispose() {
   style_sheets_for_style_sheet_list_.clear();
-  active_author_style_sheets_.clear();
+  active_style_sheets_.clear();
 }
 
 void StyleSheetCollection::Swap(StyleSheetCollection& other) {
   swap(style_sheets_for_style_sheet_list_,
        other.style_sheets_for_style_sheet_list_);
-  active_author_style_sheets_.swap(other.active_author_style_sheets_);
+  active_style_sheets_.swap(other.active_style_sheets_);
   sheet_list_dirty_ = false;
 }
 
@@ -55,7 +55,7 @@
 
 void StyleSheetCollection::AppendActiveStyleSheet(
     const ActiveStyleSheet& active_sheet) {
-  active_author_style_sheets_.push_back(active_sheet);
+  active_style_sheets_.push_back(active_sheet);
 }
 
 void StyleSheetCollection::AppendSheetForList(StyleSheet* sheet) {
@@ -63,7 +63,7 @@
 }
 
 void StyleSheetCollection::Trace(Visitor* visitor) const {
-  visitor->Trace(active_author_style_sheets_);
+  visitor->Trace(active_style_sheets_);
   visitor->Trace(style_sheets_for_style_sheet_list_);
 }
 
diff --git a/third_party/blink/renderer/core/css/style_sheet_collection.h b/third_party/blink/renderer/core/css/style_sheet_collection.h
index cc5de1a6..c2f9311 100644
--- a/third_party/blink/renderer/core/css/style_sheet_collection.h
+++ b/third_party/blink/renderer/core/css/style_sheet_collection.h
@@ -53,8 +53,8 @@
   StyleSheetCollection& operator=(const StyleSheetCollection&) = delete;
   virtual ~StyleSheetCollection() = default;
 
-  const ActiveStyleSheetVector& ActiveAuthorStyleSheets() const {
-    return active_author_style_sheets_;
+  const ActiveStyleSheetVector& ActiveStyleSheets() const {
+    return active_style_sheets_;
   }
   const HeapVector<Member<StyleSheet>>& StyleSheetsForStyleSheetList() const {
     return style_sheets_for_style_sheet_list_;
@@ -75,7 +75,7 @@
 
  protected:
   HeapVector<Member<StyleSheet>> style_sheets_for_style_sheet_list_;
-  ActiveStyleSheetVector active_author_style_sheets_;
+  ActiveStyleSheetVector active_style_sheets_;
   bool sheet_list_dirty_ = true;
 };
 
diff --git a/third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.cc b/third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.cc
index 19d3520..0098f78 100644
--- a/third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.cc
+++ b/third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.cc
@@ -53,8 +53,7 @@
 void TreeScopeStyleSheetCollection::ApplyActiveStyleSheetChanges(
     StyleSheetCollection& new_collection) {
   GetDocument().GetStyleEngine().ApplyRuleSetChanges(
-      GetTreeScope(), ActiveAuthorStyleSheets(),
-      new_collection.ActiveAuthorStyleSheets());
+      GetTreeScope(), ActiveStyleSheets(), new_collection.ActiveStyleSheets());
   new_collection.Swap(*this);
 }
 
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 337f9b8..891bb27b 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -67,7 +67,6 @@
 #include "third_party/blink/public/mojom/page_state/page_state.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/public/platform/web_battery_savings.h"
 #include "third_party/blink/public/platform/web_content_settings_client.h"
 #include "third_party/blink/public/platform/web_theme_engine.h"
 #include "third_party/blink/public/web/web_print_page_description.h"
@@ -187,6 +186,7 @@
 #include "third_party/blink/renderer/core/frame/viewport_data.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
 #include "third_party/blink/renderer/core/html/anchor_element_metrics.h"
+#include "third_party/blink/renderer/core/html/battery_savings.h"
 #include "third_party/blink/renderer/core/html/canvas/canvas_font_cache.h"
 #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
@@ -7149,7 +7149,7 @@
   if (!root_element)
     return;
 
-  WebBatterySavingsFlags savings = 0;
+  BatterySavingsFlags savings = 0;
   for (HTMLMetaElement& meta_element :
        Traversal<HTMLMetaElement>::DescendantsOf(*root_element)) {
     if (EqualIgnoringASCIICase(meta_element.GetName(), "battery-savings")) {
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc
index 3b8390c..f3750d5 100644
--- a/third_party/blink/renderer/core/dom/document_test.cc
+++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -1293,8 +1293,7 @@
 
 class BatterySavingsChromeClient : public EmptyChromeClient {
  public:
-  MOCK_METHOD2(BatterySavingsChanged,
-               void(LocalFrame&, WebBatterySavingsFlags));
+  MOCK_METHOD2(BatterySavingsChanged, void(LocalFrame&, BatterySavingsFlags));
 };
 
 class DocumentBatterySavingsTest : public PageTestBase,
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.cc b/third_party/blink/renderer/core/editing/editing_utilities.cc
index 6a2683a..fe1b00a 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -338,8 +338,6 @@
 
 // TODO(editing-dev): We should implement real version which refers
 // "user-select" CSS property.
-// TODO(editing-dev): We should make |SelectionAdjuster| to use this funciton
-// instead of |isSelectionBondary()|.
 bool IsUserSelectContain(const Node& node) {
   return IsA<HTMLTextAreaElement>(node) || IsA<HTMLInputElement>(node) ||
          IsA<HTMLSelectElement>(node);
diff --git a/third_party/blink/renderer/core/editing/selection_adjuster.cc b/third_party/blink/renderer/core/editing/selection_adjuster.cc
index f9b357f..a66d37c 100644
--- a/third_party/blink/renderer/core/editing/selection_adjuster.cc
+++ b/third_party/blink/renderer/core/editing/selection_adjuster.cc
@@ -418,11 +418,6 @@
     return FlatTreeTraversal::IsDescendantOf(*anchor_node, node);
   }
 
-  static bool IsSelectionBoundary(const Node& node) {
-    return IsA<HTMLTextAreaElement>(node) || IsA<HTMLInputElement>(node) ||
-           IsA<HTMLSelectElement>(node);
-  }
-
   static Node* EnclosingShadowHostForStart(const PositionInFlatTree& position) {
     Node* node = position.NodeAsRangeFirstNode();
     if (!node)
@@ -432,7 +427,7 @@
       return nullptr;
     if (!IsEnclosedBy(position, *shadow_host))
       return nullptr;
-    return IsSelectionBoundary(*shadow_host) ? shadow_host : nullptr;
+    return IsUserSelectContain(*shadow_host) ? shadow_host : nullptr;
   }
 
   static Node* EnclosingShadowHostForEnd(const PositionInFlatTree& position) {
@@ -444,7 +439,7 @@
       return nullptr;
     if (!IsEnclosedBy(position, *shadow_host))
       return nullptr;
-    return IsSelectionBoundary(*shadow_host) ? shadow_host : nullptr;
+    return IsUserSelectContain(*shadow_host) ? shadow_host : nullptr;
   }
 
   static PositionInFlatTree AdjustPositionInFlatTreeForStart(
diff --git a/third_party/blink/renderer/core/editing/visible_units_line_test.cc b/third_party/blink/renderer/core/editing/visible_units_line_test.cc
index be2fe78..1666949 100644
--- a/third_party/blink/renderer/core/editing/visible_units_line_test.cc
+++ b/third_party/blink/renderer/core/editing/visible_units_line_test.cc
@@ -968,6 +968,59 @@
   EXPECT_FALSE(InSameLine(position1, position2));
 }
 
+TEST_P(ParameterizedVisibleUnitsLineTest,
+       InSameLineWithGeneratedZeroWidthSpace) {
+  LoadAhem();
+  InsertStyleElement(
+      "p { font: 10px/1 Ahem; }"
+      "p { width: 4ch; white-space: pre-wrap;");
+  // We have ZWS before "abc" due by "pre-wrap".
+  const Position& after_zws = SetCaretTextToBody("<p id=t>    |abcd</p>");
+  const PositionWithAffinity after_zws_down =
+      PositionWithAffinity(after_zws, TextAffinity::kDownstream);
+  const PositionWithAffinity after_zws_up =
+      PositionWithAffinity(after_zws, TextAffinity::kUpstream);
+
+  EXPECT_EQ(
+      PositionWithAffinity(Position(*GetElementById("t")->firstChild(), 8),
+                           TextAffinity::kUpstream),
+      EndOfLine(after_zws_down));
+  EXPECT_EQ(after_zws_up, EndOfLine(after_zws_up));
+  EXPECT_FALSE(InSameLine(after_zws_up, after_zws_down));
+}
+
+TEST_P(ParameterizedVisibleUnitsLineTest, InSameLineWithZeroWidthSpace) {
+  LoadAhem();
+  InsertStyleElement(
+      "p { font: 10px/1 Ahem; }"
+      "p { width: 4ch; }");
+  const SelectionInDOMTree& selection =
+      SetSelectionTextToBody(u8"<p id=t>abcd^\u200B|wxyz</p>");
+
+  const Position& after_zws = selection.Extent();
+  const PositionWithAffinity after_zws_down =
+      PositionWithAffinity(after_zws, TextAffinity::kDownstream);
+  const PositionWithAffinity after_zws_up =
+      PositionWithAffinity(after_zws, TextAffinity::kUpstream);
+
+  const Position& before_zws = selection.Base();
+  const PositionWithAffinity before_zws_down =
+      PositionWithAffinity(before_zws, TextAffinity::kDownstream);
+  const PositionWithAffinity before_zws_up =
+      PositionWithAffinity(before_zws, TextAffinity::kUpstream);
+
+  EXPECT_EQ(
+      PositionWithAffinity(Position(*GetElementById("t")->firstChild(), 9),
+                           TextAffinity::kUpstream),
+      EndOfLine(after_zws_down));
+  EXPECT_EQ(after_zws_up, EndOfLine(after_zws_up));
+  EXPECT_FALSE(InSameLine(after_zws_up, after_zws_down));
+
+  EXPECT_EQ(after_zws_up, EndOfLine(before_zws_down));
+  EXPECT_EQ(after_zws_up, EndOfLine(before_zws_up));
+  EXPECT_TRUE(InSameLine(before_zws_up, before_zws_down));
+}
+
 TEST_P(ParameterizedVisibleUnitsLineTest, StartOfLineWithBidi) {
   LoadAhem();
   InsertStyleElement("p { font: 30px/3 Ahem; }");
diff --git a/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc b/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
deleted file mode 100644
index 4a30d7a6..0000000
--- a/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
-
-#include "base/metrics/histogram.h"
-#include "base/metrics/histogram_base.h"
-#include "base/time/default_tick_clock.h"
-#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
-#include "third_party/blink/renderer/core/execution_context/window_agent.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/web_test_support.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-using WTF::HashSet;
-using WTF::String;
-using WTF::Vector;
-
-namespace blink {
-
-namespace {
-
-const char kAgentsPerRendererByTimeHistogram[] =
-    "PerformanceManager.AgentsPerRendererByTime";
-
-base::TimeDelta kReportingInterval = base::TimeDelta::FromMinutes(5);
-
-}  // namespace
-
-AgentMetricsCollector::AgentMetricsCollector()
-    : reporting_timer_(std::make_unique<TaskRunnerTimer<AgentMetricsCollector>>(
-          // Some tests might not have a MainThreadScheduler.
-          scheduler::WebThreadScheduler::MainThreadScheduler()
-              ? scheduler::WebThreadScheduler::MainThreadScheduler()
-                    ->DefaultTaskRunner()
-              : nullptr,
-          this,
-          &AgentMetricsCollector::ReportingTimerFired)),
-      clock_(base::DefaultTickClock::GetInstance()) {
-  // From now until we call CreatedNewAgent will be reported as having 0
-  // agents.
-  time_last_reported_ = clock_->NowTicks();
-}
-
-AgentMetricsCollector::~AgentMetricsCollector() {
-  // Note: This won't be called during a fast-shutdown (i.e. tab closed). We
-  // manually call it from Page::WillBeDestroyed().
-  ReportMetrics();
-}
-
-void AgentMetricsCollector::DidAttachWindow(const LocalDOMWindow& window) {
-  ReportMetrics();
-
-  AgentToWindowsMap::AddResult result =
-      agent_to_windows_map_.insert(window.GetAgent(), nullptr);
-  if (result.is_new_entry)
-    result.stored_value->value = MakeGarbageCollected<WindowSet>();
-
-  result.stored_value->value->insert(&window);
-
-  ReportToBrowser();
-}
-
-void AgentMetricsCollector::DidDetachWindow(const LocalDOMWindow& window) {
-  ReportMetrics();
-
-  auto agent_itr = agent_to_windows_map_.find(window.GetAgent());
-  DCHECK(agent_itr != agent_to_windows_map_.end());
-
-  WindowSet& windows = *agent_itr->value.Get();
-  auto window_itr = windows.find(&window);
-  DCHECK(window_itr != windows.end());
-
-  windows.erase(window_itr);
-
-  if (windows.IsEmpty())
-    agent_to_windows_map_.erase(agent_itr);
-
-  ReportToBrowser();
-}
-
-void AgentMetricsCollector::ReportMetrics() {
-  DCHECK(!time_last_reported_.is_null());
-
-  // Don't run the timer in tests. Doing so causes tests that RunUntilIdle to
-  // never exit.
-  if (!reporting_timer_->IsActive() && !WebTestSupport::IsRunningWebTest()) {
-    reporting_timer_->StartRepeating(kReportingInterval, FROM_HERE);
-  }
-
-  // This computation and reporting is based on the one in
-  // chrome/browser/performance_manager/observers/isolation_context_metrics.cc.
-  base::TimeTicks now = clock_->NowTicks();
-
-  base::TimeDelta elapsed = now - time_last_reported_;
-  time_last_reported_ = now;
-
-  // Account for edge cases like hibernate/sleep. See
-  // GetSecondsSinceLastReportAndUpdate in isolation_context_metrics.cc
-  if (elapsed >= 2 * kReportingInterval)
-    elapsed = base::TimeDelta();
-
-  int to_add = static_cast<int>(std::round(elapsed.InSecondsF()));
-
-  // Time can be negative in tests when we replace the clock_.
-  if (to_add <= 0)
-    return;
-
-  AddTimeToTotalAgents(to_add);
-}
-
-void AgentMetricsCollector::AddTimeToTotalAgents(int time_delta_to_add) {
-  base::LinearHistogram::FactoryGet(
-      kAgentsPerRendererByTimeHistogram, 1, 100, 101,
-      base::HistogramBase::kUmaTargetedHistogramFlag)
-      ->AddCount(agent_to_windows_map_.size(), time_delta_to_add);
-}
-
-void AgentMetricsCollector::ReportToBrowser() {
-  Vector<String> agents;
-  for (const auto& kv : agent_to_windows_map_) {
-    const Member<WindowSet>& window_set = kv.value;
-
-    String tuple_origin;
-    DCHECK(!window_set->IsEmpty());
-    const auto& window = *window_set->begin();
-    auto* security_origin = window->GetSecurityOrigin();
-    if (security_origin && !security_origin->IsOpaque() &&
-        !security_origin->IsLocal()) {
-      // We shouldn't ever host multiple tuple-origins in an Agent. However,
-      // this does happen in tests because we have
-      // GetAllowUniversalAccessFromFileURLs enabled but that's ok in tests.
-      tuple_origin = security_origin->Protocol() + "://" +
-                     security_origin->RegistrableDomain();
-    } else {
-      // We use an empty string to specify that there isn't any one
-      // tuple-origin this agent represents. This will typically be for
-      // file:// or opaque origins. We shouldn't ever host multiple sites
-      // inside an agent.
-      tuple_origin = "";
-    }
-
-    agents.push_back(tuple_origin);
-  }
-
-  mojom::blink::AgentMetricsDataPtr data =
-      mojom::blink::AgentMetricsData::New();
-  data->agents = agents;
-
-  GetAgentMetricsCollectorHost()->ReportRendererMetrics(std::move(data));
-}
-
-void AgentMetricsCollector::ReportingTimerFired(TimerBase*) {
-  ReportMetrics();
-  ReportToBrowser();
-}
-
-blink::mojom::blink::AgentMetricsCollectorHost*
-AgentMetricsCollector::GetAgentMetricsCollectorHost() {
-  if (!agent_metrics_collector_host_.is_bound()) {
-    blink::Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
-        agent_metrics_collector_host_.BindNewPipeAndPassReceiver(
-            ThreadScheduler::Current()->DeprecatedDefaultTaskRunner()));
-  }
-  return agent_metrics_collector_host_.get();
-}
-
-void AgentMetricsCollector::Trace(Visitor* visitor) const {
-  visitor->Trace(agent_to_windows_map_);
-  visitor->Trace(agent_metrics_collector_host_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h b/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h
deleted file mode 100644
index f031291..0000000
--- a/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_AGENT_METRICS_COLLECTOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_AGENT_METRICS_COLLECTOR_H_
-
-#include "base/time/time.h"
-#include "third_party/blink/public/mojom/agents/agent_metrics.mojom-blink.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
-#include "third_party/blink/renderer/platform/timer.h"
-
-namespace base {
-class TickClock;
-}
-
-namespace blink {
-
-class Agent;
-class LocalDOMWindow;
-class TimerBase;
-
-// This class tracks agent-related metrics for reporting in TRACE and UMA
-// metrics. It listens for windows being attached/detached to an execution
-// context and tracks which agent these windows are associated with.
-//
-// We report metrics periodically to track how long we spent in any given state.
-// For example, suppose that for 10 seconds a page had just one agent, then an
-// ad frame loads causing a windows to load with a second agent. After 5
-// seconds, the user closes the browser. In this case, we report:
-//
-// Histogram
-// 1 ----------O        10
-// 2 -----O             5
-//
-// We therefore keep track of how much time has elapsed since the previous
-// report. Metrics are reported whenever a windows is added or removed, as
-// well as at a regular interval.
-//
-// This class is based on the metrics tracked in:
-// chrome/browser/performance_manager/observers/isolation_context_metrics.cc
-// It should eventually be migrated to that place.
-class AgentMetricsCollector final
-    : public GarbageCollected<AgentMetricsCollector> {
- public:
-  AgentMetricsCollector();
-  ~AgentMetricsCollector();
-
-  void DidAttachWindow(const LocalDOMWindow&);
-  void DidDetachWindow(const LocalDOMWindow&);
-
-  void ReportMetrics();
-
-  void SetTickClockForTesting(const base::TickClock* clock) { clock_ = clock; }
-
-  void Trace(Visitor*) const;
-
- private:
-  void AddTimeToTotalAgents(int time_delta_to_add);
-  void ReportToBrowser();
-
-  void ReportingTimerFired(TimerBase*);
-
-  blink::mojom::blink::AgentMetricsCollectorHost*
-  GetAgentMetricsCollectorHost();
-
-  std::unique_ptr<TaskRunnerTimer<AgentMetricsCollector>> reporting_timer_;
-  base::TimeTicks time_last_reported_;
-
-  // Keep a map from each agent to all the windows associated with that
-  // agent. When the last window from the set is removed, we delete the key
-  // from the map.
-  using WindowSet = HeapHashSet<WeakMember<const LocalDOMWindow>>;
-  using AgentToWindowsMap = HeapHashMap<WeakMember<Agent>, Member<WindowSet>>;
-  AgentToWindowsMap agent_to_windows_map_;
-
-  const base::TickClock* clock_;
-
-  // AgentMetricsCollector is not tied to ExecutionContext
-  HeapMojoRemote<blink::mojom::blink::AgentMetricsCollectorHost,
-                 HeapMojoWrapperMode::kWithoutContextObserver>
-      agent_metrics_collector_host_{nullptr};
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_AGENT_METRICS_COLLECTOR_H_
diff --git a/third_party/blink/renderer/core/execution_context/agent_metrics_collector_test.cc b/third_party/blink/renderer/core/execution_context/agent_metrics_collector_test.cc
deleted file mode 100644
index 0e31e282..0000000
--- a/third_party/blink/renderer/core/execution_context/agent_metrics_collector_test.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/time/default_tick_clock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/location.h"
-#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
-#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
-#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-
-namespace blink {
-
-class AgentMetricsCollectorUnitTest : public SimTest {
- public:
-  AgentMetricsCollectorUnitTest() = default;
-
-  void SetUp() override {
-    SimTest::SetUp();
-
-    tick_clock_.SetNowTicks(base::TimeTicks::Now());
-
-    // Tests turn this on but it would force all frames into a single agent.
-    // Turn it off so we get an agent per-origin.
-    WebView().GetPage()->GetSettings().SetAllowUniversalAccessFromFileURLs(
-        false);
-
-    WebView().GetPage()->GetAgentMetricsCollector()->SetTickClockForTesting(
-        &tick_clock_);
-    WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
-  }
-
-  void TearDown() override {
-    if (!torn_down_) {
-      // Avoid UAF when tick_clock_ is destroyed.
-      auto* collector = WebView().GetPage()->GetAgentMetricsCollector();
-
-      SimTest::TearDown();
-      torn_down_ = true;
-
-      collector->SetTickClockForTesting(base::DefaultTickClock::GetInstance());
-    }
-  }
-
-  bool torn_down_ = false;
-
-  HistogramTester tester_;
-  const char* kHistogramName = "PerformanceManager.AgentsPerRendererByTime";
-
-  base::SimpleTestTickClock tick_clock_;
-};
-
-// Tests that we record samples across a navigation.
-TEST_F(AgentMetricsCollectorUnitTest, AgentsPerRendererRecordOnDocumentChange) {
-  SimRequest request_a("https://example.com/a.html", "text/html");
-  SimRequest request_b("https://example.com/b.html", "text/html");
-
-  // Load the first page. The histogram won't yet have any data because it
-  // records samples by time and only when documents are created/destroyed.
-  // Immediately after we load a.html, no time has passed yet.
-  LoadURL("https://example.com/a.html");
-  request_a.Complete(R"HTML(
-    <!DOCTYPE html>
-  )HTML");
-  Compositor().BeginFrame();
-
-  tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-
-  // Load the second page. Since 10 seconds have now elapsed, as the documents
-  // are swapped we should see 10 samples recorded in the 1 agent bucket.
-  LoadURL("https://example.com/b.html");
-  request_b.Complete(R"HTML(
-    <!DOCTYPE html>
-  )HTML");
-  Compositor().BeginFrame();
-
-  tester_.ExpectUniqueSample(kHistogramName, 1, 10);
-}
-
-// Test that we correctly record the case where a second agent is added to the
-// page.
-TEST_F(AgentMetricsCollectorUnitTest, MultipleAgents) {
-  SimRequest request_a("https://foo.com/a.html", "text/html");
-  SimRequest request_b("https://bar.com/b.html", "text/html");
-
-  // Load the first page. The histogram won't yet have any data because it
-  // records samples by time and only when documents are created/destroyed.
-  // Immediately after we load a.html, no time has passed yet.
-  LoadURL("https://foo.com/a.html");
-  request_a.Complete(R"HTML(
-    <!DOCTYPE html>
-    <iframe src="about:blank"></iframe>
-  )HTML");
-  Compositor().BeginFrame();
-
-  tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-
-  // Navigate to a cross-origin page, this should create a second agent.
-  frame_test_helpers::LoadFrameDontWait(
-      MainFrame().FirstChild()->ToWebLocalFrame(),
-      KURL("https://bar.com/b.html"));
-  request_b.Complete(R"HTML(
-    <!DOCTYPE html>
-  )HTML");
-  tester_.ExpectBucketCount(kHistogramName, 1, 10);
-
-  tick_clock_.Advance(base::TimeDelta::FromSeconds(20));
-
-  // Simulate closing the page. This should cause us to report the metrics.
-  TearDown();
-
-  // The final 20 seconds had 2 agents.
-  tester_.ExpectBucketCount(kHistogramName, 1, 10);
-  tester_.ExpectBucketCount(kHistogramName, 2, 20);
-}
-
-// Ensure that multiple Pages in the same Agent are reported as only one agent.
-TEST_F(AgentMetricsCollectorUnitTest, WindowOpenSameAgents) {
-  SimRequest request_a("https://example.com/a.html", "text/html");
-  SimRequest request_b("https://example.com/b.html", "text/html");
-
-  LoadURL("https://example.com/a.html");
-  request_a.Complete(R"HTML(
-    <!DOCTYPE html>
-    <script>
-      window.open('https://example.com/b.html');
-    </script>
-  )HTML");
-  request_b.Complete(R"HTML(
-    <!DOCTYPE html>
-  )HTML");
-  Compositor().BeginFrame();
-
-  ASSERT_EQ(2u, Page::OrdinaryPages().size());
-
-  tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-
-  // Simulate closing the page. This should cause us to report the metrics.
-  TearDown();
-
-  // Both documents should end up in the same Agent, despite having separate
-  // WebViews/Page.
-  tester_.ExpectUniqueSample(kHistogramName, 1, 10);
-}
-
-// Ensure that multiple Pages in different Agents are reported as multiple
-// agents.
-TEST_F(AgentMetricsCollectorUnitTest, WindowOpenDifferentAgents) {
-  SimRequest request_a("https://example.com/a.html", "text/html");
-  SimRequest request_b("https://different.com/a.html", "text/html");
-
-  LoadURL("https://example.com/a.html");
-  request_a.Complete(R"HTML(
-    <!DOCTYPE html>
-    <script>
-      window.open('https://different.com/a.html');
-    </script>
-  )HTML");
-  request_b.Complete(R"HTML(
-    <!DOCTYPE html>
-  )HTML");
-  Compositor().BeginFrame();
-
-  ASSERT_EQ(2u, Page::OrdinaryPages().size());
-
-  tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-
-  // Simulate closing the page. This should cause us to report the metrics.
-  TearDown();
-
-  // Each document should have its own Agent.
-  tester_.ExpectUniqueSample(kHistogramName, 2, 10);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/execution_context/build.gni b/third_party/blink/renderer/core/execution_context/build.gni
index 412199d..6e4069fde 100644
--- a/third_party/blink/renderer/core/execution_context/build.gni
+++ b/third_party/blink/renderer/core/execution_context/build.gni
@@ -5,8 +5,6 @@
 blink_core_sources_execution_context = [
   "agent.cc",
   "agent.h",
-  "agent_metrics_collector.cc",
-  "agent_metrics_collector.h",
   "execution_context.cc",
   "execution_context.h",
   "execution_context_lifecycle_observer.cc",
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 39cfe72..c7aa8126 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
@@ -596,6 +596,13 @@
   }
 
   gfx::Rect window_rect = rect_in_screen;
+  // Do not set the same |window_rect| more than once. In case of backends that
+  // can reposition native windows during initialization of popups, |this| can
+  // override position of the popup on screen, which will result in
+  // RenderWidgetHostViewAura setting wrong bounds for aura::Window. In turn,
+  // that can result in offset and the content will not be properly positioned.
+  if (window_rect == WindowRectInScreen())
+    return;
 
   // Popups aren't emulated, but the WidgetScreenRect and WindowScreenRect
   // given to them are. When they set the WindowScreenRect it is based on those
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index ddc1750..28c705a 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -73,7 +73,6 @@
 #include "third_party/blink/renderer/core/events/hash_change_event.h"
 #include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/events/pop_state_event.h"
-#include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/execution_context/window_agent.h"
 #include "third_party/blink/renderer/core/frame/bar_prop.h"
@@ -163,18 +162,12 @@
 
 void LocalDOMWindow::Initialize() {
   GetAgent()->AttachContext(this);
-  if (auto* agent_metrics = GetFrame()->GetPage()->GetAgentMetricsCollector())
-    agent_metrics->DidAttachWindow(*this);
 }
 
 void LocalDOMWindow::ResetWindowAgent(WindowAgent* agent) {
   GetAgent()->DetachContext(this);
-  if (auto* agent_metrics = GetFrame()->GetPage()->GetAgentMetricsCollector())
-    agent_metrics->DidDetachWindow(*this);
   ResetAgent(agent);
   GetAgent()->AttachContext(this);
-  if (auto* agent_metrics = GetFrame()->GetPage()->GetAgentMetricsCollector())
-    agent_metrics->DidAttachWindow(*this);
 }
 
 void LocalDOMWindow::AcceptLanguagesChanged() {
@@ -807,8 +800,6 @@
   document()->Shutdown();
   document()->RemoveAllEventListenersRecursively();
   GetAgent()->DetachContext(this);
-  if (auto* agent_metrics = GetFrame()->GetPage()->GetAgentMetricsCollector())
-    agent_metrics->DidDetachWindow(*this);
   NotifyContextDestroyed();
   RemoveAllEventListeners();
   MainThreadDebugger::Instance()->DidClearContextsForFrame(GetFrame());
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index a8c5cee0..3d4c963e 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -204,6 +204,8 @@
       Frame* child) override;
   void DidFocus() override;
 
+  void EvictFromBackForwardCache();
+
   void DidChangeThemeColor();
   void DidChangeBackgroundColor(SkColor background_color, bool color_adjust);
 
@@ -777,8 +779,6 @@
   void DidResume();
   void SetContextPaused(bool);
 
-  void EvictFromBackForwardCache();
-
   HitTestResult HitTestResultForVisualViewportPos(
       const IntPoint& pos_in_viewport);
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 783b8584f..e4d27cec 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -73,6 +73,7 @@
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/html/battery_savings.h"
 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
 #include "third_party/blink/renderer/core/html/portal/document_portals.h"
@@ -3628,7 +3629,7 @@
       local_frame->View()->ConvertToRootFrame(focus));
 }
 
-void WebFrameWidgetImpl::BatterySavingsChanged(WebBatterySavingsFlags savings) {
+void WebFrameWidgetImpl::BatterySavingsChanged(BatterySavingsFlags savings) {
   widget_base_->LayerTreeHost()->SetEnableFrameRateThrottling(
       savings & kAllowReducedFrameRate);
 }
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index d4a2b62..9c5dc158 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -46,13 +46,13 @@
 #include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
 #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h"
 #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
-#include "third_party/blink/public/platform/web_battery_savings.h"
 #include "third_party/blink/public/platform/web_drag_data.h"
 #include "third_party/blink/public/web/web_frame_widget.h"
 #include "third_party/blink/public/web/web_meaningful_layout.h"
 #include "third_party/blink/renderer/core/clipboard/data_object.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/exported/web_page_popup_impl.h"
+#include "third_party/blink/renderer/core/html/battery_savings.h"
 #include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
 #include "third_party/blink/renderer/core/page/page_widget_delegate.h"
 #include "third_party/blink/renderer/platform/graphics/apply_viewport_changes.h"
@@ -550,7 +550,7 @@
 
   // The value of the applied battery-savings META element in the document
   // changed.
-  void BatterySavingsChanged(WebBatterySavingsFlags savings);
+  void BatterySavingsChanged(BatterySavingsFlags savings);
 
   const viz::LocalSurfaceId& LocalSurfaceIdFromParent();
   cc::LayerTreeHost* LayerTreeHost();
diff --git a/third_party/blink/public/platform/web_battery_savings.h b/third_party/blink/renderer/core/html/battery_savings.h
similarity index 65%
rename from third_party/blink/public/platform/web_battery_savings.h
rename to third_party/blink/renderer/core/html/battery_savings.h
index 6b33becd..5519b37 100644
--- a/third_party/blink/public/platform/web_battery_savings.h
+++ b/third_party/blink/renderer/core/html/battery_savings.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_BATTERY_SAVINGS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_BATTERY_SAVINGS_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_BATTERY_SAVINGS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_BATTERY_SAVINGS_H_
 
 namespace blink {
 
@@ -11,15 +11,14 @@
 // meta element. For instance:
 //
 // <meta name="battery-savings" content="allow-reduced-framerate">
-//
 // These constants are bits which can be combined.
-enum WebBatterySavings {
+enum BatterySavings {
   kAllowReducedFrameRate = 1 << 0,
   kAllowReducedScriptSpeed = 1 << 1,
 };
 
-using WebBatterySavingsFlags = unsigned;
+using BatterySavingsFlags = unsigned;
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_BATTERY_SAVINGS_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_BATTERY_SAVINGS_H_
diff --git a/third_party/blink/renderer/core/html/build.gni b/third_party/blink/renderer/core/html/build.gni
index 2c41552..1206b5200 100644
--- a/third_party/blink/renderer/core/html/build.gni
+++ b/third_party/blink/renderer/core/html/build.gni
@@ -7,6 +7,7 @@
   "anchor_element_metrics.h",
   "anchor_element_metrics_sender.cc",
   "anchor_element_metrics_sender.h",
+  "battery_savings.h",
   "canvas/canvas_async_blob_creator.cc",
   "canvas/canvas_async_blob_creator.h",
   "canvas/canvas_context_creation_attributes_core.cc",
diff --git a/third_party/blink/renderer/core/html/html_style_element.cc b/third_party/blink/renderer/core/html/html_style_element.cc
index 1fb65d80..62aed2a8 100644
--- a/third_party/blink/renderer/core/html/html_style_element.cc
+++ b/third_party/blink/renderer/core/html/html_style_element.cc
@@ -49,7 +49,7 @@
              GetDocument().IsActive() && sheet_) {
     sheet_->SetMediaQueries(
         MediaQuerySet::Create(params.new_value, GetExecutionContext()));
-    GetDocument().GetStyleEngine().MediaQueriesChangedInScope(GetTreeScope());
+    GetDocument().GetStyleEngine().SetNeedsActiveStyleUpdate(GetTreeScope());
   } else if (params.name == html_names::kTypeAttr) {
     HTMLElement::ParseAttribute(params);
     StyleElement::ChildrenChanged(*this);
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index eec78a97..3517624c 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -963,8 +963,11 @@
   // The location container for boxes is not always the containing block.
   LayoutObject* location_container =
       IsLayoutInline() ? Container() : To<LayoutBox>(this)->LocationContainer();
-  // Skip anonymous containing blocks.
+  // Skip anonymous containing blocks except for anonymous fieldset content box.
   while (sticky_container->IsAnonymous()) {
+    if (sticky_container->Parent() &&
+        sticky_container->Parent()->IsLayoutNGFieldset())
+      break;
     sticky_container = sticky_container->ContainingBlock();
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
index f2314916..01e5db53 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
@@ -329,7 +329,17 @@
 
   const unsigned offset = *maybe_offset;
   const TextAffinity affinity = position_with_affinity.Affinity();
-  return ComputeNGCaretPosition(*context, offset, affinity, layout_text);
+  // For upstream position, we use offset before ZWS to distinguish downstream
+  // and upstream position when line breaking before ZWS.
+  // "    Zabc" where "Z" represents zero-width-space.
+  // See AccessibilitySelectionTest.FromCurrentSelectionInTextareaWithAffinity
+  const unsigned adjusted_offset =
+      affinity == TextAffinity::kUpstream && offset &&
+              mapping->GetText()[offset - 1] == kZeroWidthSpaceCharacter
+          ? offset - 1
+          : offset;
+  return ComputeNGCaretPosition(*context, adjusted_offset, affinity,
+                                layout_text);
 }
 
 Position NGCaretPosition::ToPositionInDOMTree() const {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc
index e7651f7..43720e7 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc
@@ -289,6 +289,63 @@
              fragment_d, kAtTextOffset, base::Optional<unsigned>(wrap_offset));
 }
 
+TEST_F(NGCaretPositionTest, GeneratedZeroWidthSpace) {
+  LoadAhem();
+  InsertStyleElement(
+      "p { font: 10px/1 Ahem; }"
+      "p { width: 4ch; white-space: pre-wrap;");
+  // We have ZWS before "abc" due by "pre-wrap".
+  // text content is
+  //    [0..3] "   "
+  //    [4] ZWS
+  //    [5..8] "abcd"
+  SetBodyInnerHTML("<p id=t>    abcd</p>");
+  const Text& text = To<Text>(*GetElementById("t")->firstChild());
+  const Position after_zws(text, 4);  // before "a".
+
+  NGInlineCursor cursor;
+  cursor.MoveTo(*text.GetLayoutObject());
+
+  ASSERT_EQ(NGTextOffset(0, 4), cursor.Current().TextOffset());
+  TEST_CARET(blink::ComputeNGCaretPosition(
+                 PositionWithAffinity(after_zws, TextAffinity::kUpstream)),
+             cursor, kAtTextOffset, base::Optional<unsigned>(4));
+
+  cursor.MoveToNextForSameLayoutObject();
+  ASSERT_EQ(NGTextOffset(5, 9), cursor.Current().TextOffset());
+  TEST_CARET(blink::ComputeNGCaretPosition(
+                 PositionWithAffinity(after_zws, TextAffinity::kDownstream)),
+             cursor, kAtTextOffset, base::Optional<unsigned>(5));
+}
+
+TEST_F(NGCaretPositionTest, ZeroWidthSpace) {
+  LoadAhem();
+  InsertStyleElement(
+      "p { font: 10px/1 Ahem; }"
+      "p { width: 4ch;");
+  // dom and text content is
+  //    [0..3] "abcd"
+  //    [4] ZWS
+  //    [5..8] "wxyz"
+  SetBodyInnerHTML("<p id=t>abcd&#x200B;wxyz</p>");
+  const Text& text = To<Text>(*GetElementById("t")->firstChild());
+  const Position after_zws(text, 5);  // before "w".
+
+  NGInlineCursor cursor;
+  cursor.MoveTo(*text.GetLayoutObject());
+
+  ASSERT_EQ(NGTextOffset(0, 5), cursor.Current().TextOffset());
+  TEST_CARET(blink::ComputeNGCaretPosition(
+                 PositionWithAffinity(after_zws, TextAffinity::kUpstream)),
+             cursor, kAtTextOffset, base::Optional<unsigned>(4));
+
+  cursor.MoveToNextForSameLayoutObject();
+  ASSERT_EQ(NGTextOffset(5, 9), cursor.Current().TextOffset());
+  TEST_CARET(blink::ComputeNGCaretPosition(
+                 PositionWithAffinity(after_zws, TextAffinity::kDownstream)),
+             cursor, kAtTextOffset, base::Optional<unsigned>(5));
+}
+
 TEST_F(NGCaretPositionTest, InlineBlockBeforeContent) {
   SetInlineFormattingContext(
       "t",
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index 4696d82b..0e07fb9b 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -221,7 +221,7 @@
   void InstallSupplements(LocalFrame&) override {}
   void MainFrameScrollOffsetChanged(LocalFrame& main_frame) const override {}
   void BatterySavingsChanged(LocalFrame& main_frame,
-                             WebBatterySavingsFlags savings) override {}
+                             BatterySavingsFlags savings) override {}
 };
 
 class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
index 0dabf5ad..d681d3a9 100644
--- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -274,6 +274,12 @@
   document_->CheckCompleted();
 }
 
+void ResourceLoadObserverForFrame::EvictFromBackForwardCache() {
+  LocalFrame* frame = document_->GetFrame();
+  DCHECK(frame);
+  frame->EvictFromBackForwardCache();
+}
+
 void ResourceLoadObserverForFrame::Trace(Visitor* visitor) const {
   visitor->Trace(document_loader_);
   visitor->Trace(document_);
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
index 1cc328b8..c39badf 100644
--- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
@@ -58,6 +58,7 @@
                       const ResourceError&,
                       int64_t encoded_data_length,
                       IsInternalRequest) override;
+  void EvictFromBackForwardCache() override;
   void Trace(Visitor*) const override;
 
  private:
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
index 8efb2333..886ddeef 100644
--- a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
@@ -57,6 +57,7 @@
                       const ResourceError&,
                       int64_t encoded_data_length,
                       IsInternalRequest) override;
+  void EvictFromBackForwardCache() override {}
   void Trace(Visitor*) const override;
 
  private:
diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h
index 451dc607..ff5b954 100644
--- a/third_party/blink/renderer/core/page/chrome_client.h
+++ b/third_party/blink/renderer/core/page/chrome_client.h
@@ -39,11 +39,11 @@
 #include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
 #include "third_party/blink/public/platform/blame_context.h"
-#include "third_party/blink/public/platform/web_battery_savings.h"
 #include "third_party/blink/public/web/web_swap_result.h"
 #include "third_party/blink/public/web/web_widget_client.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/html/battery_savings.h"
 #include "third_party/blink/renderer/core/html/forms/external_date_time_chooser.h"
 #include "third_party/blink/renderer/core/html/forms/popup_menu.h"
 #include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
@@ -524,7 +524,7 @@
       std::unique_ptr<viz::DelegatedInkMetadata> metadata) {}
 
   virtual void BatterySavingsChanged(LocalFrame& main_frame,
-                                     WebBatterySavingsFlags savings) = 0;
+                                     BatterySavingsFlags savings) = 0;
 
   virtual void FormElementReset(HTMLFormElement& element) {}
 
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc
index 3571087..3020bd5 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -1167,7 +1167,7 @@
 }
 
 void ChromeClientImpl::BatterySavingsChanged(LocalFrame& main_frame,
-                                             WebBatterySavingsFlags savings) {
+                                             BatterySavingsFlags savings) {
   DCHECK(main_frame.IsMainFrame());
   WebLocalFrameImpl::FromFrame(main_frame)
       ->FrameWidgetImpl()
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h
index ab69bea..8ded391 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.h
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -285,7 +285,7 @@
   double UserZoomFactor() const override;
 
   void BatterySavingsChanged(LocalFrame& main_frame,
-                             WebBatterySavingsFlags savings) override;
+                             BatterySavingsFlags savings) override;
 
   void FormElementReset(HTMLFormElement& element) override;
 
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
index 8cf56cc..8461220 100644
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -38,7 +38,6 @@
 #include "third_party/blink/renderer/core/dom/visited_link_state.h"
 #include "third_party/blink/renderer/core/editing/drag_caret.h"
 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
-#include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
 #include "third_party/blink/renderer/core/frame/browser_controls.h"
 #include "third_party/blink/renderer/core/frame/dom_timer.h"
 #include "third_party/blink/renderer/core/frame/event_handler_registry.h"
@@ -130,12 +129,6 @@
   return *pages;
 }
 
-static AgentMetricsCollector& GlobalAgentMetricsCollector() {
-  DEFINE_STATIC_LOCAL(Persistent<AgentMetricsCollector>, metrics_collector,
-                      (MakeGarbageCollected<AgentMetricsCollector>()));
-  return *metrics_collector;
-}
-
 void Page::InsertOrdinaryPageForTesting(Page* page) {
   OrdinaryPages().insert(page);
 }
@@ -175,7 +168,6 @@
     scheduler::WebAgentGroupScheduler& agent_group_scheduler) {
   Page* page = MakeGarbageCollected<Page>(page_clients);
   page->is_ordinary_ = true;
-  page->agent_metrics_collector_ = &GlobalAgentMetricsCollector();
   page->SetPageScheduler(
       agent_group_scheduler.AsAgentGroupScheduler().CreatePageScheduler(page));
 
@@ -935,7 +927,6 @@
   visitor->Trace(main_frame_);
   visitor->Trace(plugin_data_);
   visitor->Trace(validation_message_client_);
-  visitor->Trace(agent_metrics_collector_);
   visitor->Trace(plugins_changed_observers_);
   visitor->Trace(next_related_page_);
   visitor->Trace(prev_related_page_);
@@ -985,9 +976,6 @@
     validation_message_client_->WillBeDestroyed();
   main_frame_ = nullptr;
 
-  if (agent_metrics_collector_)
-    agent_metrics_collector_->ReportMetrics();
-
   page_visibility_observer_set_.ForEachObserver(
       [](PageVisibilityObserver* observer) {
         observer->ObserverSetWillBeCleared();
diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h
index 65b72a9..dab920a 100644
--- a/third_party/blink/renderer/core/page/page.h
+++ b/third_party/blink/renderer/core/page/page.h
@@ -55,7 +55,6 @@
 }
 
 namespace blink {
-class AgentMetricsCollector;
 class AutoscrollController;
 class BrowserControls;
 class ChromeClient;
@@ -197,9 +196,6 @@
   ValidationMessageClient& GetValidationMessageClient() const {
     return *validation_message_client_;
   }
-  AgentMetricsCollector* GetAgentMetricsCollector() const {
-    return agent_metrics_collector_.Get();
-  }
   void SetValidationMessageClientForTesting(ValidationMessageClient*);
 
   ScrollingCoordinator* GetScrollingCoordinator();
@@ -441,10 +437,6 @@
 
   Member<ValidationMessageClient> validation_message_client_;
 
-  // Stored only for ordinary pages to avoid adding metrics from things like
-  // overlays, popups and SVG.
-  Member<AgentMetricsCollector> agent_metrics_collector_;
-
   Deprecation deprecation_;
   WebWindowFeatures window_features_;
 
diff --git a/third_party/blink/renderer/core/script/classic_script.cc b/third_party/blink/renderer/core/script/classic_script.cc
index 882c9ff1..f1b2a92 100644
--- a/third_party/blink/renderer/core/script/classic_script.cc
+++ b/third_party/blink/renderer/core/script/classic_script.cc
@@ -55,7 +55,8 @@
     WorkerOrWorkletGlobalScope& global_scope) {
   DCHECK(global_scope.IsContextThread());
 
-  ScriptState::Scope scope(global_scope.ScriptController()->GetScriptState());
+  v8::HandleScope handle_scope(
+      global_scope.ScriptController()->GetScriptState()->GetIsolate());
   ScriptEvaluationResult result =
       global_scope.ScriptController()->EvaluateAndReturnValue(
           GetScriptSourceCode(), sanitize_script_errors_);
diff --git a/third_party/blink/renderer/core/streams/readable_stream.cc b/third_party/blink/renderer/core/streams/readable_stream.cc
index ba9f6e0..5af2489 100644
--- a/third_party/blink/renderer/core/streams/readable_stream.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -22,6 +22,7 @@
 #include "third_party/blink/renderer/core/streams/promise_handler.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_controller.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_generic_reader.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
 #include "third_party/blink/renderer/core/streams/stream_algorithms.h"
 #include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
 #include "third_party/blink/renderer/core/streams/transferable_streams.h"
@@ -1093,6 +1094,16 @@
     ScriptState* script_state,
     UnderlyingSourceBase* underlying_source,
     size_t high_water_mark) {
+  return CreateWithCountQueueingStrategy(script_state, underlying_source,
+                                         high_water_mark,
+                                         /*optimizer=*/nullptr);
+}
+
+ReadableStream* ReadableStream::CreateWithCountQueueingStrategy(
+    ScriptState* script_state,
+    UnderlyingSourceBase* underlying_source,
+    size_t high_water_mark,
+    std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer) {
   auto* isolate = script_state->GetIsolate();
 
   // It's safer to use a workalike rather than a real CountQueuingStrategy
@@ -1129,6 +1140,7 @@
         << "Ignoring an exception in CreateWithCountQueuingStrategy().";
   }
 
+  stream->transferring_optimizer_ = std::move(optimizer);
   return stream;
 }
 
@@ -1533,9 +1545,11 @@
   //    « port2 »).
 }
 
-ReadableStream* ReadableStream::Deserialize(ScriptState* script_state,
-                                            MessagePort* port,
-                                            ExceptionState& exception_state) {
+ReadableStream* ReadableStream::Deserialize(
+    ScriptState* script_state,
+    MessagePort* port,
+    std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer,
+    ExceptionState& exception_state) {
   // We need to execute JavaScript to call "Then" on v8::Promises. We will not
   // run author code.
   v8::Isolate::AllowJavascriptExecutionScope allow_js(
@@ -1551,8 +1565,8 @@
   // 3. Perform ! SetUpCrossRealmTransformReadable(value, port).
   // In the standard |value| contains an uninitialized ReadableStream. In the
   // implementation, we create the stream here.
-  auto* readable =
-      CreateCrossRealmTransformReadable(script_state, port, exception_state);
+  auto* readable = CreateCrossRealmTransformReadable(
+      script_state, port, std::move(optimizer), exception_state);
   if (exception_state.HadException()) {
     return nullptr;
   }
@@ -1581,6 +1595,11 @@
   return stored_error_.NewLocal(isolate);
 }
 
+std::unique_ptr<ReadableStreamTransferringOptimizer>
+ReadableStream::TakeTransferringOptimizer() {
+  return std::move(transferring_optimizer_);
+}
+
 void ReadableStream::Trace(Visitor* visitor) const {
   visitor->Trace(readable_stream_controller_);
   visitor->Trace(reader_);
diff --git a/third_party/blink/renderer/core/streams/readable_stream.h b/third_party/blink/renderer/core/streams/readable_stream.h
index b9aa5fb0..0450d109 100644
--- a/third_party/blink/renderer/core/streams/readable_stream.h
+++ b/third_party/blink/renderer/core/streams/readable_stream.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_H_
 
 #include <stdint.h>
+#include <memory>
 
 #include "base/optional.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
@@ -23,6 +24,7 @@
 class ReadableStreamDefaultController;
 class ReadableStreamDefaultReaderOrReadableStreamBYOBReader;
 class ReadableStreamGetReaderOptions;
+class ReadableStreamTransferringOptimizer;
 class ReadableWritablePair;
 class ScriptPromise;
 class ScriptState;
@@ -88,6 +90,11 @@
       ScriptState* script_state,
       UnderlyingSourceBase* underlying_source,
       size_t high_water_mark);
+  static ReadableStream* CreateWithCountQueueingStrategy(
+      ScriptState* script_state,
+      UnderlyingSourceBase* underlying_source,
+      size_t high_water_mark,
+      std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer);
 
   // CreateReadableStream():
   // https://streams.spec.whatwg.org/#create-readable-stream
@@ -169,9 +176,11 @@
 
   void Serialize(ScriptState*, MessagePort* port, ExceptionState&);
 
-  static ReadableStream* Deserialize(ScriptState*,
-                                     MessagePort* port,
-                                     ExceptionState&);
+  static ReadableStream* Deserialize(
+      ScriptState*,
+      MessagePort* port,
+      std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer,
+      ExceptionState&);
 
   // Returns a reader that doesn't have the |for_author_code_| flag set. This is
   // used in contexts where reads should not be interceptable by user code. This
@@ -226,6 +235,9 @@
 
   v8::Local<v8::Value> GetStoredError(v8::Isolate*) const;
 
+  std::unique_ptr<ReadableStreamTransferringOptimizer>
+  TakeTransferringOptimizer();
+
   void Trace(Visitor*) const override;
 
  private:
@@ -292,6 +304,7 @@
   Member<ReadableStreamDefaultController> readable_stream_controller_;
   Member<ReadableStreamGenericReader> reader_;
   TraceWrapperV8Reference<v8::Value> stored_error_;
+  std::unique_ptr<ReadableStreamTransferringOptimizer> transferring_optimizer_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/readable_stream_test.cc b/third_party/blink/renderer/core/streams/readable_stream_test.cc
index b596f19c..0954a00 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_test.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_test.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/core/messaging/message_channel.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_reader.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
 #include "third_party/blink/renderer/core/streams/test_underlying_source.h"
 #include "third_party/blink/renderer/core/streams/underlying_source_base.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -93,6 +94,35 @@
   }
 };
 
+// This breaks expectations for general ReadableStreamTransferringOptimizer
+// subclasses, but we don't care.
+class TestTransferringOptimizer final
+    : public ReadableStreamTransferringOptimizer {
+  USING_FAST_MALLOC(TestTransferringOptimizer);
+
+ public:
+  TestTransferringOptimizer() = default;
+
+  UnderlyingSourceBase* PerformInProcessOptimization(
+      ScriptState* script_state) override {
+    return MakeGarbageCollected<Source>(script_state);
+  }
+
+ private:
+  class Source final : public UnderlyingSourceBase {
+   public:
+    explicit Source(ScriptState* script_state)
+        : UnderlyingSourceBase(script_state) {}
+
+    ScriptPromise Start(ScriptState* script_state) override {
+      Controller()->Enqueue("foo");
+      Controller()->Enqueue(", bar");
+      Controller()->Close();
+      return ScriptPromise::CastUndefined(script_state);
+    }
+  };
+};
+
 TEST_F(ReadableStreamTest, CreateWithoutArguments) {
   V8TestingScope scope;
 
@@ -369,8 +399,9 @@
   stream->Serialize(script_state, channel->port1(), ASSERT_NO_EXCEPTION);
   EXPECT_TRUE(stream->IsLocked());
 
-  auto* transferred = ReadableStream::Deserialize(
-      script_state, channel->port2(), ASSERT_NO_EXCEPTION);
+  auto* transferred =
+      ReadableStream::Deserialize(script_state, channel->port2(),
+                                  /*optimizer=*/nullptr, ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(transferred);
 
   underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, "hello")));
@@ -381,6 +412,68 @@
             base::make_optional<String>("hello, bye"));
 }
 
+TEST_F(ReadableStreamTest, DeserializeWithNullOptimizer) {
+  V8TestingScope scope;
+  auto optimizer = std::make_unique<ReadableStreamTransferringOptimizer>();
+  auto* script_state = scope.GetScriptState();
+  auto* isolate = scope.GetIsolate();
+
+  auto* underlying_source =
+      MakeGarbageCollected<TestUnderlyingSource>(script_state);
+  auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+      script_state, underlying_source, 0);
+  ASSERT_TRUE(stream);
+
+  auto* channel =
+      MakeGarbageCollected<MessageChannel>(scope.GetExecutionContext());
+
+  stream->Serialize(script_state, channel->port1(), ASSERT_NO_EXCEPTION);
+  EXPECT_TRUE(stream->IsLocked());
+
+  auto* transferred =
+      ReadableStream::Deserialize(script_state, channel->port2(),
+                                  std::move(optimizer), ASSERT_NO_EXCEPTION);
+  ASSERT_TRUE(transferred);
+
+  underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, "hello")));
+  underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, ", bye")));
+  underlying_source->Close();
+
+  EXPECT_EQ(ReadAll(scope, transferred),
+            base::make_optional<String>("hello, bye"));
+}
+
+TEST_F(ReadableStreamTest, DeserializeWithTestOptimizer) {
+  V8TestingScope scope;
+  auto optimizer = std::make_unique<TestTransferringOptimizer>();
+  auto* script_state = scope.GetScriptState();
+  auto* isolate = scope.GetIsolate();
+
+  auto* underlying_source =
+      MakeGarbageCollected<TestUnderlyingSource>(script_state);
+  auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+      script_state, underlying_source, 0);
+  ASSERT_TRUE(stream);
+
+  auto* channel =
+      MakeGarbageCollected<MessageChannel>(scope.GetExecutionContext());
+
+  stream->Serialize(script_state, channel->port1(), ASSERT_NO_EXCEPTION);
+  EXPECT_TRUE(stream->IsLocked());
+
+  auto* transferred =
+      ReadableStream::Deserialize(script_state, channel->port2(),
+                                  std::move(optimizer), ASSERT_NO_EXCEPTION);
+  ASSERT_TRUE(transferred);
+
+  underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, "hello")));
+  underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, ", bye")));
+  underlying_source->Close();
+
+  EXPECT_EQ(ReadAll(scope, transferred),
+            base::make_optional<String>("hello, byefoo, bar"));
+}
+
 TEST_F(ReadableStreamTest, GarbageCollectJavaScriptUnderlyingSource) {
   V8TestingScope scope;
   auto* isolate = scope.GetIsolate();
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.cc b/third_party/blink/renderer/core/streams/transferable_streams.cc
index 3701dc98..5c364db8 100644
--- a/third_party/blink/renderer/core/streams/transferable_streams.cc
+++ b/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -25,6 +25,7 @@
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_controller.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
 #include "third_party/blink/renderer/core/streams/stream_algorithms.h"
 #include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
 #include "third_party/blink/renderer/core/streams/underlying_source_base.h"
@@ -790,7 +791,7 @@
               .ToLocalChecked();
       if (done) {
         // We've finished reading `source1_`. Let's start reading `source2_`.
-        source_->has_finished_reading_source1_ = true;
+        source_->has_finished_reading_stream1_ = true;
         ReadableStreamDefaultController* controller =
             source_->Controller()->GetOriginalController();
         return source_->source2_
@@ -840,36 +841,32 @@
   };
 
   ConcatenatingUnderlyingSource(ScriptState* script_state,
-                                UnderlyingSourceBase* source1,
+                                ReadableStream* stream1,
                                 UnderlyingSourceBase* source2)
       : UnderlyingSourceBase(script_state),
-        stream_for_source1_(ReadableStream::CreateWithCountQueueingStrategy(
-            script_state,
-            source1,
-            /*high_water_mark=*/0)),
+        stream1_(stream1),
         source2_(source2) {}
 
   ScriptPromise Start(ScriptState* script_state) override {
     ExceptionState exception_state(script_state->GetIsolate(),
                                    ExceptionState::kUnknownContext, "", "");
-    reader_for_source1_ = ReadableStream::AcquireDefaultReader(
-        script_state, stream_for_source1_, /*for_author_code=*/false,
-        exception_state);
+    reader_for_stream1_ = ReadableStream::AcquireDefaultReader(
+        script_state, stream1_, /*for_author_code=*/false, exception_state);
     if (exception_state.HadException()) {
       return ScriptPromise::Reject(script_state, exception_state);
     }
-    DCHECK(reader_for_source1_);
+    DCHECK(reader_for_stream1_);
     return ScriptPromise::CastUndefined(script_state);
   }
 
   ScriptPromise pull(ScriptState* script_state) override {
-    if (has_finished_reading_source1_) {
+    if (has_finished_reading_stream1_) {
       return source2_->pull(script_state);
     }
     ExceptionState exception_state(script_state->GetIsolate(),
                                    ExceptionState::kUnknownContext, "", "");
     ScriptPromise read_promise =
-        reader_for_source1_->read(script_state, exception_state);
+        reader_for_stream1_->read(script_state, exception_state);
     if (exception_state.HadException()) {
       return ScriptPromise::Reject(script_state, exception_state);
     }
@@ -879,13 +876,13 @@
   }
 
   ScriptPromise Cancel(ScriptState* script_state, ScriptValue reason) override {
-    if (has_finished_reading_source1_) {
+    if (has_finished_reading_stream1_) {
       return source2_->Cancel(script_state, reason);
     }
     ExceptionState exception_state(script_state->GetIsolate(),
                                    ExceptionState::kUnknownContext, "", "");
     ScriptPromise cancel_promise1 =
-        reader_for_source1_->cancel(script_state, reason, exception_state);
+        reader_for_stream1_->cancel(script_state, reason, exception_state);
     if (exception_state.HadException()) {
       cancel_promise1 = ScriptPromise::Reject(script_state, exception_state);
     }
@@ -903,16 +900,16 @@
   }
 
   void Trace(Visitor* visitor) const override {
-    visitor->Trace(stream_for_source1_);
-    visitor->Trace(reader_for_source1_);
+    visitor->Trace(stream1_);
+    visitor->Trace(reader_for_stream1_);
     visitor->Trace(source2_);
     UnderlyingSourceBase::Trace(visitor);
   }
 
  private:
-  Member<ReadableStream> stream_for_source1_;
-  Member<ReadableStreamDefaultReader> reader_for_source1_;
-  bool has_finished_reading_source1_ = false;
+  Member<ReadableStream> stream1_;
+  Member<ReadableStreamDefaultReader> reader_for_stream1_;
+  bool has_finished_reading_stream1_ = false;
   Member<UnderlyingSourceBase> source2_;
 };
 
@@ -1026,18 +1023,37 @@
 CORE_EXPORT ReadableStream* CreateCrossRealmTransformReadable(
     ScriptState* script_state,
     MessagePort* port,
+    std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer,
     ExceptionState& exception_state) {
-  return MakeGarbageCollected<CrossRealmTransformReadable>(script_state, port)
-      ->CreateReadableStream(exception_state);
+  ReadableStream* stream =
+      MakeGarbageCollected<CrossRealmTransformReadable>(script_state, port)
+          ->CreateReadableStream(exception_state);
+  if (!optimizer) {
+    return stream;
+  }
+  UnderlyingSourceBase* source2 =
+      optimizer->PerformInProcessOptimization(script_state);
+  if (!source2) {
+    return stream;
+  }
+
+  return ReadableStream::CreateWithCountQueueingStrategy(
+      script_state,
+      MakeGarbageCollected<ConcatenatingUnderlyingSource>(script_state, stream,
+                                                          source2),
+      /*high_water_mark=*/0);
 }
 
 ReadableStream* CreateConcatenatedReadableStream(
     ScriptState* script_state,
     UnderlyingSourceBase* source1,
     UnderlyingSourceBase* source2) {
+  auto* const stream1 =
+      ReadableStream::CreateWithCountQueueingStrategy(script_state, source1,
+                                                      /*high_water_mark=*/0);
   return ReadableStream::CreateWithCountQueueingStrategy(
       script_state,
-      MakeGarbageCollected<ConcatenatingUnderlyingSource>(script_state, source1,
+      MakeGarbageCollected<ConcatenatingUnderlyingSource>(script_state, stream1,
                                                           source2),
       /*high_water_mark=*/0);
 }
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.h b/third_party/blink/renderer/core/streams/transferable_streams.h
index ba4ae6b..8bdb3b3 100644
--- a/third_party/blink/renderer/core/streams/transferable_streams.h
+++ b/third_party/blink/renderer/core/streams/transferable_streams.h
@@ -7,6 +7,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
 
+#include <memory>
+
 #include "third_party/blink/renderer/core/core_export.h"
 
 namespace blink {
@@ -14,6 +16,7 @@
 class ExceptionState;
 class MessagePort;
 class ReadableStream;
+class ReadableStreamTransferringOptimizer;
 class ScriptState;
 class UnderlyingSourceBase;
 class WritableStream;
@@ -31,9 +34,11 @@
 // is used symmetrically with CreateCrossRealmTransformWritable().
 // Equivalent to SetUpCrossRealmTransformReadable in the standard:
 // https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformreadable
-CORE_EXPORT ReadableStream* CreateCrossRealmTransformReadable(ScriptState*,
-                                                              MessagePort* port,
-                                                              ExceptionState&);
+CORE_EXPORT ReadableStream* CreateCrossRealmTransformReadable(
+    ScriptState*,
+    MessagePort* port,
+    std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer,
+    ExceptionState&);
 
 // Creates a ReadableStream that is identical to the concatenation of
 // a ReadableStream created with `source1` and a ReadableStream created with
diff --git a/third_party/blink/renderer/core/streams/transferable_streams_test.cc b/third_party/blink/renderer/core/streams/transferable_streams_test.cc
index cbf3e99b1..0f8d8b5 100644
--- a/third_party/blink/renderer/core/streams/transferable_streams_test.cc
+++ b/third_party/blink/renderer/core/streams/transferable_streams_test.cc
@@ -20,6 +20,7 @@
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_reader.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
 #include "third_party/blink/renderer/core/streams/underlying_source_base.h"
 #include "third_party/blink/renderer/core/streams/writable_stream.h"
 #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
@@ -163,7 +164,8 @@
       script_state, channel->port1(), ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(writable);
   auto* readable = CreateCrossRealmTransformReadable(
-      script_state, channel->port2(), ASSERT_NO_EXCEPTION);
+      script_state, channel->port2(), /*optimizer=*/nullptr,
+      ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(readable);
 
   auto* writer = writable->getWriter(script_state, ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/core/streams/writable_stream.cc b/third_party/blink/renderer/core/streams/writable_stream.cc
index 8c3dcfd..c03be139 100644
--- a/third_party/blink/renderer/core/streams/writable_stream.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
 #include "third_party/blink/renderer/core/streams/promise_handler.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
 #include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
 #include "third_party/blink/renderer/core/streams/transferable_streams.h"
 #include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
@@ -240,8 +241,8 @@
 
   // 5. Let readable be a new ReadableStream in the current Realm.
   // 6. Perform ! SetUpCrossRealmTransformReadable(readable, port1).
-  auto* readable =
-      CreateCrossRealmTransformReadable(script_state, port, exception_state);
+  auto* readable = CreateCrossRealmTransformReadable(
+      script_state, port, /*optimizer=*/nullptr, exception_state);
   if (exception_state.HadException()) {
     return;
   }
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
index 4de4f2ab..ecbd998 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -828,9 +828,6 @@
     frame->Init(nullptr);
   }
 
-  FrameLoader& loader = frame->Loader();
-  loader.ForceSandboxFlags(network::mojom::blink::WebSandboxFlags::kAll);
-
   // SVG Images will always synthesize a viewBox, if it's not available, and
   // thus never see scrollbars.
   frame->View()->SetCanHaveScrollbars(false);
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc
index e1d05f5..780df75 100644
--- a/third_party/blink/renderer/core/testing/internals.cc
+++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -139,6 +139,10 @@
 #include "third_party/blink/renderer/core/scroll/programmatic_scroll_animator.h"
 #include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
 #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/core/streams/readable_stream.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
+#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
 #include "third_party/blink/renderer/core/style_property_shorthand.h"
 #include "third_party/blink/renderer/core/svg/svg_image_element.h"
 #include "third_party/blink/renderer/core/svg_names.h"
@@ -223,6 +227,156 @@
   DISALLOW_COPY_AND_ASSIGN(UseCounterHelperObserverImpl);
 };
 
+class TestReadableStreamSource : public UnderlyingSourceBase {
+ public:
+  class Generator;
+
+  using Reply = CrossThreadOnceFunction<void(std::unique_ptr<Generator>)>;
+  using OptimizerCallback =
+      CrossThreadOnceFunction<void(scoped_refptr<base::SingleThreadTaskRunner>,
+                                   Reply)>;
+
+  enum class Type {
+    kWithNullOptimizer,
+    kWithPerformNullOptimizer,
+    kWithObservableOptimizer,
+    kWithPerfectOptimizer,
+  };
+
+  class Generator final {
+    USING_FAST_MALLOC(Generator);
+
+   public:
+    explicit Generator(int max_count) : max_count_(max_count) {}
+
+    base::Optional<int> Generate() {
+      if (count_ >= max_count_) {
+        return base::nullopt;
+      }
+      ++count_;
+      return current_++;
+    }
+
+    void Add(int n) { current_ += n; }
+
+   private:
+    friend class Optimizer;
+
+    int current_ = 0;
+    int count_ = 0;
+    const int max_count_;
+  };
+
+  class Optimizer final : public ReadableStreamTransferringOptimizer {
+    USING_FAST_MALLOC(Optimizer);
+
+   public:
+    Optimizer(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+              OptimizerCallback callback,
+              Type type)
+        : task_runner_(std::move(task_runner)),
+          callback_(std::move(callback)),
+          type_(type) {}
+
+    UnderlyingSourceBase* PerformInProcessOptimization(
+        ScriptState* script_state) override;
+
+   private:
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+    OptimizerCallback callback_;
+    const Type type_;
+  };
+
+  TestReadableStreamSource(ScriptState* script_state, Type type)
+      : UnderlyingSourceBase(script_state), type_(type) {}
+
+  ScriptPromise Start(ScriptState* script_state) override {
+    if (generator_) {
+      return ScriptPromise::CastUndefined(script_state);
+    }
+    resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+    return resolver_->Promise();
+  }
+
+  ScriptPromise pull(ScriptState* script_state) override {
+    if (!generator_) {
+      return ScriptPromise::CastUndefined(script_state);
+    }
+
+    const auto result = generator_->Generate();
+    if (!result) {
+      Controller()->Close();
+      return ScriptPromise::CastUndefined(script_state);
+    }
+    Controller()->Enqueue(*result);
+    return ScriptPromise::CastUndefined(script_state);
+  }
+
+  std::unique_ptr<ReadableStreamTransferringOptimizer>
+  CreateTransferringOptimizer(ScriptState* script_state) {
+    switch (type_) {
+      case Type::kWithNullOptimizer:
+        return nullptr;
+      case Type::kWithPerformNullOptimizer:
+        return std::make_unique<ReadableStreamTransferringOptimizer>();
+      case Type::kWithObservableOptimizer:
+      case Type::kWithPerfectOptimizer:
+        ExecutionContext* context = ExecutionContext::From(script_state);
+        return std::make_unique<Optimizer>(
+            context->GetTaskRunner(TaskType::kInternalDefault),
+            CrossThreadBindOnce(&TestReadableStreamSource::Detach,
+                                WrapCrossThreadWeakPersistent(this)),
+            type_);
+    }
+  }
+
+  void Attach(std::unique_ptr<Generator> generator) {
+    if (type_ == Type::kWithObservableOptimizer) {
+      generator->Add(100);
+    }
+    generator_ = std::move(generator);
+    if (resolver_) {
+      resolver_->Resolve();
+    }
+  }
+
+  void Detach(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+              Reply reply) {
+    Controller()->Close();
+    PostCrossThreadTask(
+        *task_runner, FROM_HERE,
+        CrossThreadBindOnce(std::move(reply), std::move(generator_)));
+  }
+
+  void Trace(Visitor* visitor) const override {
+    visitor->Trace(resolver_);
+    UnderlyingSourceBase::Trace(visitor);
+  }
+
+ private:
+  const Type type_;
+  std::unique_ptr<Generator> generator_;
+  Member<ScriptPromiseResolver> resolver_;
+};
+
+UnderlyingSourceBase*
+TestReadableStreamSource::Optimizer::PerformInProcessOptimization(
+    ScriptState* script_state) {
+  TestReadableStreamSource* source =
+      MakeGarbageCollected<TestReadableStreamSource>(script_state, type_);
+  ExecutionContext* context = ExecutionContext::From(script_state);
+
+  Reply reply = CrossThreadBindOnce(&TestReadableStreamSource::Attach,
+                                    WrapCrossThreadPersistent(source));
+
+  PostCrossThreadTask(
+      *task_runner_, FROM_HERE,
+      CrossThreadBindOnce(std::move(callback_),
+                          context->GetTaskRunner(TaskType::kInternalDefault),
+                          std::move(reply)));
+  return source;
+}
+
 }  // namespace
 
 static base::Optional<DocumentMarker::MarkerType> MarkerTypeFrom(
@@ -3514,4 +3668,31 @@
                                    : blink::mojom::AdFrameType::kRootAd);
 }
 
+ReadableStream* Internals::createReadableStream(
+    ScriptState* script_state,
+    int32_t queue_size,
+    const String& optimizer,
+    ExceptionState& exception_state) {
+  TestReadableStreamSource::Type type;
+  if (optimizer.IsEmpty()) {
+    type = TestReadableStreamSource::Type::kWithNullOptimizer;
+  } else if (optimizer == "perform-null") {
+    type = TestReadableStreamSource::Type::kWithPerformNullOptimizer;
+  } else if (optimizer == "observable") {
+    type = TestReadableStreamSource::Type::kWithObservableOptimizer;
+  } else if (optimizer == "perfect") {
+    type = TestReadableStreamSource::Type::kWithPerformNullOptimizer;
+  } else {
+    exception_state.ThrowRangeError(
+        "The \"optimizer\" parameter is not correctly set.");
+    return nullptr;
+  }
+  auto* source =
+      MakeGarbageCollected<TestReadableStreamSource>(script_state, type);
+  source->Attach(std::make_unique<TestReadableStreamSource::Generator>(10));
+  return ReadableStream::CreateWithCountQueueingStrategy(
+      script_state, source, queue_size,
+      source->CreateTransferringOptimizer(script_state));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/testing/internals.h b/third_party/blink/renderer/core/testing/internals.h
index 9faef56..52ffc9f 100644
--- a/third_party/blink/renderer/core/testing/internals.h
+++ b/third_party/blink/renderer/core/testing/internals.h
@@ -72,6 +72,7 @@
 class OriginTrialsTest;
 class Page;
 class Range;
+class ReadableStream;
 class RecordTest;
 class ScriptPromiseResolver;
 class ScrollState;
@@ -613,6 +614,11 @@
   void setIsAdSubframe(HTMLIFrameElement* iframe,
                        ExceptionState& exception_state);
 
+  ReadableStream* createReadableStream(ScriptState* script_state,
+                                       int32_t queueSize,
+                                       const String& optimizer,
+                                       ExceptionState&);
+
  private:
   Document* ContextDocument() const;
   Vector<String> IconURLs(Document*, int icon_types_mask) const;
diff --git a/third_party/blink/renderer/core/testing/internals.idl b/third_party/blink/renderer/core/testing/internals.idl
index edf43e7..71e2670 100644
--- a/third_party/blink/renderer/core/testing/internals.idl
+++ b/third_party/blink/renderer/core/testing/internals.idl
@@ -451,4 +451,6 @@
     void generateTestReport(DOMString message);
 
     [RaisesException] void setIsAdSubframe(HTMLIFrameElement iframe);
+
+    [RaisesException, CallWith=ScriptState] ReadableStream createReadableStream(long queueSize, DOMString optimizer);
 };
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc
index d685872..dc7d537 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -332,7 +332,7 @@
                                                 std::move(cached_meta_data)));
     ReportingProxy().WillEvaluateImportedClassicScript(
         source_code.length(), handler ? handler->GetCodeCacheSize() : 0);
-    ScriptState::Scope scope(ScriptController()->GetScriptState());
+    v8::HandleScope scope(isolate);
     ScriptEvaluationResult result = ScriptController()->EvaluateAndReturnValue(
         ScriptSourceCode(source_code, ScriptSourceLocationType::kUnknown,
                          handler,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
index badb6d7..06f217e 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
@@ -28,7 +28,6 @@
 #include "third_party/blink/renderer/modules/accessibility/ax_object.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_position.h"
 #include "third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
@@ -761,9 +760,6 @@
 
 TEST_F(AccessibilitySelectionTest,
        FromCurrentSelectionInTextareaWithCollapsedSelectionAndAffinity) {
-  // TODO(crbug.com/1140302): This test fails with LayoutNGTextControl.
-  ScopedLayoutNGTextControlForTest scope(false);
-
   SetBodyInnerHTML(R"HTML(
       <textarea id="textarea"
           rows="2" cols="15"
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
index 3ef1a12..873471a 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
@@ -155,7 +155,7 @@
     DCHECK(script_state);
     v8::Isolate* isolate = script_state->GetIsolate();
     DCHECK(isolate);
-    ScriptState::Scope scope(script_state);
+    v8::HandleScope scope(isolate);
 
     ScriptEvaluationResult result =
         global_scope->ScriptController()->EvaluateAndReturnValue(
diff --git a/third_party/blink/renderer/platform/instrumentation/BUILD.gn b/third_party/blink/renderer/platform/instrumentation/BUILD.gn
index 122520b..814c58d 100644
--- a/third_party/blink/renderer/platform/instrumentation/BUILD.gn
+++ b/third_party/blink/renderer/platform/instrumentation/BUILD.gn
@@ -50,6 +50,7 @@
 
   sources = [
     "histogram_test.cc",
+    "partition_alloc_memory_dump_provider_test.cc",
     "tracing/traced_value_test.cc",
     "tracing/web_process_memory_dump_test.cc",
   ]
diff --git a/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.cc b/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.cc
index eece1d52..5bc0a994 100644
--- a/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.cc
+++ b/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.cc
@@ -6,6 +6,7 @@
 
 #include "base/allocator/partition_allocator/partition_alloc.h"
 #include "base/format_macros.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/malloc_dump_provider.h"
 #include "base/trace_event/process_memory_dump.h"
@@ -84,6 +85,23 @@
         memory_dump_->CreateAllocatorDump(dump_name + "/thread_cache");
     base::trace_event::ReportPartitionAllocThreadCacheStats(
         all_thread_caches_dump, all_thread_caches_stats);
+
+    if (all_thread_caches_stats.alloc_count) {
+      int hit_rate_percent =
+          static_cast<int>((100 * all_thread_caches_stats.alloc_hits) /
+                           all_thread_caches_stats.alloc_count);
+      base::UmaHistogramPercentage("Memory.PartitionAlloc.ThreadCache.HitRate",
+                                   hit_rate_percent);
+    }
+
+    if (thread_cache_stats.alloc_count) {
+      int hit_rate_percent =
+          static_cast<int>((100 * thread_cache_stats.alloc_hits) /
+                           thread_cache_stats.alloc_count);
+      base::UmaHistogramPercentage(
+          "Memory.PartitionAlloc.ThreadCache.HitRate.MainThread",
+          hit_rate_percent);
+    }
   }
 }
 
diff --git a/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc b/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc
new file mode 100644
index 0000000..b15bf31a
--- /dev/null
+++ b/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.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 "third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
+
+namespace blink {
+
+TEST(PartitionAllocMemoryDumpProviderTest, Simple) {
+  // Make sure there is at least one allocation.
+  // Otherwise the hit rate is not computed.
+  void* data = WTF::Partitions::FastMalloc(12, "");
+  WTF::Partitions::FastFree(data);
+
+  base::HistogramTester histogram_tester;
+  base::trace_event::MemoryDumpArgs args = {
+      base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+  base::trace_event::ProcessMemoryDump pmd(args);
+  PartitionAllocMemoryDumpProvider::Instance()->OnMemoryDump(args, &pmd);
+
+#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \
+    defined(PA_THREAD_CACHE_SUPPORTED) &&        \
+    !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+  histogram_tester.ExpectTotalCount("Memory.PartitionAlloc.ThreadCache.HitRate",
+                                    1);
+  histogram_tester.ExpectTotalCount(
+      "Memory.PartitionAlloc.ThreadCache.HitRate.MainThread", 1);
+#else
+  histogram_tester.ExpectTotalCount("Memory.PartitionAlloc.ThreadCache.HitRate",
+                                    0);
+  histogram_tester.ExpectTotalCount(
+      "Memory.PartitionAlloc.ThreadCache.HitRate.MainThread", 0);
+#endif  // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) &&
+        // defined(PA_THREAD_CACHE_SUPPORTED) &&
+        // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc b/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
index 45cc073..9e1d5c63 100644
--- a/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
@@ -67,6 +67,7 @@
     void DidFinishLoadingBody() override {}
     void DidFailLoadingBody() override {}
     void DidCancelLoadingBody() override {}
+    void EvictFromBackForwardCache() override {}
   };
 
   ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index b2b28a4..98f8999 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -2292,6 +2292,12 @@
   subresource_web_bundles_.erase(&subresource_web_bundle);
 }
 
+void ResourceFetcher::EvictFromBackForwardCache() {
+  if (!resource_load_observer_)
+    return;
+  resource_load_observer_->EvictFromBackForwardCache();
+}
+
 void ResourceFetcher::Trace(Visitor* visitor) const {
   visitor->Trace(context_);
   visitor->Trace(properties_);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 07af328..793721fd 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -306,6 +306,8 @@
   void AddSubresourceWebBundle(SubresourceWebBundle& subresource_web_bundle);
   void RemoveSubresourceWebBundle(SubresourceWebBundle& subresource_web_bundle);
 
+  void EvictFromBackForwardCache();
+
  private:
   friend class ResourceCacheValidationSuppressor;
   enum class StopFetchingTarget {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
index 7053dd6..f42b6b7 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -154,7 +154,7 @@
                         const ResourceError&,
                         int64_t encoded_data_length,
                         IsInternalRequest is_internal_request) override {}
-
+    void EvictFromBackForwardCache() override {}
     const base::Optional<PartialResourceRequest>& GetLastRequest() const {
       return request_;
     }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h b/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
index 2de52bb..307db6c1 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
@@ -96,6 +96,11 @@
                               int64_t encoded_data_length,
                               IsInternalRequest) = 0;
 
+  // Evict the page from BackForwardCache. Should be called when handling an
+  // event which can't proceed if the page is in BackForwardCache and can't be
+  // easily deferred to handle later, for example network redirect handling.
+  virtual void EvictFromBackForwardCache() {}
+
   virtual void Trace(Visitor*) const {}
 };
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index e9c81d6..06cffea 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -633,6 +633,9 @@
     if (defers != WebURLLoader::DeferType::kNotDeferred &&
         !response_body_loader_->IsSuspended()) {
       response_body_loader_->Suspend();
+      if (defers == WebURLLoader::DeferType::kDeferredWithBackForwardCache) {
+        response_body_loader_->EvictFromBackForwardCacheIfDrained();
+      }
     }
     if (defers == WebURLLoader::DeferType::kNotDeferred &&
         response_body_loader_->IsSuspended()) {
@@ -1216,6 +1219,10 @@
                               inflight_keepalive_bytes_);
 }
 
+void ResourceLoader::EvictFromBackForwardCache() {
+  fetcher_->EvictFromBackForwardCache();
+}
+
 void ResourceLoader::RequestSynchronously(const ResourceRequestHead& request) {
   DCHECK(loader_);
   DCHECK_EQ(request.Priority(), ResourceLoadPriority::kHighest);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
index edf5958..781420e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -138,6 +138,7 @@
                int64_t encoded_data_length,
                int64_t encoded_body_length,
                int64_t decoded_body_length) override;
+  void EvictFromBackForwardCache() override;
 
   blink::mojom::CodeCacheType GetCodeCacheType() const;
   void SendCachedCodeToResource(mojo_base::BigBuffer data);
diff --git a/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc b/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
index 27ec56cd..7b046f7 100644
--- a/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
@@ -420,6 +420,11 @@
   client_->DidCancelLoadingBody();
 }
 
+// TODO(yuzus): Remove this and provide the capability to the loader.
+void ResponseBodyLoader::EvictFromBackForwardCache() {
+  client_->EvictFromBackForwardCache();
+}
+
 void ResponseBodyLoader::Start() {
   DCHECK(!started_);
   DCHECK(!drained_);
@@ -451,6 +456,12 @@
   suspended_ = true;
 }
 
+void ResponseBodyLoader::EvictFromBackForwardCacheIfDrained() {
+  if (IsDrained()) {
+    client_->EvictFromBackForwardCache();
+  }
+}
+
 void ResponseBodyLoader::Resume() {
   if (aborted_)
     return;
diff --git a/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h b/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
index dde4b341..66ccb4a 100644
--- a/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
+++ b/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h
@@ -99,6 +99,8 @@
   bool IsSuspended() const { return suspended_; }
   bool IsDrained() const { return drained_; }
 
+  void EvictFromBackForwardCacheIfDrained();
+
   void Trace(Visitor*) const override;
 
   // The maximal number of bytes consumed in a task. When there are more bytes
@@ -117,6 +119,7 @@
   void DidFinishLoadingBody() override;
   void DidFailLoadingBody() override;
   void DidCancelLoadingBody() override;
+  void EvictFromBackForwardCache() override;
 
   // BytesConsumer::Client implementation.
   void OnStateChange() override;
diff --git a/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h b/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h
index 58921803..ed66b262 100644
--- a/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h
+++ b/third_party/blink/renderer/platform/loader/fetch/response_body_loader_client.h
@@ -25,6 +25,9 @@
 
   // Called when the loader cancelled loading the body.
   virtual void DidCancelLoadingBody() = 0;
+
+  // Called when the body loader is suspended and the data pipe is drained.
+  virtual void EvictFromBackForwardCache() = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc b/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
index b1fa0ad..b096934 100644
--- a/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
@@ -74,6 +74,7 @@
       DCHECK(!failed_);
       cancelled_ = true;
     }
+    void EvictFromBackForwardCache() override {}
 
     void SetLoader(ResponseBodyLoader& loader) { loader_ = loader; }
     void Trace(Visitor* visitor) const override { visitor->Trace(loader_); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
index 8128883..b4a2b10 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
@@ -193,6 +193,7 @@
                       const ResourceError&,
                       int64_t encoded_data_length,
                       IsInternalRequest));
+    MOCK_METHOD0(EvictFromBackForwardCache, void());
   };
 
   MojoCreateDataPipeOptions CreateDataPipeOptions() {
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
index 2c31024d..bda30507 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
@@ -157,11 +157,11 @@
                 # to render them with <text-diff-artifact> or
                 # <img-diff-artifact>.
                 #
-                # stderr and crash_log are the only artifact names that are
+                # command, stderr and crash_log are artifact names that are
                 # not included in the auto-generated summary. This uses
                 # <text-artifact> to render them in the summary_html section
                 # of each test.
-                if name in ['stderr', 'crash_log']:
+                if name in ['command', 'stderr', 'crash_log']:
                     summaries.append(
                         '<h3>%s</h3>'
                         '<p><text-artifact artifact-id="%s" /></p>' %
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py b/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
index bbf65be..8726f99 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
@@ -89,6 +89,7 @@
 # Filename pieces when writing failures to the test results directory.
 FILENAME_SUFFIX_ACTUAL = "-actual"
 FILENAME_SUFFIX_EXPECTED = "-expected"
+FILENAME_SUFFIX_CMD = "-command"
 FILENAME_SUFFIX_DIFF = "-diff"
 FILENAME_SUFFIX_DIFFS = "-diffs"
 FILENAME_SUFFIX_STDERR = "-stderr"
@@ -129,12 +130,26 @@
             artifact_name, path, content, force_overwrite=force_overwrite)
 
     def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        typ_artifacts_dir = self.filesystem.join(
+            self.result_directory, typ_artifacts.ArtifactsSubDirectory())
+        if self.actual_driver_output.command:
+            artifact_filename = self.port.output_filename(
+                self.test_name, FILENAME_SUFFIX_CMD, '.txt')
+            artifacts_abspath = self.filesystem.join(typ_artifacts_dir,
+                                                     artifact_filename)
+            if (force_overwrite or self.result != ResultType.Pass
+                    or not self.filesystem.exists(artifacts_abspath)):
+                self._write_to_artifacts(typ_artifacts,
+                                         'command',
+                                         artifact_filename,
+                                         self.actual_driver_output.command,
+                                         force_overwrite=True)
+
         if self.actual_driver_output.error:
             artifact_filename = self.port.output_filename(
                 self.test_name, FILENAME_SUFFIX_STDERR, '.txt')
-            artifacts_abspath = self.filesystem.join(
-                self.result_directory, typ_artifacts.ArtifactsSubDirectory(),
-                artifact_filename)
+            artifacts_abspath = self.filesystem.join(typ_artifacts_dir,
+                                                     artifact_filename)
             # If a test has multiple stderr results, keep that of the last
             # failure, which is useful for debugging flaky tests with
             # --iterations=n or --repeat-each=n.
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_results.py b/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
index 0ddc277c..d362dda 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
@@ -46,16 +46,16 @@
     failures = failures or []
     if not failures and driver_output.error:
         failures.append(test_failures.PassWithStderr(driver_output))
-    return TestResult(
-        test_name,
-        retry_attempt=retry_attempt,
-        failures=failures,
-        test_run_time=test_run_time,
-        reftest_type=reftest_type,
-        pid=pid,
-        references=references,
-        device_failed=device_failed,
-        crash_site=crash_site)
+    return TestResult(test_name,
+                      retry_attempt=retry_attempt,
+                      failures=failures,
+                      test_run_time=test_run_time,
+                      reftest_type=reftest_type,
+                      pid=pid,
+                      references=references,
+                      device_failed=device_failed,
+                      crash_site=crash_site,
+                      command=driver_output.command)
 
 
 class TestResult(object):
@@ -77,7 +77,8 @@
                  pid=None,
                  references=None,
                  device_failed=False,
-                 crash_site=None):
+                 crash_site=None,
+                 command=None):
         self.test_name = test_name
         self.failures = failures or []
         self.test_run_time = test_run_time or 0  # The time taken to execute the test itself.
@@ -90,6 +91,7 @@
             failure.has_repaint_overlay for failure in self.failures)
         self.crash_site = crash_site
         self.retry_attempt = retry_attempt
+        self.command = command
 
         results = set([f.result for f in self.failures] or [ResultType.Pass])
         assert len(results) <= 2, (
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/driver.py b/third_party/blink/tools/blinkpy/web_tests/port/driver.py
index e9213e5..900427eb 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/driver.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/driver.py
@@ -126,7 +126,8 @@
                  crash_site=None,
                  leak=False,
                  leak_log=None,
-                 pid=None):
+                 pid=None,
+                 command=None):
         # FIXME: Args could be renamed to better clarify what they do.
         self.text = text
         self.image = image  # May be empty-string if the test crashes.
@@ -145,6 +146,7 @@
         self.timeout = timeout
         self.error = error  # stderr output
         self.pid = pid
+        self.command = command
 
     def has_stderr(self):
         return bool(self.error)
@@ -229,10 +231,11 @@
         self.error_from_test = str()
         self.err_seen_eof = False
 
-        command = self._command_from_driver_input(driver_input)
-        deadline = test_begin_time + int(driver_input.timeout) / 1000.0
+        test_command = self._command_from_driver_input(driver_input)
+        server_process_command = self._server_process.cmd()
 
-        self._server_process.write(command)
+        deadline = test_begin_time + int(driver_input.timeout) / 1000.0
+        self._server_process.write(test_command)
         # First block is either text or audio
         text, audio = self._read_first_block(deadline)
         # The second (optional) block is image data.
@@ -285,24 +288,25 @@
                 if self.error_from_test:
                     crash_log += '\nstdout:\n%s\nstderr:\n%s\n' % (
                         text, self.error_from_test)
+        command = "%s %s" % (" ".join(server_process_command), test_command)
 
-        return DriverOutput(
-            text,
-            image,
-            actual_image_hash,
-            audio,
-            crash=crashed,
-            test_time=time.time() - test_begin_time,
-            measurements=self._measurements,
-            timeout=timed_out,
-            error=self.error_from_test,
-            crashed_process_name=self._crashed_process_name,
-            crashed_pid=self._crashed_pid,
-            crash_log=crash_log,
-            crash_site=crash_site,
-            leak=leaked,
-            leak_log=self._leak_log,
-            pid=pid)
+        return DriverOutput(text,
+                            image,
+                            actual_image_hash,
+                            audio,
+                            crash=crashed,
+                            test_time=time.time() - test_begin_time,
+                            measurements=self._measurements,
+                            timeout=timed_out,
+                            error=self.error_from_test,
+                            crashed_process_name=self._crashed_process_name,
+                            crashed_pid=self._crashed_pid,
+                            crash_log=crash_log,
+                            crash_site=crash_site,
+                            leak=leaked,
+                            leak_log=self._leak_log,
+                            pid=pid,
+                            command=command)
 
     def _get_crash_log(self, stdout, stderr, newer_than):
         # pylint: disable=protected-access
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/server_process.py b/third_party/blink/tools/blinkpy/web_tests/port/server_process.py
index ffe637f..2ce15bd 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/server_process.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/server_process.py
@@ -103,6 +103,9 @@
     def pid(self):
         return self._pid
 
+    def cmd(self):
+        return self._cmd[:]
+
     def _reset(self):
         if getattr(self, '_proc', None):
             if self._proc.stdin:
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index a73cac4..639532c 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1143,22 +1143,6 @@
 
 ### With LayoutNGFragmentTraversal (and LayoutNGFragmentItem) enabled:
 
-# From NeverFixTests:
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/inline-formatting-context-002.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/inline-formatting-context-003.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/inline-formatting-context-004.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/inline-formatting-context-005.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/inline-formatting-context-006.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/inline-formatting-context-007.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/inline-formatting-context-010b.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/inline-formatting-context-012.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/vertical-align-baseline-003.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/vertical-align-sub-001.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/vertical-align-super-001.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/normal-flow/blocks-017.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-008.xht [ Skip ]
-virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/normal-flow/inline-replaced-height-008.xht [ Skip ]
-
 # Lots of manual tests here; just skip everything - not too interesting for LayoutNGFragmentTraversal anyway:
 virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/cascade/* [ Skip ]
 virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/text/* [ Skip ]
@@ -1644,8 +1628,9 @@
 crbug.com/1129834 external/wpt/css/css-text/white-space/trailing-other-space-separators-002.html [ Failure ]
 crbug.com/1129834 external/wpt/css/css-text/white-space/trailing-other-space-separators-003.html [ Failure ]
 crbug.com/1129834 external/wpt/css/css-text/white-space/trailing-other-space-separators-004.html [ Failure ]
-crbug.com/972992 external/wpt/css/css-text/white-space/trailing-ideographic-space-001.html [ Failure ]
-crbug.com/972992 external/wpt/css/css-text/white-space/trailing-ideographic-space-002.html [ Failure ]
+crbug.com/1129834 external/wpt/css/css-text/white-space/full-width-leading-spaces-004.html [ Failure ]
+crbug.com/1129834 external/wpt/css/css-text/white-space/trailing-ideographic-space-001.html [ Failure ]
+crbug.com/1129834 external/wpt/css/css-text/white-space/trailing-ideographic-space-002.html [ Failure ]
 
 
 # Follow up the spec change for U+2010, U+2013
@@ -2023,6 +2008,9 @@
 
 crbug.com/332189 external/wpt/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html [ Pass Failure ]
 
+# Awaiting DevTools changes.
+crbug.com/1152391 http/tests/devtools/elements/copy-styles.js [ Pass Failure ]
+
 # Some control characters still not visible
 crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-001.html [ Failure ]
 crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-002.html [ Failure ]
@@ -2589,7 +2577,6 @@
 # ====== New tests from wpt-importer added here ======
 crbug.com/626703 external/wpt/mediacapture-record/MediaRecorder-peerconnection-no-sink.https.html [ Timeout ]
 crbug.com/626703 external/wpt/mediacapture-record/MediaRecorder-peerconnection.https.html [ Timeout ]
-crbug.com/626703 external/wpt/css/css-text/white-space/full-width-leading-spaces-004.html [ Failure ]
 crbug.com/626703 [ Win7 ] virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ]
 crbug.com/626703 external/wpt/fetch/api/request/request-bad-port.any.worker.html [ Timeout ]
 crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/fetch/api/request/request-bad-port.any.worker.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 26c2868..2228b61 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -73782,6 +73782,19 @@
         {}
        ]
       ],
+      "percentage-size-indefinite-replaced.html": [
+       "3610f2e2c992b075d203bc5bfceb400c7b4fca0d",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square-only.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "percentage-size-replaced-subitems-001.html": [
        "190277a1ed1e409540410eb43bf5be0d64c142cf",
        [
@@ -87669,7 +87682,7 @@
       ]
      ],
      "color-custom-property-animation.https.html": [
-      "5cbfee89c45dd37e165676a835ece3f6283d0957",
+      "729af95ceb8f206faa4b6e80059e774dbc8af095",
       [
        null,
        [
@@ -87918,7 +87931,7 @@
       ]
      ],
      "one-custom-property-animation.https.html": [
-      "ca746f5999b6f57a43499a91007325fa93524d17",
+      "25b1cef1882436679ed46a9da10bc403883ea7c5",
       [
        null,
        [
@@ -88867,7 +88880,7 @@
       ]
      ],
      "two-custom-property-animation.https.html": [
-      "9cd20272a35ca713e7916c2d6c15ae2a1aa7e912",
+      "6669076e909c273d2c63b34c91a29e443065a248",
       [
        null,
        [
@@ -88880,7 +88893,7 @@
       ]
      ],
      "two-element-custom-property-animation.https.html": [
-      "044650dcaffbca576977a6b2ce4ec61fb00cf70c",
+      "48b0f201d4b188fe9e62c33790cb7e478811b55e",
       [
        null,
        [
@@ -88892,6 +88905,19 @@
        {}
       ]
      ],
+     "two-element-one-custom-property-animation.https.html": [
+      "1090185409d7a683b381ddb74a7d6ee4522fe108",
+      [
+       null,
+       [
+        [
+         "/css/css-paint-api/two-element-one-custom-property-animation-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "valid-image-after-load.https.html": [
       "c1bf8e85548656b60145c4d54437b10a2f07880e",
       [
@@ -154641,6 +154667,125 @@
          ]
         }
        },
+       "drawing-text-to-the-canvas": {
+        "canvas.2d.fontStretch.condensed.html": [
+         "2bda32082e3577757ca58dd460d0f0a478a7d647",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ],
+        "canvas.2d.fontStretch.expanded.html": [
+         "c679ccb57b955ff255c9c6fb02bc65323d9b6edd",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ],
+        "canvas.2d.fontStretch.extra-condensed.html": [
+         "a3a18c05c63143869a0bea7a2e93b69e796b14ca",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ],
+        "canvas.2d.fontStretch.extra-expanded.html": [
+         "4f1bf6838dd1fb37a1125c96437105b23f6fe2f2",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ],
+        "canvas.2d.fontStretch.normal.html": [
+         "b60d25f57942ed8a0325745a7994db513aeb6fde",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ],
+        "canvas.2d.fontStretch.semi-condensed.html": [
+         "c356ee176efa56305f9d32a681f975c9b9907ab8",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ],
+        "canvas.2d.fontStretch.semi-expanded.html": [
+         "bc9bb2bfa5121bdbe2e50937ff5f5f4fee4a60e7",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ],
+        "canvas.2d.fontStretch.ultra-condensed.html": [
+         "62af7780927a78e93b528eb15293ff4a99e73d92",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ],
+        "canvas.2d.fontStretch.ultra-expanded.html": [
+         "4faf47b07421b90a1d2e0842a58c2ad88c9c0df2",
+         [
+          null,
+          [
+           [
+            "/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.fontStretch-ref.html",
+            "=="
+           ]
+          ],
+          {}
+         ]
+        ]
+       },
        "line-styles": {
         "canvas_linestyles_linecap_001.htm": [
          "583dbc9d134682a778569877e38513e07736dd82",
@@ -195483,7 +195628,7 @@
       []
      ],
      "color-custom-property-animation-ref.html": [
-      "3439cd9364560c870b09a394887daec5969b6bd4",
+      "d66536456ec321b5235b95a9c4239b082da399d0",
       []
      ],
      "geometry-background-image-001-ref.html": [
@@ -195639,11 +195784,15 @@
       []
      ],
      "two-custom-property-animation-ref.html": [
-      "1acef69f9413c154b2f527d3792f24bbbdb38643",
+      "fa364bde34988eaf021c762ffb9b5776f20df402",
       []
      ],
      "two-element-custom-property-animation-ref.html": [
-      "6c6d94575eceb892278d355278a0c1463c726168",
+      "37774e086f0ab9cc8b74fed23648df1f7da7b312",
+      []
+     ],
+     "two-element-one-custom-property-animation-ref.html": [
+      "530d3dc9a13ced598f3072ba8f79937410f0c473",
       []
      ],
      "valid-image-after-load-ref.html": [
@@ -217493,6 +217642,10 @@
      "e828b629858d07afd989b80894986315bac16cc7",
      []
     ],
+    "fail.woff": [
+     "33487cdbb4f2a88b2107c191cce051cb5a247e1f",
+     []
+    ],
     "math": {
      "axisheight5000-verticalarrow14000.woff": [
       "70f366a3d0b7ec891fc4041584a1ddea55b0bc42",
@@ -217845,6 +217998,10 @@
       []
      ]
     },
+    "pass.woff": [
+     "839bb20b12fee0e6f24f76ea58501aff76fa5a14",
+     []
+    ],
     "sileot-webfont.woff": [
      "81547578d36c7989db0a03127074a5f4b33768b4",
      []
@@ -220650,6 +220807,12 @@
          ]
         }
        },
+       "drawing-text-to-the-canvas": {
+        "canvas.2d.fontStretch-ref.html": [
+         "4b3b28baf9dcb1dea96611bfdbfbce0a0aba7c3c",
+         []
+        ]
+       },
        "imagebitmap": {
         "common.sub.js": [
          "aa1e382a2088fee541a1020a03a4299a3b18d6cd",
@@ -228202,10 +228365,6 @@
         "fb8804941ba81b386e252e6f31002c5005f3b8fc",
         []
        ],
-       "iframe-loading-lazy-in-script-disabled-iframe-expected.txt": [
-        "3e45f16374002ae4a3297cc611848c7a5cfeff1a",
-        []
-       ],
        "iframe-loading-lazy-load-event-expected.txt": [
         "083da11b5c5f050bf37970286452df756b760175",
         []
@@ -251625,7 +251784,7 @@
         []
        ],
        "executormarionette.py": [
-        "da8941b69e33b0986f999f286c4a64e584349ecc",
+        "675f8e0a43291fcbc4f6020eecd642a50bc412cc",
         []
        ],
        "executoropera.py": [
@@ -251800,7 +251959,7 @@
        []
       ],
       "testrunner.py": [
-       "961c40fc5b8099136f341d1263cd855180bff9bd",
+       "e5d7042c73b30d8d6280c2e231d9d81b9d0d8975",
        []
       ],
       "update": {
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content-ref.html
new file mode 100644
index 0000000..95e3c05
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<body>
+<style>
+body {
+  margin: 0;
+}
+
+.fieldset div {
+  height:1000px;
+}
+
+span {
+  background: lime;
+  display: block;
+  height: 40px;
+  position: absolute;
+  top: 4px;
+  left: 0px;
+  width: 40px;
+}
+
+.fieldset {
+  border: none;
+  height: 400px;
+  margin: 0;
+  overflow: scroll;
+  padding: 0;
+}
+</style>
+<div class="fieldset"><div><span></span></div></div>
+<script>
+document.querySelector('.fieldset').scrollTop = 1000;
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content.html
new file mode 100644
index 0000000..f60d9ec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="help" href="http://crbug.com/1146925">
+<link rel="match" href="sticky-content-ref.html">
+<body>
+<style>
+body {
+  margin: 0;
+}
+
+fieldset div {
+  height:1000px;
+}
+
+span {
+  background: lime;
+  display: block;
+  height: 40px;
+  position: sticky;
+  top: 4px;
+  width: 40px;
+}
+
+fieldset {
+  border: none;
+  height: 400px;
+  margin: 0;
+  overflow: scroll;
+  padding: 0;
+}
+</style>
+<fieldset><div><span></span></div></fieldset>
+<script>
+document.querySelector('fieldset').scrollTop = 1000;
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
index da8941b..675f8e0 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -954,7 +954,8 @@
             assertion_count = self.protocol.asserts.get()
             if "extra" not in result:
                 result["extra"] = {}
-            result["extra"]["assertion_count"] = assertion_count
+            if assertion_count is not None:
+                result["extra"]["assertion_count"] = assertion_count
 
         return self.convert_result(test, result)
 
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testrunner.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testrunner.py
index 961c40fc..e5d7042 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testrunner.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testrunner.py
@@ -664,8 +664,8 @@
             self.logger.debug("Unexpected count in this thread %i" % self.unexpected_count)
 
         if "assertion_count" in file_result.extra:
-            assertion_count = file_result.extra.pop("assertion_count")
-            if assertion_count > 0:
+            assertion_count = file_result.extra["assertion_count"]
+            if assertion_count is not None and assertion_count > 0:
                 self.logger.assertion_count(test.id,
                                             int(assertion_count),
                                             test.min_assertion_count,
diff --git a/third_party/blink/web_tests/fast/harness/results.html b/third_party/blink/web_tests/fast/harness/results.html
index 316ebf5..63c0140 100644
--- a/third_party/blink/web_tests/fast/harness/results.html
+++ b/third_party/blink/web_tests/fast/harness/results.html
@@ -838,6 +838,10 @@
       toolbars.push(new SimpleLinkToolbar().createDom(
             pathParser.resultLink("-stderr.txt"), "standard error", "stderr"));
     }
+    if (test.command) {
+      toolbars.push(new SimpleLinkToolbar().createDom(
+            pathParser.resultLink("-command.txt"), "Command", "command"));
+    }
     return toolbars;
   },
   getResultsDiv: (test) => {
@@ -1134,6 +1138,9 @@
     if (artifacts.hasOwnProperty('reference_file_mismatch'))
       test.reference = artifacts.reference_file_mismatch;
 
+    if (artifacts.hasOwnProperty('command'))
+      test.command = artifacts.command;
+
     if (is_image && is_text)
       return 'IMAGE+TEXT';
     if (is_image)
diff --git a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor.js b/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor.js
index 7f90ee74..50e23a9e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor.js
+++ b/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor.js
@@ -19,8 +19,10 @@
   function didShowScriptSource(shownSourceFrame) {
     sourceFrame = shownSourceFrame;
     textEditor = sourceFrame._textEditor;
-    // We are probably still updating the editor in current callstack, so postponing the test execution.
-    setImmediate(textEditorUpdated);
+    // We are probably still updating the editor in current callstack, so postpone the test execution.
+    queueMicrotask(() => {
+      textEditorUpdated();
+    });
   }
 
   function textEditorUpdated(sourceFrame) {
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/source-frame.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/source-frame.js
index 4dc43cd..1b8a7ce0 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/source-frame.js
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/source-frame.js
@@ -44,7 +44,7 @@
         // Messages can contain live locations.
         await TestRunner.waitForPendingLiveLocationUpdates();
         TestRunner.addResult('Message added to source frame: ' + message.text());
-        setImmediate(function() {
+        queueMicrotask(() => {
           Console.ConsoleView.clearConsole();
         });
       }
diff --git a/third_party/blink/web_tests/http/tests/streams/chromium/resources/transferring-back-worker.js b/third_party/blink/web_tests/http/tests/streams/chromium/resources/transferring-back-worker.js
new file mode 100644
index 0000000..e60b681
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/streams/chromium/resources/transferring-back-worker.js
@@ -0,0 +1,11 @@
+self.addEventListener('message', (e) => {
+  const port = e.data.port;
+  port.onmessage = (e) => {
+    const data = e.data;
+    const transferList = [];
+    if (data.rs) {
+      transferList.push(data.rs);
+    }
+    port.postMessage(data, transferList);
+  };
+});
diff --git a/third_party/blink/web_tests/http/tests/streams/chromium/transferable-streams-optimization.html b/third_party/blink/web_tests/http/tests/streams/chromium/transferable-streams-optimization.html
new file mode 100644
index 0000000..d9e39f2
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/streams/chromium/transferable-streams-optimization.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+'use strict';
+
+async function readAll(rs) {
+  const reader = rs.getReader();
+  const seq = [];
+  while (true) {
+    const {value, done} = await reader.read();
+    if (done) {
+      break;
+    }
+    seq.push(value);
+  }
+  return seq;
+}
+
+function createIframe() {
+  const iframe = document.createElement('iframe');
+  document.body.appendChild(iframe);
+  return iframe;
+}
+
+async_test((t) => {
+  Promise.resolve().then(async () => {
+    const iframe = createIframe();
+    const rs = internals.createReadableStream(3, '');
+
+    iframe.contentWindow.postMessage(rs, '*', [rs]);
+    const ev = await new Promise((r) => iframe.contentWindow.onmessage = r);
+    const seq = await readAll(ev.data);
+
+    assert_array_equals(seq, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+  }).then(() => t.done(), t.step_func((e) => assert_unreached(e)));
+}, '[rs] transferring between frames; optimizer is not used');
+
+async_test((t) => {
+  Promise.resolve().then(async () => {
+    const iframe = createIframe();
+    const rs = internals.createReadableStream(3, 'perform-null');
+
+    iframe.contentWindow.postMessage(rs, '*', [rs]);
+    const ev = await new Promise((r) => iframe.contentWindow.onmessage = r);
+    const seq = await readAll(ev.data);
+
+    assert_array_equals(seq, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+  }).then(() => t.done(), t.step_func((e) => assert_unreached(e)));
+}, '[rs] transferring between frames; non-null but doing nothing optimizer is used');
+
+async_test((t) => {
+  Promise.resolve().then(async () => {
+    const iframe = createIframe();
+    const rs = internals.createReadableStream(3, 'observable');
+
+    iframe.contentWindow.postMessage(rs, '*', [rs]);
+    const ev = await new Promise((r) => iframe.contentWindow.onmessage = r);
+    const seq = await readAll(ev.data);
+
+    assert_array_equals(
+      seq, [100, 101, 102, 103, 204, 205, 206, 207, 208, 209]);
+  }).then(() => t.done(), t.step_func((e) => assert_unreached(e)));
+}, '[rs] transferring between frames; observable optimizer is used');
+
+async_test((t) => {
+  Promise.resolve().then(async () => {
+    const iframe = createIframe();
+    const rs = internals.createReadableStream(3, 'perfect');
+
+    iframe.contentWindow.postMessage(rs, '*', [rs]);
+    const ev = await new Promise((r) => iframe.contentWindow.onmessage = r);
+    const seq = await readAll(ev.data);
+
+    assert_array_equals(seq, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+  }).then(() => t.done(), t.step_func((e) => assert_unreached(e)));
+}, '[rs] transferring between frames; perfect optimizer is used');
+
+async_test((t) => {
+  Promise.resolve().then(async () => {
+    const iframe = createIframe();
+    const rs = internals.createReadableStream(3, 'perfect');
+    const reader = rs.getReader();
+    await reader.read();
+    await reader.read();
+    reader.releaseLock();
+
+    iframe.contentWindow.postMessage(rs, '*', [rs]);
+    const ev = await new Promise((r) => iframe.contentWindow.onmessage = r);
+    const seq = await readAll(ev.data);
+
+    assert_array_equals(seq, [2, 3, 4, 5, 6, 7, 8, 9]);
+  }).then(() => t.done(), t.step_func((e) => assert_unreached(e)));
+}, '[rs] transferring between frames; read chunks before transferring');
+
+async_test((t) => {
+  Promise.resolve().then(async () => {
+    const worker = new Worker('resources/transferring-back-worker.js');
+    const rs = internals.createReadableStream(3, 'perfect');
+    const mc = new MessageChannel();
+
+    worker.postMessage({port: mc.port2}, [mc.port2]);
+    mc.port1.start();
+    mc.port1.postMessage({rs}, [rs]);
+
+    const ev = await new Promise((r) => mc.port1.onmessage = r);
+    const seq = await readAll(ev.data.rs);
+
+    assert_array_equals(seq, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+  }).then(() => t.done(), t.step_func((e) => assert_unreached(e)));
+}, '[rs] transferring to worker; perfect optimizer is used');
+
+</script>
+</body>
+
diff --git a/third_party/blink/web_tests/virtual/policy-container/external/wpt/referrer-policy/generic/inheritance/iframe-inheritance-history-about-srcdoc-expected.txt b/third_party/blink/web_tests/virtual/policy-container/external/wpt/referrer-policy/generic/inheritance/iframe-inheritance-history-about-srcdoc-expected.txt
index 0db8bcd..df5a9a2 100644
--- a/third_party/blink/web_tests/virtual/policy-container/external/wpt/referrer-policy/generic/inheritance/iframe-inheritance-history-about-srcdoc-expected.txt
+++ b/third_party/blink/web_tests/virtual/policy-container/external/wpt/referrer-policy/generic/inheritance/iframe-inheritance-history-about-srcdoc-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-FAIL History navigation reuses original policy. assert_equals: History navigation reuses original policy. expected (undefined) undefined but got (string) "http://web-platform.test:8001/"
+PASS History navigation reuses original policy.
 PASS New srcdoc iframe uses new policy.
 Harness: the test ran to completion.
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 72bf461f..4aa6ff2 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -16775,11 +16775,17 @@
 </enum>
 
 <enum name="DevToolsGridOverlayOpenedFrom">
+  <obsolete>
+    Removed in M89.
+  </obsolete>
   <int value="0" label="Adorner"/>
   <int value="1" label="Layout pane"/>
 </enum>
 
 <enum name="DevtoolsGridSettingChanged">
+  <obsolete>
+    Superseded by DevtoolsGridSettingChanged2.
+  </obsolete>
   <int value="0" label="showGridBorder.none"/>
   <int value="1" label="showGridBorder.dashed"/>
   <int value="2" label="showGridBorder.solid"/>
@@ -16804,6 +16810,9 @@
 </enum>
 
 <enum name="DevtoolsGridSettingChanged2">
+  <obsolete>
+    Removed in M89.
+  </obsolete>
   <int value="0" label="showGridLineLabels.none"/>
   <int value="1" label="showGridLineLabels.lineNumbers"/>
   <int value="2" label="showGridLineLabels.lineNames"/>
@@ -16816,6 +16825,9 @@
 </enum>
 
 <enum name="DevToolsHighlightedPersistentCSSGridCount">
+  <obsolete>
+    Removed in M89.
+  </obsolete>
   <int value="0" label="0"/>
   <int value="1" label="1"/>
   <int value="2" label="2"/>
@@ -46095,6 +46107,7 @@
   <int value="13" label="Cryptohome missing from disk"/>
   <int value="14" label="Authentication disabled for user"/>
   <int value="15" label="TPM firmware update is required"/>
+  <int value="16" label="Cryptohome is corrupted"/>
 </enum>
 
 <enum name="LoginIsKnownUser">
@@ -46196,6 +46209,10 @@
     the user through the online flow until user updates their cryptohome
     password or agrees to start the new cryptohome.
   </int>
+  <int value="9" label="SamlPwdSyncTokenValidationFailed"/>
+  <int value="10" label="UnrecoverableCryptohome">
+    Cryptohome was corrupted and deemed unrecoverable.
+  </int>
 </enum>
 
 <enum name="LoginScreenUserClickTarget">
diff --git a/tools/metrics/histograms/histograms_xml/dev/histograms.xml b/tools/metrics/histograms/histograms_xml/dev/histograms.xml
index 599286e8..05f59ab0 100644
--- a/tools/metrics/histograms/histograms_xml/dev/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/dev/histograms.xml
@@ -103,6 +103,9 @@
 
 <histogram name="DevTools.CSSGridSettings2" enum="DevtoolsGridSettingChanged2"
     expires_after="M88">
+  <obsolete>
+    Removed in M89 because it is no longer needed for analysis.
+  </obsolete>
   <owner>yangguo@chromium.org</owner>
   <owner>brgoddar@microsoft.com</owner>
   <owner>leo.lee@microsoft.com</owner>
@@ -155,6 +158,9 @@
 
 <histogram name="DevTools.GridOverlayOpenedFrom"
     enum="DevToolsGridOverlayOpenedFrom" expires_after="M88">
+  <obsolete>
+    Removed in M89 because it is no longer needed for analysis.
+  </obsolete>
   <owner>changhaohan@chromium.org</owner>
   <owner>yangguo@chromium.org</owner>
   <owner>mathias@chromium.org</owner>
@@ -165,6 +171,9 @@
 
 <histogram name="DevTools.HighlightedPersistentCSSGridCount"
     enum="DevToolsHighlightedPersistentCSSGridCount" expires_after="M88">
+  <obsolete>
+    Removed in M89 because it is no longer needed for analysis.
+  </obsolete>
   <owner>yangguo@chromium.org</owner>
   <owner>patrick.brosset@microsoft.com</owner>
   <owner>leo.lee@microsoft.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/memory/histograms.xml b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
index 595e4f9..f6732f39d 100644
--- a/tools/metrics/histograms/histograms_xml/memory/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
@@ -1985,6 +1985,21 @@
   <summary>Throughput of a ParkableString disk write.</summary>
 </histogram>
 
+<histogram name="Memory.PartitionAlloc.ThreadCache.HitRate{ThreadType}"
+    units="%" expires_after="M92">
+  <owner>lizeb@chromium.org</owner>
+  <owner>bartekn@chromium.org</owner>
+  <summary>
+    Hit rate for PartitionAlloc's thread cache. Recorded during memory dumps, at
+    the same time as the Memory.*.PartitionAlloc.* histograms. Data is collected
+    for {ThreadType}.
+  </summary>
+  <token key="ThreadType">
+    <variant name="" summary="all threads"/>
+    <variant name=".MainThread" summary="the main thread only"/>
+  </token>
+</histogram>
+
 <histogram name="Memory.PressureLevel" enum="MemoryPressureLevel"
     expires_after="2021-04-18">
   <owner>chrisha@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml
index 8b950d1..d33c7b6 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -10728,6 +10728,9 @@
 
 <histogram name="PerformanceManager.AgentsByTime" units="units"
     expires_after="2020-12-04">
+  <obsolete>
+    Removed 2020-11.
+  </obsolete>
   <owner>bokan@chromium.org</owner>
   <owner>kouhei@chromium.org</owner>
   <owner>platform-architecture-dev@chromium.org</owner>
@@ -10740,6 +10743,9 @@
 
 <histogram name="PerformanceManager.AgentsPerRendererByTime" units="units"
     expires_after="2020-12-04">
+  <obsolete>
+    Removed 2020-11.
+  </obsolete>
   <owner>bokan@chromium.org</owner>
   <owner>kouhei@chromium.org</owner>
   <owner>platform-architecture-dev@chromium.org</owner>
@@ -10752,6 +10758,9 @@
 
 <histogram name="PerformanceManager.AgentsUniqueByTime" units="units"
     expires_after="2020-12-04">
+  <obsolete>
+    Removed 2020-11.
+  </obsolete>
   <owner>bokan@chromium.org</owner>
   <owner>kouhei@chromium.org</owner>
   <owner>platform-architecture-dev@chromium.org</owner>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index f8cad3b4..06ef6bbf 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -246,6 +246,7 @@
 crbug.com/1116469 [ android-webview ] rendering.mobile/webgl_to_texture [ Skip ]
 crbug.com/1124237 [ android-nexus-5x android-webview ] rendering.mobile/toBlob_duration.html [ Skip ]
 crbug.com/1150490 [ android-nexus-5x android-webview ] rendering.mobile/microgame_fps [ Skip ]
+crbug.com/1153607 [ android-pixel-2 ] rendering.mobile/many_images [ Skip ]
 
 # Benchmark: rasterize_and_record_micro.top_25
 crbug.com/764543 rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html [ Skip ]
diff --git a/tools/polymer/polymer.py b/tools/polymer/polymer.py
index 793ee7f..61a7b24 100644
--- a/tools/polymer/polymer.py
+++ b/tools/polymer/polymer.py
@@ -418,10 +418,9 @@
         line = '\n'.join(js_imports) + '\n\n'
         cr_define_found = True
         imports_added = True
-      elif line.startswith('Polymer({\n'):
+      elif 'Polymer({\n' in line:
         # Place the JS imports right before the opening "Polymer({" line.
-        line = line.replace(
-            r'Polymer({', '%s\n\nPolymer({' % '\n'.join(js_imports))
+        line = '\n'.join(js_imports) + '\n\n' + line
         imports_added = True
 
     # Place the HTML content right after the opening "Polymer({" line.
diff --git a/tools/polymer/polymer_test.py b/tools/polymer/polymer_test.py
index e220402..c38714c 100755
--- a/tools/polymer/polymer_test.py
+++ b/tools/polymer/polymer_test.py
@@ -46,7 +46,7 @@
     actual_js = self._read_out_file(js_out_file)
     expected_js = open(os.path.join(
         _HERE_DIR, 'tests', js_file_expected), 'rb').read()
-    self.assertEquals(expected_js, actual_js)
+    self.assertEquals(expected_js.split('\n'), actual_js.split('\n'))
 
   # Test case where HTML is extracted from a Polymer2 <dom-module>.
   def testDomModule(self):
@@ -68,6 +68,14 @@
         'dom-module', 'dom_module.html', 'dom_module_iife_arrow.js',
         'dom_module_iife_arrow.m.js', 'dom_module_iife_expected.js')
 
+  # Test case where HTML is extracted from a Polymer2 <dom-module> that is
+  # assigned to a variable.
+  def testDomModuleIifeAndAssigned(self):
+    self._run_test(
+        'dom-module', 'dom_module.html', 'dom_module_with_assignment.js',
+        'dom_module_with_assignment.m.js',
+        'dom_module_with_assignment_expected.js')
+
   # Test case where HTML is extracted from a Polymer2 <dom-module> that also
   # has a 'cr.define()' in its JS file.
   def testDomModuleWithDefine(self):
diff --git a/tools/polymer/tests/dom_module_with_assignment.js b/tools/polymer/tests/dom_module_with_assignment.js
new file mode 100644
index 0000000..a05cf3c
--- /dev/null
+++ b/tools/polymer/tests/dom_module_with_assignment.js
@@ -0,0 +1,6 @@
+const foo = 'foo';
+
+const CrTestFoo = Polymer({
+  is: 'cr-test-foo',
+  behaviors: [Polymer.PaperRippleBehavior],
+});
diff --git a/tools/polymer/tests/dom_module_with_assignment_expected.js b/tools/polymer/tests/dom_module_with_assignment_expected.js
new file mode 100644
index 0000000..c892147c
--- /dev/null
+++ b/tools/polymer/tests/dom_module_with_assignment_expected.js
@@ -0,0 +1,21 @@
+const foo = 'foo';
+
+import {Polymer, html} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {PaperRippleBehavior} from '//resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
+import '//resources/js/ignore_me.m.js';
+import '../shared_vars_css.m.js';
+import './foo.m.js';
+
+const CrTestFoo = Polymer({
+  _template: html`<!--_html_template_start_-->
+    <style>
+      div {
+        font-size: 2rem;
+      }
+    </style>
+    <div>Hello world</div>
+<!--_html_template_end_-->`,
+  is: 'cr-test-foo',
+  behaviors: [PaperRippleBehavior],
+});
diff --git a/ui/file_manager/image_loader/piex_loader.js b/ui/file_manager/image_loader/piex_loader.js
index 7eeab882..9f9e200 100644
--- a/ui/file_manager/image_loader/piex_loader.js
+++ b/ui/file_manager/image_loader/piex_loader.js
@@ -435,13 +435,18 @@
 
     const view = new Uint8Array(this.source.buffer, offset, length);
 
+    // Compute output image width and height.
+    const usesWidthAsHeight = thumbnail.orientation >= 5;
+    const height = usesWidthAsHeight ? thumbnail.width : thumbnail.height;
+    const width = usesWidthAsHeight ? thumbnail.height : thumbnail.width;
+
     // Compute pixel row stride.
-    const rowPad = thumbnail.width & 3;
-    const rowStride = 3 * thumbnail.width + rowPad;
+    const rowPad = width & 3;
+    const rowStride = 3 * width + rowPad;
 
     // Create bitmap image.
     const pixelDataOffset = 14 + 108;
-    const fileSize = pixelDataOffset + rowStride * thumbnail.height;
+    const fileSize = pixelDataOffset + rowStride * height;
     const bitmap = new DataView(new ArrayBuffer(fileSize));
 
     // BITMAPFILEHEADER 14 bytes.
@@ -453,8 +458,8 @@
 
     // DIB BITMAPV4HEADER 108 bytes.
     bitmap.setUint32(14, /* HeaderSize */ 108, true);
-    bitmap.setInt32(18, thumbnail.width, true);
-    bitmap.setInt32(22, -thumbnail.height /* top-down DIB */, true);
+    bitmap.setInt32(18, width, true);
+    bitmap.setInt32(22, -height /* top-down DIB */, true);
     bitmap.setInt16(26, /* ColorPlanes */ 1, true);
     bitmap.setInt16(28, /* BitsPerPixel BI_RGB */ 24, true);
     bitmap.setUint32(30, /* Compression: BI_RGB none */ 0, true);
@@ -508,24 +513,80 @@
     bitmap.setUint32(118, /* B Gamma */ gg, true);
 
     // Write RGB row pixels in top-down DIB order.
-    let output = pixelDataOffset;
-    for (let i = 0, y = thumbnail.height; y > 0; --y) {
-      for (let x = thumbnail.width; x > 0; --x) {
-        const R = view[i++];
-        const G = view[i++];
-        const B = view[i++];
-        bitmap.setUint8(output++, B);  // B
-        bitmap.setUint8(output++, G);  // G
-        bitmap.setUint8(output++, R);  // R
+    const h = thumbnail.height - 1;
+    const w = thumbnail.width - 1;
+    let dx = 0;
+
+    for (let input = 0, y = 0; y <= h; ++y) {
+      let output = pixelDataOffset;
+
+      /**
+       * Compute affine(a,b,c,d,tx,ty) transform of pixel (x,y)
+       *   { x': a * x + c * y + tx, y': d * y + b * x + ty }
+       * a,b,c,d in [-1,0,1], to apply the image orientation at
+       * (0,y) to find the output location of the input row.
+       * The transform derivative in x is used to calculate the
+       * relative output location of adjacent input row pixels.
+       */
+      switch (thumbnail.orientation) {
+        case 1:  // affine(+1, 0, 0, +1, 0, 0)
+          output += y * rowStride;
+          dx = 3;
+          break;
+        case 2:  // affine(-1, 0, 0, +1, w, 0)
+          output += y * rowStride + 3 * w;
+          dx = -3;
+          break;
+        case 3:  // affine(-1, 0, 0, -1, w, h)
+          output += (h - y) * rowStride + 3 * w;
+          dx = -3;
+          break;
+        case 4:  // affine(+1, 0, 0, -1, 0, h)
+          output += (h - y) * rowStride;
+          dx = 3;
+          break;
+        case 5:  // affine(0, +1, +1, 0, 0, 0)
+          output += 3 * y;
+          dx = rowStride;
+          break;
+        case 6:  // affine(0, +1, -1, 0, h, 0)
+          output += 3 * (h - y);
+          dx = rowStride;
+          break;
+        case 7:  // affine(0, -1, -1, 0, h, w)
+          output += w * rowStride + 3 * (h - y);
+          dx = -rowStride;
+          break;
+        case 8:  // affine(0, -1, +1, 0, 0, w)
+          output += w * rowStride + 3 * y;
+          dx = -rowStride;
+          break;
       }
 
-      switch (rowPad) {
-        case 3:
-          bitmap.setUint8(output++, 0);
-        case 2:
-          bitmap.setUint8(output++, 0);
-        case 1:
-          bitmap.setUint8(output++, 0);
+      for (let x = 0; x <= w; ++x, input += 3, output += dx) {
+        bitmap.setUint8(output + 0, view[input + 2]);  // B
+        bitmap.setUint8(output + 1, view[input + 1]);  // G
+        bitmap.setUint8(output + 2, view[input + 0]);  // R
+      }
+    }
+
+    // Write pixel row padding bytes if needed.
+    if (rowPad) {
+      let paddingOffset = pixelDataOffset + 3 * width;
+
+      for (let y = 0; y < height; ++y) {
+        let output = paddingOffset;
+
+        switch (rowPad) {
+          case 3:
+            bitmap.setUint8(output++, 0);
+          case 2:
+            bitmap.setUint8(output++, 0);
+          case 1:
+            bitmap.setUint8(output++, 0);
+        }
+
+        paddingOffset += rowStride;
       }
     }
 
@@ -533,8 +594,8 @@
       thumbnail: bitmap.buffer,
       mimeType: 'image/bmp',
       ifd: this.details_(result, thumbnail.orientation),
-      orientation: thumbnail.orientation,
       colorSpace: thumbnail.colorSpace,
+      orientation: 1,
     };
   }
 
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.js
index e9a3fe8..b98da13 100644
--- a/ui/file_manager/integration_tests/file_manager/quick_view.js
+++ b/ui/file_manager/integration_tests/file_manager/quick_view.js
@@ -1470,11 +1470,10 @@
     const caller = getCaller();
 
     /**
-     * The <webview> resides in the <files-safe-media type="image"> shadow DOM,
-     * which is a child of the #quick-view shadow DOM.
+     * The <files-safe-media type="image"> element is a shadow DOM child of
+     * the #quick-view element, and has a shadow DOM child <webview>.
      */
-    const webView =
-        ['#quick-view', 'files-safe-media[type="image"]', 'webview'];
+    const filesSafeMedia = ['#quick-view', 'files-safe-media[type="image"]'];
 
     // Open Files app on Downloads containing ENTRIES.rawNef.
     const appId = await setupAndWaitUntilReady(
@@ -1495,6 +1494,7 @@
       return;
     }
     await repeatUntil(async () => {
+      const webView = filesSafeMedia.concat(['webview']);
       return checkWebViewImageLoaded(await remoteCall.callRemoteTestUtil(
           'deepQueryAllElements', appId, [webView, ['display']]));
     });
@@ -1506,6 +1506,21 @@
     // Check: the correct mimeType should be displayed.
     const mimeType = await getQuickViewMetadataBoxField(appId, 'Type');
     chrome.test.assertEq('image/tiff', mimeType);
+
+    // Get the fileSafeMedia element preview thumbnail image size.
+    const element = await remoteCall.waitForElement(appId, filesSafeMedia);
+    const image = new Image();
+    image.src = element.attributes.src;
+    image.onload = () => {
+      image.imageSize = image.naturalWidth + ' x ' + image.naturalHeight;
+    };
+
+    // Check: the preview thumbnail should have an orientiated size.
+    await repeatUntil(async () => {
+      if (!image.complete || image.imageSize !== '120 x 160') {
+        return pending(caller, 'Waiting for preview thumbnail size.');
+      }
+    });
   };
 
   /**
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
index 42e29c2a0..d3ae8d7 100644
--- a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
+++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
@@ -92,6 +92,14 @@
       value: false,
     },
 
+    // Whether or not non-digit pins are allowed.
+    // If allowNonDigit is false, any characters typed in the pin dialog
+    // will be swallowed.
+    allowNonDigit: {
+      type: Boolean,
+      value: false,
+    },
+
     hasError: Boolean,
 
     disabled: {
@@ -401,11 +409,16 @@
 
   /**
    * Helper function to check whether a given |event| should be processed by
-   * the numeric only input.
+   * the input.
    * @param {Event} event The event object.
    * @private
    */
   isValidEventForInput_(event) {
+    // Valid if the key is a non-digit and allowNonDigit is enabled.
+    if (this.allowNonDigit) {
+      return true;
+    }
+
     // Valid if the key is a number, and shift is not pressed.
     if ((event.keyCode >= 48 && event.keyCode <= 57) && !event.shiftKey) {
       return true;
@@ -453,10 +466,12 @@
       return;
     }
 
-    // Do not pass events that are not numbers or special keys we care about. We
-    // use this instead of input type number because there are several issues
-    // with input type number, such as no selectionStart/selectionEnd and
-    // entered non numbers causes the caret to jump to the left.
+    // If only digits are allowed in the pin input (allowNonDigit is set to
+    // false), then do not pass events that are not numbers or special keys we
+    // care about. We use this instead of input type number because there are
+    // several issues with input type number, such as no
+    // selectionStart/selectionEnd and entered non numbers causes the caret to
+    // jump to the left.
     if (!this.isValidEventForInput_(event)) {
       event.preventDefault();
       return;
diff --git a/weblayer/browser/subresource_filter_client_impl.cc b/weblayer/browser/subresource_filter_client_impl.cc
index 511e0922..e5ec67f 100644
--- a/weblayer/browser/subresource_filter_client_impl.cc
+++ b/weblayer/browser/subresource_filter_client_impl.cc
@@ -5,7 +5,6 @@
 #include "weblayer/browser/subresource_filter_client_impl.h"
 
 #include <string>
-#include <utility>
 
 #include "base/macros.h"
 #include "build/build_config.h"
diff --git a/weblayer/browser/subresource_filter_client_impl.h b/weblayer/browser/subresource_filter_client_impl.h
index 894ea6a4..77e02c9 100644
--- a/weblayer/browser/subresource_filter_client_impl.h
+++ b/weblayer/browser/subresource_filter_client_impl.h
@@ -6,6 +6,7 @@
 #define WEBLAYER_BROWSER_SUBRESOURCE_FILTER_CLIENT_IMPL_H_
 
 #include <memory>
+#include <utility>
 
 #include "components/safe_browsing/core/db/database_manager.h"
 #include "components/subresource_filter/content/browser/subresource_filter_client.h"
@@ -56,7 +57,7 @@
   void set_database_manager_for_testing(
       scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
           database_manager) {
-    database_manager_ = database_manager;
+    database_manager_ = std::move(database_manager);
   }
 
  private:
diff --git a/weblayer/browser/test/test_weblayer_impl.cc b/weblayer/browser/test/test_weblayer_impl.cc
index c80c5a6..26291e4 100644
--- a/weblayer/browser/test/test_weblayer_impl.cc
+++ b/weblayer/browser/test/test_weblayer_impl.cc
@@ -29,7 +29,8 @@
     base::android::RunRunnableAndroid(runnable);
     return;
   }
-  observer->NotifyOnNextMetadataChange(
+  auto* const observer_ptr = observer.get();
+  observer_ptr->NotifyOnNextMetadataChange(
       base::BindOnce(&CheckMetadata, std::move(observer), top_height,
                      bottom_height, runnable));
 }