diff --git a/BUILD.gn b/BUILD.gn
index f93a89e0..df6eff8b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -357,7 +357,7 @@
       "//tools/android:push_apps_to_background",
       "//tools/android/audio_focus_grabber:audio_focus_grabber_apk",
       "//tools/android/customtabs_benchmark:customtabs_benchmark_apk",
-      "//tools/android/errorprone_plugin:errorprone_plugin_tests",
+      "//tools/android/errorprone_plugin/test:errorprone_plugin_tests",
       "//tools/android/kerberos/SpnegoAuthenticator:spnego_authenticator_apk",
       "//ui/android:ui_junit_tests",
       "//weblayer/public/java:client_aar",
@@ -442,6 +442,7 @@
       "//chromeos/components/proximity_auth:proximity_auth_unittests",
       "//components/exo/wayland:wayland_client_compatibility_tests",
       "//components/session_manager/core",
+      "//third_party/shell-encryption:shell_encryption_unittests",
       "//ui/chromeos:ui_chromeos_unittests",
     ]
   }
diff --git a/DEPS b/DEPS
index c82608a..2e7706f 100644
--- a/DEPS
+++ b/DEPS
@@ -200,7 +200,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'a1ebb44f6150ee5492580c2d570a6fb2dcd7c7a9',
+  'skia_revision': '0c2cc2356170d4a39d5d587fbb340f59e91b5d07',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -212,11 +212,11 @@
   # 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': 'df873e5fa6d33d5d402cf90dc6106e6812bc71f7',
+  'angle_revision': '0c47015b57a03230e0cab10532c3deed80604512',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '1eadcfb3be99c2eca944774a78c4e3c16132958b',
+  'swiftshader_revision': 'bfb211914759cc5deffbe9419cd1c2cae0573488',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -251,7 +251,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '56c610b145212b7acfb24a17e86fc0ba15aa3052',
+  'freetype_revision': '8cc4d0dc32a1f8734e77266bb6abdd11f18a631c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # 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': '9cfe927efca2515dd556acc8a2e482ee0662dbeb',
+  'devtools_frontend_revision': '225d4f420c39ee187ad6ef5a42b2661fed1cc285',
   # 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.
@@ -327,7 +327,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'a6a7e46e54518bd730caf47ef4d4a01ff81f9123',
+  'dawn_revision': 'c3830d436c47be71bbea1851e45ba8555b4897dd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # 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' + '@' + 'efc444306186ababe5575bb806585efc464fa772',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'aa250cf881dec006e0137dd40f079d2ce7092067',
       'condition': 'checkout_chromeos',
   },
 
@@ -919,7 +919,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6d2a0fef93155cb26724fbc0430f7a6f1d1aaed1',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '684460d29eb48bb46cb139dde4c6f6e39c3266be',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1274,7 +1274,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '3dd5b80bc4f172dd82925bb259cb7c82348409c5',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + '4654f2b60f7a3fdb1a84d39d6504ba57be77f863',
+    Var('chromium_git') + '/openscreen' + '@' + '2095c0498a0f90aa44ecba366b74ab19afdea813',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '97cfe495bb7a3853266b646d1c79e169387f9c7a',
@@ -1291,7 +1291,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '05e6cccec4351c20459256bab83bd8f79fa7ff55',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '6d300e3738dbcfd8c6f69c5bf7006d107fce871d',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1369,7 +1369,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'jfuzh1KU9b_qTmPrfQ2v7GW8FB2tUz0uUUjeyB_2LdQC'
+              'version': 'zgLQtKIJ1USKi1uy450NQyS9EhBtSpvA7ZrBu-MKih0C'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1551,7 +1551,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'bcca3b08a90fccaa6dd8d86f6079f0ca0553ab4a',
+    Var('webrtc_git') + '/src.git' + '@' + '58678a0eb7a35d2b7f75770d1d04fdd0684ab55c',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -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@8f303e8141bca8377cc2c848e5a92c93aebeee3e',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d7b599b52009fc3ede7c7031b8d16c3348fce231',
     'condition': 'checkout_src_internal',
   },
 
@@ -1631,7 +1631,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'D_LdJDf7J2321OJmcxo6ld169C_4DnTsvZVrXBfl84YC',
+        'version': 'BBiRmOh9So_xSPEf3Yuzn6hQ2VvWpMYkzK4Gf2U-_aUC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1642,7 +1642,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'DFP6775_ioCBTjnpyJoXzr5w-Xv6mSoZDrurJfFGpu4C',
+        'version': '9Aak3tK4oVEWWOriZzuRXEUPGWU0lUrVTTcsG4FucPgC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc
index 4b98241..ce2abd7 100644
--- a/android_webview/browser/aw_permission_manager.cc
+++ b/android_webview/browser/aw_permission_manager.cc
@@ -327,7 +327,6 @@
       case PermissionType::NOTIFICATIONS:
       case PermissionType::DURABLE_STORAGE:
       case PermissionType::BACKGROUND_SYNC:
-      case PermissionType::FLASH:
       case PermissionType::ACCESSIBILITY_EVENTS:
       case PermissionType::CLIPBOARD_READ_WRITE:
       case PermissionType::CLIPBOARD_SANITIZED_WRITE:
@@ -535,7 +534,6 @@
       case PermissionType::AUDIO_CAPTURE:
       case PermissionType::VIDEO_CAPTURE:
       case PermissionType::BACKGROUND_SYNC:
-      case PermissionType::FLASH:
       case PermissionType::ACCESSIBILITY_EVENTS:
       case PermissionType::CLIPBOARD_READ_WRITE:
       case PermissionType::CLIPBOARD_SANITIZED_WRITE:
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 29be6ce..74221963 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -335,6 +335,7 @@
     "clipboard/views/clipboard_history_main_button.h",
     "clipboard/views/clipboard_history_text_item_view.cc",
     "clipboard/views/clipboard_history_text_item_view.h",
+    "clipboard/views/clipboard_history_view_constants.h",
     "dbus/ash_dbus_services.cc",
     "dbus/ash_dbus_services.h",
     "dbus/display_service_provider.cc",
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc
index 56c23a80..d862052 100644
--- a/ash/capture_mode/capture_mode_controller.cc
+++ b/ash/capture_mode/capture_mode_controller.cc
@@ -351,7 +351,8 @@
     CaptureVideo(*capture_params);
 }
 
-void CaptureModeController::EndVideoRecording() {
+void CaptureModeController::EndVideoRecording(EndRecordingReason reason) {
+  RecordEndRecordingReason(reason);
   recording_service_remote_->StopRecording();
   TerminateRecordingUiElements();
 }
@@ -391,22 +392,22 @@
 
 void CaptureModeController::OnActiveUserSessionChanged(
     const AccountId& account_id) {
-  EndSessionOrRecording(/*for_suspend=*/false);
+  EndSessionOrRecording(EndRecordingReason::kActiveUserChange);
 }
 
 void CaptureModeController::OnSessionStateChanged(
     session_manager::SessionState state) {
   if (Shell::Get()->session_controller()->IsUserSessionBlocked())
-    EndSessionOrRecording(/*for_suspend=*/false);
+    EndSessionOrRecording(EndRecordingReason::kSessionBlocked);
 }
 
 void CaptureModeController::OnChromeTerminating() {
-  EndSessionOrRecording(/*for_suspend=*/false);
+  EndSessionOrRecording(EndRecordingReason::kShuttingDown);
 }
 
 void CaptureModeController::SuspendImminent(
     power_manager::SuspendImminent::Reason reason) {
-  EndSessionOrRecording(/*for_suspend=*/true);
+  EndSessionOrRecording(EndRecordingReason::kImminentSuspend);
 }
 
 void CaptureModeController::StartVideoRecordingImmediatelyForTesting() {
@@ -415,7 +416,7 @@
   OnVideoRecordCountDownFinished();
 }
 
-void CaptureModeController::EndSessionOrRecording(bool for_suspend) {
+void CaptureModeController::EndSessionOrRecording(EndRecordingReason reason) {
   if (IsActive()) {
     // Suspend or user session changes can happen while the capture mode session
     // is active or after the three-second countdown had started but not
@@ -427,7 +428,7 @@
   if (!is_recording_in_progress_)
     return;
 
-  if (for_suspend) {
+  if (reason == EndRecordingReason::kImminentSuspend) {
     // If suspend happens while recording is in progress, we consider this a
     // failure, and cut the recording immediately. The recording service may
     // have some buffered chunks that will never be received, and as a result,
@@ -436,11 +437,12 @@
     // end the recording normally by asking the service to StopRecording(), and
     // block the suspend until all chunks have been received, and then we can
     // resume it.
+    RecordEndRecordingReason(EndRecordingReason::kImminentSuspend);
     OnRecordingEnded(/*success=*/false);
     return;
   }
 
-  EndVideoRecording();
+  EndVideoRecording(reason);
 }
 
 base::Optional<CaptureModeController::CaptureParams>
@@ -566,6 +568,7 @@
   // Note that the service could disconnect between the time we ask it to
   // StopRecording(), and it calling us back with OnRecordingEnded(), so we call
   // OnRecordingEnded() in all cases.
+  RecordEndRecordingReason(EndRecordingReason::kRecordingServiceDisconnected);
   OnRecordingEnded(/*success=*/false);
 }
 
@@ -666,7 +669,7 @@
     return;
 
   // TODO(afakhry): Show the user a message about IO failure.
-  EndVideoRecording();
+  EndVideoRecording(EndRecordingReason::kFileIoError);
 }
 
 void CaptureModeController::OnVideoFileSaved(bool success) {
@@ -863,7 +866,7 @@
 
 void CaptureModeController::InterruptVideoRecording() {
   ShowVideoRecordingStoppedNotification();
-  EndVideoRecording();
+  EndVideoRecording(EndRecordingReason::kDlpInterruption);
 }
 
 void CaptureModeController::OnLowDiskSpace() {
@@ -875,7 +878,7 @@
   // allow the remaining chunks to be saved normally. However,
   // |low_disk_space_threshold_reached_| will be used to display a different
   // message in the notification.
-  EndVideoRecording();
+  EndVideoRecording(EndRecordingReason::kLowDiskSpace);
 }
 
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_controller.h b/ash/capture_mode/capture_mode_controller.h
index 81e8417..4c5d505 100644
--- a/ash/capture_mode/capture_mode_controller.h
+++ b/ash/capture_mode/capture_mode_controller.h
@@ -88,7 +88,7 @@
   // the capture session.
   void PerformCapture();
 
-  void EndVideoRecording();
+  void EndVideoRecording(EndRecordingReason reason);
 
   // Called when the feedback button on the capture bar is pressed.
   void OpenFeedbackDialog();
@@ -114,9 +114,7 @@
 
   // Used by user session change, and suspend events to end the capture mode
   // session if it's active, or stop the video recording if one is in progress.
-  // |for_suspend| is true when this is called from |SuspendImminent()|, which
-  // leads to ending the video recording immediately as if it's a failure.
-  void EndSessionOrRecording(bool for_suspend);
+  void EndSessionOrRecording(EndRecordingReason reason);
 
   // Returns the capture parameters for the capture operation that is about to
   // be performed (i.e. the window to be captured, and the capture bounds). If
diff --git a/ash/capture_mode/capture_mode_metrics.cc b/ash/capture_mode/capture_mode_metrics.cc
index 2b719c5..25a8f617 100644
--- a/ash/capture_mode/capture_mode_metrics.cc
+++ b/ash/capture_mode/capture_mode_metrics.cc
@@ -11,6 +11,8 @@
 
 namespace {
 
+constexpr char kEndRecordingReasonHistogramName[] =
+    "Ash.CaptureModeController.EndRecordingReason";
 constexpr char kBarButtonHistogramName[] =
     "Ash.CaptureModeController.BarButtons";
 constexpr char kCaptureConfigurationHistogramName[] =
@@ -61,6 +63,11 @@
 
 }  // namespace
 
+void RecordEndRecordingReason(EndRecordingReason reason) {
+  base::UmaHistogramEnumeration(
+      GetCaptureModeHistogramName(kEndRecordingReasonHistogramName), reason);
+}
+
 void RecordCaptureModeBarButtonType(CaptureModeBarButtonType button_type) {
   base::UmaHistogramEnumeration(
       GetCaptureModeHistogramName(kBarButtonHistogramName), button_type);
diff --git a/ash/capture_mode/capture_mode_metrics.h b/ash/capture_mode/capture_mode_metrics.h
index d869e6c8..950bf5c 100644
--- a/ash/capture_mode/capture_mode_metrics.h
+++ b/ash/capture_mode/capture_mode_metrics.h
@@ -11,6 +11,23 @@
 
 namespace ash {
 
+// Enumeration of the reasons that lead to ending the screen recording.
+// Note that these values are persisted to histograms so existing values should
+// remain unchanged and new values should be added to the end.
+enum class EndRecordingReason {
+  kStopRecordingButton,
+  kDisplayOrWindowClosing,
+  kActiveUserChange,
+  kSessionBlocked,
+  kShuttingDown,
+  kImminentSuspend,
+  kRecordingServiceDisconnected,
+  kFileIoError,
+  kDlpInterruption,
+  kLowDiskSpace,
+  kMaxValue = kLowDiskSpace,
+};
+
 // Enumeration of capture bar buttons that can be pressed while in capture mode.
 // Note that these values are persisted to histograms so existing values should
 // remain unchanged and new values should be added to the end.
@@ -49,6 +66,9 @@
   kMaxValue = kPowerMenu,
 };
 
+// Records the |reason| for which screen recording was ended.
+void RecordEndRecordingReason(EndRecordingReason reason);
+
 // Records capture mode bar button presses given by |button_type|.
 void RecordCaptureModeBarButtonType(CaptureModeBarButtonType button_type);
 
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc
index 4733997b..c4ff90f 100644
--- a/ash/capture_mode/capture_mode_session.cc
+++ b/ash/capture_mode/capture_mode_session.cc
@@ -10,6 +10,7 @@
 #include "ash/capture_mode/capture_mode_util.h"
 #include "ash/capture_mode/capture_window_observer.h"
 #include "ash/display/mouse_cursor_event_filter.h"
+#include "ash/display/screen_orientation_controller.h"
 #include "ash/magnifier/magnifier_glass.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/resources/vector_icons/vector_icons.h"
@@ -257,7 +258,8 @@
       : cursor_manager_(Shell::Get()->cursor_manager()),
         original_cursor_(cursor_manager_->GetCursor()),
         original_cursor_visible_(cursor_manager_->IsCursorVisible()),
-        original_cursor_locked_(cursor_manager_->IsCursorLocked()) {}
+        original_cursor_locked_(cursor_manager_->IsCursorLocked()),
+        current_orientation_(GetCurrentScreenOrientation()) {}
 
   CursorSetter(const CursorSetter&) = delete;
   CursorSetter& operator=(const CursorSetter&) = delete;
@@ -275,16 +277,19 @@
     const CaptureModeType capture_type = CaptureModeController::Get()->type();
 
     // For custom cursor, update the cursor if we need to change between image
-    // capture and video capture.
+    // capture and video capture or the screen orientation changes.
+    const OrientationLockType orientation = GetCurrentScreenOrientation();
     const bool is_cursor_changed =
         current_cursor_type != new_cursor_type ||
         (current_cursor_type == ui::mojom::CursorType::kCustom &&
-         custom_cursor_capture_type_ != capture_type);
+         (custom_cursor_capture_type_ != capture_type ||
+          current_orientation_ != orientation));
     const bool is_cursor_visibility_changed =
         cursor_manager_->IsCursorVisible() !=
         (new_cursor_type != ui::mojom::CursorType::kNone);
     if (new_cursor_type == ui::mojom::CursorType::kCustom)
       custom_cursor_capture_type_ = capture_type;
+    current_orientation_ = orientation;
 
     if (!is_cursor_changed && !is_cursor_visibility_changed)
       return;
@@ -353,6 +358,10 @@
   // cursor.
   CaptureModeType custom_cursor_capture_type_ = CaptureModeType::kImage;
 
+  // Records the current screen orientation. If screen orientation changes, we
+  // will need to update the cursor if we're using custom cursor.
+  OrientationLockType current_orientation_;
+
   // True if the cursor has reset back to its original cursor. It's to prevent
   // Reset() from setting the cursor to |original_cursor_| more than once.
   bool was_cursor_reset_to_original_ = true;
@@ -391,9 +400,11 @@
 
   TabletModeController::Get()->AddObserver(this);
   current_root_->AddObserver(this);
+  display::Screen::GetScreen()->AddObserver(this);
 }
 
 CaptureModeSession::~CaptureModeSession() {
+  display::Screen::GetScreen()->RemoveObserver(this);
   current_root_->RemoveObserver(this);
   TabletModeController::Get()->RemoveObserver(this);
   Shell::Get()->RemovePreTargetHandler(this);
@@ -561,6 +572,15 @@
   MaybeChangeRoot(Shell::GetPrimaryRootWindow());
 }
 
+void CaptureModeSession::OnDisplayMetricsChanged(
+    const display::Display& display,
+    uint32_t metrics) {
+  if (metrics & display::DisplayObserver::DISPLAY_METRIC_ROTATION) {
+    UpdateCursor(display::Screen::GetScreen()->GetCursorScreenPoint(),
+                 /*is_touch=*/false);
+  }
+}
+
 gfx::Rect CaptureModeSession::GetSelectedWindowBounds() const {
   auto* window = GetSelectedWindow();
   return window ? window->bounds() : gfx::Rect();
diff --git a/ash/capture_mode/capture_mode_session.h b/ash/capture_mode/capture_mode_session.h
index b004a10..2b3497c 100644
--- a/ash/capture_mode/capture_mode_session.h
+++ b/ash/capture_mode/capture_mode_session.h
@@ -16,6 +16,7 @@
 #include "ui/aura/window_observer.h"
 #include "ui/compositor/layer_delegate.h"
 #include "ui/compositor/layer_owner.h"
+#include "ui/display/display_observer.h"
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
 #include "ui/views/controls/button/button.h"
@@ -44,7 +45,8 @@
                                       public ui::LayerDelegate,
                                       public ui::EventHandler,
                                       public TabletModeObserver,
-                                      public aura::WindowObserver {
+                                      public aura::WindowObserver,
+                                      public display::DisplayObserver {
  public:
   // Creates the bar widget on a calculated root window.
   explicit CaptureModeSession(CaptureModeController* controller);
@@ -95,6 +97,10 @@
   // aura::WindowObserver:
   void OnWindowDestroying(aura::Window* window) override;
 
+  // display::DisplayObserver:
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t metrics) override;
+
  private:
   friend class CaptureModeSessionTestApi;
   class CursorSetter;
diff --git a/ash/capture_mode/capture_mode_test_api.cc b/ash/capture_mode/capture_mode_test_api.cc
index 3be7267..82bed56 100644
--- a/ash/capture_mode/capture_mode_test_api.cc
+++ b/ash/capture_mode/capture_mode_test_api.cc
@@ -5,6 +5,7 @@
 #include "ash/public/cpp/capture_mode_test_api.h"
 
 #include "ash/capture_mode/capture_mode_controller.h"
+#include "ash/capture_mode/capture_mode_metrics.h"
 #include "ash/capture_mode/capture_mode_types.h"
 #include "base/auto_reset.h"
 #include "base/check.h"
@@ -54,7 +55,7 @@
 
 void CaptureModeTestApi::StopVideoRecording() {
   DCHECK(controller_->is_recording_in_progress());
-  controller_->EndVideoRecording();
+  controller_->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
 }
 
 void CaptureModeTestApi::SetOnCaptureFileSavedCallback(
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc
index 4d447d57..0fd7319 100644
--- a/ash/capture_mode/capture_mode_unittests.cc
+++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -7,6 +7,7 @@
 #include "ash/capture_mode/capture_mode_bar_view.h"
 #include "ash/capture_mode/capture_mode_button.h"
 #include "ash/capture_mode/capture_mode_controller.h"
+#include "ash/capture_mode/capture_mode_metrics.h"
 #include "ash/capture_mode/capture_mode_session.h"
 #include "ash/capture_mode/capture_mode_source_view.h"
 #include "ash/capture_mode/capture_mode_toggle_button.h"
@@ -15,6 +16,7 @@
 #include "ash/capture_mode/capture_mode_util.h"
 #include "ash/capture_mode/stop_recording_button_tray.h"
 #include "ash/display/cursor_window_controller.h"
+#include "ash/display/screen_orientation_controller_test_api.h"
 #include "ash/display/window_tree_host_manager.h"
 #include "ash/magnifier/magnifier_glass.h"
 #include "ash/public/cpp/ash_features.h"
@@ -47,6 +49,9 @@
 
 namespace {
 
+constexpr char kEndRecordingReasonInClamshellHistogramName[] =
+    "Ash.CaptureModeController.EndRecordingReason.ClamshellMode";
+
 // Returns true if the software-composited cursor is enabled.
 bool IsCursorCompositingEnabled() {
   return Shell::Get()
@@ -400,17 +405,10 @@
   EXPECT_EQ(controller->source(), CaptureModeSource::kFullscreen);
 }
 
-// TODO(https://crbug.com/1141927): test is flakey.
-TEST_F(CaptureModeTest, DISABLED_VideoRecordingUiBehavior) {
-  // We need a non-zero duration to avoid infinite loop on countdown.
-  ui::ScopedAnimationDurationScaleMode animation_scale(
-      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
-
-  auto* controller = CaptureModeController::Get();
+TEST_F(CaptureModeTest, VideoRecordingUiBehavior) {
   // Start Capture Mode in a fullscreen video recording mode.
-  controller->SetSource(CaptureModeSource::kFullscreen);
-  controller->SetType(CaptureModeType::kVideo);
-  controller->Start(CaptureModeEntryType::kQuickSettings);
+  CaptureModeController* controller = StartCaptureSession(
+      CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
   EXPECT_TRUE(controller->IsActive());
   EXPECT_FALSE(controller->is_recording_in_progress());
   EXPECT_FALSE(IsCursorCompositingEnabled());
@@ -432,10 +430,14 @@
 
   // End recording via the stop-recording button. Expect that it's now hidden,
   // and the cursor compositing is now disabled.
+  base::HistogramTester histogram_tester;
   ClickOnView(stop_recording_button, event_generator);
   EXPECT_FALSE(stop_recording_button->visible_preferred());
   EXPECT_FALSE(controller->is_recording_in_progress());
   EXPECT_FALSE(IsCursorCompositingEnabled());
+  histogram_tester.ExpectBucketCount(
+      kEndRecordingReasonInClamshellHistogramName,
+      EndRecordingReason::kStopRecordingButton, 1);
 }
 
 // Tests the behavior of repositioning a region with capture mode.
@@ -1201,6 +1203,37 @@
   EXPECT_EQ(original_cursor_type, cursor_manager->GetCursor().type());
 }
 
+TEST_F(CaptureModeTest, CursorUpdatedOnDisplayRotation) {
+  using ui::mojom::CursorType;
+
+  UpdateDisplay("600x400");
+  const int64_t display_id =
+      display::Screen::GetScreen()->GetPrimaryDisplay().id();
+  display::Display::SetInternalDisplayId(display_id);
+  ScreenOrientationControllerTestApi orientation_test_api(
+      Shell::Get()->screen_orientation_controller());
+
+  auto* event_generator = GetEventGenerator();
+  auto* cursor_manager = Shell::Get()->cursor_manager();
+  CaptureModeController* controller = StartCaptureSession(
+      CaptureModeSource::kFullscreen, CaptureModeType::kImage);
+  event_generator->MoveMouseTo(gfx::Point(175, 175));
+  EXPECT_TRUE(cursor_manager->IsCursorVisible());
+
+  // Use image capture icon as the mouse cursor icon in image capture mode.
+  const ui::Cursor landscape_cursor = cursor_manager->GetCursor();
+  EXPECT_EQ(CursorType::kCustom, landscape_cursor.type());
+  CaptureModeSessionTestApi test_api(controller->capture_mode_session());
+  EXPECT_TRUE(test_api.IsUsingCustomCursor(CaptureModeType::kImage));
+
+  // Rotate the screen.
+  orientation_test_api.SetDisplayRotation(
+      display::Display::ROTATE_270, display::Display::RotationSource::ACTIVE);
+  const ui::Cursor portrait_cursor = cursor_manager->GetCursor();
+  EXPECT_TRUE(test_api.IsUsingCustomCursor(CaptureModeType::kImage));
+  EXPECT_NE(landscape_cursor, portrait_cursor);
+}
+
 // Tests that in Region mode, cursor compositing is used instead of the system
 // cursor when the cursor is being dragged.
 TEST_F(CaptureModeTest, RegionDragCursorCompositing) {
@@ -1364,6 +1397,7 @@
   EXPECT_TRUE(controller->is_recording_in_progress());
 
   // Closing the window being recorded should end video recording.
+  base::HistogramTester histogram_tester;
   window.reset();
 
   auto* stop_recording_button = Shell::GetPrimaryRootWindowController()
@@ -1371,6 +1405,9 @@
                                     ->stop_recording_button_tray();
   EXPECT_FALSE(stop_recording_button->visible_preferred());
   EXPECT_FALSE(controller->is_recording_in_progress());
+  histogram_tester.ExpectBucketCount(
+      kEndRecordingReasonInClamshellHistogramName,
+      EndRecordingReason::kDisplayOrWindowClosing, 1);
 }
 
 TEST_F(CaptureModeTest, DetachDisplayWhileWindowRecording) {
@@ -1439,18 +1476,26 @@
                                          CaptureModeType::kVideo);
   controller->StartVideoRecordingImmediatelyForTesting();
   EXPECT_TRUE(controller->is_recording_in_progress());
+  base::HistogramTester histogram_tester;
   power_manager_client()->SendSuspendImminent(
       power_manager::SuspendImminent::IDLE);
   EXPECT_FALSE(controller->is_recording_in_progress());
+  histogram_tester.ExpectBucketCount(
+      kEndRecordingReasonInClamshellHistogramName,
+      EndRecordingReason::kImminentSuspend, 1);
 }
 
 TEST_F(CaptureModeTest, SwitchUsersWhileRecording) {
   auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
                                          CaptureModeType::kVideo);
   controller->StartVideoRecordingImmediatelyForTesting();
+  base::HistogramTester histogram_tester;
   EXPECT_TRUE(controller->is_recording_in_progress());
   SwitchToUser2();
   EXPECT_FALSE(controller->is_recording_in_progress());
+  histogram_tester.ExpectBucketCount(
+      kEndRecordingReasonInClamshellHistogramName,
+      EndRecordingReason::kActiveUserChange, 1);
 }
 
 TEST_F(CaptureModeTest, SwitchUsersAfterCountdownStarts) {
@@ -1489,6 +1534,7 @@
 
   // Disconnecting the display being fullscreen recorded should end the
   // recording and remove the stop recording button.
+  base::HistogramTester histogram_tester;
   RemoveSecondaryDisplay();
   roots = Shell::GetAllRootWindows();
   ASSERT_EQ(1u, roots.size());
@@ -1498,6 +1544,9 @@
                               ->GetStatusAreaWidget()
                               ->stop_recording_button_tray();
   EXPECT_FALSE(stop_recording_button->visible_preferred());
+  histogram_tester.ExpectBucketCount(
+      kEndRecordingReasonInClamshellHistogramName,
+      EndRecordingReason::kDisplayOrWindowClosing, 1);
 }
 
 TEST_F(CaptureModeTest, ShuttingDownWhileRecording) {
diff --git a/ash/capture_mode/stop_recording_button_tray.cc b/ash/capture_mode/stop_recording_button_tray.cc
index a58ef8ad..2c650fb 100644
--- a/ash/capture_mode/stop_recording_button_tray.cc
+++ b/ash/capture_mode/stop_recording_button_tray.cc
@@ -5,6 +5,7 @@
 #include "ash/capture_mode/stop_recording_button_tray.h"
 
 #include "ash/capture_mode/capture_mode_controller.h"
+#include "ash/capture_mode/capture_mode_metrics.h"
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -39,7 +40,8 @@
          event.type() == ui::ET_GESTURE_TAP);
 
   base::RecordAction(base::UserMetricsAction("Tray_StopRecording"));
-  CaptureModeController::Get()->EndVideoRecording();
+  CaptureModeController::Get()->EndVideoRecording(
+      EndRecordingReason::kStopRecordingButton);
   return true;
 }
 
diff --git a/ash/capture_mode/video_recording_watcher.cc b/ash/capture_mode/video_recording_watcher.cc
index 5c534c2..af56308f 100644
--- a/ash/capture_mode/video_recording_watcher.cc
+++ b/ash/capture_mode/video_recording_watcher.cc
@@ -5,6 +5,7 @@
 #include "ash/capture_mode/video_recording_watcher.h"
 
 #include "ash/capture_mode/capture_mode_controller.h"
+#include "ash/capture_mode/capture_mode_metrics.h"
 #include "ash/capture_mode/capture_mode_util.h"
 #include "base/check.h"
 #include "base/check_op.h"
@@ -36,7 +37,7 @@
 
   // EndVideoRecording() destroys |this|. No need to remove observer here, since
   // it will be done in the destructor.
-  controller_->EndVideoRecording();
+  controller_->EndVideoRecording(EndRecordingReason::kDisplayOrWindowClosing);
 }
 
 void VideoRecordingWatcher::OnWindowDestroyed(aura::Window* window) {
diff --git a/ash/clipboard/views/clipboard_history_bitmap_item_view.cc b/ash/clipboard/views/clipboard_history_bitmap_item_view.cc
index ba76c6b4..b06c0a8 100644
--- a/ash/clipboard/views/clipboard_history_bitmap_item_view.cc
+++ b/ash/clipboard/views/clipboard_history_bitmap_item_view.cc
@@ -8,6 +8,7 @@
 #include "ash/clipboard/clipboard_history_resource_manager.h"
 #include "ash/clipboard/clipboard_history_util.h"
 #include "ash/clipboard/views/clipboard_history_delete_button.h"
+#include "ash/clipboard/views/clipboard_history_view_constants.h"
 #include "ash/public/cpp/rounded_image_view.h"
 #include "ash/style/ash_color_provider.h"
 #include "ash/style/scoped_light_mode_as_default.h"
@@ -29,13 +30,6 @@
 
 namespace {
 
-// The preferred height for the bitmap.
-constexpr int kBitmapHeight = 80;
-
-// The margins of the delete button.
-constexpr gfx::Insets kDeleteButtonMargins =
-    gfx::Insets(/*top=*/4, /*left=*/0, /*bottom=*/0, /*right=*/4);
-
 // The duration of the fade out animation for transitioning the placeholder
 // image to rendered HTML.
 constexpr base::TimeDelta kFadeOutDurationMs =
@@ -46,15 +40,6 @@
 constexpr base::TimeDelta kFadeInDurationMs =
     base::TimeDelta::FromMilliseconds(200);
 
-// The radius of the image's rounded corners.
-constexpr int kRoundedCornerRadius = 4;
-
-// The thickness of the image border.
-constexpr int kBorderThickness = 1;
-
-// The opacity of the image shown in a disabled item view.
-constexpr float kDisabledAlpha = 0.38f;
-
 ////////////////////////////////////////////////////////////////////////////////
 // FadeImageView
 // An ImageView which reacts to updates from ClipboardHistoryResourceManager by
@@ -68,7 +53,7 @@
                 const ClipboardHistoryResourceManager* resource_manager,
                 float opacity,
                 base::RepeatingClosure update_callback)
-      : RoundedImageView(kRoundedCornerRadius,
+      : RoundedImageView(ClipboardHistoryViews::kImageRoundedCornerRadius,
                          RoundedImageView::Alignment::kCenter),
         resource_manager_(resource_manager),
         clipboard_history_item_(*clipboard_history_item),
@@ -184,9 +169,12 @@
     SetLayoutManager(std::make_unique<views::FillLayout>());
 
     auto image_view = BuildImageView();
-    image_view->SetPreferredSize(gfx::Size(INT_MAX, kBitmapHeight));
+    image_view->SetPreferredSize(
+        gfx::Size(INT_MAX, ClipboardHistoryViews::kImageViewPreferredHeight));
     image_view->SetBorder(views::CreateRoundedRectBorder(
-        kBorderThickness, kRoundedCornerRadius, gfx::kPlaceholderColor));
+        ClipboardHistoryViews::kImageBorderThickness,
+        ClipboardHistoryViews::kImageRoundedCornerRadius,
+        gfx::kPlaceholderColor));
     image_view_ = AddChildView(std::move(image_view));
 
     InstallDeleteButton();
@@ -210,7 +198,9 @@
     auto delete_button =
         std::make_unique<ClipboardHistoryDeleteButton>(container_);
     delete_button->SetVisible(false);
-    delete_button->SetProperty(views::kMarginsKey, kDeleteButtonMargins);
+    delete_button->SetProperty(
+        views::kMarginsKey,
+        ClipboardHistoryViews::kBitmapItemDeleteButtonMargins);
     ClipboardHistoryDeleteButton* delete_button_ptr =
         delete_button_container->AddChildView(std::move(delete_button));
     AddChildView(std::move(delete_button_container));
@@ -243,7 +233,9 @@
     // bounds is still visible when the context menu is in overflow.
 
     const float image_opacity =
-        container_->IsItemEnabled() ? 1.f : kDisabledAlpha;
+        container_->IsItemEnabled()
+            ? 1.f
+            : ClipboardHistoryViews::kDisabledImageAlpha;
     const auto* clipboard_history_item = container_->clipboard_history_item();
     switch (container_->data_format_) {
       case ui::ClipboardInternalFormat::kHtml:
@@ -254,7 +246,8 @@
                                 weak_ptr_factory_.GetWeakPtr()));
       case ui::ClipboardInternalFormat::kBitmap: {
         auto image_view = std::make_unique<RoundedImageView>(
-            kRoundedCornerRadius, RoundedImageView::Alignment::kCenter);
+            ClipboardHistoryViews::kImageRoundedCornerRadius,
+            RoundedImageView::Alignment::kCenter);
         gfx::ImageSkia bitmap_image = gfx::ImageSkia::CreateFrom1xBitmap(
             clipboard_history_item->data().bitmap());
         if (image_opacity != 1.f) {
diff --git a/ash/clipboard/views/clipboard_history_delete_button.cc b/ash/clipboard/views/clipboard_history_delete_button.cc
index ce918264..16b4023 100644
--- a/ash/clipboard/views/clipboard_history_delete_button.cc
+++ b/ash/clipboard/views/clipboard_history_delete_button.cc
@@ -5,18 +5,12 @@
 #include "ash/clipboard/views/clipboard_history_delete_button.h"
 
 #include "ash/clipboard/views/clipboard_history_item_view.h"
+#include "ash/clipboard/views/clipboard_history_view_constants.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/style/ash_color_provider.h"
 #include "ash/style/scoped_light_mode_as_default.h"
 
 namespace ash {
-namespace {
-
-// The size of the `DeleteButton`.
-constexpr int kDeleteButtonSizeDip = 16;
-
-}  // namespace
-
 ClipboardHistoryDeleteButton::ClipboardHistoryDeleteButton(
     ClipboardHistoryItemView* listener)
     : views::ImageButton(base::BindRepeating(
@@ -28,7 +22,8 @@
   SetAccessibleName(base::ASCIIToUTF16(std::string(GetClassName())));
   SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
   SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
-  SetPreferredSize(gfx::Size(kDeleteButtonSizeDip, kDeleteButtonSizeDip));
+  SetPreferredSize(gfx::Size(ClipboardHistoryViews::kDeleteButtonSizeDip,
+                             ClipboardHistoryViews::kDeleteButtonSizeDip));
 }
 
 ClipboardHistoryDeleteButton::~ClipboardHistoryDeleteButton() = default;
@@ -44,7 +39,7 @@
   ScopedLightModeAsDefault scoped_light_mode_as_default;
 
   views::ImageButton::OnThemeChanged();
-  AshColorProvider::Get()->DecorateCloseButton(this, kDeleteButtonSizeDip,
-                                               kCloseButtonIcon);
+  AshColorProvider::Get()->DecorateCloseButton(
+      this, ClipboardHistoryViews::kDeleteButtonSizeDip, kCloseButtonIcon);
 }
 }  // namespace ash
diff --git a/ash/clipboard/views/clipboard_history_item_view.cc b/ash/clipboard/views/clipboard_history_item_view.cc
index e472266..f57e815 100644
--- a/ash/clipboard/views/clipboard_history_item_view.cc
+++ b/ash/clipboard/views/clipboard_history_item_view.cc
@@ -10,6 +10,7 @@
 #include "ash/clipboard/views/clipboard_history_file_item_view.h"
 #include "ash/clipboard/views/clipboard_history_main_button.h"
 #include "ash/clipboard/views/clipboard_history_text_item_view.h"
+#include "ash/clipboard/views/clipboard_history_view_constants.h"
 #include "base/auto_reset.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
@@ -20,21 +21,16 @@
 #include "ui/views/controls/menu/menu_item_view.h"
 #include "ui/views/layout/fill_layout.h"
 
-namespace {
-using Action = ash::ClipboardHistoryUtil::Action;
-
-// The insets within the contents view.
-constexpr gfx::Insets kContentsInsets(/*vertical=*/4, /*horizontal=*/16);
-
-}  // namespace
-
 namespace ash {
+namespace {
+using Action = ClipboardHistoryUtil::Action;
+}  // namespace
 
 ClipboardHistoryItemView::ContentsView::ContentsView(
     ClipboardHistoryItemView* container)
     : container_(container) {
   SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
-  SetBorder(views::CreateEmptyBorder(kContentsInsets));
+  SetBorder(views::CreateEmptyBorder(ClipboardHistoryViews::kContentsInsets));
 }
 
 ClipboardHistoryItemView::ContentsView::~ContentsView() = default;
diff --git a/ash/clipboard/views/clipboard_history_label.cc b/ash/clipboard/views/clipboard_history_label.cc
index ee7f9e5d..c7802fc9 100644
--- a/ash/clipboard/views/clipboard_history_label.cc
+++ b/ash/clipboard/views/clipboard_history_label.cc
@@ -4,20 +4,15 @@
 
 #include "ash/clipboard/views/clipboard_history_label.h"
 
+#include "ash/clipboard/views/clipboard_history_view_constants.h"
 #include "ash/style/ash_color_provider.h"
 #include "ash/style/scoped_light_mode_as_default.h"
 
-namespace {
-
-// The preferred height for the label.
-constexpr int kLabelPreferredHeight = 32;
-
-}  // namespace
-
 namespace ash {
 ClipboardHistoryLabel::ClipboardHistoryLabel(const base::string16& text)
     : views::Label(text) {
-  SetPreferredSize(gfx::Size(INT_MAX, kLabelPreferredHeight));
+  SetPreferredSize(
+      gfx::Size(INT_MAX, ClipboardHistoryViews::kLabelPreferredHeight));
   SetFontList(views::style::GetFont(views::style::CONTEXT_TOUCH_MENU,
                                     views::style::STYLE_PRIMARY));
   SetMultiLine(false);
diff --git a/ash/clipboard/views/clipboard_history_text_item_view.cc b/ash/clipboard/views/clipboard_history_text_item_view.cc
index 34bf21b..8e3099a 100644
--- a/ash/clipboard/views/clipboard_history_text_item_view.cc
+++ b/ash/clipboard/views/clipboard_history_text_item_view.cc
@@ -9,18 +9,12 @@
 #include "ash/clipboard/clipboard_history_util.h"
 #include "ash/clipboard/views/clipboard_history_delete_button.h"
 #include "ash/clipboard/views/clipboard_history_label.h"
+#include "ash/clipboard/views/clipboard_history_view_constants.h"
 #include "ash/shell.h"
 #include "base/metrics/histogram_macros.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/view_class_properties.h"
 
-namespace {
-
-// The margins of the delete button.
-constexpr gfx::Insets kDeleteButtonMargins =
-    gfx::Insets(/*top=*/0, /*left=*/8, /*bottom=*/0, /*right=*/4);
-}  // namespace
-
 namespace ash {
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -53,7 +47,9 @@
     auto delete_button =
         std::make_unique<ClipboardHistoryDeleteButton>(container());
     delete_button->SetVisible(false);
-    delete_button->SetProperty(views::kMarginsKey, kDeleteButtonMargins);
+    delete_button->SetProperty(
+        views::kMarginsKey,
+        ClipboardHistoryViews::kDefaultItemDeleteButtonMargins);
     return AddChildView(std::move(delete_button));
   }
 
diff --git a/ash/clipboard/views/clipboard_history_view_constants.h b/ash/clipboard/views/clipboard_history_view_constants.h
new file mode 100644
index 0000000..3443c49
--- /dev/null
+++ b/ash/clipboard/views/clipboard_history_view_constants.h
@@ -0,0 +1,50 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_CLIPBOARD_VIEWS_CLIPBOARD_HISTORY_VIEW_CONSTANTS_H_
+#define ASH_CLIPBOARD_VIEWS_CLIPBOARD_HISTORY_VIEW_CONSTANTS_H_
+
+#include "ui/gfx/geometry/insets.h"
+
+namespace ash {
+namespace ClipboardHistoryViews {
+
+// The insets within the contents view.
+constexpr int kContentsVerticalInset = 4;
+constexpr gfx::Insets kContentsInsets(kContentsVerticalInset,
+                                      /*horizontal=*/16);
+
+// The size of the `DeleteButton`.
+constexpr int kDeleteButtonSizeDip = 16;
+
+// The margins of the `DeleteButton` instance showing on
+// `ClipboardHistoryTextItemView` or `ClipboardHistoryFileItemView`.
+constexpr gfx::Insets kDefaultItemDeleteButtonMargins =
+    gfx::Insets(/*top=*/0, /*left=*/8, /*bottom=*/0, /*right=*/4);
+
+// The margins of the `DeleteButton` instance showing on
+// `ClipboardHistoryBitmapItemView`.
+constexpr gfx::Insets kBitmapItemDeleteButtonMargins =
+    gfx::Insets(/*top=*/4, /*left=*/0, /*bottom=*/0, /*right=*/4);
+
+// The preferred height of `ClipboardHistoryLabel`.
+constexpr int kLabelPreferredHeight = 28;
+
+// The preferred height of the image view showing on
+// `ClipboardHistoryBitmapItemView`.
+constexpr int kImageViewPreferredHeight = 72;
+
+// The radius of the image's rounded corners.
+constexpr int kImageRoundedCornerRadius = 4;
+
+// The thickness of the image border.
+constexpr int kImageBorderThickness = 1;
+
+// The opacity of the image shown in a disabled item view.
+constexpr float kDisabledImageAlpha = 0.38f;
+
+}  // namespace ClipboardHistoryViews
+}  // namespace ash
+
+#endif  // ASH_CLIPBOARD_VIEWS_CLIPBOARD_HISTORY_VIEW_CONSTANTS_H_
diff --git a/ash/services/recording/recording_service.cc b/ash/services/recording/recording_service.cc
index d7b96dc..907d5e7ce 100644
--- a/ash/services/recording/recording_service.cc
+++ b/ash/services/recording/recording_service.cc
@@ -332,7 +332,6 @@
     base::TimeTicks audio_capture_time) {
   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
   DCHECK(encoder_muxer_);
-  DCHECK(audio_capturer_);
 
   // We ignore any subsequent frames after a failure.
   if (did_failure_occur_)
diff --git a/ash/shortcut_viewer/strings/shortcut_viewer_strings_es-419.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_es-419.xtb
index 65c0055..961f29d 100644
--- a/ash/shortcut_viewer/strings/shortcut_viewer_strings_es-419.xtb
+++ b/ash/shortcut_viewer/strings/shortcut_viewer_strings_es-419.xtb
@@ -74,7 +74,7 @@
 <translation id="353037708190149633">Guardar todas las páginas abiertas en la ventana actual como marcadores en una nueva carpeta</translation>
 <translation id="355103131818127604">Abrir el vínculo en una nueva pestaña en segundo plano</translation>
 <translation id="3622741593887335780">Acercar (cuando esté activada la lupa acoplada O de pantalla completa)</translation>
-<translation id="3633851487917460983">Abrir el portapapeles</translation>
+<translation id="3633851487917460983">Abrir el Portapapeles</translation>
 <translation id="3649256019230929621">Minimizar ventana</translation>
 <translation id="3655154169297074232">Pestañas y ventanas</translation>
 <translation id="3668361878347172356">Rehacer la última acción</translation>
diff --git a/ash/shortcut_viewer/strings/shortcut_viewer_strings_or.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_or.xtb
index 1053560..b0cbc4d 100644
--- a/ash/shortcut_viewer/strings/shortcut_viewer_strings_or.xtb
+++ b/ash/shortcut_viewer/strings/shortcut_viewer_strings_or.xtb
@@ -74,6 +74,7 @@
 <translation id="353037708190149633">ଏକ ନୂଆ ଫୋଲ୍ଡର୍‍‍ରେ ବୁକମାର୍କ ରୂପରେ ଆପଣଙ୍କ ସାମ୍ପ୍ରତିକ ୱିଣ୍ଡୋର ସମସ୍ତ ଖୋଲାଥିବା ପୃଷ୍ଠା ସେଭ୍ କରନ୍ତୁ</translation>
 <translation id="355103131818127604">ପୃଷ୍ଠଭୂମିରେ ଏକ ନୂଆ ଟାବ୍‌ରେ ଏହି ଲିଙ୍କ୍ ଖୋଲନ୍ତୁ</translation>
 <translation id="3622741593887335780">ଜୁମ୍ କରନ୍ତୁ (ଯେତେବେଳେ ଡକେଡ OR ପୂର୍ଣ୍ଣସ୍କ୍ରିନ ମାଗ୍ନିଫାଏର ସକ୍ଷମ ଥିବ)</translation>
+<translation id="3633851487917460983">କ୍ଲିପବୋର୍ଡ ଖୋଲନ୍ତୁ</translation>
 <translation id="3649256019230929621">ୱିଣ୍ଡୋ ଛୋଟ କରନ୍ତୁ</translation>
 <translation id="3655154169297074232">ଟାବ୍ସ ଓ ୱିଣ୍ଡୋସ୍</translation>
 <translation id="3668361878347172356">ଆପଣ ଶେଷଥର କରିଥିବା କାର୍ଯ୍ୟକୁ ରି-ଡୁ କରନ୍ତୁ</translation>
diff --git a/ash/strings/ash_strings_eu.xtb b/ash/strings/ash_strings_eu.xtb
index 46868518..3d2788d 100644
--- a/ash/strings/ash_strings_eu.xtb
+++ b/ash/strings/ash_strings_eu.xtb
@@ -343,7 +343,7 @@
 <translation id="4212472694152630271">Aldatu PIN kodera</translation>
 <translation id="4215497585250573029">VPN ezarpenak</translation>
 <translation id="4217571870635786043">Diktaketa</translation>
-<translation id="4221957499226645091"><ph name="APP_NAME" />, instalatutako eta pausatutako aplikazioa</translation>
+<translation id="4221957499226645091"><ph name="APP_NAME" />, instalatutako aplikazioa, pausatuta</translation>
 <translation id="4239069858505860023">GPRS</translation>
 <translation id="4250229828105606438">Pantaila-argazkia</translation>
 <translation id="425364040945105958">Ez dago SIM txartelik</translation>
@@ -831,7 +831,7 @@
 <translation id="8755498163081687682">Egiaztatu zure nortasuna: <ph name="ORIGIN_NAME" /> webguneak zeu zarela berretsi nahi du</translation>
 <translation id="875593634123171288">Erakutsi VPN ezarpenak</translation>
 <translation id="8759408218731716181">Ezin da saio-hasiera anitza konfiguratu</translation>
-<translation id="878215960996152260"><ph name="APP_NAME" />, instalatutako eta blokeatutako aplikazioa</translation>
+<translation id="878215960996152260"><ph name="APP_NAME" />, instalatutako aplikazioa, blokeatuta</translation>
 <translation id="8785070478575117577">Konektatu <ph name="NETWORK_NAME" /> sarera</translation>
 <translation id="8788027118671217603"><ph name="STATE_TEXT" />. <ph name="ENTERPRISE_TEXT" /></translation>
 <translation id="8814190375133053267">Wi-Fi konexioa</translation>
diff --git a/ash/strings/ash_strings_gu.xtb b/ash/strings/ash_strings_gu.xtb
index 59e5250..6fdca72 100644
--- a/ash/strings/ash_strings_gu.xtb
+++ b/ash/strings/ash_strings_gu.xtb
@@ -91,6 +91,7 @@
 <translation id="1771761307086386028">જમણે સ્ક્રોલ કરો</translation>
 <translation id="1782199038061388045">અનુવાદ</translation>
 <translation id="1787955149152357925">બંધ છે</translation>
+<translation id="1804572139604454141">ડિસ્કમાં અત્યંત ઓછી સ્પેસ હોવાથી રેકોર્ડિંગ સમાપ્ત થયું</translation>
 <translation id="181103072419391116">સિગ્નલની સશક્તતા <ph name="SIGNAL_STRENGTH" />, તમારા વ્યવસ્થાપક દ્વારા મેનેજ કરવામાં આવે છે</translation>
 <translation id="1812997170047690955">મારી સ્ક્રીન પર શું છે?</translation>
 <translation id="1823873187264960516">ઇથરનેટ: <ph name="ADDRESS" /></translation>
diff --git a/ash/strings/ash_strings_nl.xtb b/ash/strings/ash_strings_nl.xtb
index d3a5498..051d949 100644
--- a/ash/strings/ash_strings_nl.xtb
+++ b/ash/strings/ash_strings_nl.xtb
@@ -368,7 +368,7 @@
 <translation id="4379531060876907730">Dit zijn je stylustools</translation>
 <translation id="4389184120735010762">Je hebt op de sneltoets voor het vastgezette vergrootglas gedrukt. Wil je deze functie inschakelen?</translation>
 <translation id="4412944820643904175"><ph name="FEATURE_NAME" /> is uitgeschakeld.</translation>
-<translation id="4421231901400348175">De controle over je scherm wordt gedeeld met <ph name="HELPER_NAME" /> via externe ondersteuning.</translation>
+<translation id="4421231901400348175">De controle over je scherm wordt gedeeld met <ph name="HELPER_NAME" /> via externe support.</translation>
 <translation id="4430019312045809116">Volume</translation>
 <translation id="4450893287417543264">Niet meer tonen</translation>
 <translation id="445864333228800152">Goedenavond,</translation>
@@ -532,7 +532,7 @@
 <translation id="5958529069007801266">Gelimiteerde gebruiker</translation>
 <translation id="5960825221082587934">Laat de Assistent informatie weergeven zoals de definitie, vertaling of eenheidsconversie voor je selectie.</translation>
 <translation id="5977415296283489383">Hoofdtelefoon</translation>
-<translation id="5978382165065462689">De controle over je scherm delen via externe ondersteuning.</translation>
+<translation id="5978382165065462689">De controle over je scherm delen via externe support.</translation>
 <translation id="5980301590375426705">Gastsessie sluiten</translation>
 <translation id="598882571027504733">Als je de update wilt downloaden, sluit je het toetsenbord aan en start je je Chromebook opnieuw op</translation>
 <translation id="5992218262414051481">De modus voor hoog contrast is ingeschakeld. Druk nogmaals op Ctrl+Zoeken+H om deze uit te schakelen.</translation>
diff --git a/ash/strings/ash_strings_or.xtb b/ash/strings/ash_strings_or.xtb
index 694fb8b2..7198503 100644
--- a/ash/strings/ash_strings_or.xtb
+++ b/ash/strings/ash_strings_or.xtb
@@ -91,6 +91,7 @@
 <translation id="1771761307086386028">ଡାହାଣକୁ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ</translation>
 <translation id="1782199038061388045">ଅନୁବାଦ</translation>
 <translation id="1787955149152357925">ବନ୍ଦ ଅଛି</translation>
+<translation id="1804572139604454141">ଡିସ୍କ ସ୍ପେସ୍ ଅତ୍ୟନ୍ତ କମ୍ ଥିବା ଯୋଗୁଁ ରେକର୍ଡିଂ ସମାପ୍ତ ହୋଇଛି</translation>
 <translation id="181103072419391116">ସିଗ୍‍ନାଲ୍‍ର କ୍ଷମତା <ph name="SIGNAL_STRENGTH" />, ଆପଣଙ୍କର ଆଡ୍‍ମିନିଷ୍ଟ୍ରେଟର୍‍ଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ</translation>
 <translation id="1812997170047690955">ମୋ ସ୍କ୍ରିନ୍‌ରେ କ’ଣ ଅଛି?</translation>
 <translation id="1823873187264960516">ଇଥର୍ନେଟ୍: <ph name="ADDRESS" /></translation>
@@ -238,6 +239,7 @@
 <translation id="3236488194889173876">କୌଣସି ମୋବାଇଲ୍ ନେଟ୍‌ୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ</translation>
 <translation id="3249513730522716925"><ph name="WINDOW_TITLE" /> ୱିଣ୍ଡୋ <ph name="ACTIVE_DESK" /> ଡେସ୍କରୁ <ph name="TARGET_DESK" />ଡେସ୍କକୁ ଘୁଞ୍ଚାଇ ଦିଆଯାଇଛି</translation>
 <translation id="3255483164551725916">ଆପଣ କ’ଣ କରିପାରିବେ?</translation>
+<translation id="3269597722229482060">ଡାହାଣ କ୍ଲିକ୍ କରନ୍ତୁ</translation>
 <translation id="3289674678944039601">ଆଡପ୍ଟର୍ ମାଧ୍ୟମରେ ଚାର୍ଜ ହେଉଛି</translation>
 <translation id="3290356915286466215">ଅସୁରକ୍ଷିତ</translation>
 <translation id="3294437725009624529">ଅତିଥି</translation>
@@ -340,6 +342,7 @@
 <translation id="4212472694152630271">PINକୁ ସ୍ୱିଚ୍ କରନ୍ତୁ</translation>
 <translation id="4215497585250573029">VPN ସେଟିଂସ୍</translation>
 <translation id="4217571870635786043">ଶ୍ରୁତଲିଖନ</translation>
+<translation id="4221957499226645091"><ph name="APP_NAME" />, ଇନଷ୍ଟଲ୍ କରାଯାଇଥିବା ଆପ୍, ବିରତ କରାଯାଇଛି</translation>
 <translation id="4239069858505860023">GPRS</translation>
 <translation id="4250229828105606438">ସ୍କ୍ରିନ୍‍ସଟ୍</translation>
 <translation id="425364040945105958">କୌଣସି SIM ନାହିଁ</translation>
@@ -761,6 +764,7 @@
 <translation id="8142699993796781067">ବ୍ୟକ୍ତିଗତ ନେଟୱାର୍କ</translation>
 <translation id="8152092012181020186">ବନ୍ଦ କରିବାକୁ Ctrl + W ଦବାନ୍ତୁ।</translation>
 <translation id="8155007568264258537"><ph name="FEATURE_NAME" /> ଏହି ସେଟିଂ ଆପଣଙ୍କ ଆଡମିନିଷ୍ଟ୍ରେଟରଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ ହୁଏ।</translation>
+<translation id="8155628902202578800"><ph name="USER_EMAIL_ADDRESS" /> ପାଇଁ ସୂଚନା ଡାଏଲଗ୍ ଖୋଲନ୍ତୁ</translation>
 <translation id="8167567890448493835"><ph name="LOCALE_NAME" />କୁ ବ୍ୟବହାର କରାଯାଉଛି</translation>
 <translation id="8170567869359129153">ମୋବାଇଲ ନେଟୱାର୍କ। <ph name="SIGNAL_STRENGTH" />ର ସିଗନାଲ୍ କ୍ଷମତା</translation>
 <translation id="8192202700944119416">ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଲୁଚାଯାଇଛି।</translation>
@@ -826,6 +830,7 @@
 <translation id="8755498163081687682">ଆପଣଙ୍କ ପରିଚୟ ଯାଞ୍ଚ କରନ୍ତୁ: ଏହା ଆପଣ ଅଟନ୍ତି ବୋଲି <ph name="ORIGIN_NAME" /> ସୁନିଶ୍ଚିତ କରିବାକୁ ଚାହୁଁଛି</translation>
 <translation id="875593634123171288">VPN ସେଟିଂସ୍‌ ଦେଖାନ୍ତୁ</translation>
 <translation id="8759408218731716181">ଏକାଧିକ ସାଇନ୍-ଇନ୍ ସେଟ୍ ଅପ୍ କରିପାରିବେ ନାହିଁ</translation>
+<translation id="878215960996152260"><ph name="APP_NAME" />, ଇନଷ୍ଟଲ୍ କରାଯାଇଥିବା ଆପ୍, ବ୍ଲକ୍ କରାଯାଇଛି</translation>
 <translation id="8785070478575117577"><ph name="NETWORK_NAME" />ରେ ସଂଯୋଗ କରନ୍ତୁ</translation>
 <translation id="8788027118671217603"><ph name="STATE_TEXT" />। <ph name="ENTERPRISE_TEXT" /></translation>
 <translation id="8814190375133053267">ୱାଇ-ଫାଇ</translation>
diff --git a/ash/strings/ash_strings_uz.xtb b/ash/strings/ash_strings_uz.xtb
index d7e39ef..13e48d3 100644
--- a/ash/strings/ash_strings_uz.xtb
+++ b/ash/strings/ash_strings_uz.xtb
@@ -342,7 +342,7 @@
 <translation id="4212472694152630271">PIN kod kiritish</translation>
 <translation id="4215497585250573029">VPN sozlamalari</translation>
 <translation id="4217571870635786043">Ovoz bilan yozish</translation>
-<translation id="4221957499226645091"><ph name="APP_NAME" />, Ilova oʻrnatildi, Pauzada</translation>
+<translation id="4221957499226645091"><ph name="APP_NAME" />, Oʻrnatilgan ilova, Pauzada</translation>
 <translation id="4239069858505860023">GPRS</translation>
 <translation id="4250229828105606438">Skrinshot</translation>
 <translation id="425364040945105958">SIM kartasiz</translation>
diff --git a/ash/system/tray/detailed_view_delegate.cc b/ash/system/tray/detailed_view_delegate.cc
index 7c331165..ba09d53 100644
--- a/ash/system/tray/detailed_view_delegate.cc
+++ b/ash/system/tray/detailed_view_delegate.cc
@@ -10,7 +10,7 @@
 #include "ash/system/tray/hover_highlight_view.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/tray/tray_popup_utils.h"
-#include "ash/system/unified/collapse_button.h"
+#include "ash/system/unified/custom_shape_button.h"
 #include "ash/system/unified/top_shortcut_button.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "components/vector_icons/vector_icons.h"
diff --git a/ash/system/unified/collapse_button.cc b/ash/system/unified/collapse_button.cc
index ed9c582..e108f7bd 100644
--- a/ash/system/unified/collapse_button.cc
+++ b/ash/system/unified/collapse_button.cc
@@ -8,14 +8,21 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/style/ash_color_provider.h"
 #include "ash/system/tray/tray_constants.h"
+#include "ash/system/tray/tray_popup_utils.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/scoped_canvas.h"
+#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
+#include "ui/views/animation/ink_drop_impl.h"
+#include "ui/views/controls/highlight_path_generator.h"
 
 namespace ash {
 
 CollapseButton::CollapseButton(PressedCallback callback)
-    : CustomShapeButton(std::move(callback)) {}
+    : ImageButton(std::move(callback)) {
+  views::InstallCircleHighlightPathGenerator(this);
+  TrayPopupUtils::ConfigureTrayPopupButton(this);
+}
 
 CollapseButton::~CollapseButton() = default;
 
@@ -30,36 +37,43 @@
 }
 
 gfx::Size CollapseButton::CalculatePreferredSize() const {
-  return gfx::Size(kTrayItemSize, kTrayItemSize * 3 / 2);
-}
-
-SkPath CollapseButton::CreateCustomShapePath(const gfx::Rect& bounds) const {
-  SkPath path;
-  SkScalar bottom_radius = SkIntToScalar(kTrayItemSize / 2);
-  SkScalar radii[8] = {
-      0, 0, 0, 0, bottom_radius, bottom_radius, bottom_radius, bottom_radius};
-  path.addRoundRect(gfx::RectToSkRect(bounds), radii);
-  return path;
+  return gfx::Size(kTrayItemSize, kTrayItemSize);
 }
 
 void CollapseButton::PaintButtonContents(gfx::Canvas* canvas) {
-  PaintCustomShapePath(canvas);
-
   gfx::ScopedCanvas scoped(canvas);
-  canvas->Translate(gfx::Vector2d(size().width() / 2, size().height() * 2 / 3));
+  canvas->Translate(gfx::Vector2d(size().width() / 2, size().height() / 2));
   canvas->sk_canvas()->rotate(expanded_amount_ * 180.);
   gfx::ImageSkia image = GetImageToPaint();
   canvas->DrawImageInt(image, -image.width() / 2, -image.height() / 2);
 }
 
+std::unique_ptr<views::InkDrop> CollapseButton::CreateInkDrop() {
+  return TrayPopupUtils::CreateInkDrop(this);
+}
+
+std::unique_ptr<views::InkDropRipple> CollapseButton::CreateInkDropRipple()
+    const {
+  return TrayPopupUtils::CreateInkDropRipple(
+      TrayPopupInkDropStyle::FILL_BOUNDS, this,
+      GetInkDropCenterBasedOnLastEvent());
+}
+
+std::unique_ptr<views::InkDropHighlight>
+CollapseButton::CreateInkDropHighlight() const {
+  return TrayPopupUtils::CreateInkDropHighlight(this);
+}
+
 const char* CollapseButton::GetClassName() const {
   return "CollapseButton";
 }
 
 void CollapseButton::OnThemeChanged() {
-  CustomShapeButton::OnThemeChanged();
+  views::ImageButton::OnThemeChanged();
   AshColorProvider::Get()->DecorateFloatingIconButton(this,
                                                       kUnifiedMenuExpandIcon);
+  focus_ring()->SetColor(AshColorProvider::Get()->GetControlsLayerColor(
+      AshColorProvider::ControlsLayerType::kFocusRingColor));
 }
 
 }  // namespace ash
diff --git a/ash/system/unified/collapse_button.h b/ash/system/unified/collapse_button.h
index 9a97ff5..fa43dcaa 100644
--- a/ash/system/unified/collapse_button.h
+++ b/ash/system/unified/collapse_button.h
@@ -5,7 +5,7 @@
 #ifndef ASH_SYSTEM_UNIFIED_COLLAPSE_BUTTON_H_
 #define ASH_SYSTEM_UNIFIED_COLLAPSE_BUTTON_H_
 
-#include "ash/system/unified/custom_shape_button.h"
+#include "ui/views/controls/button/image_button.h"
 
 namespace ash {
 
@@ -13,7 +13,7 @@
 // UnifiedSystemTrayBubble will support collapsed state where the height of the
 // bubble is smaller, and some rows and labels will be omitted.
 // By pressing the button, the state of the bubble will be toggled.
-class CollapseButton : public CustomShapeButton {
+class CollapseButton : public views::ImageButton {
  public:
   explicit CollapseButton(PressedCallback callback);
   ~CollapseButton() override;
@@ -21,10 +21,13 @@
   // Change the expanded state. The icon will change.
   void SetExpandedAmount(double expanded_amount);
 
-  // CustomShapeButton:
+  // views::ImageButton:
   gfx::Size CalculatePreferredSize() const override;
-  SkPath CreateCustomShapePath(const gfx::Rect& bounds) const override;
   void PaintButtonContents(gfx::Canvas* canvas) override;
+  std::unique_ptr<views::InkDrop> CreateInkDrop() override;
+  std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
+  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
+      const override;
   const char* GetClassName() const override;
   void OnThemeChanged() override;
 
diff --git a/ash/system/unified/top_shortcuts_view.cc b/ash/system/unified/top_shortcuts_view.cc
index 780b919c..40d6380 100644
--- a/ash/system/unified/top_shortcuts_view.cc
+++ b/ash/system/unified/top_shortcuts_view.cc
@@ -224,10 +224,18 @@
   // container flex occupying all remaining space.
   layout->SetFlexForView(container_, 1);
 
-  collapse_button_ = new CollapseButton(
-      base::BindRepeating(&UnifiedSystemTrayController::ToggleExpanded,
-                          base::Unretained(controller)));
-  AddChildView(collapse_button_);
+  auto* collapse_button_container =
+      AddChildView(std::make_unique<views::View>());
+  collapse_button_ =
+      collapse_button_container->AddChildView(std::make_unique<CollapseButton>(
+          base::BindRepeating(&UnifiedSystemTrayController::ToggleExpanded,
+                              base::Unretained(controller))));
+  const gfx::Size collapse_button_size = collapse_button_->GetPreferredSize();
+  collapse_button_container->SetPreferredSize(
+      gfx::Size(collapse_button_size.width(),
+                collapse_button_size.height() + kUnifiedTopShortcutSpacing));
+  collapse_button_->SetBoundsRect(gfx::Rect(
+      gfx::Point(0, kUnifiedTopShortcutSpacing), collapse_button_size));
 }
 
 // static
diff --git a/ash/wm/window_resizer.cc b/ash/wm/window_resizer.cc
index 30289b8e..5323b18 100644
--- a/ash/wm/window_resizer.cc
+++ b/ash/wm/window_resizer.cc
@@ -22,9 +22,9 @@
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/resize_utils.h"
 #include "ui/gfx/presentation_feedback.h"
 #include "ui/views/widget/widget.h"
-#include "ui/views/window/window_resize_utils.h"
 #include "ui/wm/core/coordinate_conversion.h"
 
 namespace ash {
@@ -39,28 +39,29 @@
          window_component == HTBOTTOMRIGHT || window_component == HTGROWBOX;
 }
 
-// Convert |window_component| to the HitTest used in views::WindowResizeUtils.
-views::HitTest GetWindowResizeHitTest(int window_component) {
+// Convert |window_component| to the ResizeEdge used in
+// gfx::SizeRectToAspectRatio().
+gfx::ResizeEdge GetWindowResizeEdge(int window_component) {
   switch (window_component) {
     case HTBOTTOM:
-      return views::HitTest::kBottom;
+      return gfx::ResizeEdge::kBottom;
     case HTTOP:
-      return views::HitTest::kTop;
+      return gfx::ResizeEdge::kTop;
     case HTLEFT:
-      return views::HitTest::kLeft;
+      return gfx::ResizeEdge::kLeft;
     case HTRIGHT:
-      return views::HitTest::kRight;
+      return gfx::ResizeEdge::kRight;
     case HTTOPLEFT:
-      return views::HitTest::kTopLeft;
+      return gfx::ResizeEdge::kTopLeft;
     case HTTOPRIGHT:
-      return views::HitTest::kTopRight;
+      return gfx::ResizeEdge::kTopRight;
     case HTBOTTOMLEFT:
-      return views::HitTest::kBottomLeft;
+      return gfx::ResizeEdge::kBottomLeft;
     case HTBOTTOMRIGHT:
-      return views::HitTest::kBottomRight;
+      return gfx::ResizeEdge::kBottomRight;
     default:
       NOTREACHED();
-      return views::HitTest::kBottomRight;
+      return gfx::ResizeEdge::kBottomRight;
   }
 }
 
@@ -468,11 +469,9 @@
   DCHECK(!min_size.IsEmpty());
   DCHECK(!max_size.IsEmpty());
 
-  views::WindowResizeUtils::SizeMinMaxToAspectRatio(aspect_ratio, &min_size,
-                                                    &max_size);
-  views::WindowResizeUtils::SizeRectToAspectRatio(
-      GetWindowResizeHitTest(details().window_component), aspect_ratio,
-      min_size, max_size, new_bounds);
+  gfx::SizeMinMaxToAspectRatio(aspect_ratio, &min_size, &max_size);
+  gfx::SizeRectToAspectRatio(GetWindowResizeEdge(details().window_component),
+                             aspect_ratio, min_size, max_size, new_bounds);
 }
 
 }  // namespace ash
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc
index 9a4a7a7..be169dac 100644
--- a/base/allocator/partition_allocator/partition_bucket.cc
+++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -569,7 +569,7 @@
       void* addr = SlotSpanMetadata<thread_safe>::ToPointer(new_slot_span);
       root->RecommitSystemPagesForData(
           addr, new_slot_span->bucket->get_bytes_per_span(),
-          PageUpdatePermissions);
+          PageKeepPermissionsIfPossible);
       new_slot_span->Reset();
       *is_already_zeroed = kDecommittedPagesAreAlwaysZeroed;
     }
diff --git a/base/allocator/partition_allocator/partition_page.cc b/base/allocator/partition_allocator/partition_page.cc
index ebd83974..aafb7ba0 100644
--- a/base/allocator/partition_allocator/partition_page.cc
+++ b/base/allocator/partition_allocator/partition_page.cc
@@ -168,7 +168,7 @@
   PA_DCHECK(!bucket->is_direct_mapped());
   void* addr = SlotSpanMetadata::ToPointer(this);
   root->DecommitSystemPagesForData(addr, bucket->get_bytes_per_span(),
-                                   PageUpdatePermissions);
+                                   PageKeepPermissionsIfPossible);
 
   // We actually leave the decommitted slot span in the active list. We'll sweep
   // it on to the decommitted list when we next walk the active list.
diff --git a/base/allocator/partition_allocator/thread_cache.cc b/base/allocator/partition_allocator/thread_cache.cc
index 5bdaf5c..8caff4f 100644
--- a/base/allocator/partition_allocator/thread_cache.cc
+++ b/base/allocator/partition_allocator/thread_cache.cc
@@ -181,6 +181,62 @@
   root->RawFree(tcache_ptr);
 }
 
+void ThreadCache::FillBucket(size_t bucket_index) {
+  // Filling multiple elements from the central allocator at a time has several
+  // advantages:
+  // - Amortize lock acquisition
+  // - Increase hit rate
+  // - Can improve locality, as consecutive allocations from the central
+  //   allocator will likely return close addresses, especially early on.
+  //
+  // However, do not take too many items, to prevent memory bloat.
+  //
+  // Cache filling / purging policy:
+  // We aim at keeping the buckets neither empty nor full, while minimizing
+  // requests to the central allocator.
+  //
+  // For each bucket, there is a |limit| of how many cached objects there are in
+  // the bucket, so |count| < |limit| at all times.
+  // - Clearing: limit -> limit / 2
+  // - Filling: 0 -> limit / 4
+  //
+  // These thresholds are somewhat arbitrary, with these considerations:
+  // (1) Batched filling should not completely fill the bucket
+  // (2) Batched clearing should not completely clear the bucket
+  // (3) Batched filling should not be too eager
+  //
+  // If (1) and (2) do not hold, we risk oscillations of bucket filling /
+  // clearing which would greatly increase calls to the central allocator. (3)
+  // tries to keep memory usage low. So clearing half of the bucket, and filling
+  // a quarter of it are sensible defaults.
+  Bucket& bucket = buckets_[bucket_index];
+  int count = bucket.limit / 4;
+
+  size_t utilized_slot_size;
+  bool is_already_zeroed;
+
+  // Same as calling RawAlloc() |count| times, but acquires the lock only once.
+  internal::ScopedGuard<internal::ThreadSafe> guard(root_->lock_);
+  for (int i = 0; i < count; i++) {
+    // We allow the allocator to return nullptr, since filling the cache may
+    // safely fail, and the proper flag will be handled by the central
+    // allocator.
+    //
+    // |raw_size| is set to the slot size, as we don't know it. However, it is
+    // only used for direct-mapped allocations and single-slot ones anyway,
+    // which are not handled here.
+    void* ptr = root_->AllocFromBucket(
+        &root_->buckets[bucket_index], PartitionAllocReturnNull,
+        root_->buckets[bucket_index].slot_size /* raw_size */,
+        &utilized_slot_size, &is_already_zeroed);
+    // Central allocator is out of memory.
+    if (!ptr)
+      break;
+
+    PutInBucket(bucket, ptr);
+  }
+}
+
 void ThreadCache::ClearBucket(ThreadCache::Bucket& bucket, size_t limit) {
   // Avoids acquiring the lock needlessly.
   if (!bucket.count)
diff --git a/base/allocator/partition_allocator/thread_cache.h b/base/allocator/partition_allocator/thread_cache.h
index 23670aa..eca7277 100644
--- a/base/allocator/partition_allocator/thread_cache.h
+++ b/base/allocator/partition_allocator/thread_cache.h
@@ -195,8 +195,11 @@
   explicit ThreadCache(PartitionRoot<ThreadSafe>* root);
   static void Delete(void* thread_cache_ptr);
   void PurgeInternal();
+  // Fills a bucket from the central allocator.
+  void FillBucket(size_t bucket_index);
   // Empties the |bucket| until there are at most |limit| objects in it.
   void ClearBucket(Bucket& bucket, size_t limit);
+  ALWAYS_INLINE void PutInBucket(Bucket& bucket, void* ptr);
 
   // TODO(lizeb): Optimize the threshold.
   static constexpr size_t kSizeThreshold = 512;
@@ -208,7 +211,7 @@
       kBucketCount < kNumBuckets,
       "Cannot have more cached buckets than what the allocator supports");
 
-  std::atomic<bool> should_purge_;
+  std::atomic<bool> should_purge_{false};
   Bucket buckets_[kBucketCount];
   ThreadCacheStats stats_;
   PartitionRoot<ThreadSafe>* const root_;
@@ -232,9 +235,6 @@
 ALWAYS_INLINE bool ThreadCache::MaybePutInCache(void* address,
                                                 size_t bucket_index) {
   PA_REENTRANCY_GUARD(is_in_thread_cache_);
-  if (UNLIKELY(should_purge_.load(std::memory_order_relaxed)))
-    PurgeInternal();
-
   INCREMENT_COUNTER(stats_.cache_fill_count);
 
   if (UNLIKELY(bucket_index >= kBucketCount)) {
@@ -246,18 +246,17 @@
 
   PA_DCHECK(bucket.count != 0 || bucket.freelist_head == nullptr);
 
-  auto* entry = reinterpret_cast<PartitionFreelistEntry*>(address);
-  entry->SetNextForThreadCache(bucket.freelist_head);
-  bucket.freelist_head = entry;
-  bucket.count++;
-
+  PutInBucket(bucket, address);
   INCREMENT_COUNTER(stats_.cache_fill_hits);
 
   // Batched deallocation, amortizing lock acquisitions.
   if (UNLIKELY(bucket.count >= bucket.limit)) {
-    ClearBucket(bucket, bucket.limit >> 1);
+    ClearBucket(bucket, bucket.limit / 2);
   }
 
+  if (UNLIKELY(should_purge_.load(std::memory_order_relaxed)))
+    PurgeInternal();
+
   return true;
 }
 
@@ -272,25 +271,39 @@
   }
 
   auto& bucket = buckets_[bucket_index];
-  auto* result = bucket.freelist_head;
-  if (UNLIKELY(!result)) {
+  if (LIKELY(bucket.freelist_head)) {
+    INCREMENT_COUNTER(stats_.alloc_hits);
+  } else {
     PA_DCHECK(bucket.count == 0);
     INCREMENT_COUNTER(stats_.alloc_miss_empty);
     INCREMENT_COUNTER(stats_.alloc_misses);
-    return nullptr;
+
+    FillBucket(bucket_index);
+
+    // Very unlikely, means that the central allocator is out of memory. Let it
+    // deal with it (may return nullptr, may crash).
+    if (UNLIKELY(!bucket.freelist_head))
+      return nullptr;
   }
 
   PA_DCHECK(bucket.count != 0);
+  auto* result = bucket.freelist_head;
   auto* next = result->GetNext();
   PA_DCHECK(result != next);
   bucket.count--;
   PA_DCHECK(bucket.count != 0 || !next);
   bucket.freelist_head = next;
 
-  INCREMENT_COUNTER(stats_.alloc_hits);
   return result;
 }
 
+ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket, void* ptr) {
+  auto* entry = reinterpret_cast<PartitionFreelistEntry*>(ptr);
+  entry->SetNextForThreadCache(bucket.freelist_head);
+  bucket.freelist_head = entry;
+  bucket.count++;
+}
+
 }  // namespace internal
 }  // namespace base
 
diff --git a/base/allocator/partition_allocator/thread_cache_unittest.cc b/base/allocator/partition_allocator/thread_cache_unittest.cc
index b92d817d..a3c9060 100644
--- a/base/allocator/partition_allocator/thread_cache_unittest.cc
+++ b/base/allocator/partition_allocator/thread_cache_unittest.cc
@@ -35,6 +35,14 @@
 
 namespace {
 
+constexpr size_t kSmallSize = 12;
+constexpr size_t kMaxCountForSmallBucket = 128;
+constexpr size_t kFillCountForSmallBucket = kMaxCountForSmallBucket / 4;
+
+constexpr size_t kMediumSize = 200;
+constexpr size_t kMaxCountForMediumBucket = 64;
+constexpr size_t kFillCountForMediumBucket = kMaxCountForMediumBucket / 4;
+
 class LambdaThreadDelegate : public PlatformThread::Delegate {
  public:
   explicit LambdaThreadDelegate(OnceClosure f) : f_(std::move(f)) {}
@@ -96,83 +104,89 @@
 };
 
 TEST_F(ThreadCacheTest, Simple) {
-  const size_t kTestSize = 12;
-  void* ptr = g_root->Alloc(kTestSize, "");
+  void* ptr = g_root->Alloc(kSmallSize, "");
   ASSERT_TRUE(ptr);
 
   // There is a cache.
   auto* tcache = g_root->thread_cache_for_testing();
   EXPECT_TRUE(tcache);
 
-  uint16_t index = PartitionRoot<ThreadSafe>::SizeToBucketIndex(kTestSize);
-  EXPECT_EQ(0u, tcache->bucket_count_for_testing(index));
+  uint16_t index = PartitionRoot<ThreadSafe>::SizeToBucketIndex(kSmallSize);
+  EXPECT_EQ(kFillCountForSmallBucket - 1,
+            tcache->bucket_count_for_testing(index));
 
   g_root->Free(ptr);
   // Freeing fills the thread cache.
-  EXPECT_EQ(1u, tcache->bucket_count_for_testing(index));
+  EXPECT_EQ(kFillCountForSmallBucket, tcache->bucket_count_for_testing(index));
 
-  void* ptr2 = g_root->Alloc(kTestSize, "");
+  void* ptr2 = g_root->Alloc(kSmallSize, "");
   EXPECT_EQ(ptr, ptr2);
   // Allocated from the thread cache.
-  EXPECT_EQ(0u, tcache->bucket_count_for_testing(index));
+  EXPECT_EQ(kFillCountForSmallBucket - 1,
+            tcache->bucket_count_for_testing(index));
 }
 
 TEST_F(ThreadCacheTest, InexactSizeMatch) {
-  const size_t kTestSize = 12;
-  void* ptr = g_root->Alloc(kTestSize, "");
+  void* ptr = g_root->Alloc(kSmallSize, "");
   ASSERT_TRUE(ptr);
 
   // There is a cache.
   auto* tcache = g_root->thread_cache_for_testing();
   EXPECT_TRUE(tcache);
 
-  uint16_t index = PartitionRoot<ThreadSafe>::SizeToBucketIndex(kTestSize);
-  EXPECT_EQ(0u, tcache->bucket_count_for_testing(index));
+  uint16_t index = PartitionRoot<ThreadSafe>::SizeToBucketIndex(kSmallSize);
+  EXPECT_EQ(kFillCountForSmallBucket - 1,
+            tcache->bucket_count_for_testing(index));
 
   g_root->Free(ptr);
   // Freeing fills the thread cache.
-  EXPECT_EQ(1u, tcache->bucket_count_for_testing(index));
+  EXPECT_EQ(kFillCountForSmallBucket, tcache->bucket_count_for_testing(index));
 
-  void* ptr2 = g_root->Alloc(kTestSize + 1, "");
+  void* ptr2 = g_root->Alloc(kSmallSize + 1, "");
   EXPECT_EQ(ptr, ptr2);
   // Allocated from the thread cache.
-  EXPECT_EQ(0u, tcache->bucket_count_for_testing(index));
+  EXPECT_EQ(kFillCountForSmallBucket - 1,
+            tcache->bucket_count_for_testing(index));
 }
 
 TEST_F(ThreadCacheTest, MultipleObjectsCachedPerBucket) {
-  size_t bucket_index = FillThreadCacheAndReturnIndex(100, 10);
+  size_t bucket_index =
+      FillThreadCacheAndReturnIndex(kMediumSize, kFillCountForMediumBucket + 2);
   auto* tcache = g_root->thread_cache_for_testing();
-  EXPECT_EQ(10u, tcache->bucket_count_for_testing(bucket_index));
+  EXPECT_EQ(2 * kFillCountForMediumBucket,
+            tcache->bucket_count_for_testing(bucket_index));
 }
 
 TEST_F(ThreadCacheTest, ObjectsCachedCountIsLimited) {
-  size_t bucket_index = FillThreadCacheAndReturnIndex(100, 1000);
+  size_t bucket_index = FillThreadCacheAndReturnIndex(kMediumSize, 1000);
   auto* tcache = g_root->thread_cache_for_testing();
   EXPECT_LT(tcache->bucket_count_for_testing(bucket_index), 1000u);
 }
 
 TEST_F(ThreadCacheTest, Purge) {
-  size_t bucket_index = FillThreadCacheAndReturnIndex(100, 10);
+  size_t bucket_index = FillThreadCacheAndReturnIndex(kMediumSize, 10);
   auto* tcache = g_root->thread_cache_for_testing();
-  EXPECT_EQ(10u, tcache->bucket_count_for_testing(bucket_index));
+  EXPECT_EQ(kFillCountForMediumBucket,
+            tcache->bucket_count_for_testing(bucket_index));
   tcache->Purge();
   EXPECT_EQ(0u, tcache->bucket_count_for_testing(bucket_index));
 }
 
 TEST_F(ThreadCacheTest, NoCrossPartitionCache) {
-  const size_t kTestSize = 12;
   ThreadSafePartitionRoot root{{PartitionOptions::Alignment::kAlignedAlloc,
                                 PartitionOptions::ThreadCache::kDisabled}};
 
-  size_t bucket_index = FillThreadCacheAndReturnIndex(kTestSize);
-  void* ptr = root.Alloc(kTestSize, "");
+  size_t bucket_index = FillThreadCacheAndReturnIndex(kSmallSize);
+  void* ptr = root.Alloc(kSmallSize, "");
   ASSERT_TRUE(ptr);
 
   auto* tcache = g_root->thread_cache_for_testing();
-  EXPECT_EQ(1u, tcache->bucket_count_for_testing(bucket_index));
+  EXPECT_EQ(kFillCountForSmallBucket,
+            tcache->bucket_count_for_testing(bucket_index));
 
   ThreadSafePartitionRoot::Free(ptr);
-  EXPECT_EQ(1u, tcache->bucket_count_for_testing(bucket_index));
+  EXPECT_EQ(kFillCountForSmallBucket,
+            tcache->bucket_count_for_testing(bucket_index));
 }
 
 #if defined(PA_ENABLE_THREAD_CACHE_STATISTICS)  // Required to record hits and
@@ -201,14 +215,13 @@
 }
 
 TEST_F(ThreadCacheTest, MultipleThreadCaches) {
-  const size_t kTestSize = 100;
-  FillThreadCacheAndReturnIndex(kTestSize);
+  FillThreadCacheAndReturnIndex(kMediumSize);
   auto* parent_thread_tcache = g_root->thread_cache_for_testing();
   ASSERT_TRUE(parent_thread_tcache);
 
   LambdaThreadDelegate delegate{BindLambdaForTesting([&]() {
     EXPECT_FALSE(g_root->thread_cache_for_testing());  // No allocations yet.
-    FillThreadCacheAndReturnIndex(kTestSize);
+    FillThreadCacheAndReturnIndex(kMediumSize);
     auto* tcache = g_root->thread_cache_for_testing();
     EXPECT_TRUE(tcache);
 
@@ -221,15 +234,20 @@
 }
 
 TEST_F(ThreadCacheTest, ThreadCacheReclaimedWhenThreadExits) {
-  const size_t kTestSize = 100;
   // Make sure that there is always at least one object allocated in the test
   // bucket, so that the PartitionPage is no reclaimed.
-  void* tmp = g_root->Alloc(kTestSize, "");
+  //
+  // Allocate enough objects to force a cache fill at the next allocation.
+  std::vector<void*> tmp;
+  for (size_t i = 0; i < kMaxCountForMediumBucket / 4; i++) {
+    tmp.push_back(g_root->Alloc(kMediumSize, ""));
+  }
+
   void* other_thread_ptr;
 
   LambdaThreadDelegate delegate{BindLambdaForTesting([&]() {
     EXPECT_FALSE(g_root->thread_cache_for_testing());  // No allocations yet.
-    other_thread_ptr = g_root->Alloc(kTestSize, "");
+    other_thread_ptr = g_root->Alloc(kMediumSize, "");
     g_root->Free(other_thread_ptr);
     // |other_thread_ptr| is now in the thread cache.
   })};
@@ -238,22 +256,23 @@
   PlatformThread::Create(0, &delegate, &thread_handle);
   PlatformThread::Join(thread_handle);
 
-  void* this_thread_ptr = g_root->Alloc(kTestSize, "");
+  void* this_thread_ptr = g_root->Alloc(kMediumSize, "");
   // |other_thread_ptr| was returned to the central allocator, and is returned
-  // |here, as is comes from the freelist.
+  // here, as it comes from the freelist.
   EXPECT_EQ(this_thread_ptr, other_thread_ptr);
   g_root->Free(other_thread_ptr);
-  g_root->Free(tmp);
+
+  for (void* ptr : tmp)
+    g_root->Free(ptr);
 }
 
 TEST_F(ThreadCacheTest, ThreadCacheRegistry) {
-  const size_t kTestSize = 100;
   auto* parent_thread_tcache = g_root->thread_cache_for_testing();
   ASSERT_TRUE(parent_thread_tcache);
 
   LambdaThreadDelegate delegate{BindLambdaForTesting([&]() {
     EXPECT_FALSE(g_root->thread_cache_for_testing());  // No allocations yet.
-    FillThreadCacheAndReturnIndex(kTestSize);
+    FillThreadCacheAndReturnIndex(kSmallSize);
     auto* tcache = g_root->thread_cache_for_testing();
     EXPECT_TRUE(tcache);
 
@@ -273,7 +292,6 @@
 
 #if defined(PA_ENABLE_THREAD_CACHE_STATISTICS)
 TEST_F(ThreadCacheTest, RecordStats) {
-  const size_t kTestSize = 100;
   auto* tcache = g_root->thread_cache_for_testing();
   DeltaCounter alloc_counter{tcache->stats_.alloc_count};
   DeltaCounter alloc_hits_counter{tcache->stats_.alloc_hits};
@@ -286,7 +304,7 @@
   DeltaCounter cache_fill_misses_counter{tcache->stats_.cache_fill_misses};
 
   // Cache has been purged, first allocation is a miss.
-  void* data = g_root->Alloc(kTestSize, "");
+  void* data = g_root->Alloc(kMediumSize, "");
   EXPECT_EQ(1u, alloc_counter.Delta());
   EXPECT_EQ(1u, alloc_miss_counter.Delta());
   EXPECT_EQ(0u, alloc_hits_counter.Delta());
@@ -299,38 +317,36 @@
 
   tcache->Purge();
   cache_fill_counter.Reset();
-  constexpr size_t kMaxCountForBucket = 128;
   // Buckets are never full, fill always succeeds.
   size_t bucket_index =
-      FillThreadCacheAndReturnIndex(kTestSize, kMaxCountForBucket + 10);
-  EXPECT_EQ(kMaxCountForBucket + 10, cache_fill_counter.Delta());
+      FillThreadCacheAndReturnIndex(kMediumSize, kMaxCountForMediumBucket + 10);
+  EXPECT_EQ(kMaxCountForMediumBucket + 10, cache_fill_counter.Delta());
   EXPECT_EQ(0u, cache_fill_misses_counter.Delta());
 
   // Memory footprint.
   ThreadCacheStats stats;
   ThreadCacheRegistry::Instance().DumpStats(true, &stats);
   // Bucket was cleared (count halved, then refilled).
-  EXPECT_EQ(
-      g_root->buckets[bucket_index].slot_size * (kMaxCountForBucket / 2 + 10),
-      stats.bucket_total_memory);
+  EXPECT_EQ(g_root->buckets[bucket_index].slot_size *
+                (kMaxCountForMediumBucket / 2 + kFillCountForMediumBucket),
+            stats.bucket_total_memory);
   EXPECT_EQ(sizeof(ThreadCache), stats.metadata_overhead);
 }
 
 TEST_F(ThreadCacheTest, MultipleThreadCachesAccounting) {
-  const size_t kTestSize = 100;
-  void* data = g_root->Alloc(kTestSize, "");
-  g_root->Free(data);
+  FillThreadCacheAndReturnIndex(kMediumSize);
   uint64_t alloc_count = g_root->thread_cache_for_testing()->stats_.alloc_count;
 
   LambdaThreadDelegate delegate{BindLambdaForTesting([&]() {
     EXPECT_FALSE(g_root->thread_cache_for_testing());  // No allocations yet.
-    size_t bucket_index = FillThreadCacheAndReturnIndex(kTestSize);
+    size_t bucket_index = FillThreadCacheAndReturnIndex(kMediumSize);
 
     ThreadCacheStats stats;
     ThreadCacheRegistry::Instance().DumpStats(false, &stats);
     // 2* for this thread and the parent one.
-    EXPECT_EQ(2 * g_root->buckets[bucket_index].slot_size,
-              stats.bucket_total_memory);
+    EXPECT_EQ(
+        2 * g_root->buckets[bucket_index].slot_size * kFillCountForMediumBucket,
+        stats.bucket_total_memory);
     EXPECT_EQ(2 * sizeof(ThreadCache), stats.metadata_overhead);
 
     uint64_t this_thread_alloc_count =
@@ -349,14 +365,13 @@
   std::atomic<bool> other_thread_started{false};
   std::atomic<bool> purge_called{false};
 
-  const size_t kTestSize = 100;
-  size_t bucket_index = FillThreadCacheAndReturnIndex(kTestSize);
+  size_t bucket_index = FillThreadCacheAndReturnIndex(kSmallSize);
   ThreadCache* this_thread_tcache = g_root->thread_cache_for_testing();
   ThreadCache* other_thread_tcache = nullptr;
 
   LambdaThreadDelegate delegate{
       BindLambdaForTesting([&]() NO_THREAD_SAFETY_ANALYSIS {
-        FillThreadCacheAndReturnIndex(kTestSize);
+        FillThreadCacheAndReturnIndex(kSmallSize);
         other_thread_tcache = g_root->thread_cache_for_testing();
 
         other_thread_started.store(true, std::memory_order_release);
@@ -364,11 +379,11 @@
         }
 
         // Purge() was not triggered from the other thread.
-        EXPECT_EQ(1u,
+        EXPECT_EQ(kFillCountForSmallBucket,
                   other_thread_tcache->bucket_count_for_testing(bucket_index));
         // Allocations do not trigger Purge().
-        void* data = g_root->Alloc(1, "");
-        EXPECT_EQ(1u,
+        void* data = g_root->Alloc(kSmallSize, "");
+        EXPECT_EQ(kFillCountForSmallBucket - 1,
                   other_thread_tcache->bucket_count_for_testing(bucket_index));
         // But deallocations do.
         g_root->Free(data);
@@ -382,14 +397,17 @@
   while (!other_thread_started.load(std::memory_order_acquire)) {
   }
 
-  EXPECT_EQ(1u, this_thread_tcache->bucket_count_for_testing(bucket_index));
-  EXPECT_EQ(1u, other_thread_tcache->bucket_count_for_testing(bucket_index));
+  EXPECT_EQ(kFillCountForSmallBucket,
+            this_thread_tcache->bucket_count_for_testing(bucket_index));
+  EXPECT_EQ(kFillCountForSmallBucket,
+            other_thread_tcache->bucket_count_for_testing(bucket_index));
 
   ThreadCacheRegistry::Instance().PurgeAll();
   // This thread is synchronously purged.
   EXPECT_EQ(0u, this_thread_tcache->bucket_count_for_testing(bucket_index));
   // Not the other one.
-  EXPECT_EQ(1u, other_thread_tcache->bucket_count_for_testing(bucket_index));
+  EXPECT_EQ(kFillCountForSmallBucket,
+            other_thread_tcache->bucket_count_for_testing(bucket_index));
 
   purge_called.store(true, std::memory_order_release);
   PlatformThread::Join(thread_handle);
diff --git a/base/containers/flat_tree.h b/base/containers/flat_tree.h
index 22952d0..2cc9ad5c 100644
--- a/base/containers/flat_tree.h
+++ b/base/containers/flat_tree.h
@@ -254,9 +254,9 @@
 
   void clear();
 
-  size_type size() const;
-  size_type max_size() const;
-  bool empty() const;
+  constexpr size_type size() const;
+  constexpr size_type max_size() const;
+  constexpr bool empty() const;
 
   // --------------------------------------------------------------------------
   // Iterators.
@@ -681,19 +681,21 @@
 }
 
 template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
-auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::size() const
-    -> size_type {
+constexpr auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::size()
+    const -> size_type {
   return body_.size();
 }
 
 template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
-auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::max_size() const
+constexpr auto
+flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::max_size() const
     -> size_type {
   return body_.max_size();
 }
 
 template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
-bool flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::empty() const {
+constexpr bool flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::empty()
+    const {
   return body_.empty();
 }
 
diff --git a/base/ios/device_util.h b/base/ios/device_util.h
index b1bed5c..50bd13ad 100644
--- a/base/ios/device_util.h
+++ b/base/ios/device_util.h
@@ -74,6 +74,10 @@
 // something that should be anonymous, you should probably pass NULL.
 std::string GetDeviceIdentifier(const char* salt);
 
+// Returns the iOS Vendor ID for this device. Using this value can have privacy
+// implications.
+std::string GetVendorId();
+
 // Returns a hashed version of |in_string| using |salt| (which must not be
 // zero-length). Different salt values should result in differently hashed
 // strings.
diff --git a/base/ios/device_util.mm b/base/ios/device_util.mm
index e9c11110..06a8e85 100644
--- a/base/ios/device_util.mm
+++ b/base/ios/device_util.mm
@@ -157,6 +157,11 @@
                          salt ? salt : kDefaultSalt);
 }
 
+std::string GetVendorId() {
+  return base::SysNSStringToUTF8(
+      [[[UIDevice currentDevice] identifierForVendor] UUIDString]);
+}
+
 std::string GetSaltedString(const std::string& in_string,
                             const std::string& salt) {
   DCHECK(salt.length());
diff --git a/base/mac/mac_util.mm b/base/mac/mac_util.mm
index 727d45c..972e2dec 100644
--- a/base/mac/mac_util.mm
+++ b/base/mac/mac_util.mm
@@ -5,6 +5,7 @@
 #include "base/mac/mac_util.h"
 
 #import <Cocoa/Cocoa.h>
+#include <CoreServices/CoreServices.h>
 #import <IOKit/IOKitLib.h>
 #include <errno.h>
 #include <stddef.h>
@@ -31,46 +32,64 @@
 
 namespace {
 
-// Looks into Shared File Lists corresponding to Login Items for the item
-// representing the current application.  If such an item is found, returns a
-// retained reference to it. Caller is responsible for releasing the reference.
-LSSharedFileListItemRef GetLoginItemForApp() {
-  ScopedCFTypeRef<LSSharedFileListRef> login_items(LSSharedFileListCreate(
-      NULL, kLSSharedFileListSessionLoginItems, NULL));
+class LoginItemsFileList {
+ public:
+  LoginItemsFileList() = default;
+  LoginItemsFileList(const LoginItemsFileList&) = delete;
+  LoginItemsFileList& operator=(const LoginItemsFileList&) = delete;
+  ~LoginItemsFileList() = default;
 
-  if (!login_items.get()) {
-    DLOG(ERROR) << "Couldn't get a Login Items list.";
-    return NULL;
+  bool Initialize() WARN_UNUSED_RESULT {
+    DCHECK(!login_items_.get()) << __func__ << " called more than once.";
+    login_items_.reset(LSSharedFileListCreate(
+        nullptr, kLSSharedFileListSessionLoginItems, nullptr));
+    DLOG_IF(ERROR, !login_items_.get()) << "Couldn't get a Login Items list.";
+    return login_items_.get();
   }
 
-  base::scoped_nsobject<NSArray> login_items_array(
-      CFToNSCast(LSSharedFileListCopySnapshot(login_items, NULL)));
+  LSSharedFileListRef GetLoginFileList() {
+    DCHECK(login_items_.get()) << "Initialize() failed or not called.";
+    return login_items_;
+  }
 
-  NSURL* url = [NSURL fileURLWithPath:[base::mac::MainBundle() bundlePath]];
+  // Looks into Shared File Lists corresponding to Login Items for the item
+  // representing the specified bundle.  If such an item is found, returns a
+  // retained reference to it. Caller is responsible for releasing the
+  // reference.
+  ScopedCFTypeRef<LSSharedFileListItemRef> GetLoginItemForApp() {
+    DCHECK(login_items_.get()) << "Initialize() failed or not called.";
 
-  for(NSUInteger i = 0; i < [login_items_array count]; ++i) {
-    LSSharedFileListItemRef item =
-        reinterpret_cast<LSSharedFileListItemRef>(login_items_array[i]);
-    base::ScopedCFTypeRef<CFErrorRef> error;
-    CFURLRef item_url_ref =
-        LSSharedFileListItemCopyResolvedURL(item, 0, error.InitializeInto());
+    NSURL* url = [NSURL fileURLWithPath:[base::mac::MainBundle() bundlePath]];
 
-    // This function previously used LSSharedFileListItemResolve(), which could
-    // return a NULL URL even when returning no error. This caused
-    // <https://crbug.com/760989>. It's not clear one way or the other whether
-    // LSSharedFileListItemCopyResolvedURL() shares this behavior, so this check
-    // remains in place.
-    if (!error && item_url_ref) {
-      ScopedCFTypeRef<CFURLRef> item_url(item_url_ref);
-      if (CFEqual(item_url, url)) {
-        CFRetain(item);
-        return item;
+    base::scoped_nsobject<NSArray> login_items_array(
+        CFToNSCast(LSSharedFileListCopySnapshot(login_items_, nullptr)));
+
+    for (id login_item in login_items_array.get()) {
+      LSSharedFileListItemRef item =
+          reinterpret_cast<LSSharedFileListItemRef>(login_item);
+      base::ScopedCFTypeRef<CFErrorRef> error;
+      ScopedCFTypeRef<CFURLRef> item_url(
+          LSSharedFileListItemCopyResolvedURL(item, 0, error.InitializeInto()));
+
+      // This function previously used LSSharedFileListItemResolve(), which
+      // could return a NULL URL even when returning no error. This caused
+      // <https://crbug.com/760989>. It's not clear one way or the other whether
+      // LSSharedFileListItemCopyResolvedURL() shares this behavior, so this
+      // check remains in place.
+      if (!error && item_url) {
+        if (CFEqual(item_url, url)) {
+          return ScopedCFTypeRef<LSSharedFileListItemRef>(
+              item, base::scoped_policy::RETAIN);
+        }
       }
     }
+
+    return ScopedCFTypeRef<LSSharedFileListItemRef>();
   }
 
-  return NULL;
-}
+ private:
+  ScopedCFTypeRef<LSSharedFileListRef> login_items_;
+};
 
 bool IsHiddenLoginItem(LSSharedFileListItemRef item) {
   ScopedCFTypeRef<CFBooleanRef> hidden(reinterpret_cast<CFBooleanRef>(
@@ -143,7 +162,12 @@
 }
 
 bool CheckLoginItemStatus(bool* is_hidden) {
-  ScopedCFTypeRef<LSSharedFileListItemRef> item(GetLoginItemForApp());
+  LoginItemsFileList login_items;
+  if (!login_items.Initialize())
+    return false;
+
+  base::ScopedCFTypeRef<LSSharedFileListItemRef> item(
+      login_items.GetLoginItemForApp());
   if (!item.get())
     return false;
 
@@ -154,22 +178,20 @@
 }
 
 void AddToLoginItems(bool hide_on_startup) {
-  ScopedCFTypeRef<LSSharedFileListItemRef> item(GetLoginItemForApp());
+  LoginItemsFileList login_items;
+  if (!login_items.Initialize())
+    return;
+
+  base::ScopedCFTypeRef<LSSharedFileListItemRef> item(
+      login_items.GetLoginItemForApp());
+
   if (item.get() && (IsHiddenLoginItem(item) == hide_on_startup)) {
     return;  // Already is a login item with required hide flag.
   }
 
-  ScopedCFTypeRef<LSSharedFileListRef> login_items(LSSharedFileListCreate(
-      NULL, kLSSharedFileListSessionLoginItems, NULL));
-
-  if (!login_items.get()) {
-    DLOG(ERROR) << "Couldn't get a Login Items list.";
-    return;
-  }
-
   // Remove the old item, it has wrong hide flag, we'll create a new one.
   if (item.get()) {
-    LSSharedFileListItemRemove(login_items, item);
+    LSSharedFileListItemRemove(login_items.GetLoginFileList(), item);
   }
 
   NSURL* url = [NSURL fileURLWithPath:[base::mac::MainBundle() bundlePath]];
@@ -180,7 +202,7 @@
 
   ScopedCFTypeRef<LSSharedFileListItemRef> new_item;
   new_item.reset(LSSharedFileListInsertItemURL(
-      login_items, kLSSharedFileListItemLast, NULL, NULL,
+      login_items.GetLoginFileList(), kLSSharedFileListItemLast, NULL, NULL,
       reinterpret_cast<CFURLRef>(url),
       reinterpret_cast<CFDictionaryRef>(properties), NULL));
 
@@ -190,19 +212,16 @@
 }
 
 void RemoveFromLoginItems() {
-  ScopedCFTypeRef<LSSharedFileListItemRef> item(GetLoginItemForApp());
+  LoginItemsFileList login_items;
+  if (!login_items.Initialize())
+    return;
+
+  base::ScopedCFTypeRef<LSSharedFileListItemRef> item(
+      login_items.GetLoginItemForApp());
   if (!item.get())
     return;
 
-  ScopedCFTypeRef<LSSharedFileListRef> login_items(LSSharedFileListCreate(
-      NULL, kLSSharedFileListSessionLoginItems, NULL));
-
-  if (!login_items.get()) {
-    DLOG(ERROR) << "Couldn't get a Login Items list.";
-    return;
-  }
-
-  LSSharedFileListItemRemove(login_items, item);
+  LSSharedFileListItemRemove(login_items.GetLoginFileList(), item);
 }
 
 bool WasLaunchedAsLoginOrResumeItem() {
@@ -257,7 +276,12 @@
   if (!WasLaunchedAsLoginOrResumeItem())
     return false;
 
-  ScopedCFTypeRef<LSSharedFileListItemRef> item(GetLoginItemForApp());
+  LoginItemsFileList login_items;
+  if (!login_items.Initialize())
+    return false;
+
+  base::ScopedCFTypeRef<LSSharedFileListItemRef> item(
+      login_items.GetLoginItemForApp());
   if (!item.get()) {
     // OS X can launch items for the resume feature.
     return false;
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java b/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java
index c044cb4..b5d780e 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java
@@ -5,6 +5,7 @@
 package org.chromium.base.test.util;
 
 import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
 import android.provider.Settings;
@@ -48,11 +49,10 @@
                 activity.finish();
             }
         });
+        final String error = "Failed to finish the Activity. Did you start a second Activity and "
+                + "not finish it?";
         try {
-            waitForActivityState(
-                    "Failed to finish the Activity. Did you start a second Activity and not finish"
-                            + " it?",
-                    activity, Stage.DESTROYED);
+            waitForActivityState(error, activity, Stage.DESTROYED);
         } catch (Throwable e) {
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) throw e;
 
@@ -61,13 +61,22 @@
             Intent intent = new Intent(Settings.ACTION_SETTINGS);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             activity.startActivity(intent);
-            waitForActivityState(
-                    "Failed to finish the Activity. Did you start a second Activity and not finish"
-                            + " it?",
-                    activity, Stage.DESTROYED);
+            try {
+                waitForActivityState(error, activity, Stage.DESTROYED);
+            } finally {
+                // We can't finish com.android.settings, so return to launcher instead.
+                fireHomescreenIntent(activity);
+            }
         }
     }
 
+    private static void fireHomescreenIntent(Context context) {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_HOME);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(intent);
+    }
+
     /**
      * Recreates the provided Activity, returning the newly created Activity once it's finished
      * starting up.
diff --git a/base/threading/hang_watcher.cc b/base/threading/hang_watcher.cc
index 9ee8d1f..8306ad3d 100644
--- a/base/threading/hang_watcher.cc
+++ b/base/threading/hang_watcher.cc
@@ -41,7 +41,8 @@
 constexpr base::FeatureParam<int> kThreadPoolLogLevel{
     &HangWatcher::kEnableHangWatcher, "threadpool_log_level", 0};
 
-constexpr auto HangWatchScopeEnabled::kDefaultHangWatchTime =
+// static
+const base::TimeDelta HangWatchScopeEnabled::kDefaultHangWatchTime =
     base::TimeDelta::FromSeconds(10);
 
 namespace {
diff --git a/build/android/OWNERS b/build/android/OWNERS
index a10904e8..0b64bda0 100644
--- a/build/android/OWNERS
+++ b/build/android/OWNERS
@@ -1,3 +1,4 @@
+bjoyce@chromium.org
 jbudorick@chromium.org
 mheikal@chromium.org
 pasko@chromium.org
diff --git a/build/android/bytecode/java/org/chromium/bytecode/FragmentActivityReplacer.java b/build/android/bytecode/java/org/chromium/bytecode/FragmentActivityReplacer.java
index 565ebe6..bfe94223 100644
--- a/build/android/bytecode/java/org/chromium/bytecode/FragmentActivityReplacer.java
+++ b/build/android/bytecode/java/org/chromium/bytecode/FragmentActivityReplacer.java
@@ -21,6 +21,7 @@
  */
 public class FragmentActivityReplacer extends ByteCodeRewriter {
     private static final String GET_ACTIVITY_METHOD_NAME = "getActivity";
+    private static final String GET_LIFECYCLE_ACTIVITY_METHOD_NAME = "getLifecycleActivity";
     private static final String NEW_METHOD_DESCRIPTOR = "()Landroid/app/Activity;";
     private static final String OLD_METHOD_DESCRIPTOR =
             "()Landroidx/fragment/app/FragmentActivity;";
@@ -44,16 +45,23 @@
 
     @Override
     protected ClassVisitor getClassVisitorForClass(String classPath, ClassVisitor delegate) {
-        ClassVisitor getActivityReplacer = new GetActivityReplacer(delegate);
-        if (classPath.equals("androidx/fragment/app/Fragment.class")) {
-            return new FragmentClassVisitor(getActivityReplacer);
+        ClassVisitor invocationVisitor = new InvocationReplacer(delegate);
+        switch (classPath) {
+            case "androidx/fragment/app/Fragment.class":
+                return new FragmentClassVisitor(invocationVisitor);
+            case "com/google/android/gms/common/api/internal/SupportLifecycleFragmentImpl.class":
+                return new SupportLifecycleFragmentImplClassVisitor(invocationVisitor);
+            default:
+                return invocationVisitor;
         }
-        return getActivityReplacer;
     }
 
-    /** Updates any Fragment.getActivity/requireActivity() calls to call the replaced method. */
-    private static class GetActivityReplacer extends ClassVisitor {
-        private GetActivityReplacer(ClassVisitor baseVisitor) {
+    /**
+     * Updates any Fragment.getActivity/requireActivity() or getLifecycleActivity() calls to call
+     * the replaced method.
+     */
+    private static class InvocationReplacer extends ClassVisitor {
+        private InvocationReplacer(ClassVisitor baseVisitor) {
             super(Opcodes.ASM7, baseVisitor);
         }
 
@@ -68,7 +76,8 @@
                     if ((opcode == Opcodes.INVOKEVIRTUAL || opcode == Opcodes.INVOKESPECIAL)
                             && descriptor.equals(OLD_METHOD_DESCRIPTOR)
                             && (name.equals(GET_ACTIVITY_METHOD_NAME)
-                                    || name.equals(REQUIRE_ACTIVITY_METHOD_NAME))) {
+                                    || name.equals(REQUIRE_ACTIVITY_METHOD_NAME)
+                                    || name.equals(GET_LIFECYCLE_ACTIVITY_METHOD_NAME))) {
                         super.visitMethodInsn(
                                 opcode, owner, name, NEW_METHOD_DESCRIPTOR, isInterface);
                     } else {
@@ -92,16 +101,17 @@
                 int access, String name, String descriptor, String signature, String[] exceptions) {
             // Update the descriptor of getActivity() and requireActivity().
             MethodVisitor baseVisitor;
-            if (name.equals(GET_ACTIVITY_METHOD_NAME)
-                    || name.equals(REQUIRE_ACTIVITY_METHOD_NAME)) {
-                baseVisitor = super.visitMethod(
-                        access & ~Opcodes.ACC_FINAL, name, NEW_METHOD_DESCRIPTOR, null, exceptions);
+            if (descriptor.equals(OLD_METHOD_DESCRIPTOR)
+                    && (name.equals(GET_ACTIVITY_METHOD_NAME)
+                            || name.equals(REQUIRE_ACTIVITY_METHOD_NAME))) {
+                baseVisitor =
+                        super.visitMethod(access, name, NEW_METHOD_DESCRIPTOR, null, exceptions);
             } else {
                 baseVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
             }
 
             // Replace getActivity() with `return ContextUtils.activityFromContext(getContext());`
-            if (name.equals(GET_ACTIVITY_METHOD_NAME)) {
+            if (name.equals(GET_ACTIVITY_METHOD_NAME) && descriptor.equals(OLD_METHOD_DESCRIPTOR)) {
                 baseVisitor.visitVarInsn(Opcodes.ALOAD, 0);
                 baseVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "androidx/fragment/app/Fragment",
                         "getContext", "()Landroid/content/Context;", false);
@@ -123,4 +133,34 @@
             });
         }
     }
+
+    /**
+     * Update SupportLifecycleFragmentImpl.getLifecycleActivity().
+     */
+    private static class SupportLifecycleFragmentImplClassVisitor extends ClassVisitor {
+        private SupportLifecycleFragmentImplClassVisitor(ClassVisitor baseVisitor) {
+            super(Opcodes.ASM7, baseVisitor);
+        }
+
+        @Override
+        public MethodVisitor visitMethod(
+                int access, String name, String descriptor, String signature, String[] exceptions) {
+            // SupportLifecycleFragmentImpl has two getActivity methods:
+            //   1. public FragmentActivity getLifecycleActivity():
+            //      This is what you'll see in the source. This delegates to Fragment.getActivity().
+            //   2. public Activity getLifecycleActivity():
+            //      This is generated because the class implements LifecycleFragment, which
+            //      declares this method, and delegates to #1.
+            //
+            // Here we change the return type of #1 and delete #2.
+            if (name.equals(GET_LIFECYCLE_ACTIVITY_METHOD_NAME)) {
+                if (descriptor.equals(OLD_METHOD_DESCRIPTOR)) {
+                    return super.visitMethod(
+                            access, name, NEW_METHOD_DESCRIPTOR, signature, exceptions);
+                }
+                return null;
+            }
+            return super.visitMethod(access, name, descriptor, signature, exceptions);
+        }
+    }
 }
diff --git a/build/android/gyp/compile_java.py b/build/android/gyp/compile_java.py
index 215231f3..8043e228 100755
--- a/build/android/gyp/compile_java.py
+++ b/build/android/gyp/compile_java.py
@@ -245,16 +245,6 @@
   return '\n'.join(lines)
 
 
-def CheckErrorproneStderrWarning(jar_path, expected_warning_regex,
-                                 javac_output):
-  if not re.search(expected_warning_regex, javac_output):
-    raise Exception('Expected `{}` warning when compiling `{}`'.format(
-        expected_warning_regex, os.path.basename(jar_path)))
-
-  # Do not print warning
-  return ''
-
-
 def _ParsePackageAndClassNames(java_file):
   package_name = ''
   class_names = []
@@ -502,22 +492,12 @@
         f.write(' '.join(java_files))
       cmd += ['@' + java_files_rsp_path]
 
-
-      # |errorprone_expected_warning_regex| is used in tests for errorprone
-      # warnings. Fail compile if expected warning is not present.
-      stderr_filter = ProcessJavacOutput
-      if (options.enable_errorprone
-          and options.errorprone_expected_warning_regex):
-        stderr_filter = functools.partial(
-            CheckErrorproneStderrWarning, options.jar_path,
-            options.errorprone_expected_warning_regex)
-
       logging.debug('Build command %s', cmd)
       start = time.time()
       build_utils.CheckOutput(cmd,
                               print_stdout=options.chromium_code,
                               stdout_filter=ProcessJavacOutput,
-                              stderr_filter=stderr_filter,
+                              stderr_filter=ProcessJavacOutput,
                               fail_on_output=options.warnings_as_errors)
       end = time.time() - start
       logging.info('Java compilation took %ss', end)
@@ -602,10 +582,6 @@
       action='store_true',
       help='Enable errorprone checks')
   parser.add_option(
-      '--errorprone-expected-warning-regex',
-      help='When set, throws an exception if the errorprone compile does not '
-      'log a warning which matches the regex.')
-  parser.add_option(
       '--warnings-as-errors',
       action='store_true',
       help='Treat all warnings as errors.')
diff --git a/build/android/gyp/nocompile_test.py b/build/android/gyp/nocompile_test.py
new file mode 100644
index 0000000..fdf069c
--- /dev/null
+++ b/build/android/gyp/nocompile_test.py
@@ -0,0 +1,153 @@
+# 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.
+"""Checks that compiling targets in BUILD.gn file fails."""
+
+import argparse
+import json
+import os
+import subprocess
+import sys
+from util import build_utils
+
+_CHROMIUM_SRC = os.path.normpath(os.path.join(__file__, '..', '..', '..', '..'))
+_NINJA_PATH = os.path.join(_CHROMIUM_SRC, 'third_party', 'depot_tools', 'ninja')
+
+# Relative to _CHROMIUM_SRC
+_GN_SRC_REL_PATH = os.path.join('third_party', 'depot_tools', 'gn')
+
+
+def _raise_command_exception(args, returncode, output):
+  """Raises an exception whose message describes a command failure.
+
+    Args:
+      args: shell command-line (as passed to subprocess.Popen())
+      returncode: status code.
+      output: command output.
+    Raises:
+      a new Exception.
+    """
+  message = 'Command failed with status {}: {}\n' \
+      'Output:-----------------------------------------\n{}\n' \
+      '------------------------------------------------\n'.format(
+          returncode, args, output)
+  raise Exception(message)
+
+
+def _run_command(args, cwd=None):
+  """Runs shell command. Raises exception if command fails."""
+  p = subprocess.Popen(args,
+                       stdout=subprocess.PIPE,
+                       stderr=subprocess.STDOUT,
+                       cwd=cwd)
+  pout, _ = p.communicate()
+  if p.returncode != 0:
+    _raise_command_exception(args, p.returncode, pout)
+
+
+def _run_command_get_output(args, success_output):
+  """Runs shell command and returns command output."""
+  p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+  pout, _ = p.communicate()
+  if p.returncode == 0:
+    return success_output
+
+  # For Python3 only:
+  if isinstance(pout, bytes) and sys.version_info >= (3, ):
+    pout = pout.decode('utf-8')
+  return pout
+
+
+def _copy_and_append_gn_args(src_args_path, dest_args_path, extra_args):
+  """Copies args.gn.
+
+    Args:
+      src_args_path: args.gn file to copy.
+      dest_args_path: Copy file destination.
+      extra_args: Text to append to args.gn after copy.
+    """
+  with open(src_args_path) as f_in, open(dest_args_path, 'w') as f_out:
+    f_out.write(f_in.read())
+    f_out.write('\n')
+    f_out.write('\n'.join(extra_args))
+
+
+def _find_lines_after_prefix(text, prefix, num_lines):
+  """Searches |text| for a line which starts with |prefix|.
+
+  Args:
+    text: String to search in.
+    prefix: Prefix to search for.
+    num_lines: Number of lines, starting with line with prefix, to return.
+  Returns:
+    Matched lines. Returns None otherwise.
+  """
+  lines = text.split('\n')
+  for i, line in enumerate(lines):
+    if line.startswith(prefix):
+      return '\n'.join(lines[i:i + num_lines])
+  return None
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--gn-args-path',
+                      required=True,
+                      help='Path to args.gn file.')
+  parser.add_argument('--test-configs-path',
+                      required=True,
+                      help='Path to file with test configurations')
+  parser.add_argument('--out-dir',
+                      required=True,
+                      help='Path to output directory to use for compilation.')
+  parser.add_argument('--stamp', help='Path to touch.')
+  options = parser.parse_args()
+
+  with open(options.test_configs_path) as f:
+    test_configs = json.loads(f.read())
+
+  if not os.path.exists(options.out_dir):
+    os.makedirs(options.out_dir)
+
+  out_gn_args_path = os.path.join(options.out_dir, 'args.gn')
+  extra_gn_args = [
+      'enable_android_nocompile_tests = true', 'treat_warnings_as_errors = true'
+  ]
+  _copy_and_append_gn_args(options.gn_args_path, out_gn_args_path,
+                           extra_gn_args)
+
+  # As all of the test targets are declared in the same BUILD.gn file, it does
+  # not matter which test target is used as the root target.
+  gn_args = [
+      _GN_SRC_REL_PATH, '--root-target=' + test_configs[0]['target'], 'gen',
+      os.path.relpath(options.out_dir, _CHROMIUM_SRC)
+  ]
+  _run_command(gn_args, cwd=_CHROMIUM_SRC)
+
+  error_messages = []
+  for config in test_configs:
+    # Strip leading '//'
+    gn_path = config['target'][2:]
+    expectation = config['expect']
+    ninja_args = [_NINJA_PATH, '-C', options.out_dir, gn_path]
+
+    # Purpose of quotes at beginning of message is to make it clear that
+    # "Compile successful." is not a compiler log message.
+    test_output = _run_command_get_output(ninja_args, '""\nCompile successful.')
+
+    failure_message = _find_lines_after_prefix(test_output, 'FAILED:', 5)
+    if not failure_message or expectation not in failure_message:
+      error_message = '//{} failed.\nExpected compile output:\n'\
+          '{}\nActual compile output:\n{}'.format(
+              gn_path, expectation, test_output)
+      error_messages.append(error_message)
+
+  if error_messages:
+    raise Exception('\n'.join(error_messages))
+
+  if options.stamp:
+    build_utils.Touch(options.stamp)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/build/android/pylib/base/result_sink.py b/build/android/pylib/base/result_sink.py
index 4aafedde2..70a6d29 100644
--- a/build/android/pylib/base/result_sink.py
+++ b/build/android/pylib/base/result_sink.py
@@ -84,7 +84,7 @@
     if len(test_log) > report_check_size:
       test_log_formatted = ('<pre>' + test_log[:report_check_size] +
                             '...Full output in Artifact.</pre>')
-    else:
+    elif test_log:
       test_log_formatted = '<pre>' + test_log + '</pre>'
 
     tr = {
diff --git a/build/config/android/android_nocompile.gni b/build/config/android/android_nocompile.gni
new file mode 100644
index 0000000..d806d09
--- /dev/null
+++ b/build/config/android/android_nocompile.gni
@@ -0,0 +1,87 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+import("//build/config/python.gni")
+
+declare_args() {
+  # Used by tests to enable generating build files for GN targets which should
+  # not compile.
+  enable_android_nocompile_tests = false
+}
+
+# Defines a test suite which checks that the 'test targets' fail to compile. The
+# test suite runs 'gn gen' with a custom output directory and attempts to compile
+# each test target.
+#
+# All of the tests should be defined in the same dedicated BUILD.gn file in order
+# to minimize the number of targets that are processed by 'gn gen'.
+#
+# Variables
+#   tests: List of test configurations. A test configuration has the following
+#     keys:
+#     'target': The GN target which should not compile when
+#       enable_android_nocompile_tests=true The target should compile when
+#       enable_android_nocompile_tests=false.
+#     'expected_compile_output': Error message to test for when compile fails.
+#     'nocompile_sources': Source files which do not compile. This ensures that
+#       the test suite is re-run when one of these files change (as the test
+#       targets might not depend of the files when
+#       enable_android_nocompile_tests=false).
+template("android_nocompile_test_suite") {
+  assert(!enable_android_nocompile_tests)
+
+  python2_action(target_name) {
+    testonly = true
+    script = "//build/android/gyp/nocompile_test.py"
+
+    _tests = invoker.tests
+    _test0 = _tests[0]
+    _test0_dir = get_label_info(_test0["target"], "dir")
+    foreach(_test_config, _tests) {
+      assert(
+          _test0_dir == get_label_info(_test_config["target"], "dir"),
+          "To avoid running 'gn gen' for each test, all tests in an " +
+          "android_nocompile_test_suite() should be declared in same BUILD.gn file")
+    }
+
+    deps = []
+    if (defined(invoker.deps)) {
+      deps = invoker.deps
+    }
+
+    sources = []
+    _json_test_configs = []
+    foreach(_test_config, _tests) {
+      _test = _test_config["target"]
+      deps += [ _test ]
+      sources += _test_config["nocompile_sources"]
+      _dep_dir = get_label_info(_test, "dir")
+      _dep_name = get_label_info(_test, "name")
+      _json_test_configs += [
+        {
+          target = "${_dep_dir}:${_dep_name}"
+          expect = _test_config["expected_compile_output"]
+        },
+      ]
+    }
+
+    _config_path = "$target_gen_dir/${target_name}.nocompile_config"
+    write_file(_config_path, _json_test_configs, "json")
+
+    _stamp_path = "${target_gen_dir}/${target_name}.stamp"
+    args = [
+      "--gn-args-path",
+      "args.gn",
+      "--out-dir",
+      rebase_path("${target_out_dir}/${target_name}/nocompile_out",
+                  root_build_dir),
+      "--test-configs-path",
+      rebase_path(_config_path, root_build_dir),
+      "--stamp",
+      rebase_path(_stamp_path, root_build_dir),
+    ]
+    outputs = [ _stamp_path ]
+  }
+}
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index a4b528b..06adf7e 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -3239,8 +3239,7 @@
       }
       if (_chromium_code) {
         args += [ "--chromium-code=1" ]
-        if (treat_warnings_as_errors &&
-            !defined(invoker.errorprone_expected_warning_regex)) {
+        if (treat_warnings_as_errors) {
           args += [ "--warnings-as-errors" ]
         }
       }
@@ -3260,9 +3259,6 @@
           "--processorpath=@FileArg($_rebased_errorprone_buildconfig:deps_info:host_classpath)",
           "--enable-errorprone",
         ]
-        if (defined(invoker.errorprone_expected_warning_regex)) {
-          args += [ "--errorprone-expected-warning-regex=${invoker.errorprone_expected_warning_regex}" ]
-        }
       }
       foreach(e, _processor_args) {
         args += [ "--processor-arg=" + e ]
@@ -3369,8 +3365,6 @@
   #  java_files: Optional list of Java source file paths for this target.
   #  javac_args: Optional list of extra arguments to pass to javac.
   #  errorprone_args: Optional list of extra arguments to pass to.
-  #  errorprone_expected_warning_regex: When set, throws an exception if the
-  #    errorprone compile does not log a warning which matches the regex.
   #  srcjar_deps: Optional list of .srcjar targets (not file paths). The Java
   #    source files they contain will also be compiled for this target.
   #  java_sources_file: Optional path to a file which will be written with
@@ -3917,10 +3911,6 @@
             }
             javac_args += invoker.errorprone_args
           }
-          if (defined(invoker.errorprone_expected_warning_regex)) {
-            errorprone_expected_warning_regex =
-                invoker.errorprone_expected_warning_regex
-          }
           deps = [ ":$_header_target_name" ]
           header_jar_path = _final_ijar_path
           generated_jar_path = _generated_jar_path
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index a453337..14ff094 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1474,8 +1474,6 @@
   #
   #   javac_args: Additional arguments to pass to javac.
   #   errorprone_args: Additional arguments to pass to errorprone.
-  #   errorprone_expected_warning_regex: When set, throws an exception if the
-  #     errorprone compile does not log a warning which matches the regex.
   #
   #   data_deps, testonly
   #
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn
index 0473a8d..f90b331 100644
--- a/build/config/sanitizers/BUILD.gn
+++ b/build/config/sanitizers/BUILD.gn
@@ -271,22 +271,12 @@
   cflags = []
   if (is_asan) {
     cflags += [ "-fsanitize=address" ]
-    if (asan_use_blacklist) {
-      if (is_win) {
-        if (!defined(asan_win_blacklist_path)) {
-          asan_win_blacklist_path =
-              rebase_path("//tools/memory/asan/blacklist_win.txt",
-                          root_build_dir)
-        }
-        cflags += [ "-fsanitize-blacklist=$asan_win_blacklist_path" ]
-      } else {
-        # TODO(rnk): Remove this as discussed in http://crbug.com/427202.
-        if (!defined(asan_blacklist_path)) {
-          asan_blacklist_path =
-              rebase_path("//tools/memory/asan/blacklist.txt", root_build_dir)
-        }
-        cflags += [ "-fsanitize-blacklist=$asan_blacklist_path" ]
+    if (is_win) {
+      if (!defined(asan_win_blacklist_path)) {
+        asan_win_blacklist_path =
+            rebase_path("//tools/memory/asan/blocklist_win.txt", root_build_dir)
       }
+      cflags += [ "-fsanitize-blacklist=$asan_win_blacklist_path" ]
     }
   }
 }
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index 75664f7..bd42159 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -104,9 +104,6 @@
   #     trace-pc-guard,indirect-calls
   sanitizer_coverage_flags = ""
 
-  # Use blacklists from tools/memory/asan when compiling with asan.
-  asan_use_blacklist = true
-
   # When enabled, only relevant sanitizer defines are set, but compilation
   # happens with no extra flags. This is useful when in component build
   # enabling sanitizers only in some of the components.
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 8ad5cf81..f3e23d74 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20201201.0.1
+0.20201201.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 8ad5cf81..f3e23d74 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20201201.0.1
+0.20201201.2.1
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index 09bab25..d4268477 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -35,8 +35,7 @@
 # Allows different projects to specify their own suppression/ignore lists for
 # sanitizer tools.
 # asan_suppressions_file = "path/to/asan_suppressions.cc"
-# asan_blacklist_path = "path/to/asan/blacklist.txt"
-# asan_win_blacklist_path = "path/to/asan/blacklist_win.txt"
+# asan_win_blacklist_path = "path/to/asan/blocklist_win.txt"
 # lsan_suppressions_file = "path/to/lsan_suppressions.cc"
 # tsan_suppressions_file = "path/to/tsan_suppressions.cc"
 # tsan_blacklist_path = "path/to/tsan/ignores.txt"
diff --git a/cc/layers/content_layer_client.h b/cc/layers/content_layer_client.h
index e7643fc..25d1a337 100644
--- a/cc/layers/content_layer_client.h
+++ b/cc/layers/content_layer_client.h
@@ -22,7 +22,7 @@
   // layer this client paints, that the client is capable of painting via
   // paintContents(). Calling paintContents() will return a DisplayItemList
   // that is guaranteed valid only within this region.
-  virtual gfx::Rect PaintableRegion() = 0;
+  virtual gfx::Rect PaintableRegion() const = 0;
 
   // Paints the content area for the layer, typically dirty rects submitted
   // to the layer itself, into a DisplayItemList that it returns. The
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 2f6a867..563a07f 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -1442,73 +1442,8 @@
         raster_contents_scale_ / raster_device_scale_ / raster_source_scale_;
   }
 
-  // We rasterize at the maximum scale that will occur during the animation, if
-  // the maximum scale is known. However we want to avoid excessive memory use.
-  // If the scale is smaller than what we would choose otherwise, then it's
-  // always better off for us memory-wise. But otherwise, we don't choose a
-  // scale at which this layer's rastered content would become larger than the
-  // viewport.
-  if (draw_properties().screen_space_transform_is_animating) {
-    bool can_raster_at_maximum_scale = false;
-    bool should_raster_at_starting_scale = false;
-    CombinedAnimationScale animation_scales =
-        layer_tree_impl()->property_trees()->GetAnimationScales(
-            transform_tree_index(), layer_tree_impl());
-    float maximum_scale = animation_scales.maximum_animation_scale;
-    float starting_scale = animation_scales.starting_animation_scale;
-    if (maximum_scale != kNotScaled) {
-      gfx::Size bounds_at_maximum_scale =
-          gfx::ScaleToCeiledSize(raster_source_->GetSize(), maximum_scale);
-      int64_t maximum_area =
-          static_cast<int64_t>(bounds_at_maximum_scale.width()) *
-          static_cast<int64_t>(bounds_at_maximum_scale.height());
-      gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
-
-      // Use the square of the maximum viewport dimension direction, to
-      // compensate for viewports with different aspect ratios.
-      int64_t max_viewport_dimension =
-          std::max(static_cast<int64_t>(viewport.width()),
-                   static_cast<int64_t>(viewport.height()));
-      int64_t squared_viewport_area =
-          max_viewport_dimension * max_viewport_dimension;
-
-      if (maximum_area <= squared_viewport_area)
-        can_raster_at_maximum_scale = true;
-    }
-    if (starting_scale != kNotScaled && starting_scale > maximum_scale) {
-      gfx::Size bounds_at_starting_scale =
-          gfx::ScaleToCeiledSize(raster_source_->GetSize(), starting_scale);
-      int64_t start_area =
-          static_cast<int64_t>(bounds_at_starting_scale.width()) *
-          static_cast<int64_t>(bounds_at_starting_scale.height());
-      gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
-      int64_t viewport_area = static_cast<int64_t>(viewport.width()) *
-                              static_cast<int64_t>(viewport.height());
-      if (start_area <= viewport_area)
-        should_raster_at_starting_scale = true;
-    }
-
-    // Use the computed scales for the raster scale directly, do not try to use
-    // the ideal scale here. The current ideal scale may be way too large in the
-    // case of an animation with scale, and will be constantly changing.
-    float animation_desired_scale;
-    if (should_raster_at_starting_scale)
-      animation_desired_scale = starting_scale;
-    else if (can_raster_at_maximum_scale)
-      animation_desired_scale = maximum_scale;
-    else
-      animation_desired_scale = 1.f * ideal_page_scale_ * ideal_device_scale_;
-
-    if (HasWillChangeTransformHint()) {
-      // If we have a will-change: transform hint, do not shrink the content
-      // raster scale, otherwise we will end up throwing away larger tiles we
-      // may need again.
-      raster_contents_scale_ =
-          std::max(preserved_raster_contents_scale, animation_desired_scale);
-    } else {
-      raster_contents_scale_ = animation_desired_scale;
-    }
-  }
+  if (draw_properties().screen_space_transform_is_animating)
+    AdjustRasterScaleForTransformAnimation(preserved_raster_contents_scale);
 
   if (HasWillChangeTransformHint()) {
     raster_contents_scale_ =
@@ -1544,6 +1479,46 @@
   DCHECK_LE(low_res_raster_contents_scale_, MaximumContentsScale());
 }
 
+void PictureLayerImpl::AdjustRasterScaleForTransformAnimation(
+    float preserved_raster_contents_scale) {
+  DCHECK(draw_properties().screen_space_transform_is_animating);
+  CombinedAnimationScale animation_scales =
+      layer_tree_impl()->property_trees()->GetAnimationScales(
+          transform_tree_index(), layer_tree_impl());
+  float maximum_scale = animation_scales.maximum_animation_scale;
+  float starting_scale = animation_scales.starting_animation_scale;
+  // Adjust raster scale only if the animation scale is known.
+  if (maximum_scale == kNotScaled && starting_scale == kNotScaled)
+    return;
+
+  // We rasterize at the maximum scale that will occur during the animation.
+  raster_contents_scale_ = std::max(maximum_scale, starting_scale);
+  DCHECK_NE(raster_contents_scale_, kNotScaled);
+
+  // However we want to avoid excessive memory use. Choose a scale at which this
+  // layer's rastered content is not larger than the viewport.
+  gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
+  float max_viewport_dimension = std::max(viewport.width(), viewport.height());
+  DCHECK(max_viewport_dimension);
+  // Use square to compensate for viewports with different aspect ratios.
+  float squared_viewport_area = max_viewport_dimension * max_viewport_dimension;
+  gfx::Size bounds_at_maximum_scale =
+      gfx::ScaleToCeiledSize(raster_source_->GetSize(), raster_contents_scale_);
+  float maximum_area = static_cast<float>(bounds_at_maximum_scale.width()) *
+                       bounds_at_maximum_scale.height();
+  // Clamp the scale to make the rastered content not larger than the viewport.
+  if (UNLIKELY(maximum_area > squared_viewport_area))
+    raster_contents_scale_ /= std::sqrt(maximum_area / squared_viewport_area);
+
+  if (HasWillChangeTransformHint()) {
+    // If we have a will-change: transform hint, do not shrink the content
+    // raster scale, otherwise we will end up throwing away larger tiles we
+    // may need again.
+    raster_contents_scale_ =
+        std::max(preserved_raster_contents_scale, raster_contents_scale_);
+  }
+}
+
 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
     const std::vector<PictureLayerTiling*>& used_tilings) {
   DCHECK(layer_tree_impl()->IsActiveTree());
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index be63a23..a79a2441 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -177,6 +177,8 @@
   void AddLowResolutionTilingIfNeeded();
   bool ShouldAdjustRasterScale() const;
   void RecalculateRasterScales();
+  void AdjustRasterScaleForTransformAnimation(
+      float preserved_raster_contents_scale);
   float MinimumRasterContentsScaleForWillChangeTransform() const;
   // Returns false if raster translation is not applicable.
   bool CalculateRasterTranslation(gfx::Vector2dF& raster_translation) const;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 1995afc1..5f135b6 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -1088,7 +1088,7 @@
   float device_scale = 1.f;
   float page_scale = 1.f;
   float maximum_animation_scale = 1.f;
-  float starting_animation_scale = 0.f;
+  float starting_animation_scale = kNotScaled;
   bool animating_transform = true;
 
   ResetTilingsAndRasterScales();
@@ -1156,7 +1156,7 @@
   float device_scale = 1.f;
   float page_scale = 1.f;
   float maximum_animation_scale = 1.f;
-  float starting_animation_scale = 0.f;
+  float starting_animation_scale = kNotScaled;
   bool animating_transform = false;
 
   // Contents exactly fit on one tile at scale 1, no low res.
@@ -2746,8 +2746,8 @@
                                starting_animation_scale, animating_transform);
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f);
 
-  // Starting animation scale greater than maximum animation scale
-  // Bounds at starting scale within the viewport
+  // Starting animation scale greater than maximum animation scale.
+  // Bounds at starting scale within the viewport.
   animating_transform = true;
   starting_animation_scale = 5.f;
 
@@ -2763,15 +2763,15 @@
                                starting_animation_scale, animating_transform);
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f);
 
-  // Starting Animation scale greater than maximum animation scale
-  // Bounds at starting scale outisde the viewport
+  // Starting Animation scale greater than maximum animation scale.
+  // Bounds at starting scale outside the viewport.
   animating_transform = true;
   starting_animation_scale = 11.f;
 
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 3.f);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 10.f);
 }
 
 TEST_F(LegacySWPictureLayerImplTest, HighResTilingDuringAnimation) {
@@ -2785,7 +2785,7 @@
   float device_scale = 1.f;
   float page_scale = 1.f;
   float maximum_animation_scale = 1.f;
-  float starting_animation_scale = 0.f;
+  float starting_animation_scale = kNotScaled;
   bool animating_transform = false;
 
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f);
@@ -2819,17 +2819,16 @@
                                starting_animation_scale, animating_transform);
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 4.f);
 
-  // When animating with an unknown maximum animation scale factor, a new
-  // high-res tiling should be created at a source scale of 1.
+  // When animating with an unknown animation scale factors, a new high-res
+  // tiling should be created at the current contents scale.
   animating_transform = true;
   contents_scale = 2.f;
-  maximum_animation_scale = 0.f;
+  maximum_animation_scale = kNotScaled;
 
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(),
-                 page_scale * device_scale);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f);
 
   // Further changes to scale during the animation should not cause a new
   // high-res tiling to get created.
@@ -2838,8 +2837,7 @@
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(),
-                 page_scale * device_scale);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f);
 
   // Once we stop animating, a new high-res tiling should be created.
   animating_transform = false;
@@ -2852,8 +2850,8 @@
 
   // When animating with a maxmium animation scale factor that is so large
   // that the layer grows larger than the viewport at this scale, a new
-  // high-res tiling should get created at a source scale of 1, not at its
-  // maximum scale.
+  // high-res tiling should get created at a source scale that the rasterized
+  // layer will not be larger than the viewport, not at its maximum scale.
   animating_transform = true;
   contents_scale = 2.f;
   maximum_animation_scale = 11.f;
@@ -2861,8 +2859,7 @@
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(),
-                 page_scale * device_scale);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 10.f);
 
   // Once we stop animating, a new high-res tiling should be created.
   animating_transform = false;
@@ -2876,7 +2873,8 @@
   // When animating with a maxmium animation scale factor that is so large
   // that the layer grows larger than the viewport at this scale, and where
   // the intial source scale is < 1, a new high-res tiling should get created
-  // at source scale 1.
+  // at a source scale that the rasterized layer will not be larger than the
+  // viewport.
   animating_transform = true;
   contents_scale = 0.1f;
   maximum_animation_scale = 11.f;
@@ -2884,8 +2882,7 @@
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(),
-                 device_scale * page_scale);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 10.f);
 
   // Once we stop animating, a new high-res tiling should be created.
   animating_transform = false;
@@ -2898,7 +2895,8 @@
 
   // When animating toward a smaller scale, but that is still so large that the
   // layer grows larger than the viewport at this scale, a new high-res tiling
-  // should get created at source scale 1.
+  // should get created at a source scale that the rasterized layer is not
+  // larger than the viewport.
   animating_transform = true;
   contents_scale = 11.f;
   maximum_animation_scale = 11.f;
@@ -2906,8 +2904,7 @@
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(),
-                 device_scale * page_scale);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 10.f);
 
   // Once we stop animating, a new high-res tiling should be created.
   animating_transform = false;
@@ -2931,7 +2928,7 @@
   float device_scale = 1.f;
   float page_scale = 1.f;
   float maximum_animation_scale = 1.f;
-  float starting_animation_scale = 0.f;
+  float starting_animation_scale = kNotScaled;
   bool animating_transform = false;
 
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f);
@@ -2990,7 +2987,7 @@
   float device_scale = 1.f;
   float page_scale = 1.f;
   float maximum_animation_scale = 1.f;
-  float starting_animation_scale = 0.f;
+  float starting_animation_scale = kNotScaled;
   bool animating_transform = false;
 
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f);
@@ -3019,13 +3016,14 @@
   float device_scale = 1.f;
   float page_scale = 1.f;
   float maximum_animation_scale = 1.f;
-  float starting_animation_scale = 0.f;
+  float starting_animation_scale = kNotScaled;
   bool animating_transform = false;
 
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f);
 
   // The maximum animation scale exceeds the squared size of the maximum
-  // viewport dimension, so raster scale should fall back to 1.
+  // viewport dimension, so raster scale should be shrunk to make the
+  // rasterized layer not larger than the viewport.
   animating_transform = true;
   contents_scale = 2.f;
   maximum_animation_scale = 21.f;
@@ -3033,8 +3031,7 @@
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
                                maximum_animation_scale,
                                starting_animation_scale, animating_transform);
-  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(),
-                 page_scale * device_scale);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 20.f);
 }
 
 TEST_F(LegacySWPictureLayerImplTest, TilingSetRasterQueue) {
@@ -3480,7 +3477,7 @@
   float device_scale = 1.5f;
   float page_scale = 1.f;
   float maximum_animation_scale = 1.f;
-  float starting_animation_scale = 0.f;
+  float starting_animation_scale = kNotScaled;
   bool animating_transform = false;
 
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
@@ -3558,7 +3555,7 @@
   float device_scale = 1.5f;
   float page_scale = 1.f;
   float maximum_animation_scale = 1.f;
-  float starting_animation_scale = 0.f;
+  float starting_animation_scale = kNotScaled;
   bool animating_transform = false;
 
   SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
diff --git a/cc/metrics/frame_sorter.cc b/cc/metrics/frame_sorter.cc
index 3f5542f..71faf50d 100644
--- a/cc/metrics/frame_sorter.cc
+++ b/cc/metrics/frame_sorter.cc
@@ -114,7 +114,7 @@
   DCHECK(!pending_frames_.empty());
   size_t flushed_count = 0;
   while (!pending_frames_.empty()) {
-    const auto first = pending_frames_.front();
+    const auto& first = pending_frames_.front();
     auto& frame_state = frame_states_[first.frame_id];
     if (!frame_state.IsComplete())
       break;
diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc
index d67859f..d8fdfe9 100644
--- a/cc/test/fake_content_layer_client.cc
+++ b/cc/test/fake_content_layer_client.cc
@@ -31,7 +31,7 @@
 
 FakeContentLayerClient::~FakeContentLayerClient() = default;
 
-gfx::Rect FakeContentLayerClient::PaintableRegion() {
+gfx::Rect FakeContentLayerClient::PaintableRegion() const {
   CHECK(bounds_set_);
   return gfx::Rect(bounds_);
 }
diff --git a/cc/test/fake_content_layer_client.h b/cc/test/fake_content_layer_client.h
index 9b27b9d..811c940 100644
--- a/cc/test/fake_content_layer_client.h
+++ b/cc/test/fake_content_layer_client.h
@@ -42,7 +42,7 @@
   FakeContentLayerClient();
   ~FakeContentLayerClient() override;
 
-  gfx::Rect PaintableRegion() override;
+  gfx::Rect PaintableRegion() const override;
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override;
   bool FillsBoundsCompletely() const override;
 
diff --git a/cc/test/solid_color_content_layer_client.cc b/cc/test/solid_color_content_layer_client.cc
index 971de4c..9d9f5498 100644
--- a/cc/test/solid_color_content_layer_client.cc
+++ b/cc/test/solid_color_content_layer_client.cc
@@ -14,7 +14,7 @@
 
 namespace cc {
 
-gfx::Rect SolidColorContentLayerClient::PaintableRegion() {
+gfx::Rect SolidColorContentLayerClient::PaintableRegion() const {
   return gfx::Rect(size_);
 }
 
diff --git a/cc/test/solid_color_content_layer_client.h b/cc/test/solid_color_content_layer_client.h
index 4b2d4077..2a8cd5d 100644
--- a/cc/test/solid_color_content_layer_client.h
+++ b/cc/test/solid_color_content_layer_client.h
@@ -26,9 +26,8 @@
         border_size_(border_size),
         border_color_(border_color) {}
 
-  gfx::Rect PaintableRegion() override;
-
   // ContentLayerClient implementation.
+  gfx::Rect PaintableRegion() const override;
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override;
   bool FillsBoundsCompletely() const override;
 
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 63b1f71..c936a7c 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -59,7 +59,7 @@
 
   bool FillsBoundsCompletely() const override { return false; }
 
-  gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); }
+  gfx::Rect PaintableRegion() const override { return gfx::Rect(bounds_); }
 
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override {
     auto display_list = base::MakeRefCounted<DisplayItemList>();
@@ -192,7 +192,7 @@
 
   bool FillsBoundsCompletely() const override { return false; }
 
-  gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); }
+  gfx::Rect PaintableRegion() const override { return gfx::Rect(bounds_); }
 
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override {
     // Intentionally return a solid color, empty mask display list. This
@@ -441,7 +441,7 @@
       : bounds_(bounds), color_(color), vertical_(vertical) {}
   ~CheckerContentLayerClient() override = default;
   bool FillsBoundsCompletely() const override { return false; }
-  gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); }
+  gfx::Rect PaintableRegion() const override { return gfx::Rect(bounds_); }
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override {
     auto display_list = base::MakeRefCounted<DisplayItemList>();
     display_list->StartPaint();
@@ -488,7 +488,7 @@
       : bounds_(bounds) {}
   ~CircleContentLayerClient() override = default;
   bool FillsBoundsCompletely() const override { return false; }
-  gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); }
+  gfx::Rect PaintableRegion() const override { return gfx::Rect(bounds_); }
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override {
     auto display_list = base::MakeRefCounted<DisplayItemList>();
     display_list->StartPaint();
@@ -713,7 +713,7 @@
         new StaticPictureLayer(std::move(display_list)));
   }
 
-  gfx::Rect PaintableRegion() override { return gfx::Rect(bounds()); }
+  gfx::Rect PaintableRegion() const override { return gfx::Rect(bounds()); }
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override {
     return display_list_;
   }
diff --git a/cc/trees/layer_tree_host_pixeltest_tiles.cc b/cc/trees/layer_tree_host_pixeltest_tiles.cc
index 65911d4..a3f7a12b 100644
--- a/cc/trees/layer_tree_host_pixeltest_tiles.cc
+++ b/cc/trees/layer_tree_host_pixeltest_tiles.cc
@@ -71,7 +71,7 @@
   explicit BlueYellowClient(const gfx::Size& size)
       : size_(size), blue_top_(true) {}
 
-  gfx::Rect PaintableRegion() override { return gfx::Rect(size_); }
+  gfx::Rect PaintableRegion() const override { return gfx::Rect(size_); }
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override {
     auto display_list = base::MakeRefCounted<DisplayItemList>();
 
@@ -151,7 +151,7 @@
  public:
   explicit PrimaryColorClient(const gfx::Size& size) : size_(size) {}
 
-  gfx::Rect PaintableRegion() override { return gfx::Rect(size_); }
+  gfx::Rect PaintableRegion() const override { return gfx::Rect(size_); }
   scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override {
     // When painted, the DisplayItemList should produce blocks of red, green,
     // and blue to test primary color reproduction.
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index a569585..5741146 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -31,7 +31,6 @@
   "java/res/drawable-hdpi/bookmark_check_gray.png",
   "java/res/drawable-hdpi/bookmark_edit_active.png",
   "java/res/drawable-hdpi/bookmark_move_active.png",
-  "java/res/drawable-hdpi/breadcrumb_arrow.png",
   "java/res/drawable-hdpi/btn_bg_holo_active_normal.png",
   "java/res/drawable-hdpi/btn_bg_holo_active_pressed.png",
   "java/res/drawable-hdpi/btn_bg_holo_pressed.png",
@@ -170,7 +169,6 @@
   "java/res/drawable-mdpi/bookmark_check_gray.png",
   "java/res/drawable-mdpi/bookmark_edit_active.png",
   "java/res/drawable-mdpi/bookmark_move_active.png",
-  "java/res/drawable-mdpi/breadcrumb_arrow.png",
   "java/res/drawable-mdpi/btn_bg_holo_active_normal.png",
   "java/res/drawable-mdpi/btn_bg_holo_active_pressed.png",
   "java/res/drawable-mdpi/btn_bg_holo_pressed.png",
@@ -298,7 +296,6 @@
   "java/res/drawable-xhdpi/bookmark_check_gray.png",
   "java/res/drawable-xhdpi/bookmark_edit_active.png",
   "java/res/drawable-xhdpi/bookmark_move_active.png",
-  "java/res/drawable-xhdpi/breadcrumb_arrow.png",
   "java/res/drawable-xhdpi/btn_bg_holo_active_normal.png",
   "java/res/drawable-xhdpi/btn_bg_holo_active_pressed.png",
   "java/res/drawable-xhdpi/btn_bg_holo_pressed.png",
@@ -407,7 +404,6 @@
   "java/res/drawable-xxhdpi/bookmark_check_gray.png",
   "java/res/drawable-xxhdpi/bookmark_edit_active.png",
   "java/res/drawable-xxhdpi/bookmark_move_active.png",
-  "java/res/drawable-xxhdpi/breadcrumb_arrow.png",
   "java/res/drawable-xxhdpi/btn_close_white.png",
   "java/res/drawable-xxhdpi/btn_left.png",
   "java/res/drawable-xxhdpi/btn_mic.png",
@@ -512,7 +508,6 @@
   "java/res/drawable-xxxhdpi/bookmark_check_gray.png",
   "java/res/drawable-xxxhdpi/bookmark_edit_active.png",
   "java/res/drawable-xxxhdpi/bookmark_move_active.png",
-  "java/res/drawable-xxxhdpi/breadcrumb_arrow.png",
   "java/res/drawable-xxxhdpi/btn_close_white.png",
   "java/res/drawable-xxxhdpi/btn_left.png",
   "java/res/drawable-xxxhdpi/btn_mic.png",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java
index 1d4b3a45..23b0ae9 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java
@@ -50,11 +50,21 @@
             @NonNull String initialUrl, Map<String, String> parameters, String experimentIds,
             @Nullable String callerAccount, @Nullable String userName) {
         if (shouldStartTriggerScript(parameters)) {
-            if (TextUtils.isEmpty(parameters.get(PARAMETER_TRIGGER_SCRIPTS_BASE64))
+            if (!AutofillAssistantPreferencesUtil.isProactiveHelpSwitchOn()) {
+                // Opt-out users who have disabled the proactive help Chrome setting.
+                AutofillAssistantMetrics.recordLiteScriptStarted(
+                        webContents, LiteScriptStarted.LITE_SCRIPT_PROACTIVE_TRIGGERING_DISABLED);
+                return;
+            }
+            if ((!TextUtils.isEmpty(parameters.get(PARAMETER_TRIGGER_FIRST_TIME_USER))
+                        || !TextUtils.isEmpty(parameters.get(PARAMETER_REQUEST_TRIGGER_SCRIPT)))
                     && !UnifiedConsentServiceBridge.isUrlKeyedAnonymizedDataCollectionEnabled(
                             AutofillAssistantUiController.getProfile())) {
-                // Opt-out users who have disabled anonymous data collection, unless the trigger
-                // scripts are directly specified in base64 format.
+                // Proactive help that requires communicating with a remote endpoint is tied to the
+                // MSBB flag. Even though proactive help is toggled on, we need to stop if MSBB is
+                // off. The proactive help setting will appear disabled to the user.
+                AutofillAssistantMetrics.recordLiteScriptStarted(
+                        webContents, LiteScriptStarted.LITE_SCRIPT_PROACTIVE_TRIGGERING_DISABLED);
                 return;
             }
 
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTriggerScriptIntegrationTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTriggerScriptIntegrationTest.java
index 8ff3509f..93be77cc2 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTriggerScriptIntegrationTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTriggerScriptIntegrationTest.java
@@ -34,7 +34,6 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.chrome.autofill_assistant.R;
 import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto;
 import org.chromium.chrome.browser.autofill_assistant.proto.ChipIcon;
@@ -264,9 +263,11 @@
     @Test
     @MediumTest
     @Features.EnableFeatures(ChromeFeatureList.AUTOFILL_ASSISTANT_PROACTIVE_HELP)
+    // Disable translate to prevent the popup from covering part of the website.
+    @Features.DisableFeatures("Translate")
     public void elementCondition() throws Exception {
         SelectorProto.Builder touch_area_four = SelectorProto.newBuilder().addFilters(
-                SelectorProto.Filter.newBuilder().setCssSelector("#touch_area_four"));
+                SelectorProto.Filter.newBuilder().setCssSelector("#touch_area_one"));
         TriggerScriptProto.Builder buttonVisibleTriggerScript =
                 TriggerScriptProto.newBuilder()
                         .setTriggerCondition(TriggerScriptConditionProto.newBuilder().setSelector(
@@ -296,7 +297,7 @@
         onView(withId(R.id.progress_bar)).check(matches(not(isDisplayed())));
         onView(withId(R.id.step_progress_bar)).check(matches(isDisplayed()));
 
-        tapElement(mTestRule, "touch_area_four");
+        tapElement(mTestRule, "touch_area_one");
         waitUntilViewMatchesCondition(withText("Area invisible"), isCompletelyDisplayed());
         onView(withId(R.id.progress_bar)).check(matches(not(isDisplayed())));
         onView(withId(R.id.step_progress_bar)).check(matches(not(isDisplayed())));
@@ -357,7 +358,7 @@
     @Test
     @MediumTest
     @Features.EnableFeatures(ChromeFeatureList.AUTOFILL_ASSISTANT_PROACTIVE_HELP)
-    @DisabledTest(message = "https://crbug.com/1149965")
+    @Features.DisableFeatures(ChromeFeatureList.AUTOFILL_ASSISTANT_DISABLE_ONBOARDING_FLOW)
     public void transitionToRegularScriptWithoutOnboarding() throws Exception {
         TriggerScriptProto.Builder triggerScript =
                 TriggerScriptProto
@@ -365,7 +366,7 @@
                         /* no trigger condition */
                         .setUserInterface(createDefaultUI("Trigger script",
                                 /* bubbleMessage = */ "",
-                                /* withProgressBar = */ true)
+                                /* withProgressBar = */ false)
                                                   .setRegularScriptLoadingStatusMessage(
                                                           "Loading regular script"));
 
@@ -399,8 +400,6 @@
         onView(withText("Continue")).perform(click());
         waitUntilViewMatchesCondition(withText("Done"), isCompletelyDisplayed());
         onView(withText("Loading regular script")).check(matches(isDisplayed()));
-        onView(withId(R.id.progress_bar)).check(matches(not(isDisplayed())));
-        onView(withId(R.id.step_progress_bar)).check(matches(isDisplayed()));
     }
 
     @Test
@@ -419,7 +418,7 @@
                         /* no trigger condition */
                         .setUserInterface(createDefaultUI("Trigger script",
                                 /* bubbleMessage = */ "",
-                                /* withProgressBar = */ true));
+                                /* withProgressBar = */ false));
         GetTriggerScriptsResponseProto triggerScripts =
                 (GetTriggerScriptsResponseProto) GetTriggerScriptsResponseProto.newBuilder()
                         .addTriggerScripts(triggerScript)
@@ -483,4 +482,51 @@
         waitUntilViewMatchesCondition(withText("Done"), isCompletelyDisplayed());
         onView(withText("Loading regular script")).check(matches(isDisplayed()));
     }
+
+    @Test
+    @MediumTest
+    @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT_DISABLE_ONBOARDING_FLOW,
+            ChromeFeatureList.AUTOFILL_ASSISTANT_PROACTIVE_HELP})
+    public void
+    transitionToRegularScriptWithoutOnboardingWithDisableOnboardingFlowFeatureOn()
+            throws Exception {
+        TriggerScriptProto.Builder triggerScript =
+                TriggerScriptProto
+                        .newBuilder()
+                        /* no trigger condition */
+                        .setUserInterface(createDefaultUI("Trigger script",
+                                /* bubbleMessage = */ "",
+                                /* withProgressBar = */ false)
+                                                  .setRegularScriptLoadingStatusMessage(
+                                                          "Loading regular script"));
+        GetTriggerScriptsResponseProto triggerScripts =
+                (GetTriggerScriptsResponseProto) GetTriggerScriptsResponseProto.newBuilder()
+                        .addTriggerScripts(triggerScript)
+                        .build();
+
+        setupTriggerScripts(triggerScripts);
+        AutofillAssistantPreferencesUtil.setInitialPreferences(false);
+        startAutofillAssistantOnTab(TEST_PAGE);
+
+        waitUntilViewMatchesCondition(withText("Trigger script"), isCompletelyDisplayed());
+
+        ArrayList<ActionProto> list = new ArrayList<>();
+        list.add((ActionProto) ActionProto.newBuilder()
+                         .setPrompt(PromptProto.newBuilder().addChoices(
+                                 PromptProto.Choice.newBuilder().setChip(
+                                         ChipProto.newBuilder().setText("Done"))))
+                         .build());
+        AutofillAssistantTestScript script = new AutofillAssistantTestScript(
+                (SupportedScriptProto) SupportedScriptProto.newBuilder()
+                        .setPath(TEST_PAGE)
+                        .setPresentation(PresentationProto.newBuilder().setAutostart(true).setChip(
+                                ChipProto.newBuilder().setText("Done")))
+                        .build(),
+                list);
+        setupRegularScripts(script);
+
+        onView(withText("Continue")).perform(click());
+        waitUntilViewMatchesCondition(withText("Done"), isCompletelyDisplayed());
+        onView(withText("Loading regular script")).check(matches(isDisplayed()));
+    }
 }
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
index c1d6dd3..a8691fd 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
@@ -119,20 +119,12 @@
                 AutofillAssistantMetrics.recordLiteScriptStarted(
                         tab.getWebContents(), LiteScriptStarted.LITE_SCRIPT_INTENT_RECEIVED);
 
-                // For trigger scripts since M-88, there is a dedicated Chrome setting that can be
-                // used to forever opt-out.
-                if (arguments.requestsTriggerScript()
-                        && !AutofillAssistantPreferencesUtil.isProactiveHelpSwitchOn()) {
-                    // Opt out users who have disabled the proactive help Chrome setting.
-                    AutofillAssistantMetrics.recordLiteScriptStarted(tab.getWebContents(),
-                            LiteScriptStarted.LITE_SCRIPT_PROACTIVE_TRIGGERING_DISABLED);
-                    return;
-                }
-
                 // Legacy, remove as soon as possible. Trigger scripts before M-88 were tied to the
-                // regular autofill assistant Chrome setting.
+                // regular autofill assistant Chrome setting. Since M-88, they also respect the new
+                // proactive help setting.
                 if (arguments.containsTriggerScript()
-                        && !AutofillAssistantPreferencesUtil.isAutofillAssistantSwitchOn()) {
+                        && (!AutofillAssistantPreferencesUtil.isAutofillAssistantSwitchOn()
+                                || !AutofillAssistantPreferencesUtil.isProactiveHelpSwitchOn())) {
                     if (AutofillAssistantPreferencesUtil
                                     .isAutofillAssistantLiteScriptCancelThresholdReached()) {
                         AutofillAssistantMetrics.recordLiteScriptStarted(tab.getWebContents(),
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferencesUtil.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferencesUtil.java
index 2eb8fba..d5b8071 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferencesUtil.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferencesUtil.java
@@ -100,6 +100,10 @@
 
     /** Checks whether the Autofill Assistant onboarding screen should be shown. */
     static boolean getShowOnboarding() {
+        if (ChromeFeatureList.isEnabled(
+                    ChromeFeatureList.AUTOFILL_ASSISTANT_DISABLE_ONBOARDING_FLOW)) {
+            return false;
+        }
         return !isAutofillAssistantSwitchOn() || !isAutofillOnboardingAccepted();
     }
 
diff --git a/chrome/android/java/res/drawable-hdpi/breadcrumb_arrow.png b/chrome/android/java/res/drawable-hdpi/breadcrumb_arrow.png
deleted file mode 100644
index d627ca2..0000000
--- a/chrome/android/java/res/drawable-hdpi/breadcrumb_arrow.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/breadcrumb_arrow.png b/chrome/android/java/res/drawable-mdpi/breadcrumb_arrow.png
deleted file mode 100644
index e499ff5..0000000
--- a/chrome/android/java/res/drawable-mdpi/breadcrumb_arrow.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/breadcrumb_arrow.png b/chrome/android/java/res/drawable-xhdpi/breadcrumb_arrow.png
deleted file mode 100644
index 2155335a..0000000
--- a/chrome/android/java/res/drawable-xhdpi/breadcrumb_arrow.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/breadcrumb_arrow.png b/chrome/android/java/res/drawable-xxhdpi/breadcrumb_arrow.png
deleted file mode 100644
index 737a4a9..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/breadcrumb_arrow.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/breadcrumb_arrow.png b/chrome/android/java/res/drawable-xxxhdpi/breadcrumb_arrow.png
deleted file mode 100644
index 19f5c443..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/breadcrumb_arrow.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragment.java
index fae8e216..8c26a9e4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragment.java
@@ -157,15 +157,21 @@
                 UnifiedConsentServiceBridge.isUrlKeyedAnonymizedDataCollectionEnabled(
                         Profile.getLastUsedRegularProfile());
 
-        boolean proactive_toggle_enabled =
-                url_keyed_anonymized_data_collection_enabled && assistant_switch_on_or_missing;
         boolean proactive_help_on = SharedPreferencesManager.getInstance().readBoolean(
                 ChromePreferenceKeys.AUTOFILL_ASSISTANT_PROACTIVE_HELP, true);
+        boolean proactive_toggle_enabled;
+        boolean show_disclaimer;
+        if (ChromeFeatureList.isEnabled(
+                    ChromeFeatureList.AUTOFILL_ASSISTANT_DISABLE_PROACTIVE_HELP_TIED_TO_MSBB)) {
+            proactive_toggle_enabled = assistant_switch_on_or_missing;
+            show_disclaimer = false;
+        } else {
+            proactive_toggle_enabled =
+                    url_keyed_anonymized_data_collection_enabled && assistant_switch_on_or_missing;
+            show_disclaimer = !proactive_toggle_enabled && assistant_switch_on_or_missing;
+        }
         mProactiveHelpPreference.setEnabled(proactive_toggle_enabled);
         mProactiveHelpPreference.setChecked(proactive_toggle_enabled && proactive_help_on);
-
-        boolean show_disclaimer =
-                !url_keyed_anonymized_data_collection_enabled && assistant_switch_on_or_missing;
         mGoogleServicesSettingsLink.setVisible(show_disclaimer);
 
         mAssistantVoiceSearchEnabledPref.setChecked(mSharedPreferencesManager.readBoolean(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java
index 76c1cb1..a5fb27f7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java
@@ -30,7 +30,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        setStartIconDrawable(BookmarkUtils.getFolderIcon(getContext()));
+        setStartIconDrawable(BookmarkUtils.getFolderIcon(getContext(), BookmarkType.NORMAL));
     }
 
     // BookmarkRow implementation.
@@ -45,7 +45,7 @@
         BookmarkItem item = super.setBookmarkId(bookmarkId, location);
         mTitleView.setText(item.getTitle());
 
-        // Set description.
+        // Set description and icon.
         if (item.getId().getType() == BookmarkType.READING_LIST) {
             int unreadCount = mDelegate.getModel().getUnreadCount(bookmarkId);
             mDescriptionView.setText(unreadCount > 0
@@ -60,12 +60,16 @@
                                     R.plurals.bookmarks_count, childCount, childCount)
                             : getResources().getString(R.string.no_bookmarks));
         }
+
+        setStartIconDrawable(BookmarkUtils.getFolderIcon(getContext(), item.getId().getType()));
         return item;
     }
 
     @Override
     protected ColorStateList getDefaultStartIconTint() {
+        @BookmarkType
+        int type = (mBookmarkId == null) ? BookmarkType.NORMAL : mBookmarkId.getType();
         return AppCompatResources.getColorStateList(
-                getContext(), BookmarkUtils.getFolderIconTint());
+                getContext(), BookmarkUtils.getFolderIconTint(type));
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
index 08aa597..cd10a2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
@@ -30,6 +30,7 @@
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver;
 import org.chromium.components.bookmarks.BookmarkId;
+import org.chromium.components.bookmarks.BookmarkType;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectableItemView;
 
 import java.util.ArrayList;
@@ -365,7 +366,7 @@
 
             Drawable iconDrawable;
             if (entry.mType == FolderListEntry.TYPE_NORMAL) {
-                iconDrawable = BookmarkUtils.getFolderIcon(view.getContext());
+                iconDrawable = BookmarkUtils.getFolderIcon(view.getContext(), BookmarkType.NORMAL);
             } else {
                 // For new folder, start_icon is different.
                 VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
index 5fe23ca..2547f85 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
@@ -8,6 +8,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.provider.Browser;
 import android.text.TextUtils;
@@ -37,6 +38,7 @@
 import org.chromium.components.browser_ui.widget.TintedDrawable;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.ui.UiUtils;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.ui.base.PageTransition;
 
@@ -301,18 +303,25 @@
 
     /**
      * @param context {@link Context} used to retrieve the drawable.
-     * @return A {@link TintedDrawable} to use for displaying bookmark folders.
+     * @param type The bookmark type of the folder.
+     * @return A {@link Drawable} to use for displaying bookmark folders.
      */
-    public static TintedDrawable getFolderIcon(Context context) {
+    public static Drawable getFolderIcon(Context context, @BookmarkType int type) {
+        if (type == BookmarkType.READING_LIST) {
+            return UiUtils.getTintedDrawable(
+                    context, R.drawable.ic_reading_list_folder, getFolderIconTint(type));
+        }
         return TintedDrawable.constructTintedDrawable(
-                context, R.drawable.ic_folder_blue_24dp, getFolderIconTint());
+                context, R.drawable.ic_folder_blue_24dp, getFolderIconTint(type));
     }
 
     /**
+     * @param type The bookmark type.
      * @return The tint used on the bookmark folder icon.
      */
-    public static int getFolderIconTint() {
-        return R.color.default_icon_color_tint_list;
+    public static int getFolderIconTint(@BookmarkType int type) {
+        return (type == BookmarkType.READING_LIST) ? R.color.default_icon_color_blue
+                                                   : R.color.default_icon_color_tint_list;
     }
 
     private static void openUrl(Context context, String url, ComponentName componentName) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java
index 2d729767..6a1dc79 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java
@@ -11,6 +11,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.core.util.Pair;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -96,10 +97,15 @@
 
     // Build the model for a single item in the bookmark bottom sheet.
     private PropertyModel buildItemModel(BookmarkItem bookmarkItem) {
+        @BookmarkType
+        int type = bookmarkItem.getId().getType();
         PropertyModel model =
                 new PropertyModel.Builder(BookmarkBottomSheetItemProperties.ALL_KEYS)
                         .with(BookmarkBottomSheetItemProperties.TITLE, bookmarkItem.getTitle())
                         .with(BookmarkBottomSheetItemProperties.SUBTITLE, getSubtitle(bookmarkItem))
+                        .with(BookmarkBottomSheetItemProperties.ICON_DRAWABLE_AND_COLOR,
+                                new Pair<>(BookmarkUtils.getFolderIcon(mContext, type),
+                                        BookmarkUtils.getFolderIconTint(type)))
                         .with(BookmarkBottomSheetItemProperties.ON_CLICK_LISTENER,
                                 () -> onClick(bookmarkItem))
                         .build();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetFolderRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetFolderRow.java
index d2cb5d0..68b6757 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetFolderRow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetFolderRow.java
@@ -5,20 +5,26 @@
 package org.chromium.chrome.browser.bookmarks.bottomsheet;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 
+import androidx.annotation.ColorRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.appcompat.content.res.AppCompatResources;
+import androidx.core.util.Pair;
 
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.bookmarks.BookmarkRow;
-import org.chromium.chrome.browser.bookmarks.BookmarkUtils;
 
 /**
  * Represents a folder row in bookmark bottom sheet.
  */
 class BookmarkBottomSheetFolderRow extends BookmarkRow {
     private Runnable mOnClickListener;
+    private @ColorRes int mIconColor = R.color.default_icon_color_tint_list;
 
     /**
      * Constructor for inflating from XML.
@@ -35,6 +41,11 @@
         mDescriptionView.setText(subtitle == null ? "" : subtitle);
     }
 
+    void setIcon(Pair<Drawable, Integer> drawableAndColor) {
+        mIconColor = drawableAndColor.second;
+        setStartIconDrawable(drawableAndColor.first);
+    }
+
     void setOnClickListener(@NonNull Runnable listener) {
         mOnClickListener = listener;
     }
@@ -48,9 +59,6 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mMoreIcon.setVisibility(GONE);
-
-        // TODO(xingliu): Load the correct icon.
-        setStartIconDrawable(BookmarkUtils.getFolderIcon(getContext()));
     }
 
     // BookmarkRow overrides.
@@ -64,4 +72,9 @@
     public boolean onLongClick(View view) {
         return false;
     }
+
+    @Override
+    protected ColorStateList getDefaultStartIconTint() {
+        return AppCompatResources.getColorStateList(getContext(), mIconColor);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetItemProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetItemProperties.java
index 9b06bca..f8a5455 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetItemProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetItemProperties.java
@@ -4,7 +4,10 @@
 
 package org.chromium.chrome.browser.bookmarks.bottomsheet;
 
+import android.graphics.drawable.Drawable;
+
 import androidx.annotation.IntDef;
+import androidx.core.util.Pair;
 import androidx.recyclerview.widget.RecyclerView;
 
 import org.chromium.ui.modelutil.PropertyKey;
@@ -39,10 +42,19 @@
             new PropertyModel.ReadableObjectPropertyKey<>();
 
     /**
+     * The pair of {@link Drawable} and the color resource id(as Integer) of the bottom sheet item
+     * icon. e.g. A folder icon and its color resource id.
+     */
+    static final PropertyModel
+            .ReadableObjectPropertyKey<Pair<Drawable, Integer>> ICON_DRAWABLE_AND_COLOR =
+            new PropertyModel.ReadableObjectPropertyKey<>();
+
+    /**
      * A callback invoked when the bottom sheet bookmark item is clicked.
      */
     static final PropertyModel.ReadableObjectPropertyKey<Runnable> ON_CLICK_LISTENER =
             new PropertyModel.ReadableObjectPropertyKey<>();
 
-    static final PropertyKey[] ALL_KEYS = new PropertyKey[] {TITLE, SUBTITLE, ON_CLICK_LISTENER};
+    static final PropertyKey[] ALL_KEYS =
+            new PropertyKey[] {TITLE, SUBTITLE, ICON_DRAWABLE_AND_COLOR, ON_CLICK_LISTENER};
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetRowViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetRowViewBinder.java
index e2b7613..80b3295 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetRowViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetRowViewBinder.java
@@ -17,6 +17,8 @@
             view.setTitle(model.get(BookmarkBottomSheetItemProperties.TITLE));
         } else if (BookmarkBottomSheetItemProperties.SUBTITLE.equals(propertyKey)) {
             view.setSubtitle(model.get(BookmarkBottomSheetItemProperties.SUBTITLE));
+        } else if (BookmarkBottomSheetItemProperties.ICON_DRAWABLE_AND_COLOR.equals(propertyKey)) {
+            view.setIcon(model.get(BookmarkBottomSheetItemProperties.ICON_DRAWABLE_AND_COLOR));
         } else if (BookmarkBottomSheetItemProperties.ON_CLICK_LISTENER.equals(propertyKey)) {
             view.setOnClickListener(model.get(BookmarkBottomSheetItemProperties.ON_CLICK_LISTENER));
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
index cf22f3d..8e072e7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
@@ -59,16 +59,10 @@
     private static final float BASE_PAGE_BRIGHTNESS_STATE_MAXIMIZED = .4f;
 
     // -------------------------------------------------------------------------
-    // TODO(donnd): crbug.com/1143472 - The arrow and close buttons from the
-    // legacy UI are no longer used. Remove code related to these buttons here
-    // and in the native interface.
+    // TODO(donnd): crbug.com/1143472 - The close button from the legacy UI is
+    // no longer used. Remove code related to the button here and in the native
+    // interface.
     //
-    /** The opacity of the arrow icon. */
-    private static final float ARROW_ICON_OPACITY_TRANSPARENT = 0.f;
-
-    /** The rotation of the arrow icon. */
-    private static final float ARROW_ICON_ROTATION = -90.f;
-
     /** The opacity of the Open-Tab icon when the Panel is peeking. */
     private static final float OPEN_TAB_ICON_OPACITY_STATE_PEEKED = 1.f;
 
@@ -481,20 +475,6 @@
     }
 
     /**
-     * @return The opacity of the arrow icon.
-     */
-    public float getArrowIconOpacity() {
-        return ARROW_ICON_OPACITY_TRANSPARENT;
-    }
-
-    /**
-     * @return The rotation of the arrow icon, in degrees.
-     */
-    public float getArrowIconRotation() {
-        return ARROW_ICON_ROTATION;
-    }
-
-    /**
      * @return The opacity of the close icon.
      */
     public float getCloseIconOpacity() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
index 6c5e618..27057d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
@@ -113,8 +113,6 @@
 
         final int iconColor = panel.getIconColor();
         final int dragHandlebarColor = panel.getDragHandlebarColor();
-        float arrowIconOpacity = panel.getArrowIconOpacity();
-        float arrowIconRotation = panel.getArrowIconRotation();
 
         float closeIconOpacity = panel.getCloseIconOpacity();
 
@@ -144,24 +142,24 @@
         int panelShadowResourceId = R.drawable.overlay_side_shadow;
         int closeIconResourceId = INVALID_RESOURCE_ID;
 
-        // TODO(donnd): crbug.com/1143472 - Remove four parameters for the now
-        // defunct arrow |R.drawable.breadcrumb_arrow| and close buttons from
-        // the interface and the associated code on the native side.
+        // TODO(donnd): crbug.com/1143472 - Remove parameters for the now
+        // defunct close button from the interface and the associated code on
+        // the native side.
         ContextualSearchSceneLayerJni.get().updateContextualSearchLayer(mNativePtr,
                 ContextualSearchSceneLayer.this, panelShadowResourceId, searchBarBackgroundColor,
                 searchContextViewId, searchTermViewId, searchCaptionViewId,
                 R.drawable.modern_toolbar_shadow, R.drawable.ic_logo_googleg_24dp,
-                quickActionIconResId, R.drawable.breadcrumb_arrow, dragHandlebarId,
-                openNewTabIconId, closeIconResourceId, R.drawable.progress_bar_background,
-                R.drawable.progress_bar_foreground, searchPromoViewId,
-                R.drawable.contextual_search_promo_ripple, searchBarBannerTextViewId, mDpToPx,
-                panel.getFullscreenWidth() * mDpToPx, panel.getTabHeight() * mDpToPx,
-                panel.getBasePageBrightness(), panel.getBasePageY() * mDpToPx, panelWebContents,
-                searchPromoVisible, searchPromoHeightPx, searchPromoOpacity,
-                searchPromoBackgroundColor, searchBarBannerVisible, searchBarBannerHeightPx,
-                searchBarBannerPaddingPx, searchBarBannerRippleWidthPx,
-                searchBarBannerRippleOpacity, searchBarBannerTextOpacity, searchPanelX * mDpToPx,
-                searchPanelY * mDpToPx, searchPanelWidth * mDpToPx, searchPanelHeight * mDpToPx,
+                quickActionIconResId, dragHandlebarId, openNewTabIconId, closeIconResourceId,
+                R.drawable.progress_bar_background, R.drawable.progress_bar_foreground,
+                searchPromoViewId, R.drawable.contextual_search_promo_ripple,
+                searchBarBannerTextViewId, mDpToPx, panel.getFullscreenWidth() * mDpToPx,
+                panel.getTabHeight() * mDpToPx, panel.getBasePageBrightness(),
+                panel.getBasePageY() * mDpToPx, panelWebContents, searchPromoVisible,
+                searchPromoHeightPx, searchPromoOpacity, searchPromoBackgroundColor,
+                searchBarBannerVisible, searchBarBannerHeightPx, searchBarBannerPaddingPx,
+                searchBarBannerRippleWidthPx, searchBarBannerRippleOpacity,
+                searchBarBannerTextOpacity, searchPanelX * mDpToPx, searchPanelY * mDpToPx,
+                searchPanelWidth * mDpToPx, searchPanelHeight * mDpToPx,
                 searchBarMarginSide * mDpToPx, searchBarMarginTop * mDpToPx,
                 searchBarHeight * mDpToPx, searchContextOpacity,
                 searchBarControl.getTextLayerMinHeight(), searchTermOpacity,
@@ -169,12 +167,11 @@
                 searchCaptionVisible, searchBarBorderVisible, searchBarBorderHeight * mDpToPx,
                 quickActionIconVisible, thumbnailVisible, thumbnailUrl,
                 customImageVisibilityPercentage, barImageSize, iconColor, dragHandlebarColor,
-                arrowIconOpacity, arrowIconRotation, closeIconOpacity, isProgressBarVisible,
-                progressBarHeight * mDpToPx, progressBarOpacity, progressBarCompletion,
-                dividerLineVisibilityPercentage, dividerLineWidth, dividerLineHeight,
-                dividerLineColor, dividerLineXOffset, touchHighlightVisible, touchHighlightXOffset,
-                touchHighlightWidth, Profile.getLastUsedRegularProfile(), roundedBarTopResourceId,
-                separatorLineColor);
+                closeIconOpacity, isProgressBarVisible, progressBarHeight * mDpToPx,
+                progressBarOpacity, progressBarCompletion, dividerLineVisibilityPercentage,
+                dividerLineWidth, dividerLineHeight, dividerLineColor, dividerLineXOffset,
+                touchHighlightVisible, touchHighlightXOffset, touchHighlightWidth,
+                Profile.getLastUsedRegularProfile(), roundedBarTopResourceId, separatorLineColor);
     }
 
     @CalledByNative
@@ -227,9 +224,9 @@
                 int searchBarBackgroundColor, int searchContextResourceId, int searchTermResourceId,
                 int searchCaptionResourceId, int searchBarShadowResourceId,
                 int searchProviderIconResourceId, int quickActionIconResourceId,
-                int arrowUpResourceId, int dragHandlebarResourceId, int openTabIconResourceId,
-                int closeIconResourceId, int progressBarBackgroundResourceId,
-                int progressBarResourceId, int searchPromoResourceId, int barBannerRippleResourceId,
+                int dragHandlebarResourceId, int openTabIconResourceId, int closeIconResourceId,
+                int progressBarBackgroundResourceId, int progressBarResourceId,
+                int searchPromoResourceId, int barBannerRippleResourceId,
                 int barBannerTextResourceId, float dpToPx, float layoutWidth, float layoutHeight,
                 float basePageBrightness, float basePageYOffset, WebContents webContents,
                 boolean searchPromoVisible, float searchPromoHeight, float searchPromoOpacity,
@@ -245,9 +242,8 @@
                 float searchBarBorderHeight, boolean quickActionIconVisible,
                 boolean thumbnailVisible, String thumbnailUrl,
                 float customImageVisibilityPercentage, int barImageSize, int iconColor,
-                int dragHandlebarColor, float arrowIconOpacity, float arrowIconRotation,
-                float closeIconOpacity, boolean isProgressBarVisible, float progressBarHeight,
-                float progressBarOpacity, float progressBarCompletion,
+                int dragHandlebarColor, float closeIconOpacity, boolean isProgressBarVisible,
+                float progressBarHeight, float progressBarOpacity, float progressBarCompletion,
                 float dividerLineVisibilityPercentage, float dividerLineWidth,
                 float dividerLineHeight, int dividerLineColor, float dividerLineXOffset,
                 boolean touchHighlightVisible, float touchHighlightXOffset,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
index 79cb0ae..875da96c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
@@ -262,7 +262,7 @@
 
     // Implements BrowserPaymentRequest:
     @Override
-    public String triggerPaymentAppUiSkipIfApplicable(boolean isUserGestureShow) {
+    public String onShowCalledAndAppsQueriedAndDetailsFinalized(boolean isUserGestureShow) {
         // If we are skipping showing the Payment Request UI, we should call into the payment app
         // immediately after we determine the apps are ready and UI is shown.
         if (mShouldSkipShowingPaymentRequestUi || mSkipToGPayHelper != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java
index 335a4a3e..02b280a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java
@@ -26,8 +26,8 @@
     /** Id of the favicon. It is optional and used when caching the favion on device. */
     public int faviconId;
 
-    /** The path to the icon image file for whitelisted tile, empty string otherwise. */
-    public final String whitelistIconPath;
+    /** The path to the icon image file for allowlisted tile, empty string otherwise. */
+    public final String allowlistIconPath;
 
     /** The generated tile's title originated from this {@code TileTitleSource}. */
     @TileTitleSource
@@ -48,12 +48,12 @@
         (produced by a ranking algorithm). */
     public final Date dataGenerationTime;
 
-    public SiteSuggestion(String title, GURL url, String whitelistIconPath, int titleSource,
+    public SiteSuggestion(String title, GURL url, String allowlistIconPath, int titleSource,
             int source, int sectionType, Date dataGenerationTime) {
         this.title = title;
         this.url = url;
         this.faviconId = INVALID_FAVICON_ID;
-        this.whitelistIconPath = whitelistIconPath;
+        this.allowlistIconPath = allowlistIconPath;
         this.source = source;
         this.titleSource = titleSource;
         this.sectionType = sectionType;
@@ -72,14 +72,14 @@
         if (sectionType != that.sectionType) return false;
         if (!title.equals(that.title)) return false;
         if (!url.equals(that.url)) return false;
-        return whitelistIconPath.equals(that.whitelistIconPath);
+        return allowlistIconPath.equals(that.allowlistIconPath);
     }
 
     @Override
     public int hashCode() {
         int result = title.hashCode();
         result = 31 * result + url.hashCode();
-        result = 31 * result + whitelistIconPath.hashCode();
+        result = 31 * result + allowlistIconPath.hashCode();
         result = 31 * result + source;
         result = 31 * result + sectionType;
         result = 31 * result + titleSource;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelper.java
index e499b22..9c9daee5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelper.java
@@ -90,7 +90,7 @@
     // other classes.
     private void fetchIcon(
             final SiteSuggestion siteData, final LargeIconBridge.LargeIconCallback iconCallback) {
-        if (siteData.whitelistIconPath.isEmpty()) {
+        if (siteData.allowlistIconPath.isEmpty()) {
             mLargeIconBridge.getLargeIconForUrl(siteData.url, mMinIconSize, iconCallback);
             return;
         }
@@ -98,9 +98,9 @@
         AsyncTask<Bitmap> task = new AsyncTask<Bitmap>() {
             @Override
             protected Bitmap doInBackground() {
-                Bitmap bitmap = BitmapFactory.decodeFile(siteData.whitelistIconPath);
+                Bitmap bitmap = BitmapFactory.decodeFile(siteData.allowlistIconPath);
                 if (bitmap == null) {
-                    Log.d(TAG, "Image decoding failed: %s.", siteData.whitelistIconPath);
+                    Log.d(TAG, "Image decoding failed: %s.", siteData.allowlistIconPath);
                 }
                 return bitmap;
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java
index 512bc7e7..470cbcc6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java
@@ -126,7 +126,7 @@
             stream.writeInt(topSitesInfo.get(i).faviconId);
             stream.writeUTF(topSitesInfo.get(i).title);
             stream.writeUTF(topSitesInfo.get(i).url.serialize());
-            stream.writeUTF(topSitesInfo.get(i).whitelistIconPath);
+            stream.writeUTF(topSitesInfo.get(i).allowlistIconPath);
             stream.writeInt(topSitesInfo.get(i).titleSource);
             stream.writeInt(topSitesInfo.get(i).source);
             stream.writeInt(topSitesInfo.get(i).sectionType);
@@ -164,12 +164,12 @@
             GURL url = GURL.deserialize(stream.readUTF());
             if (url.isEmpty()) throw new IOException("GURL deserialization failed.");
 
-            String whitelistIconPath = stream.readUTF();
+            String allowlistIconPath = stream.readUTF();
             int titleSource = stream.readInt();
             int source = stream.readInt();
             int sectionType = stream.readInt();
             dataGenerationTime = new Date(stream.readLong());
-            SiteSuggestion newSite = new SiteSuggestion(title, url, whitelistIconPath, titleSource,
+            SiteSuggestion newSite = new SiteSuggestion(title, url, allowlistIconPath, titleSource,
                     source, sectionType, dataGenerationTime);
             newSite.faviconId = faviconId;
             suggestions.add(newSite);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileRenderer.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileRenderer.java
index fe8db927..97900bf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileRenderer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileRenderer.java
@@ -191,7 +191,7 @@
 
     private void fetchIcon(
             final SiteSuggestion siteData, final LargeIconBridge.LargeIconCallback iconCallback) {
-        if (siteData.whitelistIconPath.isEmpty()) {
+        if (siteData.allowlistIconPath.isEmpty()) {
             mImageFetcher.makeLargeIconRequest(siteData.url, mMinIconSize, iconCallback);
             return;
         }
@@ -199,9 +199,9 @@
         AsyncTask<Bitmap> task = new AsyncTask<Bitmap>() {
             @Override
             protected Bitmap doInBackground() {
-                Bitmap bitmap = BitmapFactory.decodeFile(siteData.whitelistIconPath);
+                Bitmap bitmap = BitmapFactory.decodeFile(siteData.allowlistIconPath);
                 if (bitmap == null) {
-                    Log.d(TAG, "Image decoding failed: %s", siteData.whitelistIconPath);
+                    Log.d(TAG, "Image decoding failed: %s", siteData.allowlistIconPath);
                 }
                 return bitmap;
             }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
index 3f6d6cf..22b41ed9a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
@@ -25,6 +25,7 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.base.task.TaskTraits;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.share.ShareDelegate;
@@ -161,6 +162,7 @@
 
     @Test
     @LargeTest
+    @DisableIf.Build(supported_abis_includes = "x86", message = "https://crbug.com/1154180")
     public void testShareIntent() throws ExecutionException, InterruptedException {
         MockChromeActivity mockActivity = TestThreadUtils.runOnUiThreadBlocking(() -> {
             // Sets a test component as last shared and "shareDirectly" option is set so that
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragmentTest.java
index 472944a..c34ec922 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragmentTest.java
@@ -143,6 +143,31 @@
             Preference syncAndServicesLink = prefs.findPreference(
                     AutofillAssistantPreferenceFragment.PREF_GOOGLE_SERVICES_SETTINGS_LINK);
             assertNotNull(syncAndServicesLink);
+            assertTrue(syncAndServicesLink.isVisible());
+        });
+    }
+
+    @Test
+    @LargeTest
+    @Feature({"Sync"})
+    @EnableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT,
+            ChromeFeatureList.AUTOFILL_ASSISTANT_DISABLE_PROACTIVE_HELP_TIED_TO_MSBB})
+    public void
+    testProactiveHelpNotLinkedToMsbbIfLinkDisabled() {
+        final AutofillAssistantPreferenceFragment prefs =
+                startAutofillAssistantPreferenceFragment();
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            ChromeSwitchPreference proactiveHelpSwitch =
+                    (ChromeSwitchPreference) prefs.findPreference(
+                            AutofillAssistantPreferenceFragment
+                                    .PREF_ASSISTANT_PROACTIVE_HELP_SWITCH);
+            assertTrue(proactiveHelpSwitch.isEnabled());
+
+            Preference syncAndServicesLink = prefs.findPreference(
+                    AutofillAssistantPreferenceFragment.PREF_GOOGLE_SERVICES_SETTINGS_LINK);
+            assertNotNull(syncAndServicesLink);
+            assertFalse(syncAndServicesLink.isVisible());
         });
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
index fe9f9632..bb30b1f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
@@ -89,6 +89,7 @@
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.history.HistoryActivity;
@@ -1658,6 +1659,7 @@
     @Test
     @SmallTest
     @Feature({"Preferences"})
+    @FlakyTest(message = "crbug.com/1154362")
     @SuppressWarnings("AlwaysShowAction") // We need to ensure the icon is in the action bar.
     public void testSearchIconVisibleInActionBarWithFeature() {
         setPasswordSource(null); // Initialize empty preferences.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelperTest.java
index d35994c3..09d5ae7c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelperTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelperTest.java
@@ -112,14 +112,14 @@
         siteSuggestions.add(new SiteSuggestion("0 TOP_SITES", new GURL("https://www.foo.com"), "",
                 TileTitleSource.TITLE_TAG, TileSource.TOP_SITES, TileSectionType.PERSONALIZED,
                 new Date()));
-        siteSuggestions.add(new SiteSuggestion("1 WHITELIST", new GURL("https://www.bar.com"),
-                "/not_exist.png", TileTitleSource.UNKNOWN, TileSource.WHITELIST,
+        siteSuggestions.add(new SiteSuggestion("1 ALLOWLIST", new GURL("https://www.bar.com"),
+                "/not_exist.png", TileTitleSource.UNKNOWN, TileSource.ALLOWLIST,
                 TileSectionType.PERSONALIZED, new Date()));
         siteSuggestions.add(new SiteSuggestion("2 TOP_SITES", new GURL("https://www.baz.com"),
-                createBitmapAndWriteToFile(), TileTitleSource.UNKNOWN, TileSource.WHITELIST,
+                createBitmapAndWriteToFile(), TileTitleSource.UNKNOWN, TileSource.ALLOWLIST,
                 TileSectionType.PERSONALIZED, new Date()));
         siteSuggestions.add(new SiteSuggestion("3 TOP_SITES", new GURL("https://www.qux.com"), "",
-                TileTitleSource.UNKNOWN, TileSource.WHITELIST, TileSectionType.PERSONALIZED,
+                TileTitleSource.UNKNOWN, TileSource.ALLOWLIST, TileSectionType.PERSONALIZED,
                 new Date()));
         siteSuggestions.get(0).faviconId = 0;
         siteSuggestions.get(1).faviconId = 1;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesHostTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesHostTest.java
index 20ca14f6..a3f7ba484 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesHostTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesHostTest.java
@@ -245,8 +245,8 @@
         siteSuggestions.add(new SiteSuggestion("0 TOP_SITES", new GURL("https://www.0.com"), "",
                 TileTitleSource.TITLE_TAG, TileSource.TOP_SITES, TileSectionType.PERSONALIZED,
                 new Date()));
-        siteSuggestions.add(new SiteSuggestion("1 WHITELIST", new GURL("https://www.1.com"), "",
-                TileTitleSource.UNKNOWN, TileSource.WHITELIST, TileSectionType.PERSONALIZED,
+        siteSuggestions.add(new SiteSuggestion("1 ALLOWLIST", new GURL("https://www.1.com"), "",
+                TileTitleSource.UNKNOWN, TileSource.ALLOWLIST, TileSectionType.PERSONALIZED,
                 new Date()));
         siteSuggestions.add(new SiteSuggestion("2 TOP_SITES", new GURL("https://www.2.com"), "",
                 TileTitleSource.UNKNOWN, TileSource.TOP_SITES, TileSectionType.PERSONALIZED,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtilsTest.java
index a3a23d4..b810992 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtilsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtilsTest.java
@@ -88,8 +88,8 @@
         siteSuggestions.add(new SiteSuggestion("0 TOP_SITES", new GURL("https://www.foo.com"), "",
                 TileTitleSource.TITLE_TAG, TileSource.TOP_SITES, TileSectionType.PERSONALIZED,
                 new Date()));
-        siteSuggestions.add(new SiteSuggestion("1 WHITELIST", new GURL("https://www.bar.com"), "",
-                TileTitleSource.UNKNOWN, TileSource.WHITELIST, TileSectionType.PERSONALIZED,
+        siteSuggestions.add(new SiteSuggestion("1 ALLOWLIST", new GURL("https://www.bar.com"), "",
+                TileTitleSource.UNKNOWN, TileSource.ALLOWLIST, TileSectionType.PERSONALIZED,
                 new Date()));
         siteSuggestions.get(1).faviconId = 1;
         return siteSuggestions;
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index f786940b..a698728 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -5538,7 +5538,7 @@
 <translation id="7443806024147773267">Cuando accedas a tu Cuenta de Google, podrás consultar tus contraseñas en cualquier momento</translation>
 <translation id="7444983668544353857">Inhabilitar <ph name="NETWORKDEVICE" /></translation>
 <translation id="7448430327655618736">Instala apps automáticamente</translation>
-<translation id="7448538354405258275">Un representante de atención al cliente puede usar el número EID para ayudarte a activar un servicio.</translation>
+<translation id="7448538354405258275">Un representante de Atención al Cliente puede usar el número EID para ayudarte a activar un servicio.</translation>
 <translation id="7449752890690775568">¿Quieres quitar la contraseña?</translation>
 <translation id="7450761244949417357">Se está abriendo en <ph name="ALTERNATIVE_BROWSER_NAME" /> en este momento</translation>
 <translation id="7453008956351770337">Al seleccionar esta impresora, concedes a la siguiente extensión permiso para acceder a tu impresora.</translation>
@@ -6997,7 +6997,7 @@
 <translation id="909108997331068008">El perfil de <ph name="EXISTING_USER" /> ya accedió a <ph name="NEW_USER" /></translation>
 <translation id="9094033019050270033">Actualizar contraseña</translation>
 <translation id="9094038138851891550">El nombre de usuario no es válido</translation>
-<translation id="9094859731829297286">¿Seguro que quieres reservar un espacio fijo en el disco para Linux?</translation>
+<translation id="9094859731829297286">¿Seguro que quieres reservar un disco de tamaño fijo para Linux?</translation>
 <translation id="9094982973264386462">Quitar</translation>
 <translation id="9095253524804455615">Quitar</translation>
 <translation id="909554839118732438">Cerrar las ventanas de incógnito</translation>
diff --git a/chrome/app/resources/generated_resources_eu.xtb b/chrome/app/resources/generated_resources_eu.xtb
index 8640872..4b0bce0e 100644
--- a/chrome/app/resources/generated_resources_eu.xtb
+++ b/chrome/app/resources/generated_resources_eu.xtb
@@ -4487,7 +4487,7 @@
 <translation id="6212752530110374741">Bidali esteka posta elektronikoz</translation>
 <translation id="6213230117190778270">Jaso</translation>
 <translation id="6215620815501168899">Itxi EID zenbakiaren eta QR kodearen leiho gainerakorra</translation>
-<translation id="6216601812881225442">Ezin da aldatu diskoaren tamaina. Linux-ek aldez aurretik esleituta duen biltegiratzeko tokia doitzeko, egin babeskopia bat eta, ondoren, lehenera ezazu beste edukiontzi batean.</translation>
+<translation id="6216601812881225442">Ezin da aldatu diskoaren tamaina. Linux-ek aldez aurretik esleituta daukan biltegiratzeko tokia doitzeko, egin babeskopia bat eta, ondoren, lehenera ezazu beste edukiontzi batean.</translation>
 <translation id="6216696360484424239">Hasi saioa automatikoki</translation>
 <translation id="6218058416316985984"><ph name="DEVICE_TYPE" /> ez dago konektatuta Internetera. Konekta ezazu eta saiatu berriro.</translation>
 <translation id="6220413761270491930">Errore bat gertatu da luzapena kargatzean</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index d6be2047..4ed95a2 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -1147,6 +1147,7 @@
 <translation id="2288735659267887385">ઍક્સેસિબિલિટી સેટિંગ્સ</translation>
 <translation id="2289270750774289114">જ્યારે કોઈ સાઇટ નજીકના બ્લૂટૂથ ડિવાઇસને શોધવા માગે ત્યારે પૂછો (સુઝાવ આપેલ)</translation>
 <translation id="2290615375132886363">ટૅબ્લેટ નૅવિગેશનનાં બટન</translation>
+<translation id="229182044471402145">કોઈ મેળ ખાતો ફૉન્ટ મળ્યો નથી.</translation>
 <translation id="2292848386125228270">કૃપા કરીને એક સામાન્ય વપરાશકર્તા તરીકે <ph name="PRODUCT_NAME" /> શરૂ કરો. જો તમને ડેવલપમેન્ટ માટે રૂટ તરીકે ચલાવવાની જરૂર હોય, તો --no-sandbox ચિહ્ન સાથે ફરીથી ચલાવો.</translation>
 <translation id="2294358108254308676">શું તમે <ph name="PRODUCT_NAME" /> ઇન્સ્ટોલ કરવા માંગો છો?</translation>
 <translation id="2295864384543949385"><ph name="NUM_RESULTS" /> પરિણામ</translation>
@@ -4261,6 +4262,7 @@
 <translation id="5946591249682680882">રીપોર્ટ ID <ph name="WEBRTC_LOG_REPORT_ID" /></translation>
 <translation id="5949544233750246342">ફાઇલનું વિશ્લેષણ કરવામાં અસમર્થ</translation>
 <translation id="5950819593680344519">Chromeને તમારા કમ્પ્યુટરમાં હાનિકારક સૉફ્ટવેર મળ્યું નથી • ગઈકાલે ચેક કર્યું</translation>
+<translation id="5951303645598168883"><ph name="ORIGIN" /> સ્થાનિક ફૉન્ટનો ઉપયોગ કરવા માગે છે</translation>
 <translation id="5951624318208955736">મૉનિટર</translation>
 <translation id="5955282598396714173">તમારા પાસવર્ડનો સમય પૂરો થઈ ગયો છે. કૃપા કરીને સાઇન આઉટ કરો પછી તેને બદલવા માટે ફરીથી સાઇન ઇન કરો.</translation>
 <translation id="5955304353782037793">app</translation>
@@ -5693,6 +5695,7 @@
 <translation id="7635048370253485243">તમારા વ્યવસ્થાપકે પિન કરેલું છે</translation>
 <translation id="763632859238619983">કોઈપણ સાઇટને ચુકવણી હૅન્ડલર ઇન્સ્ટૉલ કરવાની મંજૂરી ન આપો</translation>
 <translation id="7636919061354591437">આ ડિવાઇસ પર ઇન્સ્ટૉલ કરો</translation>
+<translation id="7637593984496473097">ડિસ્કમાં પર્યાપ્ત સ્પેસ નથી</translation>
 <translation id="7638605456503525968">સીરિયલ પોર્ટ</translation>
 <translation id="764017888128728"><ph name="PASSWORD_MANAGER_BRAND" />, તમને તમે સાચવેલા પાસવર્ડ વડે યોગ્ય હોય તેવી સાઇટમાં ઑટોમૅટિક રીતે સાઇન ઇન કરે છે.</translation>
 <translation id="7642778300616172920">સંવેદનશીલ કન્ટેન્ટ છુપાવો</translation>
diff --git a/chrome/app/resources/generated_resources_km.xtb b/chrome/app/resources/generated_resources_km.xtb
index 98c9e57..b96469c 100644
--- a/chrome/app/resources/generated_resources_km.xtb
+++ b/chrome/app/resources/generated_resources_km.xtb
@@ -4263,7 +4263,7 @@
 <translation id="5946591249682680882">លេខសម្គាល់របាយការណ៍ <ph name="WEBRTC_LOG_REPORT_ID" /></translation>
 <translation id="5949544233750246342">មិនអាច​ញែក​ឯកសារ​បានទេ</translation>
 <translation id="5950819593680344519">Chrome រកមិនឃើញ​កម្មវិធី​បង្កគ្រោះថ្នាក់​នៅលើ​កុំព្យូទ័រ​របស់អ្នក​ទេ • បានពិនិត្យមើល​ម្សិលមិញ</translation>
-<translation id="5951303645598168883"><ph name="ORIGIN" /> ចង់ប្រើ​ពុម្ពអក្សរ​មូលដ្ឋាន</translation>
+<translation id="5951303645598168883"><ph name="ORIGIN" /> ចង់ប្រើ​ពុម្ពអក្សរ​ដែល​មាន​នៅ​លើ​ឧបករណ៍</translation>
 <translation id="5951624318208955736">ផ្ទាំង​អេក្រង់</translation>
 <translation id="5955282598396714173">ពាក្យសម្ងាត់របស់អ្នកបានផុតកំណត់ហើយ។ សូមចេញពីគណនី ហើយចូលមកវិញម្តងទៀត ដើម្បីប្តូរវា។</translation>
 <translation id="5955304353782037793">កម្មវិធី</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb
index 4733649..709fe3b2 100644
--- a/chrome/app/resources/generated_resources_ko.xtb
+++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -4966,7 +4966,7 @@
 <translation id="6785518634832172390">PIN은 12자리 이하여야 합니다.</translation>
 <translation id="6786747875388722282">확장 프로그램</translation>
 <translation id="6787839852456839824">단축키</translation>
-<translation id="6788036387349419582">{COUNT,plural, =1{연락처 #개를 사용할 수 없습니다. 연락처와 Nearby Share를 사용하려면 Google 계정과 연결된 이메일 주소를 연락처에 추가하세요.}other{연락처 #개를 사용할 수 없습니다. 연락처와 Nearby Share를 사용하려면 Google 계정과 연결된 이메일 주소를 연락처에 추가하세요.}}</translation>
+<translation id="6788036387349419582">{COUNT,plural, =1{연락처 #개를 사용할 수 없습니다. 연락처와 Nearby Share를 사용하려면 상대방의 Google 계정과 연결된 이메일 주소를 연락처에 추가하세요.}other{연락처 #개를 사용할 수 없습니다. 연락처와 Nearby Share를 사용하려면 상대방의 Google 계정과 연결된 이메일 주소를 연락처에 추가하세요.}}</translation>
 <translation id="6788210894632713004">압축해제된 확장 프로그램</translation>
 <translation id="6789592661892473991">수평 분할</translation>
 <translation id="6790428901817661496">재생</translation>
diff --git a/chrome/app/resources/generated_resources_mk.xtb b/chrome/app/resources/generated_resources_mk.xtb
index 85fbcdae2..a490b06 100644
--- a/chrome/app/resources/generated_resources_mk.xtb
+++ b/chrome/app/resources/generated_resources_mk.xtb
@@ -1654,7 +1654,7 @@
 <translation id="2858138569776157458">Популарни</translation>
 <translation id="2861301611394761800">Ажурирањето на системот заврши. Рестартирајте го системот.</translation>
 <translation id="2861941300086904918">Управник за безбедност на матичен клиент</translation>
-<translation id="2862815659905780618">Отстрани ја развојната околина на Linux</translation>
+<translation id="2862815659905780618">Отстранете ја Linux-околината за програмирање</translation>
 <translation id="2864601841139725659">Поставете ја сликата на профилот</translation>
 <translation id="2865919525181940183">Слика од екранот со прикажаните програми</translation>
 <translation id="286674810810214575">Се проверуваат изворите за напојување…</translation>
@@ -2380,7 +2380,7 @@
 <translation id="3706463572498736864">Страници на лист</translation>
 <translation id="370649949373421643">Овозможи Wi-Fi</translation>
 <translation id="370665806235115550">Се вчитува...</translation>
-<translation id="3707163604290651814">Во моменов сте најавени како <ph name="NAME" /></translation>
+<translation id="3707163604290651814">Во моментов сте најавени како <ph name="NAME" /></translation>
 <translation id="3709244229496787112">Прелистувачот беше исклучен пред да заврши преземањето.</translation>
 <translation id="3711931198657368127">&amp;Залепи и оди на <ph name="URL" /></translation>
 <translation id="3711945201266135623">Најдени се <ph name="NUM_PRINTERS" /> печатачи од серверот за печатење</translation>
@@ -3761,7 +3761,7 @@
 <translation id="5368720394188453070">Вашиот телефон е заклучен. Отклучете го за да влезете.</translation>
 <translation id="5368779022775404937">Најавете се на <ph name="REALM" /></translation>
 <translation id="5369491905435686894">Овозможи забрзување на глувчето</translation>
-<translation id="5369694795837229225">Постави развојна околина на Linux</translation>
+<translation id="5369694795837229225">Поставете Linux-околина за програмирање</translation>
 <translation id="5370819323174483825">&amp;Повторно вчитај</translation>
 <translation id="5372529912055771682">Оваа верзија на оперативниот систем не го поддржува обезбедениот режим на запишување. Проверете дали ја користите најновата верзија и обидете се повторно.</translation>
 <translation id="5372579129492968947">Откачи екстензија</translation>
@@ -6070,7 +6070,7 @@
 <translation id="8032244173881942855">Не може да се емитува картичката.</translation>
 <translation id="8033827949643255796">избрано</translation>
 <translation id="8033958968890501070">Истекување</translation>
-<translation id="8036049989879571495">Поставете развојна околина на Linux (бета)</translation>
+<translation id="8036049989879571495">Поставете Linux-околина за програмирање (бета)</translation>
 <translation id="8037117027592400564">Прочитајте го текстот што се изговара со помош на синтетизиран говор.</translation>
 <translation id="8037357227543935929">Прашај (стандардно)</translation>
 <translation id="803771048473350947">Датотека</translation>
diff --git a/chrome/app/resources/generated_resources_my.xtb b/chrome/app/resources/generated_resources_my.xtb
index c63770e..ccc173c9 100644
--- a/chrome/app/resources/generated_resources_my.xtb
+++ b/chrome/app/resources/generated_resources_my.xtb
@@ -335,7 +335,7 @@
 <translation id="1374844444528092021">"<ph name="NETWORK_NAME" />" ကွန်ယက်က လိုအပ်သော လက်မှတ်ကို ထည့်သွင်းမထားခြင်း သို့မဟုတ် သက်တမ်းမရှိတော့ခြင်း ဖြစ်နေပါသည်။ ကျေးဇူးပြုပြီး လက်မှတ်အသစ် ရယူပြီး နောက်တစ်ကြိမ် ပြန်ဆက်သွယ်ပေးပါ။</translation>
 <translation id="1375321115329958930">သိမ်းဆည်းထားသည့် စကားဝှက်များ</translation>
 <translation id="137651782282853227">သိမ်းထားသော လိပ်စာများ ဤနေရာတွင်ပေါ်လာပါမည်</translation>
-<translation id="1376771218494401509">&amp;ဝင်းဒိုး အမည်ပေးရန်...</translation>
+<translation id="1376771218494401509">ဝင်းဒိုး အမည်ပေးရန်...</translation>
 <translation id="1377600615067678409">ယခု ကျော်လိုက်မည်</translation>
 <translation id="1378613616312864539"><ph name="NAME" /> သည် ဤဆက်တင်ကို ထိန်းချုပ်နေပါသည်</translation>
 <translation id="1380028686461971526">ကွန်ရက်သို့ အော်တို ချိတ်ဆက်ရန်</translation>
@@ -7006,7 +7006,7 @@
 <translation id="9102610709270966160">နောက်ဆက်တွဲကို အသုံးပြုရန်</translation>
 <translation id="9103479157856427471">စာရိုက်သည့်အတိုင်း ဇူးမ်ဆွဲထားသော ဖန်သားပြင်က လိုက်ပြသည်</translation>
 <translation id="9103868373786083162">မှတ်တမ်းကို ကြည့်ရန် နောက်ကိုသွား၊ ဆက်စပ် မီနူးကို နှိပ်ပါ</translation>
-<translation id="9108035152087032312">&amp;ဝင်းဒိုး အမည်ပေးရန်...</translation>
+<translation id="9108035152087032312">ဝင်းဒိုး အမည်ပေးရန်...</translation>
 <translation id="9108072915170399168">လက်ရှိဒေတာသုံးစွဲမှုဆက်တင်သည် အင်တာနက်မရှိဘဲသုံးရန်ဖြစ်သည်</translation>
 <translation id="9108692355621501797">ထုတ်ကုန်က မည်သည့်ဒေတာများကို မည်သည့်အတွက် စုဆောင်းပြီး မည်သို့ဆောင်ရွက်လိုက်သည်တို့ကို 'ပညာရေးအတွက် G Suite' အသုံးပြုသူနှင့် မိဘများ သိရှိစေရန် <ph name="LINK_BEGIN" />'ပညာရေးအတွက် G Suite' ပုဂ္ဂိုလ်ရေးလုံခြုံမှု သတိပေးချက်<ph name="LINK_END" /> က ကူညီပေးနိုင်သည်။</translation>
 <translation id="9108808586816295166">လုံခြုံသော DNS ကို အမြဲမရနိုင်ပါ</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index 17b79019..74e2c83 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -2778,7 +2778,7 @@
 <translation id="4146026355784316281">Altijd openen met systeemviewer</translation>
 <translation id="4146785383423576110">Resetten en opruimen</translation>
 <translation id="4147897805161313378">Google Foto's</translation>
-<translation id="4147911968024186208">Probeer het opnieuw. Als deze fout opnieuw wordt weergegeven, neem je contact op met een medewerker van de ondersteuning.</translation>
+<translation id="4147911968024186208">Probeer het opnieuw. Als deze fout opnieuw wordt weergegeven, neem je contact op met een medewerker van support.</translation>
 <translation id="4150201353443180367">Weergave</translation>
 <translation id="4152670763139331043">{NUM_TABS,plural, =1{1 tabblad}other{# tabbladen}}</translation>
 <translation id="4154664944169082762">Vingerafdrukken</translation>
@@ -4268,7 +4268,7 @@
 <translation id="5955282598396714173">Je wachtwoord is verlopen. Log uit en weer in om het te wijzigen.</translation>
 <translation id="5955304353782037793">app</translation>
 <translation id="5955721306465922729">Een website wil deze app openen.</translation>
-<translation id="5955809630138889698">Dit apparaat is mogelijk alleen geschikt voor de online demomodus. Neem contact op met een medewerker van de ondersteuning voor meer informatie.</translation>
+<translation id="5955809630138889698">Dit apparaat is mogelijk alleen geschikt voor de online demomodus. Neem contact op met een medewerker van support voor meer informatie.</translation>
 <translation id="5956585768868398362">Is dit de zoekpagina die je had verwacht?</translation>
 <translation id="5957613098218939406">Meer opties</translation>
 <translation id="5957987129450536192">Tik op het icoon 'Selecteer om uitgesproken te worden' in de buurt van je profielfoto en selecteer vervolgens wat je wilt horen.</translation>
diff --git a/chrome/app/resources/generated_resources_or.xtb b/chrome/app/resources/generated_resources_or.xtb
index d5fe8486..c919673 100644
--- a/chrome/app/resources/generated_resources_or.xtb
+++ b/chrome/app/resources/generated_resources_or.xtb
@@ -138,6 +138,7 @@
 <translation id="114721135501989771">Chromeରେ Google ସ୍ମାର୍ଟ୍ସ ପ୍ରାପ୍ତ କରନ୍ତୁ</translation>
 <translation id="1147322039136785890">ବର୍ତ୍ତମାନ <ph name="SUPERVISED_USER_NAME" />ର ପାଳି</translation>
 <translation id="1147991416141538220">ଆକ୍ସେସ୍ କରିବାକୁ ଅନୁମତି ପାଇଁ, ଏହି ଡିଭାଇସ୍‍ର ଆଡ୍‍ମିନିଷ୍ଟ୍ରେଟର୍‍ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।</translation>
+<translation id="1148063863818152153">ଆପଣଙ୍କ ଡିଭାଇସ୍ EID</translation>
 <translation id="1149401351239820326">ମିଆଦ ଶେଷ ହେଉଥିବା ମାସ</translation>
 <translation id="1149725087019908252"><ph name="FILE_NAME" /> ସ୍କାନ୍ ହେଉଛି</translation>
 <translation id="1150490752229770117">ଏହି <ph name="DEVICE_TYPE" /> ପାଇଁ ଏହା ଶେଷ ସ୍ୱଚାଳିତ ସଫ୍ଟୱେୟାର୍ ଏବଂ ସୁରକ୍ଷା ଅପ୍‌ଡେଟ୍ ଅଟେ। ଭବିଷ୍ୟତରେ ଅପ୍‌ଡେଟ୍‍ଗୁଡ଼ିକ ପାଇବା ପାଇଁ, ଏକ ନୂଆ ମଡେଲ୍‍କୁ ଅପ୍‌ଗ୍ରେଡ୍ କରନ୍ତୁ। <ph name="LINK_BEGIN" />ଅଧିକ ଜାଣନ୍ତୁ<ph name="LINK_END" /></translation>
@@ -312,6 +313,7 @@
 <translation id="1343865611738742294">USB ଡିଭାଇସ୍‌ଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବାକୁ Linuxକୁ ଅନୁମତି ଦିଅନ୍ତୁ। USBକୁ କାଢ଼ି ଦିଆଯିବା ପରେ Linux ଏହାକୁ ମନେ ରଖେ ନାହିଁ।</translation>
 <translation id="1346630054604077329">ସୁନିଶ୍ଚିତ କରି ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ</translation>
 <translation id="1347256498747320987">ଅପ୍‌ଡେଟ୍ ଓ ଆପ୍ସ ଇନ୍‌ଷ୍ଟଲ୍ କରନ୍ତୁ। ଜାରି ରଖି, ଆପଣ ଏଥିରେ ରାଜି ଅଛନ୍ତି ଯେ, ସମ୍ଭବତଃ ସେଲ୍ୟୁଲର୍ ଡାଟା ବ୍ୟବହାର କରି ଏହି ଡିଭାଇସ୍ Google, ଆପଣଙ୍କର ମୋବାଇଲ୍ ନେଟ୍‌ୱର୍କ ସେବା ପ୍ରଦାତା ତଥା ଆପଣଙ୍କ ଡିଭାଇସ୍ ନିର୍ମାତାଙ୍କଠାରୁ ଅପ୍‌ଡେଟ୍‌ଗୁଡ଼ିକ ଓ ଆପ୍ସକୁ ସ୍ୱଚାଳିତ ଭାବେ ଡାଉନ୍‌ଲୋଡ୍ ଓ ଇନ୍‌ଷ୍ଟଲ୍ କରିପାରିବ। ଏହି ଆପ୍ସ ମଧ୍ୟରୁ କେତେକ ଇନ୍-ଆପ୍ କ୍ରୟ କରିବାକୁ ଅଫର୍ କରିପାରନ୍ତି। <ph name="BEGIN_LINK1" />ଅଧିକ ଜାଣନ୍ତୁ<ph name="END_LINK1" /></translation>
+<translation id="1347512539447549782">Linux ଷ୍ଟୋରେଜ୍</translation>
 <translation id="1347975661240122359">ବ୍ୟାଟେରୀ ସ୍ତର <ph name="BATTERY_LEVEL" />%ରେ ପହଞ୍ଚିଲେ ଅପ୍‌ଡେଟ୍‌ ଆରମ୍ଭ ହେବ।</translation>
 <translation id="1353686479385938207"><ph name="PROVIDER_NAME" />: <ph name="NETWORK_NAME" /></translation>
 <translation id="1353980523955420967">PPD ମିଳୁନାହିଁ। ଆପଣଙ୍କ Chromebook ଅନ୍‌ଲାଇନ୍ ଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ ଏବଂ ପୁଣି ଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
@@ -551,6 +553,7 @@
 <translation id="1608668830839595724">ଚୟନ କରାଯାଇଥିବା ଆଇଟମ୍‌ଗୁଡ଼ିକ ପାଇଁ ଅଧିକ ପଦକ୍ଷେପଗୁଡ଼ିକ</translation>
 <translation id="161042844686301425">ସାୟାନ୍</translation>
 <translation id="1611432201750675208">ଆପଣଙ୍କ ଡିଭାଇସ୍ ଲକ୍ ଅଛି</translation>
+<translation id="1612019740169791082">ଡିସ୍କ ରିସାଇଜକୁ ସପୋର୍ଟ କରିବା ପାଇଁ ଆପଣଙ୍କ କଣ୍ଟେନର୍ କନଫିଗର୍ କରାଯାଇନାହିଁ। Linux ପାଇଁ ରିଜର୍ଭ କରାଯାଇଥିବା ସ୍ପେସର ପରିମାଣକୁ ଆଡଜଷ୍ଟ କରିବାକୁ, ବ୍ୟାକଅପ୍ ନିଅନ୍ତୁ ଏବଂ ତା'ପରେ ଏକ ନୂଆ କଣ୍ଟେନରରେ ଏହାକୁ ରିଷ୍ଟୋର୍ କରନ୍ତୁ।</translation>
 <translation id="1614511179807650956">ଆପଣ ବୋଧହୁଏ, ଆପଣଙ୍କର ମୋବାଇଲ୍‌ ଡାଟା ରିହାତି ବ୍ୟବହାର କରିସାରିଛନ୍ତି। ଅଧିକ ଡାଟା କିଣିବାକୁ <ph name="NAME" />ର ସକ୍ରିୟକରଣ ପୋର୍ଟାଲ୍‍କୁ ଯାଆନ୍ତୁ</translation>
 <translation id="161460670679785907">ଆପଣଙ୍କର ଫୋନ୍‌କୁ ଚିହ୍ନଟ କରିପାରୁନାହିଁ</translation>
 <translation id="1616206807336925449">ଏହି ଏକ୍ସଟେନ୍‍ସନ୍‍ ପାଇଁ କୌଣସି ବିଶେଷ ଅନୁମତିର ଆବଶ୍ୟକତା ନାହିଁ।</translation>
@@ -685,6 +688,7 @@
 <translation id="175772926354468439">ଥିମ୍ ସକ୍ଷମ କରନ୍ତୁ</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="17584710573359123">Chrome ୱେବ୍‌ ଷ୍ଟୋର୍‌ରେ ଦେଖନ୍ତୁ</translation>
+<translation id="1761845175367251960"><ph name="NAME" />ଙ୍କ ଆକାଉଣ୍ଟଗୁଡ଼ିକ</translation>
 <translation id="176193854664720708">ଟିପଚିହ୍ନ ସେନ୍ସର୍ ପାୱାର୍ ବଟନ୍‍‍ରେ ଅଛି। ଏହାକୁ କୌଣସି ଆଙ୍ଗୁଳିରେ ହାଲୁକା ଭାବରେ ସ୍ପର୍ଶ କରନ୍ତୁ।</translation>
 <translation id="1763046204212875858">ଆପ୍ଲିକେସନ୍‍ ସର୍ଟକଟ୍ ତିଆରି କରନ୍ତୁ</translation>
 <translation id="1763808908432309942">ଏକ ନୂଆ ଟାବ୍‌ରେ ଖୋଲେ</translation>
@@ -891,6 +895,7 @@
 <translation id="1999115740519098545">ଆରମ୍ଭ ପୃଷ୍ଠାରେ</translation>
 <translation id="2000419248597011803">ଆପଣଙ୍କର ଡିଫଲ୍ଟ ସନ୍ଧାନ ଇଞ୍ଜିନ୍‌କୁ ଠିକଣା ବାର୍‌ ଏବଂ ସନ୍ଧାନ ବାକ୍ସରୁ କିଛି କୁକୀ ଏବଂ ସନ୍ଧାନ ପଠାନ୍ତୁ</translation>
 <translation id="2002109485265116295">ରିଅଲ୍-ଟାଇମ୍</translation>
+<translation id="200217416291116199">ଅପଗ୍ରେଡ୍ ସମ୍ପୂର୍ଣ୍ଣ ହୋଇନପାରିବା ସ୍ଥଳେ ଫାଇଲଗୁଡ଼ିକର ବ୍ୟାକ୍ ଅପ୍ ନେବା ପାଇଁ ସୁପାରିଶ କରାଯାଇଛି। ଅପଗ୍ରେଡ୍ କରିବା ଆରମ୍ଭ କଲେ Linux ବନ୍ଦ ହୋଇଯିବ। ଆଗକୁ ବଢ଼ିବା ପୂର୍ବରୁ ଦୟାକରି ଖୋଲା ଥିବା ଫାଇଲଗୁଡ଼ିକୁ ସେଭ୍ କରନ୍ତୁ।</translation>
 <translation id="2003130567827682533">'<ph name="NAME" />' ଡାଟା ସକ୍ରିୟ କରିବାକୁ, ପ୍ରଥମେ ଏକ ୱାଇ-ଫାଇ ନେଟ୍‍ୱର୍କରେ ସଂଯୋଗ କରନ୍ତୁ</translation>
 <translation id="2005199804247617997">ଅନ୍ୟ ପ୍ରୋଫାଇଲଗୁଡ଼ିକ</translation>
 <translation id="2006638907958895361"><ph name="APP" />ରେ ଲିଙ୍କ୍ ଖୋଲନ୍ତୁ</translation>
@@ -1139,6 +1144,7 @@
 <translation id="2288735659267887385">ଆକ୍ସେସିବିଲିଟୀ ସେଟିଂ</translation>
 <translation id="2289270750774289114">ଯେତେବେଳେ ଏକ ସାଇଟ୍ ଆଖପାଖର ବ୍ଲୁଟୂଥ୍ ଡିଭାଇସ୍‍ଗୁଡ଼ିକୁ ଖୋଜିବାକୁ ଚାହୁଁଛି, ସେତେବେଳେ ପଚାରନ୍ତୁ (ସୁପାରିଶ କରାଯାଇଛି)</translation>
 <translation id="2290615375132886363">ଟାବଲେଟର ନାଭିଗେସନ୍ ବଟନଗୁଡ଼ିକ</translation>
+<translation id="229182044471402145">କୌଣସି ମେଳ ହେଉଥିବା ଫଣ୍ଟ ମିଳିଲା ନାହିଁ।</translation>
 <translation id="2292848386125228270">ଦୟାକରି ଏକ ସାମାନ୍ୟ ଉପଯୋଗକର୍ତ୍ତା ଭାବରେ <ph name="PRODUCT_NAME" /> ଆରମ୍ଭ କରନ୍ତୁ। ଡେଭଲପ୍‌ମେଣ୍ଟ ପାଇଁ ଯଦି ଆପଣଙ୍କୁ ରୁଟ୍ ଭାବରେ ଚଲାଇବାକୁ ପଡ଼େ, ତେବେ --ବିନା କୌଣସି ସ୍ୟାଣ୍ଡବକ୍ସ ଫ୍ଲାଗ୍ ସହିତ ପୁଣି ଚଲାନ୍ତୁ।</translation>
 <translation id="2294358108254308676">ଆପଣ <ph name="PRODUCT_NAME" /> ଇନ୍‌ଷ୍ଟଲ୍ କରିବାକୁ ଚାହାନ୍ତି କି?</translation>
 <translation id="2295864384543949385"><ph name="NUM_RESULTS" />ଟି ଫଳାଫଳ</translation>
@@ -1601,6 +1607,7 @@
 <translation id="2807517655263062534">ଆପଣ ଡାଉନ୍‌ଲୋଡ୍ କରିଥିବା ଫାଇଲ୍‌ଗୁଡ଼ିକ ଏଠାରେ ଦେଖାଯିବ</translation>
 <translation id="2809586584051668049">ଏବଂ ଆହୁରି <ph name="NUMBER_ADDITIONAL_DISABLED" /> ଜଣ</translation>
 <translation id="2810390687497823527">ଯଦି ଆପଣ କୌଣସି ଏକ୍ସଟେନ୍‌ସନ୍‍କୁ ଚିହ୍ନଟ କରିପାରୁନାହାଁନ୍ତି କିମ୍ବା ଆପଣଙ୍କର ବ୍ରାଉଜ‍‍ର୍ ଆଶା ଅନୁଯାୟୀ କାର୍ଯ୍ୟ କରୁନାହିଁ, ତେବେ ଆପଣ ଏଠାରେ ଏକ୍ସଟେନ୍‌ସନ୍‍ଗୁଡ଼ିକୁ ବନ୍ଦ କରିପାରିବେ କିମ୍ବା କଷ୍ଟମାଇଜ୍ କରିପାରିବେ।</translation>
+<translation id="2811205483104563968">ଆକାଉଣ୍ଟଗୁଡ଼ିକ</translation>
 <translation id="2812049959647166806">ଥଣ୍ଡର୍‌ବୋଲ୍ଟ ସମର୍ଥିତ ନୁହେଁ</translation>
 <translation id="2812989263793994277">କୌଣସି ଛବି ଦେଖାନ୍ତୁ ନାହିଁ</translation>
 <translation id="2813094189969465044">ମାତାପିତାଙ୍କ ଦ୍ଵାରା ନିୟନ୍ତ୍ରଣଗୁଡିକ</translation>
@@ -1639,6 +1646,7 @@
 <translation id="2858138569776157458">ଶ୍ରେଷ୍ଠ ସାଇଟ୍‌ଗୁଡ଼ିକ</translation>
 <translation id="2861301611394761800">ସିଷ୍ଟମ୍‌ ଅପ୍‌ଡେଟ୍‌ ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି। ଦୟାକରି, ସିଷ୍ଟମ୍‌ ପୁନରାରମ୍ଭ କରନ୍ତୁ।</translation>
 <translation id="2861941300086904918">ମୂଳ କ୍ଲାଏଣ୍ଟ ସୁରକ୍ଷା ପରିଚାଳକ</translation>
+<translation id="2862815659905780618">Linux ଡେଭଲପମେଣ୍ଟ ପରିବେଶକୁ କାଢ଼ି ଦିଅନ୍ତୁ</translation>
 <translation id="2864601841139725659">ଆପଣଙ୍କ ପ୍ରୋଫାଇଲ୍ ଛବି ସେଟ୍ କରନ୍ତୁ</translation>
 <translation id="2865919525181940183">ବର୍ତ୍ତମାନ ସ୍କ୍ରିନ୍‍‍ରେ ଥିବା ପ୍ରୋଗ୍ରାମ୍‍ଗୁଡ଼ିକର ସ୍କ୍ରିନ୍‍ସଟ୍</translation>
 <translation id="286674810810214575">ପାୱାର ସୋର୍ସଗୁଡ଼ିକୁ ଯାଞ୍ଚ କରାଯାଉଛି...</translation>
@@ -1752,6 +1760,7 @@
 <translation id="2989123969927553766">ମାଉସ୍ ସ୍କ୍ରୋଲ୍ ଆକ୍ସଲରେସନ୍</translation>
 <translation id="2989474696604907455">ସଂଯୁକ୍ତ ହୋଇନାହିଁ</translation>
 <translation id="2989786307324390836">DER-ଏନ୍‌କୋଡେଡ୍ ବାଇନାରୀ, ଏକକ ସାର୍ଟିଫିକେଟ୍</translation>
+<translation id="2990313168615879645">Google ଆକାଉଣ୍ଟ ଯୋଗ କରନ୍ତୁ</translation>
 <translation id="2992931425024192067">ସମସ୍ତ ବିଜ୍ଞପ୍ତି ବିଷୟବସ୍ତୁ ଦେଖାନ୍ତୁ</translation>
 <translation id="2993517869960930405">ଆପ୍‌ ସୂଚନା</translation>
 <translation id="2996286169319737844">ଡାଟା ଆପଣଙ୍କର ପାସ୍‌ଫ୍ରେଜ୍ ସହ ଏନ୍‌କ୍ରିପ୍ଟ କରାଯାଇଛି। ଏଥିରେ Google Payରୁ ପେମେଣ୍ଟ ପଦ୍ଧତି ଓ ଠିକଣା ଅନ୍ତର୍ଭୁକ୍ତ ନାହିଁ।</translation>
@@ -2363,6 +2372,7 @@
 <translation id="3706463572498736864">ଶିଟ୍‌ ପିଛା ପୃଷ୍ଠା</translation>
 <translation id="370649949373421643">ୱାଇ-ଫାଇ ସକ୍ଷମ କରନ୍ତୁ</translation>
 <translation id="370665806235115550">ଲୋଡ୍ କରୁଛି...</translation>
+<translation id="3707163604290651814">ବର୍ତ୍ତମାନ <ph name="NAME" /> ଭାବରେ ସାଇନ୍ ଇନ୍ କରିଛନ୍ତି</translation>
 <translation id="3709244229496787112">ଡାଉନ୍‌ଲୋଡ୍ ସମାପ୍ତ ହେବା ପୂର୍ବରୁ ବ୍ରାଉଜର୍ ବନ୍ଦ ହୋଇଯାଇଥିଲା।</translation>
 <translation id="3711931198657368127">ପେଷ୍ଟ କରି <ph name="URL" />କୁ ଯାଆନ୍ତୁ</translation>
 <translation id="3711945201266135623">ପ୍ରିଣ୍ଟ ସର୍ଭରରୁ <ph name="NUM_PRINTERS" />ଟି ପ୍ରିଣ୍ଟର୍ ମିଳିଛି</translation>
@@ -2867,6 +2877,7 @@
 <translation id="4309420042698375243"><ph name="NUM_KILOBYTES" />K (<ph name="NUM_KILOBYTES_LIVE" />K ଲାଇଭ୍)</translation>
 <translation id="4310139701823742692">ଫାଇଲ୍‌ର ଫର୍ମାଟ୍ ଭୁଲ୍ ଅଛି। PPD ଫାଇଲ୍ ଯାଞ୍ଚ କରି ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="431076611119798497">&amp;ବିବରଣୀ</translation>
+<translation id="4312701113286993760">{COUNT,plural, =1{1ଟି Google ଆକାଉଣ୍ଟ}other{<ph name="EXTRA_ACCOUNTS" />ଟି Google ଆକାଉଣ୍ଟ}}</translation>
 <translation id="4312866146174492540">ବ୍ଲକ୍ କରନ୍ତୁ (ଡିଫଲ୍ଟ)</translation>
 <translation id="4314815835985389558">ସିଙ୍କ ପରିଚାଳନା କରନ୍ତୁ</translation>
 <translation id="4316850752623536204">ଡେଭେଲପର୍‌ ୱେବ୍‍ସାଇଟ୍</translation>
@@ -3247,6 +3258,7 @@
 <translation id="4764368918650455114">ଉଭୟ ଡିଭାଇସକୁ ଅନଲକ୍ କରାଯାଇଛି, ସେଗୁଡ଼ିକ ପାଖାପାଖି ରହିଛି ଏବଂ ବ୍ଲୁଟୁଥ୍ ଚାଲୁ ଅଛି ବୋଲି ସୁନିଶ୍ଚିତ କରନ୍ତୁ। ଯଦି ଆପଣ ଏକ Chromebook ସହ ସେୟାର୍ କରୁଛନ୍ତି, ତେବେ ସେଥିରେ Nearby Share ଚାଲୁ କରାଯାଇଛି ବୋଲି ସୁନିଶ୍ଚିତ କରନ୍ତୁ (ସମୟ ଚୟନ କରି ସ୍ଥିତି କ୍ଷେତ୍ର ଖୋଲନ୍ତୁ, ତା'ପରେ Nearby Share ଚୟନ କରନ୍ତୁ)। <ph name="LINK_BEGIN" />ଅଧିକ ଜାଣନ୍ତୁ<ph name="LINK_END" /></translation>
 <translation id="4765582662863429759">ଆପଣଙ୍କର ଫୋନ୍‌ରୁ Chromebookକୁ ଟେକ୍ସଟ୍‍ ପ୍ରତିସାରଣ କରିବାକୁ Androidର ମେସେଜ୍‌ଗୁଡ଼ିକୁ ଅନୁମତି ଦିଏ।</translation>
 <translation id="4768332406694066911">ଆପଣଙ୍କ ପାଖରେ ଏହି ସଂଗଠନଗୁଡ଼ିକରୁ ସାର୍ଟିଫିକେଟ୍‍ଗୁଡ଼ିକ ଅଛି ଯାହା ଆପଣଙ୍କୁ ଚିହ୍ନଟ କରିଥାଏ</translation>
+<translation id="4773112038801431077">Linux ଅପଗ୍ରେଡ୍ କରନ୍ତୁ</translation>
 <translation id="477647109558161443">ଏକ ଡେସ୍କଟପ୍ ସର୍ଟକଟ୍ ତିଆରି କରନ୍ତୁ</translation>
 <translation id="4776917500594043016"><ph name="USER_EMAIL_ADDRESS" />ଙ୍କ ପାଇଁ ପାସ୍‌ୱାର୍ଡ</translation>
 <translation id="4777825441726637019">Play ଷ୍ଟୋର୍</translation>
@@ -3740,6 +3752,7 @@
 <translation id="5368720394188453070">ଆପଣଙ୍କର ଫୋନ୍‌ ଲକ୍‌ ହୋଇଯାଇଛି। ଏଥିରେ ପ୍ରବେଶ କରିବାକୁ ଅନ୍‌ଲକ୍‌ କରନ୍ତୁ।</translation>
 <translation id="5368779022775404937"><ph name="REALM" />ରେ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ</translation>
 <translation id="5369491905435686894">ମାଉସ୍ ଆକ୍ସଲରେସନ୍ ସକ୍ଷମ କରନ୍ତୁ</translation>
+<translation id="5369694795837229225">Linux ଡେଭଲପମେଣ୍ଟ ପରିବେଶ ସେଟ୍ ଅପ୍ କରନ୍ତୁ</translation>
 <translation id="5370819323174483825">&amp;ରିଲୋଡ୍ କରନ୍ତୁ</translation>
 <translation id="5372529912055771682">ପ୍ରଦାନ କରାଯାଇଥିବା ନାମାଙ୍କନ ମୋଡ୍, ଅପରେଟିଂ ସିଷ୍ଟମ୍‍ର ଏହି ସଂସ୍କରଣକୁ ସମର୍ଥନ କରୁନାହିଁ।  ଦୟାକରି, ଏହା ସୁନିଶ୍ଚିତ କରନ୍ତୁ ଯେ ଆପଣ ନବୀନତମ ସଂସ୍କରଣ ଚଲାଉଛନ୍ତି ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="5372579129492968947">ଏକ୍ସଟେନ୍‌ସନ୍ ଅନ୍‌ପିନ୍ କରନ୍ତୁ</translation>
@@ -4242,6 +4255,7 @@
 <translation id="5946591249682680882">ରିପୋର୍ଟ ID <ph name="WEBRTC_LOG_REPORT_ID" /></translation>
 <translation id="5949544233750246342">ଫାଇଲ୍‌କୁ ପାର୍ସ କରିବାରେ ଅକ୍ଷମ</translation>
 <translation id="5950819593680344519">Chrome ଆପଣଙ୍କ କମ୍ପ୍ୟୁଟରରେ କ୍ଷତିକାରକ ସଫ୍ଟୱେରକୁ ଖୋଜି ପାଇଲା ନାହିଁ • ଗତକାଲି ଯାଞ୍ଚ କରାଯାଇଛି</translation>
+<translation id="5951303645598168883"><ph name="ORIGIN" /> ସ୍ଥାନୀୟ ଫଣ୍ଟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବାକୁ ଚାହେଁ</translation>
 <translation id="5951624318208955736">ମନିଟର୍</translation>
 <translation id="5955282598396714173">ଆପଣଙ୍କ ପାସ୍‍ୱର୍ଡର ସମୟସୀମା ଶେଷ ହୋଇଛି। ପରିବାର୍ତ୍ତନ କରିବାକୁ ଦୟାକରି ସାଇନ୍‌ ଆଉଟ୍‌ କରନ୍ତୁ, ଏହାପରେ ସାଇନ୍‍ ଇନ୍‍ କରନ୍ତୁ।</translation>
 <translation id="5955304353782037793">ଆପ୍</translation>
@@ -4465,6 +4479,8 @@
 <translation id="6212168817037875041">ଡିସ୍‌ପ୍ଲେ ବନ୍ଦ କରନ୍ତୁ</translation>
 <translation id="6212752530110374741">ଇମେଲ୍‍ ଲିଙ୍କ୍‌</translation>
 <translation id="6213230117190778270">ପ୍ରାପ୍ତ କରନ୍ତୁ</translation>
+<translation id="6215620815501168899">EID ଏବଂ QR କୋଡ୍ ପପଅପକୁ ବନ୍ଦ କରନ୍ତୁ</translation>
+<translation id="6216601812881225442">ଆପଣଙ୍କ କଣ୍ଟେନର୍ ଏହାକୁ ରିସାଇଜ୍ କରିବା ସୁବିଧାକୁ ସମର୍ଥନ କରେ ନାହିଁ। Linux ନିମନ୍ତେ ପୂର୍ବରୁ-ଆବଣ୍ଟନ କରାଯାଇଥିବା ସ୍ପେସର ପରିମାଣକୁ ଆଡଜଷ୍ଟ କରିବା ପାଇଁ ବ୍ୟାକଅପ୍ ନିଅନ୍ତୁ ଏବଂ ତା'ପରେ ଏକ ନୂଆ କଣ୍ଟେନରରେ ଏହାକୁ ରିଷ୍ଟୋର୍ କରନ୍ତୁ।</translation>
 <translation id="6216696360484424239">ସ୍ୱଚାଳିତ ଭାବେ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ</translation>
 <translation id="6218058416316985984"><ph name="DEVICE_TYPE" /> ଅଫ୍‍ଲାଇନ୍ ଅଛି। ଇଣ୍ଟର୍ନେଟ୍‌‍କୁ ସଂଯୋଗ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="6220413761270491930">ଏକ୍ସଟେନ୍‌ସନ୍ ଲୋଡ୍ ହେବା ସମୟରେ ତ୍ରୁଟି</translation>
@@ -4661,6 +4677,7 @@
 <translation id="6434309073475700221">ବର୍ଜିତ କରନ୍ତୁ</translation>
 <translation id="6434325376267409267">ଆପଣ <ph name="APP_NAME" /> ବ୍ୟବହାର କରିପାରିବା ପୂର୍ବରୁ ଆପଣଙ୍କର ଡିଭାଇସ୍ ଅପଡେଟ୍ ହେବା ଦରକାର।</translation>
 <translation id="6436164536244065364">ୱେବ୍ ଷ୍ଟୋର୍‌‌ରେ ଦେଖନ୍ତୁ</translation>
+<translation id="6438234780621650381">ସେଟିଂସ୍ ରିସେଟ୍ କରନ୍ତୁ</translation>
 <translation id="6438992844451964465"><ph name="WINDOW_TITLE" /> - ଅଡିଓ ବାଜୁଛି</translation>
 <translation id="6442187272350399447">ବହୁତ ବଢ଼ିଆ</translation>
 <translation id="6444070574980481588">ତାରିଖ ଓ ସମୟ ସେଟ୍ କରନ୍ତୁ</translation>
@@ -4858,6 +4875,7 @@
 <translation id="6680442031740878064"><ph name="AVAILABLE_SPACE" />: ଉପଲବ୍ଧ ଅଛି</translation>
 <translation id="6680650203439190394">କେତେ ଶିଘ୍ର</translation>
 <translation id="6681668084120808868">ଫଟୋ ଉଠାନ୍ତୁ</translation>
+<translation id="6683948477137300040">ଡିଭାଇସ୍ EID ଏବଂ QR କୋଡ୍ ପପଅପ୍ ଦେଖାନ୍ତୁ</translation>
 <translation id="6684827949542560880">ନବୀନତମ ଅପଡେଟ୍ ଡାଉନଲୋଡ୍ କରାଯାଉଛି</translation>
 <translation id="668599234725812620">Google Play ଖୋଲନ୍ତୁ</translation>
 <translation id="6686490380836145850">ଦକ୍ଷିଣ ସହ ଟ୍ୟାବଗୁଡିକ ନିକଟକୁ କରନ୍ତୁ</translation>
@@ -5095,6 +5113,7 @@
 <translation id="6955535239952325894">ପରିଚାଳିତ ବ୍ରାଉଜରଗୁଡ଼ିକରେ ଏହି ସେଟିଂସ୍ ଅକ୍ଷମ କରାଯାଇଛି</translation>
 <translation id="6957044667612803194">ଏହି ସୁରକ୍ଷାକୀ ପିନ୍‌ଗୁଡ଼ିକୁ ସମର୍ଥନ କରେ ନାହିଁ</translation>
 <translation id="6957231940976260713">ସେବାର ନାମ</translation>
+<translation id="6960507406838246615">Linux ଅପଡେଟ୍ ଆବଶ୍ୟକ</translation>
 <translation id="696103774840402661">ଏହି <ph name="DEVICE_TYPE" />ରେ ଥିବା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତାଙ୍କର ସବୁ ଫାଇଲ୍ ଏବଂ ସ୍ଥାନୀୟ ଡାଟାକୁ ସ୍ଥାୟୀ ଭାବେ ଡିଲିଟ୍ କରାଯାଇଛି।</translation>
 <translation id="6964390816189577014">ହିରୋ</translation>
 <translation id="6964760285928603117">ଗୋଷ୍ଠୀରୁ କାଢ଼ି ଦିଅନ୍ତୁ</translation>
@@ -5114,6 +5133,7 @@
 <translation id="697312151395002334">ପପ୍-ଅପଗୁଡ଼ିକ ପଠାଇ ରିଡାଇରେକ୍ଟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଆଯାଇଛି</translation>
 <translation id="6973611239564315524">Debian 10 (Buster)ର ଏକ ଅପଗ୍ରେଡ୍ ଉପଲବ୍ଧ ଅଛି</translation>
 <translation id="6974609594866392343">ଅଫ୍‍ଲାଇନ୍‌ ଡେମୋ ମୋଡ୍</translation>
+<translation id="697508444536771064">Linuxକୁ ବନ୍ଦ କରନ୍ତୁ</translation>
 <translation id="6977381486153291903">ଫାର୍ମୱେର୍ ପୁନରାବୃତ୍ତି</translation>
 <translation id="6977877318519394148">Rosetta ଇନଷ୍ଟଲ୍ କରନ୍ତୁ</translation>
 <translation id="6978121630131642226">ସନ୍ଧାନ ଇଞ୍ଜିନଗୁଡିକ</translation>
@@ -5515,6 +5535,7 @@
 <translation id="7443806024147773267">ଯେତେବେଳେ ଆପଣ ଆପଣଙ୍କର Google ଆକାଉଣ୍ଟରେ ସାଇନ୍ ଇନ୍ କରିଥିବା ସମୟରେ ଆପଣଙ୍କର ପାସ୍‍ୱାର୍ଡଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରନ୍ତୁ</translation>
 <translation id="7444983668544353857"><ph name="NETWORKDEVICE" />କୁ ଅକ୍ଷମ କରନ୍ତୁ</translation>
 <translation id="7448430327655618736">ସ୍ୱଚାଳିତ ଭାବେ ଆପ୍ସ ଇନଷ୍ଟଲ୍ କରନ୍ତୁ</translation>
+<translation id="7448538354405258275">ସେବାକୁ ସକ୍ରିୟ କରିବାରେ ଆପଣଙ୍କୁ ସାହାଯ୍ୟ କରିବା ପାଇଁ ଜଣେ ଗ୍ରାହକ ସେବା ପ୍ରତିନିଧି EID ନମ୍ବର ବ୍ୟବହାର କରିପାରିବେ।</translation>
 <translation id="7449752890690775568">ପାସୱାର୍ଡ କାଢ଼ି ଦେବେ?</translation>
 <translation id="7450761244949417357">ବର୍ତ୍ତମାନ <ph name="ALTERNATIVE_BROWSER_NAME" />ରେ ଖୋଲୁଛି</translation>
 <translation id="7453008956351770337">ଏହି ପ୍ରିଣ୍ଟର୍‌ର ଚୟନ କରିବା ଦ୍ଵାରା ଆପଣ ନିମ୍ନୋକ୍ତ ଏକ୍ସଟେନ୍‌ସନ୍‌କୁ ଆପଣଙ୍କର ପ୍ରିଣ୍ଟର୍ ଆକ୍‌ସେସ୍ କରିବା ପାଇଁ ଅନୁମତି ଦେଉଛନ୍ତି।</translation>
@@ -5669,6 +5690,7 @@
 <translation id="7635048370253485243">ଆପଣଙ୍କ ଆଡମିନିଷ୍ଟ୍ରେଟର୍ ପିନ୍ କରିଛନ୍ତି</translation>
 <translation id="763632859238619983">ପେମେଣ୍ଟ ହ୍ୟାଣ୍ଡଲର୍ ଇନ୍‌ଷ୍ଟଲ୍ କରିବାକୁ କୌଣସି ସାଇଟ୍‌କୁ ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ</translation>
 <translation id="7636919061354591437">ଏହି ଡିଭାଇସ୍‌ରେ ଇନ୍‌ଷ୍ଟଲ୍ କରନ୍ତୁ</translation>
+<translation id="7637593984496473097">ପର୍ଯ୍ୟାପ୍ତ ଡିସ୍କ ସ୍ପେସ୍ ନାହିଁ</translation>
 <translation id="7638605456503525968">କ୍ରମିକ ପୋର୍ଟଗୁଡ଼ିକ</translation>
 <translation id="764017888128728"><ph name="PASSWORD_MANAGER_BRAND" /> ସ୍ୱଚାଳିତ ରୂପେ ଆପଣ ସେଭ୍ କରିଥିବା ପାସ୍‌ୱର୍ଡଗୁଡ଼ିକ ମାଧ୍ୟମରେ ଆପଣଙ୍କୁ ଯୋଗ୍ୟ ସାଇଟ୍‌ଗୁଡ଼ିକରେ ସାଇନ୍ ଇନ୍ କରାଏ।</translation>
 <translation id="7642778300616172920">ସମ୍ବେଦନଶୀଳ ବିଷୟବସ୍ତୁକୁ ଲୁଚାନ୍ତୁ</translation>
@@ -6041,6 +6063,7 @@
 <translation id="8032244173881942855">ଟାବ୍‌ କାଷ୍ଟ କରିବାରେ ଅକ୍ଷମ।</translation>
 <translation id="8033827949643255796">ଚୟନ କରାଯାଇଛି</translation>
 <translation id="8033958968890501070">ସମୟ ସମାପ୍ତି</translation>
+<translation id="8036049989879571495">Linux ଡେଭଲପମେଣ୍ଟ ପରିବେଶ (ବିଟା) ସେଟ୍ ଅପ୍ କରନ୍ତୁ</translation>
 <translation id="8037117027592400564">ସ୍ପୀଚ୍‍ର ସମ୍ମିଶ୍ରଣ ବ୍ୟବହାର କରି ସମସ୍ତ କୁହାଯାଇଥିବା ଟେକ୍ସଟ୍‍ ପଢ଼ନ୍ତୁ</translation>
 <translation id="8037357227543935929">ପଚାରନ୍ତୁ (ଡିଫଲ୍ଟ)</translation>
 <translation id="803771048473350947">ଫାଇଲ୍</translation>
@@ -6968,6 +6991,7 @@
 <translation id="909108997331068008"><ph name="EXISTING_USER" />ଙ୍କ ପ୍ରୋଫାଇଲ୍ ପୂର୍ବରୁ <ph name="NEW_USER" />ରେ ସାଇନ୍ ଇନ୍ ହୋଇଛି</translation>
 <translation id="9094033019050270033">ପାସ୍‌ୱର୍ଡ ଅପ୍‌ଡେଟ୍ କରନ୍ତୁ</translation>
 <translation id="9094038138851891550">ଉପଯୋଗକର୍ତ୍ତାନାମ ଅବୈଧ ଅଟେ</translation>
+<translation id="9094859731829297286">Linux ପାଇଁ ଆପଣ ଏକ ନିର୍ଦ୍ଦିଷ୍ଟ ଆକାରର ଡିସ୍କ ରିଜର୍ଭ କରିବାକୁ ଚାହୁଁଥିବା ନିଶ୍ଚିତ କି?</translation>
 <translation id="9094982973264386462">କାଢ଼ନ୍ତୁ</translation>
 <translation id="9095253524804455615">କାଢ଼ିଦିଅନ୍ତୁ</translation>
 <translation id="909554839118732438">ଇନକଗ୍ନିଟୋ ୱିଣ୍ଡୋ ବନ୍ଦ କରନ୍ତୁ</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index 13cda64..31e7c4c 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -4491,7 +4491,7 @@
 <translation id="6212168817037875041">Desligar a tela</translation>
 <translation id="6212752530110374741">Enviar link por e-mail</translation>
 <translation id="6213230117190778270">Receber</translation>
-<translation id="6215620815501168899">Feche EID e o pop-up do código QR</translation>
+<translation id="6215620815501168899">Feche o EID e o pop-up do código QR</translation>
 <translation id="6216601812881225442">Seu contêiner não é compatível com redimensionamento. Para ajustar a quantidade de espaço pré-alocada para o Linux, faça backup e restaure-o em um novo contêiner.</translation>
 <translation id="6216696360484424239">Fazer login automaticamente</translation>
 <translation id="6218058416316985984">O <ph name="DEVICE_TYPE" /> está off-line. Conecte-se à Internet e tente novamente.</translation>
@@ -4885,7 +4885,7 @@
 <translation id="6680442031740878064">Disponível: <ph name="AVAILABLE_SPACE" /></translation>
 <translation id="6680650203439190394">Velocidade</translation>
 <translation id="6681668084120808868">Tirar foto</translation>
-<translation id="6683948477137300040">Mostre EID do dispositivo e o pop-up do código QR</translation>
+<translation id="6683948477137300040">Mostre o EID do dispositivo e o pop-up do código QR</translation>
 <translation id="6684827949542560880">Fazendo o download da atualização mais recente</translation>
 <translation id="668599234725812620">Abrir o Google Play</translation>
 <translation id="6686490380836145850">Fechar guias à direita</translation>
diff --git a/chrome/app/resources/generated_resources_ur.xtb b/chrome/app/resources/generated_resources_ur.xtb
index f150acf6..119da07 100644
--- a/chrome/app/resources/generated_resources_ur.xtb
+++ b/chrome/app/resources/generated_resources_ur.xtb
@@ -336,6 +336,7 @@
 <translation id="1374844444528092021">نیٹ ورک "<ph name="NETWORK_NAME" />" کے ذریعے مطلوب سرٹیفکیٹ یا تو انسٹال نہیں ہے یا اب درست نہیں ہے۔ براہ کرم ایک نیا سرٹیفکیٹ حاصل کریں اور دوبارہ منسلک کرنے کی کوشش کریں۔</translation>
 <translation id="1375321115329958930">محفوظ کردہ پاس ورڈز</translation>
 <translation id="137651782282853227">محفوظ کردہ پتے یہاں ظاہر ہوں گے</translation>
+<translation id="1376771218494401509">ونڈو کا نام رکھیں...</translation>
 <translation id="1377600615067678409">ابھی نظر انداز کریں</translation>
 <translation id="1378613616312864539"><ph name="NAME" /> اس ترتیب کو کنٹرول کر رہا ہے</translation>
 <translation id="1380028686461971526">نیٹ ورک سے خودکار طور پر منسلک ہوں</translation>
@@ -3182,6 +3183,7 @@
 <translation id="4651484272688821107">ڈیمو موڈ کے وسائل کے ساتھ آن لائن جزو کو لوڈ نہیں کیا جا سکا۔</translation>
 <translation id="4652935475563630866">‏کیمرے کی ترتیب میں تبدیلی کے لیے، Parallels ڈیسک ٹاپ کو بند کر کے دوبارہ چلانے کی ضرورت ہے۔ آگے بڑھنے کے لیے Parallels ڈیسک ٹاپ کو بند کر کے دوبارہ چلائیں۔</translation>
 <translation id="4653405415038586100">‏Linux کو کنفیگر کرنے میں خرابی</translation>
+<translation id="4653408778024877479">{NUM_WEAK,plural, =0{}=1{1 کمزور پاس ورڈ}other{{NUM_WEAK} کمزور پاس ورڈز}}</translation>
 <translation id="4657914796247705218">‏TrackPoint کی رفتار</translation>
 <translation id="465878909996028221">‏صرف http، ‏https اور فائل پروٹوکولز ہی براؤزر کے ری ڈائریکٹس کے لئے تعاون یافتہ ہیں۔</translation>
 <translation id="4659077111144409915">بنیادی اکاؤنٹ</translation>
@@ -4964,6 +4966,7 @@
 <translation id="6785518634832172390">‏PIN ‏12 یا اس سے کم ہندسوں کا ہونا چاہیے</translation>
 <translation id="6786747875388722282">توسیعات</translation>
 <translation id="6787839852456839824">کی بورڈ شارٹ کٹس</translation>
+<translation id="6788036387349419582">{COUNT,plural, =1{‏# رابطہ دستیاب نہیں ہے۔ ان کے ساتھ قریبی آلات کے ساتھ اشتراک کا استعمال کرنے کے لیے، ان کے Google اکاؤنٹ سے وابستہ ای میل پتہ کو اپنے رابطوں میں شامل کریں۔}other{‏# رابطے دستیاب نہیں ہیں۔ ان کے ساتھ قریبی آلات کے ساتھ اشتراک کا استعمال کرنے کے لیے، ان کے Google اکاؤنٹ سے وابستہ ای میل پتہ کو اپنے رابطوں میں شامل کریں۔}}</translation>
 <translation id="6788210894632713004">غیر پیک شدہ ایکسٹینشن</translation>
 <translation id="6789592661892473991">افقی تقسیم کریں</translation>
 <translation id="6790428901817661496">چلائیں</translation>
@@ -5010,6 +5013,7 @@
 <translation id="683373380308365518">اسمارٹ اور محفوظ براؤزر پر سوئچ کریں</translation>
 <translation id="6835762382653651563">براہ کرم اپنا <ph name="DEVICE_TYPE" /> اپ ڈیٹ کرنے کیلئے انٹرنیٹ سے منسلک ہوں۔</translation>
 <translation id="6838034009068684089">جب کوئی سائٹ ونڈوز کھولنا اور آپ کی اسکرین پر رکھنا چاہے تو پوچھیں (تجاویز کردہ)</translation>
+<translation id="6838694093138907871">غلط کوڈ، براہ کرم دوبارہ کوشش کریں۔</translation>
 <translation id="6839225236531462745">سرٹیفکیٹ حذف کرنے میں خرابی</translation>
 <translation id="6839916869147598086">سائن ان تبدیل ہو چکا ہے</translation>
 <translation id="6840155290835956714">بھیجنے سے پہلے پوچھیں</translation>
@@ -5250,6 +5254,7 @@
 <translation id="7093866338626856921">نام والے آلات کے ساتھ ڈیٹا کا تبادلہ کریں: <ph name="HOSTNAMES" /></translation>
 <translation id="7098389117866926363">‏USB-C آلہ (پیچھے موجود بایاں پورٹ)</translation>
 <translation id="7098447629416471489">محفوظ کردہ دیگر سرچ انجن یہاں ظاہر ہوں گے</translation>
+<translation id="709869441357640014">{NUM_COMPROMISED,plural, =0{}=1{1 متاثرہ پاس ورڈ}other{{NUM_COMPROMISED} متاثرہ پاس ورڈز}}</translation>
 <translation id="7099337801055912064">‏بڑے PPD کو لوڈ نہیں کر سکتا۔ زیادہ سے زیادہ سائز ‎250 kB‎ ہے۔</translation>
 <translation id="7102687220333134671">خود کار اپ ڈیٹس آن ہیں</translation>
 <translation id="7102832101143475489">درخواست کا وقت ختم ہو گیا</translation>
@@ -6256,6 +6261,7 @@
 <translation id="8253198102038551905">نیٹ ورک کی خصوصیات حاصل کرنے کیلئے '+' پر کلک کریں</translation>
 <translation id="8255451560461371599">کوئی پس منظر نہیں</translation>
 <translation id="8256319818471787266">Sparky</translation>
+<translation id="8257435388931378346">سوئچ <ph name="ACTION" /> تفویض کریں</translation>
 <translation id="8257950718085972371">کیمرا تک رسائی کو مسدود کرنا جاری رکھیں</translation>
 <translation id="8259239505248583312">آئیے شروع کریں</translation>
 <translation id="8260864402787962391">ماؤس</translation>
@@ -6519,6 +6525,7 @@
 <translation id="8584280235376696778">&amp;ویڈیو نئے ٹیب میں کھولیں</translation>
 <translation id="8584427708066927472">پاس ورڈ کو اس آلے سے حذف کیا گیا</translation>
 <translation id="8585480574870650651">‏Crostini ہٹائیں</translation>
+<translation id="8585841788766257444">ذیل میں فہرست کردہ سائٹس ڈیفالٹ کے بجائے حسب ضرورت ترتیب کی پیروی کرتی ہیں</translation>
 <translation id="8588866096426746242">پروفائل کے اعداد و شمار دکھائیں</translation>
 <translation id="8588868914509452556">‏<ph name="WINDOW_TITLE" /> - VR ہیڈ سیٹ پر پیش کر رہا ہے</translation>
 <translation id="8590375307970699841">خود کار اپ ڈیٹس ترتیب دیں</translation>
@@ -6953,6 +6960,7 @@
 <translation id="9044646465488564462">نیٹ ورک سے منسلک ہونے میں ناکام ہوگیا: <ph name="DETAILS" /></translation>
 <translation id="9045430190527754450">‏Google کو اس صفحے کا ویب پتہ بھیجتا ہے جس تک آپ رسائی حاصل کرنے کی کوشش کر رہے ہیں</translation>
 <translation id="9046895021617826162">منسلک کرنا ناکام ہوگیا</translation>
+<translation id="9048868107467198961">سیکیورٹی کا کوئی مسئلہ نہیں ملا</translation>
 <translation id="9050666287014529139">پاس فریز</translation>
 <translation id="9052208328806230490">آپ نے اپنے پرنٹرز کو <ph name="CLOUD_PRINT_NAME" /> کے ساتھ اکاؤنٹ <ph name="EMAIL" /> استعمال کر کے رجسٹر کیا ہے</translation>
 <translation id="9052404922357793350">مسدود کرنا جاری رکھیں</translation>
@@ -6999,6 +7007,7 @@
 <translation id="9102610709270966160">ایکسٹینشن کو فعال کریں</translation>
 <translation id="9103479157856427471">زوم ان کردہ اسکرین کی بورڈ فوکس کے مطابق ہوتی ہے</translation>
 <translation id="9103868373786083162">پیچھے جانے کیلئے دبائیں، سرگزشت دیکھنے کیلئے سیاق وسباق کا مینو</translation>
+<translation id="9108035152087032312">ونڈو کا نام رکھیں...</translation>
 <translation id="9108072915170399168">موجودہ ڈیٹا استعمال کی ترتیب بغیر انٹرنیٹ کے ہے</translation>
 <translation id="9108692355621501797">‏<ph name="LINK_BEGIN" />G Suite for Education کی رازداری کے نوٹس<ph name="LINK_END" /> کا مقصد G Suite for Education کے صارفین اور والدین کو یہ سمجھنے میں مدد فراہم کرنا ہے کہ پروڈکٹ کون سا ڈیٹا اکٹھا کرتا ہے، کیوں کرتا ہے اور اس کے ساتھ کیا کِیا جاتا ہے۔</translation>
 <translation id="9108808586816295166">‏ممکن ہے کہ محفوظ DNS ہر وقت دستیاب نہ ہو</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index 3df11fe..d08ab3a 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -335,6 +335,7 @@
 <translation id="1374844444528092021">网络“<ph name="NETWORK_NAME" />”所需的证书尚未安装或已无效。请获取新的证书并尝试重新连接。</translation>
 <translation id="1375321115329958930">已保存的密码</translation>
 <translation id="137651782282853227">已保存的地址将显示在这里</translation>
+<translation id="1376771218494401509">为窗口命名(&amp;W)…</translation>
 <translation id="1377600615067678409">暂时跳过</translation>
 <translation id="1378613616312864539">此设置由“<ph name="NAME" />”控制</translation>
 <translation id="1380028686461971526">自动联网</translation>
@@ -3177,6 +3178,7 @@
 <translation id="4651484272688821107">无法加载包含演示模式资源的在线组件。</translation>
 <translation id="4652935475563630866">重新启动 Parallels Desktop 后,对摄像头设置做出的更改才能生效。请重新启动 Parallels Desktop 以继续。</translation>
 <translation id="4653405415038586100">配置 Linux 时出错</translation>
+<translation id="4653408778024877479">{NUM_WEAK,plural, =0{}=1{有 1 个安全系数低的密码}other{有 {NUM_WEAK} 个安全系数低的密码}}</translation>
 <translation id="4657914796247705218">TrackPoint 速度</translation>
 <translation id="465878909996028221">浏览器重定向仅支持 http、https 和文件协议。</translation>
 <translation id="4659077111144409915">主帐号</translation>
@@ -4961,6 +4963,7 @@
 <translation id="6785518634832172390">PIN 码不得超过 12 位数</translation>
 <translation id="6786747875388722282">扩展程序</translation>
 <translation id="6787839852456839824">键盘快捷键</translation>
+<translation id="6788036387349419582">{COUNT,plural, =1{有 # 个联系人不可用。如需使用“附近分享”功能与这个联系人分享内容,请将其 Google 帐号所关联的电子邮件地址添加到您的通讯录中。}other{有 # 个联系人不可用。如需使用“附近分享”功能与这些联系人分享内容,请将其 Google 帐号所关联的电子邮件地址添加到您的通讯录中。}}</translation>
 <translation id="6788210894632713004">未封装的扩展程序</translation>
 <translation id="6789592661892473991">水平分割</translation>
 <translation id="6790428901817661496">播放</translation>
@@ -5007,6 +5010,7 @@
 <translation id="683373380308365518">改用智能且安全的浏览器</translation>
 <translation id="6835762382653651563">请连接到互联网,以便更新您的<ph name="DEVICE_TYPE" />。</translation>
 <translation id="6838034009068684089">在网站想在您的屏幕上打开和放置窗口时询问您(推荐)</translation>
+<translation id="6838694093138907871">激活码无效,请重试。</translation>
 <translation id="6839225236531462745">证书删除错误</translation>
 <translation id="6839916869147598086">登录发生变化</translation>
 <translation id="6840155290835956714">发送前先询问</translation>
@@ -5247,6 +5251,7 @@
 <translation id="7093866338626856921">与具有下列名称的设备交换数据:<ph name="HOSTNAMES" /></translation>
 <translation id="7098389117866926363">USB-C 设备(背面左侧端口)</translation>
 <translation id="7098447629416471489">其他已保存的搜索引擎将显示在这里</translation>
+<translation id="709869441357640014">{NUM_COMPROMISED,plural, =0{}=1{有 1 个密码已遭泄露}other{有 {NUM_COMPROMISED} 个密码已遭泄露}}</translation>
 <translation id="7099337801055912064">无法加载过大的 PPD。大小上限为 250 KB。</translation>
 <translation id="7102687220333134671">已开启自动更新功能</translation>
 <translation id="7102832101143475489">此请求已超时</translation>
@@ -6253,6 +6258,7 @@
 <translation id="8253198102038551905">点击“+”可查看网络属性</translation>
 <translation id="8255451560461371599">无背景图片</translation>
 <translation id="8256319818471787266">狗狗</translation>
+<translation id="8257435388931378346">为“<ph name="ACTION" />”操作分配开关键</translation>
 <translation id="8257950718085972371">继续禁止使用摄像头</translation>
 <translation id="8259239505248583312">开始使用</translation>
 <translation id="8260864402787962391">鼠标</translation>
@@ -6516,6 +6522,7 @@
 <translation id="8584280235376696778">在新标签页中打开视频(&amp;O)</translation>
 <translation id="8584427708066927472">密码已从此设备中删除</translation>
 <translation id="8585480574870650651">移除 Crostini</translation>
+<translation id="8585841788766257444">下列网站采用的是自定义设置(而非默认设置)</translation>
 <translation id="8588866096426746242">显示个人资料统计信息</translation>
 <translation id="8588868914509452556"><ph name="WINDOW_TITLE" /> - 正在向头戴设备显示 VR</translation>
 <translation id="8590375307970699841">设置自动更新</translation>
@@ -6950,6 +6957,7 @@
 <translation id="9044646465488564462">无法连接到网络:<ph name="DETAILS" /></translation>
 <translation id="9045430190527754450">将您尝试访问的网页的网址发送至 Google</translation>
 <translation id="9046895021617826162">连接失败</translation>
+<translation id="9048868107467198961">未发现任何安全问题</translation>
 <translation id="9050666287014529139">密码</translation>
 <translation id="9052208328806230490">您已使用帐号 <ph name="EMAIL" /> 将您的打印机注册为<ph name="CLOUD_PRINT_NAME" /></translation>
 <translation id="9052404922357793350">继续拦截</translation>
@@ -6996,6 +7004,7 @@
 <translation id="9102610709270966160">启用扩展程序</translation>
 <translation id="9103479157856427471">放大的屏幕跟随键盘焦点</translation>
 <translation id="9103868373786083162">点按该按钮可后退,点按上下文菜单可查看历史记录</translation>
+<translation id="9108035152087032312">为窗口命名(&amp;W)…</translation>
 <translation id="9108072915170399168">当前的流量使用设置是“不使用互联网”</translation>
 <translation id="9108692355621501797"><ph name="LINK_BEGIN" />G Suite 教育版隐私权声明<ph name="LINK_END" />旨在帮助 G Suite 教育版用户和家长了解此产品会收集哪些数据、为什么收集这些数据以及会使用这些数据做什么。</translation>
 <translation id="9108808586816295166">安全 DNS 未必一直可用</translation>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index cfe82ac6..319d6b9 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1142,6 +1142,14 @@
     More
   </message>
 
+  <!-- Privacy Sandbox -->
+  <message name="IDS_SETTINGS_PRIVACY_SANDBOX_TITLE" desc="The title of the Privacy Sandbox page">
+    Privacy Sandbox
+  </message>
+  <message name="IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_HEADING" desc="The heading displayed at the top of the Privacy Sandbox page">
+    The Privacy Sandbox
+  </message>
+
   <!-- Safety check -->
   <message name="IDS_SETTINGS_SAFETY_CHECK_SECTION_TITLE" desc="'Safety check' is a noun phrase (sentence case). 'Safety check' refers to an area of the Settings page where users can quickly check whether their safety-related settings are fully protecting them.">
     Safety check
@@ -3204,6 +3212,9 @@
   <message name="IDS_SETTINGS_SECURITY_KEYS_SET_PIN" desc="A header that appears in the Settings subpage for security keys (which are external devices for user authentication). PINs are often four-digit codes, commonly used to authorise the use of ATM cards. A similar mechanism can be used with security keys and this is the heading for the section about settings them.">
     Create a PIN
   </message>
+  <message name="IDS_SETTINGS_SECURITY_KEYS_SET_PIN_BUTTON" desc="The label of a button that appears in the Settings subpage for security keys (which are external devices for user authentication). The button takes the user to a page where they can set or change their PIN. PINs are often four-digit codes, commonly used to authorise the use of ATM cards. A similar mechanism can be used with security keys.">
+    Set PIN
+  </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_SET_PIN_DESC" desc="A description that appears in the Settings subpage for security keys (which are external devices for user authentication). PINs are often four-digit codes, commonly used to authorise the use of ATM cards. A similar mechanism can be used with security keys and this is the description for the section about settings them.">
     Protect your security key with a PIN (Personal Identification Number)
   </message>
@@ -3386,10 +3397,16 @@
   <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_DELETE" desc="The label for a button that when clicked deletes a fingerprint from a security key (an authentication hardware device) with a built-in fingerprint reader.">
     Delete this fingerprint
   </message>
+  <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_NO_PIN" desc="An error message shown when a user attempts to enroll a fingerprint on their security key (an authentication hardware device), but the user has not set up a PIN (short, often numeric codes that are often used with, for example, ATM cards) for that security key.">
+    Your security key is not protected with a PIN. To manage fingerprints, first create a PIN.
+  </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_TOUCH_TO_CONTINUE" desc="A label instructing the user to physically touch the activation button on their security key (an authentication hardware device).">
     To continue, insert and touch your security key
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_PROMPT" desc="A label instructing the user to enter the PIN (short, often numeric codes that are often used with, for example, ATM cards) for their security key (an authentication hardware device).">
     Enter the PIN for your security key. If you don’t know the PIN, you’ll need to reset the security key.
   </message>
+  <message name="IDS_SETTINGS_SECURITY_KEYS_FORCE_PIN_CHANGE" desc="An error message shown when a user attempts to use a security key (an authentication hardware device) that has a default PIN (short, often numeric codes that are often used with, for example, ATM cards) set. Before using the key, the user needs to change the PIN to a new code.">
+    To use your new security key, set a new PIN
+  </message>
 </grit-part>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_BIO_NO_PIN.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_BIO_NO_PIN.png.sha1
new file mode 100644
index 0000000..afedeff
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_BIO_NO_PIN.png.sha1
@@ -0,0 +1 @@
+eb44b9901d0b216dffdf900a4622130c193ae9af
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_FORCE_PIN_CHANGE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_FORCE_PIN_CHANGE.png.sha1
new file mode 100644
index 0000000..c430844b
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_FORCE_PIN_CHANGE.png.sha1
@@ -0,0 +1 @@
+c16d9b56a804083f1767c81d54d9f02e0fc65433
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_SET_PIN_BUTTON.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_SET_PIN_BUTTON.png.sha1
new file mode 100644
index 0000000..afedeff
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SECURITY_KEYS_SET_PIN_BUTTON.png.sha1
@@ -0,0 +1 @@
+eb44b9901d0b216dffdf900a4622130c193ae9af
\ No newline at end of file
diff --git a/chrome/app/vector_icons/live_caption.icon b/chrome/app/vector_icons/live_caption.icon
index e74d9ed64..5962632 100644
--- a/chrome/app/vector_icons/live_caption.icon
+++ b/chrome/app/vector_icons/live_caption.icon
@@ -3,15 +3,15 @@
 // found in the LICENSE file.
 
 CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 5,
-CUBIC_TO, 2, 4.45f, 2.45f, 4, 3, 4,
-H_LINE_TO, 17,
-CUBIC_TO, 17.55f, 4, 18, 4.45f, 18, 5,
-V_LINE_TO, 15,
-CUBIC_TO, 18, 15.55f, 17.55f, 16, 17, 16,
-H_LINE_TO, 3,
-CUBIC_TO, 2.45f, 16, 2, 15.55f, 2, 15,
-V_LINE_TO, 5,
+MOVE_TO, 2, 5.5f,
+CUBIC_TO, 2, 4.67f, 2.67f, 4, 3.5f, 4,
+H_LINE_TO, 16.5f,
+CUBIC_TO, 17.33f, 4, 18, 4.67f, 18, 5.5f,
+V_LINE_TO, 14.5f,
+CUBIC_TO, 18, 15.33f, 17.33f, 16, 16.5f, 16,
+H_LINE_TO, 3.5f,
+CUBIC_TO, 2.67f, 16, 2, 15.33f, 2, 14.5f,
+V_LINE_TO, 5.5f,
 CLOSE,
 MOVE_TO, 4, 6,
 H_LINE_TO, 16,
@@ -20,26 +20,26 @@
 V_LINE_TO, 6,
 CLOSE,
 MOVE_TO, 5, 8,
-H_LINE_TO, 7,
+H_LINE_TO, 9,
 V_LINE_TO, 10,
 H_LINE_TO, 5,
 V_LINE_TO, 8,
 CLOSE,
-MOVE_TO, 13, 11,
-H_LINE_TO, 15,
-V_LINE_TO, 13,
-H_LINE_TO, 13,
-V_LINE_TO, 11,
-CLOSE,
-MOVE_TO, 15, 8,
-H_LINE_TO, 8,
-V_LINE_TO, 10,
-H_LINE_TO, 15,
-V_LINE_TO, 8,
-CLOSE,
 MOVE_TO, 5, 11,
 H_LINE_TO, 12,
 V_LINE_TO, 13,
 H_LINE_TO, 5,
 V_LINE_TO, 11,
+CLOSE,
+MOVE_TO, 15, 11,
+H_LINE_TO, 13,
+V_LINE_TO, 13,
+H_LINE_TO, 15,
+V_LINE_TO, 11,
+CLOSE,
+MOVE_TO, 10, 8,
+H_LINE_TO, 15,
+V_LINE_TO, 10,
+H_LINE_TO, 10,
+V_LINE_TO, 8,
 CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 494c2eb..b4e9f4d 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3451,6 +3451,8 @@
       "content_settings/generated_notification_pref.h",
       "custom_handlers/register_protocol_handler_permission_request.cc",
       "custom_handlers/register_protocol_handler_permission_request.h",
+      "device_api/device_service_impl.cc",
+      "device_api/device_service_impl.h",
       "device_identity/device_identity_provider.cc",
       "device_identity/device_identity_provider.h",
       "device_identity/device_oauth2_token_service.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a1912a2..a352e67e 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -7005,6 +7005,7 @@
 #endif  // OS_WIN
 
   if (!strcmp("dns-over-https", entry.internal_name) &&
+      SystemNetworkContextManager::GetInstance() &&
       (SystemNetworkContextManager::GetStubResolverConfigReader()
            ->ShouldDisableDohForManaged() ||
        features::kDnsOverHttpsShowUiParam.Get())) {
@@ -7083,6 +7084,10 @@
       base::BindRepeating(&ShouldSkipNonDeprecatedFeatureEntry));
 }
 
+flags_ui::FlagsState* GetCurrentFlagsState() {
+  return FlagsStateSingleton::GetFlagsState();
+}
+
 bool IsRestartNeededToCommitChanges() {
   return FlagsStateSingleton::GetFlagsState()->IsRestartNeededToCommitChanges();
 }
diff --git a/chrome/browser/about_flags.h b/chrome/browser/about_flags.h
index 2b33e725..64f399af 100644
--- a/chrome/browser/about_flags.h
+++ b/chrome/browser/about_flags.h
@@ -72,6 +72,9 @@
     base::ListValue* supported_entries,
     base::ListValue* unsupported_entries);
 
+// Gets the FlagsState used in about_flags.
+flags_ui::FlagsState* GetCurrentFlagsState();
+
 // Returns true if one of the feature entry flags has been flipped since
 // startup.
 bool IsRestartNeededToCommitChanges();
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.cc b/chrome/browser/android/compositor/layer/contextual_search_layer.cc
index 452a8a5..228d5f2 100644
--- a/chrome/browser/android/compositor/layer/contextual_search_layer.cc
+++ b/chrome/browser/android/compositor/layer/contextual_search_layer.cc
@@ -41,7 +41,6 @@
     int search_bar_shadow_resource_id,
     int search_provider_icon_resource_id,
     int quick_action_icon_resource_id,
-    int arrow_up_resource_id,
     int drag_handlebar_resource_id,
     int open_tab_icon_resource_id,
     int close_icon_resource_id,
@@ -83,8 +82,6 @@
     int bar_image_size,
     int icon_color,
     int drag_handlebar_color,
-    float arrow_icon_opacity,
-    float arrow_icon_rotation,
     float close_icon_opacity,
     bool progress_bar_visible,
     float progress_bar_height,
@@ -235,45 +232,6 @@
                      search_term_caption_spacing);
 
   // ---------------------------------------------------------------------------
-  // Arrow Icon.  Deprecated -- old layout only.
-  // ---------------------------------------------------------------------------
-  // Grabs the arrow icon resource.
-  ui::Resource* arrow_icon_resource =
-      resource_manager_->GetStaticResourceWithTint(arrow_up_resource_id,
-                                                   icon_color);
-
-  // Positions the icon at the end of the bar.
-  float arrow_icon_left;
-  if (is_rtl) {
-    arrow_icon_left = search_bar_margin_side;
-  } else {
-    arrow_icon_left = search_panel_width - arrow_icon_resource->size().width() -
-                      search_bar_margin_side;
-  }
-
-  // Centers the Arrow Icon vertically in the bar.
-  float arrow_icon_top = search_bar_top + search_bar_height / 2 -
-                         arrow_icon_resource->size().height() / 2;
-
-  arrow_icon_->SetUIResourceId(arrow_icon_resource->ui_resource()->id());
-  arrow_icon_->SetBounds(arrow_icon_resource->size());
-  arrow_icon_->SetPosition(
-      gfx::PointF(arrow_icon_left, arrow_icon_top));
-  arrow_icon_->SetOpacity(arrow_icon_opacity);
-
-  gfx::Transform transform;
-  if (arrow_icon_rotation != 0.f) {
-    // Apply rotation about the center of the icon.
-    float pivot_x = floor(arrow_icon_resource->size().width() / 2);
-    float pivot_y = floor(arrow_icon_resource->size().height() / 2);
-    gfx::PointF pivot_origin(pivot_x, pivot_y);
-    transform.Translate(pivot_origin.x(), pivot_origin.y());
-    transform.RotateAboutZAxis(arrow_icon_rotation);
-    transform.Translate(-pivot_origin.x(), -pivot_origin.y());
-  }
-  arrow_icon_->SetTransform(transform);
-
-  // ---------------------------------------------------------------------------
   // Search Promo
   // ---------------------------------------------------------------------------
   if (search_promo_visible) {
@@ -690,7 +648,6 @@
       search_provider_icon_layer_(cc::UIResourceLayer::Create()),
       thumbnail_layer_(cc::UIResourceLayer::Create()),
       quick_action_icon_layer_(cc::UIResourceLayer::Create()),
-      arrow_icon_(cc::UIResourceLayer::Create()),
       search_promo_(cc::UIResourceLayer::Create()),
       search_promo_container_(cc::SolidColorLayer::Create()),
       bar_banner_container_(cc::SolidColorLayer::Create()),
@@ -715,10 +672,6 @@
   // Search Bar Caption
   search_caption_->SetIsDrawable(true);
 
-  // Arrow Icon
-  arrow_icon_->SetIsDrawable(true);
-  layer_->AddChild(arrow_icon_);
-
   // Search Opt Out Promo
   search_promo_container_->SetIsDrawable(true);
   search_promo_container_->SetBackgroundColor(kSearchBackgroundColor);
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.h b/chrome/browser/android/compositor/layer/contextual_search_layer.h
index 44757bb..7bfd9708 100644
--- a/chrome/browser/android/compositor/layer/contextual_search_layer.h
+++ b/chrome/browser/android/compositor/layer/contextual_search_layer.h
@@ -43,7 +43,6 @@
                      int search_bar_shadow_resource_id,
                      int search_provider_icon_resource_id,
                      int quick_action_icon_resource_id,
-                     int arrow_up_resource_id,
                      int drag_handlebar_resource_id,
                      int open_tab_icon_resource_id,
                      int close_icon_resource_id,
@@ -85,8 +84,6 @@
                      int bar_image_size,
                      int icon_color,
                      int drag_handlebar_color,
-                     float arrow_icon_opacity,
-                     float arrow_icon_rotation,
                      float close_icon_opacity,
                      bool progress_bar_visible,
                      float progress_bar_height,
@@ -147,7 +144,6 @@
   scoped_refptr<cc::UIResourceLayer> search_provider_icon_layer_;
   scoped_refptr<cc::UIResourceLayer> thumbnail_layer_;
   scoped_refptr<cc::UIResourceLayer> quick_action_icon_layer_;
-  scoped_refptr<cc::UIResourceLayer> arrow_icon_;
   scoped_refptr<cc::UIResourceLayer> search_promo_;
   scoped_refptr<cc::SolidColorLayer> search_promo_container_;
   scoped_refptr<cc::SolidColorLayer> bar_banner_container_;
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
index ad8fd36c..e1aeb36 100644
--- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
@@ -76,7 +76,6 @@
     jint search_bar_shadow_resource_id,
     jint search_provider_icon_resource_id,
     jint quick_action_icon_resource_id,
-    jint arrow_up_resource_id,
     jint drag_handlebar_resource_id,
     jint open_tab_icon_resource_id,
     jint close_icon_resource_id,
@@ -123,8 +122,6 @@
     jint bar_image_size,
     jint icon_color,
     jint drag_handlebar_color,
-    jfloat arrow_icon_opacity,
-    jfloat arrow_icon_rotation,
     jfloat close_icon_opacity,
     jboolean progress_bar_visible,
     jfloat progress_bar_height,
@@ -171,26 +168,24 @@
       search_context_resource_id, search_term_resource_id,
       search_caption_resource_id, search_bar_shadow_resource_id,
       search_provider_icon_resource_id, quick_action_icon_resource_id,
-      arrow_up_resource_id, drag_handlebar_resource_id,
-      open_tab_icon_resource_id, close_icon_resource_id,
-      progress_bar_background_resource_id, progress_bar_resource_id,
-      search_promo_resource_id, bar_banner_ripple_resource_id,
-      bar_banner_text_resource_id, dp_to_px, content_layer,
-      search_promo_visible, search_promo_height, search_promo_opacity,
-      search_promo_background_color, search_bar_banner_visible,
-      search_bar_banner_height, search_bar_banner_padding,
-      search_bar_banner_ripple_width, search_bar_banner_ripple_opacity,
-      search_bar_banner_text_opacity, search_panel_x, search_panel_y,
-      search_panel_width, search_panel_height, search_bar_margin_side,
-      search_bar_margin_top, search_bar_height, search_context_opacity,
-      search_text_layer_min_height, search_term_opacity,
+      drag_handlebar_resource_id, open_tab_icon_resource_id,
+      close_icon_resource_id, progress_bar_background_resource_id,
+      progress_bar_resource_id, search_promo_resource_id,
+      bar_banner_ripple_resource_id, bar_banner_text_resource_id, dp_to_px,
+      content_layer, search_promo_visible, search_promo_height,
+      search_promo_opacity, search_promo_background_color,
+      search_bar_banner_visible, search_bar_banner_height,
+      search_bar_banner_padding, search_bar_banner_ripple_width,
+      search_bar_banner_ripple_opacity, search_bar_banner_text_opacity,
+      search_panel_x, search_panel_y, search_panel_width, search_panel_height,
+      search_bar_margin_side, search_bar_margin_top, search_bar_height,
+      search_context_opacity, search_text_layer_min_height, search_term_opacity,
       search_term_caption_spacing, search_caption_animation_percentage,
       search_caption_visible, search_bar_border_visible,
       search_bar_border_height, quick_action_icon_visible, thumbnail_visible,
       custom_image_visibility_percentage, bar_image_size, icon_color,
-      drag_handlebar_color, arrow_icon_opacity, arrow_icon_rotation,
-      close_icon_opacity, progress_bar_visible, progress_bar_height,
-      progress_bar_opacity, progress_bar_completion,
+      drag_handlebar_color, close_icon_opacity, progress_bar_visible,
+      progress_bar_height, progress_bar_opacity, progress_bar_completion,
       divider_line_visibility_percentage, divider_line_width,
       divider_line_height, divider_line_color, divider_line_x_offset,
       touch_highlight_visible, touch_highlight_x_offset, touch_highlight_width,
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h
index 41680fbc..39e04b91 100644
--- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h
+++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h
@@ -51,7 +51,6 @@
       jint search_bar_shadow_resource_id,
       jint search_provider_icon_resource_id,
       jint quick_action_icon_resource_id,
-      jint arrow_up_resource_id,
       jint drag_handlebar_resource_id,
       jint open_tab_icon_resource_id,
       jint close_icon_resource_id,
@@ -98,8 +97,6 @@
       jint bar_image_size,
       jint icon_color,
       jint drag_handlebar_color,
-      jfloat arrow_icon_opacity,
-      jfloat arrow_icon_rotation,
       jfloat close_icon_opacity,
       jboolean progress_bar_visible,
       jfloat progress_bar_height,
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
index ed06d0b..3ae6c53 100644
--- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc
+++ b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
@@ -153,7 +153,7 @@
   JNIEnv* env = AttachCurrentThread();
   std::vector<base::string16> titles;
   std::vector<base::android::ScopedJavaLocalRef<jobject>> urls;
-  std::vector<std::string> whitelist_icons;
+  std::vector<std::string> allowlist_icons;
   std::vector<int> title_sources;
   std::vector<int> sources;
   std::vector<int> section_types;
@@ -165,7 +165,7 @@
     for (const auto& tile : tiles) {
       titles.emplace_back(tile.title);
       urls.emplace_back(url::GURLAndroid::FromNativeGURL(env, tile.url));
-      whitelist_icons.emplace_back(tile.whitelist_icon_path.value());
+      allowlist_icons.emplace_back(tile.allowlist_icon_path.value());
       title_sources.emplace_back(static_cast<int>(tile.title_source));
       sources.emplace_back(static_cast<int>(tile.source));
       data_generation_times.emplace_back(
@@ -176,7 +176,7 @@
       env, observer_, ToJavaArrayOfStrings(env, titles),
       url::GURLAndroid::ToJavaArrayOfGURLs(env, urls),
       ToJavaIntArray(env, section_types),
-      ToJavaArrayOfStrings(env, whitelist_icons),
+      ToJavaArrayOfStrings(env, allowlist_icons),
       ToJavaIntArray(env, title_sources), ToJavaIntArray(env, sources),
       ToJavaLongArray(env, data_generation_times));
 }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 5363b278..1ddd395c 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -56,6 +56,7 @@
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "chrome/browser/data_use_measurement/chrome_data_use_measurement.h"
 #include "chrome/browser/defaults.h"
+#include "chrome/browser/device_api/device_service_impl.h"
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
@@ -311,6 +312,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/browser/web_ui_url_loader_factory.h"
+#include "content/public/common/bindings_policy.h"
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/content_descriptors.h"
 #include "content/public/common/content_features.h"
@@ -2984,21 +2986,26 @@
       ToBlinkPreferredColorScheme(native_theme->GetPreferredColorScheme());
 #endif  // defined(OS_ANDROID)
 
+  bool force_light = false;
   // Force a light preferred color scheme on certain URLs if kWebUIDarkMode is
   // disabled; some of the UI is not yet correctly themed.
   if (!base::FeatureList::IsEnabled(features::kWebUIDarkMode)) {
     // Update based on last committed url.
-    bool force_light = url.SchemeIs(content::kChromeUIScheme);
+    force_light |= url.SchemeIs(content::kChromeUIScheme);
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-    if (!force_light) {
-      force_light = url.SchemeIs(extensions::kExtensionScheme) &&
-                    url.host_piece() == extension_misc::kPdfExtensionId;
-    }
+    force_light |= url.SchemeIs(extensions::kExtensionScheme) &&
+                   url.host_piece() == extension_misc::kPdfExtensionId;
 #endif
-    if (force_light) {
-      web_prefs->preferred_color_scheme =
-          blink::mojom::PreferredColorScheme::kLight;
-    }
+  }
+
+  // Reauth WebUI doesn't support dark mode yet because it shares the dialog
+  // with GAIA web contents that is not correctly themed.
+  force_light |= url.SchemeIs(content::kChromeUIScheme) &&
+                 url.host_piece() == chrome::kChromeUISigninReauthHost;
+
+  if (force_light) {
+    web_prefs->preferred_color_scheme =
+        blink::mojom::PreferredColorScheme::kLight;
   }
 
   return old_preferred_color_scheme != web_prefs->preferred_color_scheme;
@@ -4962,6 +4969,13 @@
 }
 
 #if !defined(OS_ANDROID)
+void ChromeContentBrowserClient::CreateDeviceInfoService(
+    content::RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver) {
+  DCHECK(render_frame_host);
+  DeviceServiceImpl::Create(render_frame_host, std::move(receiver));
+}
+
 content::SerialDelegate* ChromeContentBrowserClient::GetSerialDelegate() {
   if (!serial_delegate_)
     serial_delegate_ = std::make_unique<ChromeSerialDelegate>();
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 2ffb17e..74c5d1f9 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -538,6 +538,9 @@
       mojo::PendingReceiver<blink::mojom::WebUsbService> receiver) override;
   content::BluetoothDelegate* GetBluetoothDelegate() override;
 #if !defined(OS_ANDROID)
+  void CreateDeviceInfoService(
+      content::RenderFrameHost* render_frame_host,
+      mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver) override;
   content::SerialDelegate* GetSerialDelegate() override;
   content::HidDelegate* GetHidDelegate() override;
   content::FontAccessDelegate* GetFontAccessDelegate() override;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index f43d9af..1945f20 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -193,6 +193,7 @@
     "//chromeos/dbus/upstart",
     "//chromeos/disks",
     "//chromeos/geolocation",
+    "//chromeos/ime:gencode",
     "//chromeos/login/auth",
     "//chromeos/login/login_state",
     "//chromeos/login/session",
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.cc
index 7afae76..cc007c3 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.cc
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.cc
@@ -24,6 +24,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/browser_resources.h"
+#include "chromeos/ime/input_methods.h"
 #include "extensions/browser/extension_pref_value_map.h"
 #include "extensions/browser/extension_pref_value_map_factory.h"
 #include "extensions/browser/extension_registry.h"
@@ -162,6 +163,12 @@
 ComponentExtensionIMEManagerDelegateImpl::
     ComponentExtensionIMEManagerDelegateImpl() {
   ReadComponentExtensionsInfo(&component_extension_list_);
+
+  for (const auto& input_method : input_method::kInputMethods) {
+    if (input_method.is_login_keyboard) {
+      login_layout_set_.insert(input_method.xkb_layout_id);
+    }
+  }
 }
 
 ComponentExtensionIMEManagerDelegateImpl::
@@ -192,6 +199,16 @@
                      base::Owned(copied_file_path)));
 }
 
+bool ComponentExtensionIMEManagerDelegateImpl::IsInLoginLayoutAllowlist(
+    const std::vector<std::string>& layouts) {
+  for (const auto& layout : layouts) {
+    if (login_layout_set_.find(layout) != login_layout_set_.end()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 std::unique_ptr<base::DictionaryValue>
 ComponentExtensionIMEManagerDelegateImpl::GetManifest(
     const std::string& manifest_string) {
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.h b/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.h
index 5b852ce7..367a05c 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.h
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.h
@@ -34,6 +34,8 @@
             const std::string& extension_id,
             const std::string& manifest,
             const base::FilePath& file_path) override;
+  bool IsInLoginLayoutAllowlist(
+      const std::vector<std::string>& layouts) override;
 
   static bool IsIMEExtensionID(const std::string& id);
 
@@ -64,6 +66,8 @@
   // The list of component extension IME.
   std::vector<ComponentExtensionIME> component_extension_list_;
 
+  std::set<std::string> login_layout_set_;
+
   DISALLOW_COPY_AND_ASSIGN(ComponentExtensionIMEManagerDelegateImpl);
 };
 
diff --git a/chrome/browser/chromeos/login/screens/enable_debugging_screen.cc b/chrome/browser/chromeos/login/screens/enable_debugging_screen.cc
index f9e71d3..30c7233 100644
--- a/chrome/browser/chromeos/login/screens/enable_debugging_screen.cc
+++ b/chrome/browser/chromeos/login/screens/enable_debugging_screen.cc
@@ -5,7 +5,26 @@
 #include "chrome/browser/chromeos/login/screens/enable_debugging_screen.h"
 
 #include "base/check.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/login/ui/login_display_host.h"
+#include "chrome/browser/chromeos/login/ui/login_web_dialog.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
+#include "chromeos/dbus/cryptohome/cryptohome_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
+#include "components/prefs/pref_service.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+constexpr char kUserActionCancel[] = "cancel";
+constexpr char kUserActionDone[] = "done";
+constexpr char kUserActionLearnMore[] = "learnMore";
+constexpr char kUserActionRemoveRootFSProtection[] = "removeRootFSProtection";
+}  // namespace
 
 namespace chromeos {
 
@@ -26,20 +45,16 @@
     view_->SetDelegate(nullptr);
 }
 
-void EnableDebuggingScreen::OnExit(bool success) {
-  if (is_hidden())
-    return;
-  exit_callback_.Run();
-}
-
 void EnableDebuggingScreen::OnViewDestroyed(EnableDebuggingScreenView* view) {
   if (view_ == view)
     view_ = nullptr;
 }
 
 void EnableDebuggingScreen::ShowImpl() {
-  if (view_)
+  if (view_) {
     view_->Show();
+    WaitForCryptohome();
+  }
 }
 
 void EnableDebuggingScreen::HideImpl() {
@@ -47,4 +62,153 @@
     view_->Hide();
 }
 
+void EnableDebuggingScreen::OnUserAction(const std::string& action_id) {
+  if (action_id == kUserActionCancel || action_id == kUserActionDone) {
+    exit_callback_.Run();
+  } else if (action_id == kUserActionLearnMore) {
+    HandleLearnMore();
+  } else if (action_id == kUserActionRemoveRootFSProtection) {
+    HandleRemoveRootFSProtection();
+  } else {
+    BaseScreen::OnUserAction(action_id);
+  }
+}
+
+void EnableDebuggingScreen::HandleLearnMore() {
+  VLOG(1) << "Trying to view the help article about debugging features.";
+  const std::string help_content =
+      l10n_util::GetStringUTF8(IDS_ENABLE_DEBUGGING_HELP);
+  const GURL data_url = GURL("data:text/html;charset=utf-8," + help_content);
+
+  LoginWebDialog* dialog = new LoginWebDialog(
+      Profile::FromWebUI(
+          LoginDisplayHost::default_host()->GetOobeUI()->web_ui()),
+      nullptr, LoginDisplayHost::default_host()->GetNativeWindow(),
+      base::string16(), data_url);
+  dialog->Show();
+}
+
+void EnableDebuggingScreen::HandleRemoveRootFSProtection() {
+  UpdateUIState(EnableDebuggingScreenView::UI_STATE_WAIT);
+  chromeos::DebugDaemonClient* client =
+      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
+  client->RemoveRootfsVerification(
+      base::BindOnce(&EnableDebuggingScreen::OnRemoveRootfsVerification,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+// Removes rootfs verification, add flag to start with enable debugging features
+// screen and reboots the machine.
+void EnableDebuggingScreen::OnRemoveRootfsVerification(bool success) {
+  if (!success) {
+    UpdateUIState(EnableDebuggingScreenView::UI_STATE_ERROR);
+    return;
+  }
+
+  PrefService* prefs = g_browser_process->local_state();
+  prefs->SetBoolean(prefs::kDebuggingFeaturesRequested, true);
+  prefs->CommitPendingWrite();
+  chromeos::PowerManagerClient::Get()->RequestRestart(
+      power_manager::REQUEST_RESTART_OTHER,
+      "login debugging screen removing rootfs verification");
+}
+
+void EnableDebuggingScreen::WaitForCryptohome() {
+  UpdateUIState(EnableDebuggingScreenView::UI_STATE_WAIT);
+  chromeos::CryptohomeClient* client = chromeos::CryptohomeClient::Get();
+  client->WaitForServiceToBeAvailable(base::BindOnce(
+      &EnableDebuggingScreen::OnCryptohomeDaemonAvailabilityChecked,
+      weak_ptr_factory_.GetWeakPtr()));
+}
+
+void EnableDebuggingScreen::OnCryptohomeDaemonAvailabilityChecked(
+    bool service_is_available) {
+  DVLOG(1) << "Enable-debugging-screen: cryptohomed availability="
+           << service_is_available;
+  if (!service_is_available) {
+    LOG(ERROR) << "Crypthomed is not available.";
+    UpdateUIState(EnableDebuggingScreenView::UI_STATE_ERROR);
+    return;
+  }
+
+  chromeos::DebugDaemonClient* client =
+      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
+  client->WaitForServiceToBeAvailable(base::BindOnce(
+      &EnableDebuggingScreen::OnDebugDaemonServiceAvailabilityChecked,
+      weak_ptr_factory_.GetWeakPtr()));
+}
+
+void EnableDebuggingScreen::OnDebugDaemonServiceAvailabilityChecked(
+    bool service_is_available) {
+  DVLOG(1) << "Enable-debugging-screen: debugd availability="
+           << service_is_available;
+  if (!service_is_available) {
+    LOG(ERROR) << "Debug daemon is not available.";
+    UpdateUIState(EnableDebuggingScreenView::UI_STATE_ERROR);
+    return;
+  }
+
+  // Check the status of debugging features.
+  chromeos::DebugDaemonClient* client =
+      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
+  client->QueryDebuggingFeatures(
+      base::BindOnce(&EnableDebuggingScreen::OnQueryDebuggingFeatures,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void EnableDebuggingScreen::OnQueryDebuggingFeatures(bool success,
+                                                     int features_flag) {
+  DVLOG(1) << "Enable-debugging-screen: OnQueryDebuggingFeatures"
+           << ", success=" << success << ", features=" << features_flag;
+  if (!success ||
+      features_flag == debugd::DevFeatureFlag::DEV_FEATURES_DISABLED) {
+    UpdateUIState(EnableDebuggingScreenView::UI_STATE_ERROR);
+    return;
+  }
+
+  if ((features_flag &
+       debugd::DevFeatureFlag::DEV_FEATURE_ROOTFS_VERIFICATION_REMOVED) == 0) {
+    UpdateUIState(EnableDebuggingScreenView::UI_STATE_REMOVE_PROTECTION);
+    return;
+  }
+
+  if ((features_flag & DebugDaemonClient::DEV_FEATURE_ALL_ENABLED) !=
+      DebugDaemonClient::DEV_FEATURE_ALL_ENABLED) {
+    UpdateUIState(EnableDebuggingScreenView::UI_STATE_SETUP);
+  } else {
+    UpdateUIState(EnableDebuggingScreenView::UI_STATE_DONE);
+  }
+}
+
+void EnableDebuggingScreen::HandleSetup(const std::string& password) {
+  UpdateUIState(EnableDebuggingScreenView::UI_STATE_WAIT);
+  chromeos::DebugDaemonClient* client =
+      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
+  client->EnableDebuggingFeatures(
+      password,
+      base::BindOnce(&EnableDebuggingScreen::OnEnableDebuggingFeatures,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void EnableDebuggingScreen::OnEnableDebuggingFeatures(bool success) {
+  if (!success) {
+    UpdateUIState(EnableDebuggingScreenView::UI_STATE_ERROR);
+    return;
+  }
+
+  UpdateUIState(EnableDebuggingScreenView::UI_STATE_DONE);
+}
+
+void EnableDebuggingScreen::UpdateUIState(
+    EnableDebuggingScreenView::UIState state) {
+  if (state == EnableDebuggingScreenView::UI_STATE_SETUP ||
+      state == EnableDebuggingScreenView::UI_STATE_ERROR ||
+      state == EnableDebuggingScreenView::UI_STATE_DONE) {
+    PrefService* prefs = g_browser_process->local_state();
+    prefs->ClearPref(prefs::kDebuggingFeaturesRequested);
+    prefs->CommitPendingWrite();
+  }
+  view_->UpdateUIState(state);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/enable_debugging_screen.h b/chrome/browser/chromeos/login/screens/enable_debugging_screen.h
index f3c0334..cc6a4c48 100644
--- a/chrome/browser/chromeos/login/screens/enable_debugging_screen.h
+++ b/chrome/browser/chromeos/login/screens/enable_debugging_screen.h
@@ -9,6 +9,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/login/screens/base_screen.h"
 #include "chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h"
 
@@ -23,20 +24,47 @@
   ~EnableDebuggingScreen() override;
 
   // Called by EnableDebuggingScreenHandler.
-  void OnExit(bool success);
   void OnViewDestroyed(EnableDebuggingScreenView* view);
+  void HandleSetup(const std::string& password);
 
  protected:
   // BaseScreen:
   void ShowImpl() override;
   void HideImpl() override;
+  void OnUserAction(const std::string& action_id) override;
 
   base::RepeatingClosure* exit_callback() { return &exit_callback_; }
 
  private:
+  // Handle user actions
+  void HandleLearnMore();
+  void HandleRemoveRootFSProtection();
+
+  // Wait for cryptohomed before checking debugd. See http://crbug.com/440506
+  void WaitForCryptohome();
+
+  // Callback for CryptohomeClient::WaitForServiceToBeAvailable
+  void OnCryptohomeDaemonAvailabilityChecked(bool service_is_available);
+
+  // Callback for DebugDaemonClient::WaitForServiceToBeAvailable
+  void OnDebugDaemonServiceAvailabilityChecked(bool service_is_available);
+
+  // Callback for DebugDaemonClient::EnableDebuggingFeatures().
+  void OnEnableDebuggingFeatures(bool success);
+
+  // Callback for DebugDaemonClient::QueryDebuggingFeatures().
+  void OnQueryDebuggingFeatures(bool success, int features_flag);
+
+  // Callback for DebugDaemonClient::RemoveRootfsVerification().
+  void OnRemoveRootfsVerification(bool success);
+
+  void UpdateUIState(EnableDebuggingScreenView::UIState state);
+
   EnableDebuggingScreenView* view_;
   base::RepeatingClosure exit_callback_;
 
+  base::WeakPtrFactory<EnableDebuggingScreen> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(EnableDebuggingScreen);
 };
 
diff --git a/chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h b/chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h
index 774ab57..b982e5b9 100644
--- a/chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h
+++ b/chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h
@@ -20,6 +20,7 @@
 
   MOCK_METHOD(void, ShowImpl, ());
   MOCK_METHOD(void, HideImpl, ());
+  MOCK_METHOD(void, OnUserAction, (const std::string& action_id));
 
   void ExitScreen();
 };
@@ -32,6 +33,7 @@
   MOCK_METHOD(void, Show, ());
   MOCK_METHOD(void, Hide, ());
   MOCK_METHOD(void, MockSetDelegate, (EnableDebuggingScreen * screen));
+  MOCK_METHOD(void, UpdateUIState, (UIState state));
 
   void SetDelegate(EnableDebuggingScreen* screen) override;
 
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
index c3e9d76f4..f6948a3 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -460,6 +460,9 @@
 }
 
 LoginDisplayHostWebUI::~LoginDisplayHostWebUI() {
+  if (GetOobeUI())
+    GetOobeUI()->signin_screen_handler()->SetDelegate(nullptr);
+
   SessionManagerClient::Get()->RemoveObserver(this);
   CrasAudioHandler::Get()->RemoveAudioObserver(this);
   display::Screen::GetScreen()->RemoveObserver(this);
@@ -818,7 +821,7 @@
                                              views::View* view) {
   if (view != static_cast<views::View*>(login_view_))
     return;
-  login_view_ = nullptr;
+  ResetLoginView();
   widget->RemoveRemovalsObserver(this);
 }
 
@@ -830,7 +833,7 @@
   login_window_->RemoveObserver(this);
 
   login_window_ = nullptr;
-  login_view_ = nullptr;
+  ResetLoginView();
 }
 
 void LoginDisplayHostWebUI::OnWidgetBoundsChanged(views::Widget* widget,
@@ -949,7 +952,7 @@
   // `login_view_` pointer.
   if (login_view_) {
     login_view_->SetUIEnabled(true);
-    login_view_ = nullptr;
+    ResetLoginView();
   }
 
   if (login_window_) {
@@ -976,6 +979,17 @@
   PlayStartupSoundIfPossible();
 }
 
+void LoginDisplayHostWebUI::ResetLoginView() {
+  if (!login_view_)
+    return;
+
+  OobeUI* oobe_ui = login_view_->GetOobeUI();
+  if (oobe_ui)
+    oobe_ui->signin_screen_handler()->SetDelegate(nullptr);
+
+  login_view_ = nullptr;
+}
+
 void LoginDisplayHostWebUI::OnLoginPromptVisible() {
   if (!login_prompt_visible_time_.is_null())
     return;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.h b/chrome/browser/chromeos/login/ui/login_display_host_webui.h
index 8677a03..16d4d9c 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_webui.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.h
@@ -199,6 +199,9 @@
   // Plays startup sound if needed and audio device is ready.
   void PlayStartupSoundIfPossible();
 
+  // Resets login view and unbinds login display from the signin screen handler.
+  void ResetLoginView();
+
   // Sign in screen controller.
   std::unique_ptr<ExistingUserController> existing_user_controller_;
 
diff --git a/chrome/browser/chromeos/login/ui/login_display_webui.cc b/chrome/browser/chromeos/login/ui/login_display_webui.cc
index a94dcae..35129c2 100644
--- a/chrome/browser/chromeos/login/ui/login_display_webui.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_webui.cc
@@ -34,8 +34,6 @@
 // LoginDisplayWebUI, public: --------------------------------------------------
 
 LoginDisplayWebUI::~LoginDisplayWebUI() {
-  if (webui_handler_)
-    webui_handler_->ResetSigninScreenHandlerDelegate();
   ui::UserActivityDetector* activity_detector = ui::UserActivityDetector::Get();
   if (activity_detector && activity_detector->HasObserver(this))
     activity_detector->RemoveObserver(this);
diff --git a/chrome/browser/device_api/OWNERS b/chrome/browser/device_api/OWNERS
new file mode 100644
index 0000000..bba2979
--- /dev/null
+++ b/chrome/browser/device_api/OWNERS
@@ -0,0 +1,5 @@
+apotapchuk@chromium.org
+anqing@chromium.org
+
+# Policy stack owners.
+file://chrome/browser/chromeos/policy/OWNERS
diff --git a/chrome/browser/device_api/device_service_impl.cc b/chrome/browser/device_api/device_service_impl.cc
new file mode 100644
index 0000000..1710491
--- /dev/null
+++ b/chrome/browser/device_api/device_service_impl.cc
@@ -0,0 +1,72 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "chrome/browser/device_api/device_service_impl.h"
+
+#include <memory>
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/web_applications/components/policy/web_app_policy_constants.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "url/origin.h"
+
+namespace {
+
+bool IsTrustedContext(content::RenderFrameHost* host,
+                      const url::Origin& origin) {
+  PrefService* prefs =
+      Profile::FromBrowserContext(host->GetBrowserContext())->GetPrefs();
+
+  // TODO(apotapchuk): Implement a more efficient way of checking the trustness
+  // status of the app.
+  for (const base::Value& entry :
+       prefs->GetList(prefs::kWebAppInstallForceList)->GetList()) {
+    if (origin ==
+        url::Origin::Create(GURL(entry.FindKey(web_app::kUrlKey)->GetString())))
+      return true;
+  }
+  return false;
+}
+
+}  // namespace
+
+DeviceServiceImpl::DeviceServiceImpl(
+    content::RenderFrameHost* host,
+    mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver)
+    : FrameServiceBase(host, std::move(receiver)), host_(host) {
+  pref_change_registrar_.Init(
+      Profile::FromBrowserContext(host->GetBrowserContext())->GetPrefs());
+  pref_change_registrar_.Add(
+      prefs::kWebAppInstallForceList,
+      base::BindRepeating(&DeviceServiceImpl::OnForceInstallWebAppListChanged,
+                          base::Unretained(this)));
+}
+DeviceServiceImpl::~DeviceServiceImpl() = default;
+
+// static
+void DeviceServiceImpl::Create(
+    content::RenderFrameHost* host,
+    mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  if (!IsTrustedContext(host,
+                        url::Origin::Create(host->GetLastCommittedURL()))) {
+    // Not sending bad message here since the API is always exposed to the end
+    // user.
+    return;
+  }
+  // The object is bound to the lifetime of |host| and the mojo
+  // connection. See FrameServiceBase for details.
+  new DeviceServiceImpl(host, std::move(receiver));
+}
+
+void DeviceServiceImpl::OnForceInstallWebAppListChanged() {
+  // DeviceServiceImpl is allocated on the heap, thus it is safe to remove it
+  // like this.
+  if (!IsTrustedContext(host_, origin())) {
+    delete this;
+  }
+}
diff --git a/chrome/browser/device_api/device_service_impl.h b/chrome/browser/device_api/device_service_impl.h
new file mode 100644
index 0000000..8ab0c152
--- /dev/null
+++ b/chrome/browser/device_api/device_service_impl.h
@@ -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.
+
+#ifndef CHROME_BROWSER_DEVICE_API_DEVICE_SERVICE_IMPL_H_
+#define CHROME_BROWSER_DEVICE_API_DEVICE_SERVICE_IMPL_H_
+
+#include "base/scoped_observer.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "content/public/browser/frame_service_base.h"
+#include "third_party/blink/public/mojom/device/device.mojom.h"
+
+namespace content {
+class RenderFrameHost;
+}
+
+// A browser-side mojo service, which corresponds to the navigator.device Web
+// API. Available only to trusted web applications.
+class DeviceServiceImpl final
+    : public content::FrameServiceBase<blink::mojom::DeviceAPIService> {
+ public:
+  // Tries to attach this mojo service to |host| for trusted web applications.
+  // Will dynamically disconnect if the trustness status is revoked.
+  static void Create(
+      content::RenderFrameHost* host,
+      mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver);
+
+  DeviceServiceImpl(const DeviceServiceImpl&) = delete;
+  DeviceServiceImpl& operator=(const DeviceServiceImpl&) = delete;
+  ~DeviceServiceImpl() override;
+
+ private:
+  DeviceServiceImpl(
+      content::RenderFrameHost* host,
+      mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver);
+
+  void OnForceInstallWebAppListChanged();
+
+  content::RenderFrameHost* const host_;
+  PrefChangeRegistrar pref_change_registrar_;
+};
+
+#endif  // CHROME_BROWSER_DEVICE_API_DEVICE_SERVICE_IMPL_H_
diff --git a/chrome/browser/device_api/device_service_unittest.cc b/chrome/browser/device_api/device_service_unittest.cc
new file mode 100644
index 0000000..2b7f547
--- /dev/null
+++ b/chrome/browser/device_api/device_service_unittest.cc
@@ -0,0 +1,78 @@
+// 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/device_api/device_service_impl.h"
+
+#include <utility>
+
+#include "chrome/browser/web_applications/components/policy/web_app_policy_constants.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/navigation_simulator.h"
+#include "url/gurl.h"
+
+namespace {
+
+constexpr char kDefaultAppInstallUrl[] = "https://example.com/";
+constexpr char kTrustedUrl[] = "https://example.com/sample";
+constexpr char kUntrustedUrl[] = "https://non-example.com/sample";
+
+}  // namespace
+
+class DeviceAPIServiceTest : public ChromeRenderViewHostTestHarness {
+ public:
+  void SetUp() override {
+    ChromeRenderViewHostTestHarness::SetUp();
+    InstallTrustedApp();
+  }
+
+  void InstallTrustedApp() {
+    ListPrefUpdate update(profile()->GetPrefs(),
+                          prefs::kWebAppInstallForceList);
+    base::DictionaryValue app_policy;
+    app_policy.SetString(web_app::kUrlKey, kDefaultAppInstallUrl);
+    update->Append(std::move(app_policy));
+  }
+
+  void RemoveTrustedApp() {
+    ListPrefUpdate update(profile()->GetPrefs(),
+                          prefs::kWebAppInstallForceList);
+    update->ClearList();
+  }
+
+  void TryCreatingService(const GURL& url) {
+    content::NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(),
+                                                               url);
+    DeviceServiceImpl::Create(main_rfh(), remote_.BindNewPipeAndPassReceiver());
+  }
+
+  mojo::Remote<blink::mojom::DeviceAPIService>* remote() { return &remote_; }
+
+ private:
+  mojo::Remote<blink::mojom::DeviceAPIService> remote_;
+  std::unique_ptr<base::RunLoop> loop_;
+};
+
+TEST_F(DeviceAPIServiceTest, ConnectsForTrustedApps) {
+  TryCreatingService(GURL(kTrustedUrl));
+  remote()->FlushForTesting();
+  ASSERT_TRUE(remote()->is_connected());
+}
+
+TEST_F(DeviceAPIServiceTest, DoesNotConnectForUntrustedApps) {
+  TryCreatingService(GURL(kUntrustedUrl));
+  remote()->FlushForTesting();
+  ASSERT_FALSE(remote()->is_connected());
+}
+
+TEST_F(DeviceAPIServiceTest, DisconnectWhenTrustRevoked) {
+  TryCreatingService(GURL(kTrustedUrl));
+  remote()->FlushForTesting();
+  RemoveTrustedApp();
+  remote()->FlushForTesting();
+  ASSERT_FALSE(remote()->is_connected());
+}
diff --git a/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 99736df8..59e0cc92 100644
--- a/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/values.h"
 #include "chrome/browser/devtools/protocol/devtools_protocol_test_support.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/ssl_status.h"
@@ -66,6 +67,26 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
+                       NewTabPageInCreatedContextDoesNotCrash) {
+  AttachToBrowser();
+  SendCommandSync("Target.createBrowserContext");
+  std::string* context_id_value = result_.FindStringPath("browserContextId");
+  ASSERT_TRUE(context_id_value);
+  std::string context_id = *context_id_value;
+
+  base::DictionaryValue params;
+  params.SetStringPath("url", chrome::kChromeUINewTabURL);
+  params.SetStringPath("browserContextId", context_id);
+  content::WebContentsAddedObserver observer;
+  SendCommandSync("Target.createTarget", std::move(params));
+  content::WebContents* wc = observer.GetWebContents();
+  ASSERT_TRUE(content::WaitForLoadStop(wc));
+  EXPECT_EQ(chrome::kChromeUINewTabURL, wc->GetLastCommittedURL().spec());
+
+  // Should not crash by this point.
+}
+
 IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, VisibleSecurityStateSecureState) {
   net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
   https_server.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc
index 5c24dc2..4e04a86c 100644
--- a/chrome/browser/download/download_prefs.cc
+++ b/chrome/browser/download/download_prefs.cc
@@ -556,7 +556,6 @@
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // TODO(https://crbug.com/1148848): Sort out path sanitization for Lacros.
   // This will require refactoring the ash-only code below so it can be shared.
-  // For now, only allow downloads into the Downloads directory and children.
   const base::FilePath default_downloads_path =
       GetDefaultDownloadDirectoryForProfile();
   // Relative paths might be unsafe, so use the default path.
@@ -569,6 +568,12 @@
   if (default_downloads_path == path || default_downloads_path.IsParent(path))
     return path;
 
+  // Allow documents directory ("MyFiles") and subdirectories.
+  base::FilePath documents_path =
+      base::PathService::CheckedGet(chrome::DIR_USER_DOCUMENTS);
+  if (documents_path == path || documents_path.IsParent(path))
+    return path;
+
   // Otherwise, return the safe default.
   return default_downloads_path;
 #elif BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/download/download_prefs_unittest.cc b/chrome/browser/download/download_prefs_unittest.cc
index 6071be57..d8a4d507 100644
--- a/chrome/browser/download/download_prefs_unittest.cc
+++ b/chrome/browser/download/download_prefs_unittest.cc
@@ -26,6 +26,11 @@
 #include "components/drive/drive_pref_names.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "base/path_service.h"
+#include "chrome/common/chrome_paths.h"
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 using safe_browsing::FileTypePolicies;
 
 namespace {
@@ -381,9 +386,19 @@
   const base::FilePath default_dir =
       prefs.GetDefaultDownloadDirectoryForProfile();
 
-  // Test a valid path.
+  // Test a valid subdirectory of downloads.
   ExpectValidDownloadDir(&profile, &prefs, default_dir.AppendASCII("testdir"));
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  // Test a valid subdirectory of documents. This isn't tested for ash because
+  // these tests run on the linux "emulator", where ash uses ~/Documents, but
+  // the ash path sanitization code doesn't handle that path.
+  base::FilePath documents_path =
+      base::PathService::CheckedGet(chrome::DIR_USER_DOCUMENTS);
+  ExpectValidDownloadDir(&profile, &prefs,
+                         documents_path.AppendASCII("testdir"));
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
   // Test with an invalid path outside the download directory.
   profile.GetPrefs()->SetString(prefs::kDownloadDefaultDirectory,
                                 "/home/chronos");
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
index 9410aa0..3d6059a 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
@@ -28,6 +28,8 @@
 #include "crypto/scoped_nss_types.h"
 #include "crypto/scoped_test_system_nss_key_slot.h"
 #include "extensions/browser/extension_registry.h"
+#include "extensions/test/extension_test_message_listener.h"
+#include "extensions/test/result_catcher.h"
 #include "net/cert/nss_cert_database.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -37,6 +39,17 @@
 
 namespace {
 
+// The test extension will query for the state of the system token.
+constexpr char kWaitingForSystemTokenStateMessage[] =
+    "Waiting for system token state message";
+
+// The message sent from a browsertest to the background script in case the
+// system token is enabled.
+constexpr char kSystemTokenEnabledMessage[] = "System token enabled.";
+// The message sent from a browsertest to the background script in case the
+// system token is disabled.
+constexpr char kSystemTokenDisabledMessage[] = "System token disabled.";
+
 // The test extension has a certificate referencing this private key which will
 // be stored in the user's token in the test setup.
 //
@@ -106,8 +119,7 @@
     0xbb, 0xc2, 0x63, 0x8a, 0xaa, 0x28, 0xd5, 0x37, 0x72, 0xed, 0x02, 0x20,
     0x16, 0xde, 0x3d, 0x57, 0xc5, 0xd5, 0x3d, 0x90, 0x8b, 0xfd, 0x90, 0x3b,
     0xd8, 0x71, 0x69, 0x5e, 0x8d, 0xb4, 0x48, 0x1c, 0xa4, 0x01, 0xce, 0xc1,
-    0xb5, 0x6f, 0xe9, 0x1b, 0x32, 0x91, 0x34, 0x38
-};
+    0xb5, 0x6f, 0xe9, 0x1b, 0x32, 0x91, 0x34, 0x38};
 
 void ImportPrivateKeyPKCS8ToSlot(const unsigned char* pkcs8_der,
                                  size_t pkcs8_der_size,
@@ -115,8 +127,7 @@
   SECItem pki_der_user = {
       siBuffer,
       // NSS requires non-const data even though it is just for input.
-      const_cast<unsigned char*>(pkcs8_der),
-      pkcs8_der_size};
+      const_cast<unsigned char*>(pkcs8_der), pkcs8_der_size};
 
   SECKEYPrivateKey* seckey_raw = nullptr;
   ASSERT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfoAndReturnKey(
@@ -208,6 +219,16 @@
   const std::string kUpdateManifestFileName =
       "enterprise_platform_keys_update_manifest.xml";
 
+  void SetUpTestListeners() {
+    catcher_ = std::make_unique<extensions::ResultCatcher>();
+    listener_ = std::make_unique<ExtensionTestMessageListener>(
+        kWaitingForSystemTokenStateMessage,
+        /*will_reply=*/true);
+  }
+
+  std::unique_ptr<extensions::ResultCatcher> catcher_;
+  std::unique_ptr<ExtensionTestMessageListener> listener_;
+
  private:
   void PrepareTestSystemSlotOnIO(
       crypto::ScopedTestSystemNSSKeySlot* system_slot) override {
@@ -252,20 +273,20 @@
 
 IN_PROC_BROWSER_TEST_P(EnterprisePlatformKeysTest, Basic) {
   {
-   base::RunLoop loop;
-   GetNSSCertDatabaseForProfile(
-       profile(),
-       base::BindOnce(&EnterprisePlatformKeysTest::DidGetCertDatabase,
-                      base::Unretained(this), loop.QuitClosure()));
-   loop.Run();
+    base::RunLoop loop;
+    GetNSSCertDatabaseForProfile(
+        profile(),
+        base::BindOnce(&EnterprisePlatformKeysTest::DidGetCertDatabase,
+                       base::Unretained(this), loop.QuitClosure()));
+    loop.Run();
   }
   policy_test_utils::SetExtensionInstallForcelistPolicy(
       kTestExtensionID,
       embedded_test_server()->GetURL("/" + kUpdateManifestFileName), profile(),
       mock_policy_provider());
 
-  // By default, the system token is disabled.
-  std::string system_token_availability;
+  SetUpTestListeners();
+  ASSERT_TRUE(listener_->WaitUntilSatisfied());
 
   // Only if the system token exists, and the current user is of the same domain
   // as the device is enrolled to, the system token is available to the
@@ -273,13 +294,12 @@
   if (system_token_status() == SystemTokenStatus::EXISTS &&
       enrollment_status() == EnrollmentStatus::ENROLLED &&
       user_status() == UserStatus::MANAGED_AFFILIATED_DOMAIN) {
-    system_token_availability = "systemTokenEnabled";
+    listener_->Reply(kSystemTokenEnabledMessage);
+  } else {
+    listener_->Reply(kSystemTokenDisabledMessage);
   }
 
-  ASSERT_TRUE(TestExtension(
-      base::StringPrintf("chrome-extension://%s/basic.html?%s",
-                         kTestExtensionID, system_token_availability.c_str())))
-      << message_;
+  ASSERT_TRUE(catcher_->GetNextResult());
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index a290c998..b70fd4a 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -4361,7 +4361,7 @@
   {
     "name": "show-metered-toggle",
     "owners": [ "stevenjb" ],
-    "expiry_milestone": 87
+    "expiry_milestone": 92
   },
   {
     "name": "show-overdraw-feedback",
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 4fad004d..378fff4 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -79,7 +79,10 @@
     &autofill_assistant::features::kAutofillAssistant,
     &autofill_assistant::features::kAutofillAssistantChromeEntry,
     &autofill_assistant::features::kAutofillAssistantDirectActions,
+    &autofill_assistant::features::kAutofillAssistantDisableOnboardingFlow,
     &autofill_assistant::features::kAutofillAssistantProactiveHelp,
+    &autofill_assistant::features::
+        kAutofillAssistantDisableProactiveHelpTiedToMSBB,
     &device::kWebAuthPhoneSupport,
     &download::features::kDownloadAutoResumptionNative,
     &download::features::kDownloadLater,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 0e5cff3..67cf453 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -219,7 +219,11 @@
     public static final String AUTOFILL_ASSISTANT = "AutofillAssistant";
     public static final String AUTOFILL_ASSISTANT_CHROME_ENTRY = "AutofillAssistantChromeEntry";
     public static final String AUTOFILL_ASSISTANT_DIRECT_ACTIONS = "AutofillAssistantDirectActions";
+    public static final String AUTOFILL_ASSISTANT_DISABLE_ONBOARDING_FLOW =
+            "AutofillAssistantDisableOnboardingFlow";
     public static final String AUTOFILL_ASSISTANT_PROACTIVE_HELP = "AutofillAssistantProactiveHelp";
+    public static final String AUTOFILL_ASSISTANT_DISABLE_PROACTIVE_HELP_TIED_TO_MSBB =
+            "AutofillAssistantDisableProactiveHelpTiedToMSBB";
     public static final String AUTOFILL_MANUAL_FALLBACK_ANDROID = "AutofillManualFallbackAndroid";
     public static final String AUTOFILL_REFRESH_STYLE_ANDROID = "AutofillRefreshStyleAndroid";
     public static final String AUTOFILL_KEYBOARD_ACCESSORY = "AutofillKeyboardAccessory";
diff --git a/chrome/browser/metrics/authenticator_utility.cc b/chrome/browser/metrics/authenticator_utility.cc
index c3fd6a49..95e990c 100644
--- a/chrome/browser/metrics/authenticator_utility.cc
+++ b/chrome/browser/metrics/authenticator_utility.cc
@@ -56,7 +56,11 @@
   }
   Profile* profile = profile_manager->GetProfileByPath(
       profile_manager->GetLastUsedProfileDir(profile_manager->user_data_dir()));
-  DCHECK(profile);
+  // Some tests have profiles but do not load the last profile before
+  // PostBrowserStart().
+  if (!profile) {
+    return;
+  }
 
   // Return to a low-priority thread for the actual check.
   base::ThreadPool::PostTask(
diff --git a/chrome/browser/metrics/perf/BUILD.gn b/chrome/browser/metrics/perf/BUILD.gn
index b5bbd29..50f96b6 100644
--- a/chrome/browser/metrics/perf/BUILD.gn
+++ b/chrome/browser/metrics/perf/BUILD.gn
@@ -11,6 +11,7 @@
     "//base",
     "//base/test:test_support",
     "//chrome/browser",
+    "//chrome/test:test_support",
     "//chromeos/dbus",
     "//content/test:test_support",
     "//testing/gtest",
diff --git a/chrome/browser/metrics/perf/metric_provider.cc b/chrome/browser/metrics/perf/metric_provider.cc
index ebe16aa..1efbf32 100644
--- a/chrome/browser/metrics/perf/metric_provider.cc
+++ b/chrome/browser/metrics/perf/metric_provider.cc
@@ -9,6 +9,13 @@
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chromeos/constants/chromeos_features.h"
+#include "components/sync/base/user_selectable_type.h"
+#include "components/sync/driver/sync_service.h"
+#include "components/sync/driver/sync_user_settings.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "third_party/metrics_proto/sampled_profile.pb.h"
@@ -21,17 +28,64 @@
 // metric provider.
 const char kUploadCountHistogramPrefix[] = "ChromeOS.CWP.Upload";
 
+// Name prefix of the histogram that tracks the various outcomes of saving the
+// collected profile to local cache.
+const char kRecordOutcomeHistogramPrefix[] = "ChromeOS.CWP.Record";
+
 // An upper bound on the count of reports expected to be uploaded by an UMA
 // callback.
 const int kMaxValueUploadReports = 10;
 
+// The MD5 prefix to replace the original comm_md5_prefix of COMM events in perf
+// data proto, if necessary. We used string "<redacted>" to compute this MD5
+// prefix.
+const uint64_t kRedactedCommMd5Prefix = 0xee1f021828a1fcbc;
+
+// This function modifies the comm_md5_prefix of all the COMM events in the
+// given perf data proto by replacing it with the md5 prefix of an artificial
+// string.
+void RedactCommMd5Prefixes(PerfDataProto* proto) {
+  for (PerfDataProto::PerfEvent& event : *proto->mutable_events()) {
+    if (event.has_comm_event()) {
+      event.mutable_comm_event()->set_comm_md5_prefix(kRedactedCommMd5Prefix);
+    }
+  }
+}
+
+// Check if App Sync is enabled for a given user profile.
+bool IsAppSyncEnabledForUserProfile(Profile* profile) {
+  syncer::SyncService* sync_service =
+      ProfileSyncServiceFactory::GetForProfile(profile);
+  if (!sync_service)
+    return false;
+  syncer::SyncUserSettings* sync_settings = sync_service->GetUserSettings();
+
+  // Chrome versions >= M78 have a feature that splits the sync settings between
+  // Chrome and ChromeOS. The App Sync toggle is moved under the ChromeOS
+  // settings. If the split sync setting is enabled, we will directly read from
+  // the OS settings. Otherwise, we read from Chrome settings. We then check if
+  // the sync feature is enabled and the App Sync toggle is on.
+  if (chromeos::features::IsSplitSettingsSyncEnabled()) {
+    return sync_settings->IsOsSyncFeatureEnabled() &&
+           sync_settings->GetSelectedOsTypes().Has(
+               syncer::UserSelectableOsType::kOsApps);
+  }
+  // Read chrome settings if split sync is disabled.
+  return sync_service->IsSyncFeatureEnabled() &&
+         sync_settings->GetSelectedTypes().Has(
+             syncer::UserSelectableType::kApps);
+}
+
 }  // namespace
 
 using MetricCollector = internal::MetricCollector;
 
-MetricProvider::MetricProvider(std::unique_ptr<MetricCollector> collector)
+MetricProvider::MetricProvider(std::unique_ptr<MetricCollector> collector,
+                               ProfileManager* profile_manager)
     : upload_uma_histogram_(std::string(kUploadCountHistogramPrefix) +
                             collector->ToolName()),
+      record_uma_histogram_(std::string(kRecordOutcomeHistogramPrefix) +
+                            collector->ToolName()),
       // Run the collector at a higher priority to enable fast triggering of
       // profile collections. In particular, we want fast triggering when
       // jankiness is detected, but even random based periodic collection
@@ -42,6 +96,7 @@
       collector_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
           {base::TaskPriority::USER_VISIBLE})),
       metric_collector_(std::move(collector)),
+      profile_manager_(profile_manager),
       weak_factory_(this) {
   metric_collector_->set_profile_done_callback(base::BindRepeating(
       &MetricProvider::OnProfileDone, weak_factory_.GetWeakPtr()));
@@ -156,11 +211,46 @@
   recording_enabled_ = false;
 }
 
+// Check the current state of App Sync in the settings. This is done by getting
+// all currently fully initialized profiles and reading the sync settings from
+// them.
+MetricProvider::RecordAttemptStatus MetricProvider::GetAppSyncState() {
+  if (!profile_manager_)
+    return RecordAttemptStatus::kProfileManagerUnset;
+
+  std::vector<Profile*> profiles = profile_manager_->GetLoadedProfiles();
+  if (profiles.size() == 0)
+    return RecordAttemptStatus::kNoLoadedProfile;
+
+  for (Profile* profile : profiles) {
+    if (!IsAppSyncEnabledForUserProfile(profile))
+      return RecordAttemptStatus::kAppSyncDisabled;
+  }
+
+  return RecordAttemptStatus::kAppSyncEnabled;
+}
+
 void MetricProvider::AddProfileToCache(
     std::unique_ptr<SampledProfile> sampled_profile) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (!recording_enabled_)
+  if (!recording_enabled_) {
+    base::UmaHistogramEnumeration(record_uma_histogram_,
+                                  RecordAttemptStatus::kRecordingDisabled);
     return;
+  }
+
+  // For privacy reasons, Chrome can not collect Android app names that may be
+  // present in the perf data, unless the user consent to enabling App Sync.
+  // Therefore, if the user does not enable App Sync, we redact comm_md5_prefix
+  // in all COMM events of perf data proto, so these MD5 prefixes can not be
+  // used to recover Android app names. We perform the check on App Sync here
+  // because the procedure to get the user profile (from which sync settings can
+  // be obtained) must execute on the UI thread.
+  auto app_sync_state = GetAppSyncState();
+  base::UmaHistogramEnumeration(record_uma_histogram_, app_sync_state);
+  if (app_sync_state != RecordAttemptStatus::kAppSyncEnabled)
+    RedactCommMd5Prefixes(sampled_profile->mutable_perf_data());
+
   collector_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&MetricCollector::AddCachedDataDelta,
                                 base::Unretained(metric_collector_.get()),
diff --git a/chrome/browser/metrics/perf/metric_provider.h b/chrome/browser/metrics/perf/metric_provider.h
index 155cddf..0f0aac15 100644
--- a/chrome/browser/metrics/perf/metric_provider.h
+++ b/chrome/browser/metrics/perf/metric_provider.h
@@ -19,6 +19,8 @@
 class TimeDelta;
 }  // namespace base
 
+class ProfileManager;
+
 namespace metrics {
 
 class SampledProfile;
@@ -30,7 +32,8 @@
 // on its dedicated sequence, via PostTask messages.
 class MetricProvider {
  public:
-  explicit MetricProvider(std::unique_ptr<internal::MetricCollector> collector);
+  MetricProvider(std::unique_ptr<internal::MetricCollector> collector,
+                 ProfileManager* profile_manager);
 
   virtual ~MetricProvider();
 
@@ -63,6 +66,18 @@
   void OnJankStopped();
 
  protected:
+  // Enumeration representing the various outcomes of saving the collected
+  // profile to local cache. These values are persisted to logs. Entries should
+  // not be renumbererd and numeric values should never be reused.
+  enum class RecordAttemptStatus {
+    kRecordingDisabled = 0,
+    kProfileManagerUnset = 1,
+    kNoLoadedProfile = 2,
+    kAppSyncDisabled = 3,
+    kAppSyncEnabled = 4,
+    kMaxValue = kAppSyncEnabled,
+  };
+
   // For testing.
   void set_cache_updated_callback(base::RepeatingClosure callback) {
     cache_updated_callback_ = std::move(callback);
@@ -74,6 +89,9 @@
   static void OnProfileDone(base::WeakPtr<MetricProvider> provider,
                             std::unique_ptr<SampledProfile> sampled_profile);
 
+  // Check the state of App Sync in the current session.
+  RecordAttemptStatus GetAppSyncState();
+
   // Saves a profile to the local cache.
   void AddProfileToCache(std::unique_ptr<SampledProfile> sampled_profile);
 
@@ -86,6 +104,10 @@
   // Name of the histogram that counts the number of uploaded reports.
   const std::string upload_uma_histogram_;
 
+  // Name of the histogram that tracks the various outcomes of saving the
+  // collected profile to local cache.
+  const std::string record_uma_histogram_;
+
   // Use a dedicated sequence for the collector. Thread safe. Initialized at
   // construction time, then immutable.
   const scoped_refptr<base::SequencedTaskRunner> collector_task_runner_;
@@ -95,6 +117,10 @@
   // have executed.
   std::unique_ptr<internal::MetricCollector> metric_collector_;
 
+  // The profile manager that manages user profiles with their sync settings, we
+  // do not own this object and only hold a reference to it.
+  ProfileManager* profile_manager_;
+
   // Called when |cached_profile_data_| is populated.
   base::RepeatingClosure cache_updated_callback_;
 
diff --git a/chrome/browser/metrics/perf/metric_provider_unittest.cc b/chrome/browser/metrics/perf/metric_provider_unittest.cc
index 31246c4..23fc54d 100644
--- a/chrome/browser/metrics/perf/metric_provider_unittest.cc
+++ b/chrome/browser/metrics/perf/metric_provider_unittest.cc
@@ -14,6 +14,15 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/test/bind.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/constants/chromeos_features.h"
+#include "components/sync/base/user_selectable_type.h"
+#include "components/sync/driver/test_sync_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/metrics_proto/sampled_profile.pb.h"
@@ -48,9 +57,45 @@
   stats->set_num_fork_events(400);
   stats->set_num_exit_events(500);
 
+  // MMapEvent.
+  PerfDataProto_PerfEvent* event1 = proto.add_events();
+  event1->mutable_header()->set_type(1);
+  event1->mutable_mmap_event()->set_pid(1234);
+  event1->mutable_mmap_event()->set_filename_md5_prefix(0xabcdefab);
+
+  // CommEvent.
+  PerfDataProto_PerfEvent* event2 = proto.add_events();
+  event2->mutable_header()->set_type(2);
+  event2->mutable_comm_event()->set_pid(5678);
+  event2->mutable_comm_event()->set_comm_md5_prefix(0x0123456abcd);
+
   return proto;
 }
 
+// Converts a protobuf to serialized format as a byte vector.
+std::vector<uint8_t> SerializeMessageToVector(
+    const google::protobuf::MessageLite& message) {
+  std::vector<uint8_t> result(message.ByteSize());
+  message.SerializeToArray(result.data(), result.size());
+  return result;
+}
+
+using TestSyncService = syncer::TestSyncService;
+
+std::unique_ptr<KeyedService> TestingSyncFactoryFunction(
+    content::BrowserContext* context) {
+  return std::make_unique<TestSyncService>();
+}
+
+// Allow access to some private methods for testing.
+class TestMetricProvider : public MetricProvider {
+ public:
+  using MetricProvider::MetricProvider;
+  ~TestMetricProvider() override = default;
+
+  using MetricProvider::RecordAttemptStatus;
+};
+
 // Allows access to some private methods for testing.
 class TestMetricCollector : public internal::MetricCollector {
  public:
@@ -59,7 +104,7 @@
       : internal::MetricCollector("UMA.CWP.TestData", collection_params),
         weak_factory_(this) {}
 
-  const char* ToolName() const override { return "test"; }
+  const char* ToolName() const override { return "Test"; }
   base::WeakPtr<internal::MetricCollector> GetWeakPtr() override {
     return weak_factory_.GetWeakPtr();
   }
@@ -80,7 +125,7 @@
 const base::TimeDelta kPeriodicCollectionInterval =
     base::TimeDelta::FromHours(1);
 const base::TimeDelta kMaxCollectionDelay = base::TimeDelta::FromSeconds(1);
-
+const uint64_t kRedactedCommMd5Prefix = 0xee1f021828a1fcbc;
 }  // namespace
 
 class MetricProviderTest : public testing::Test {
@@ -99,8 +144,8 @@
     test_params.restore_session.max_collection_delay = kMaxCollectionDelay;
     test_params.periodic_interval = kPeriodicCollectionInterval;
 
-    metric_provider_ = std::make_unique<MetricProvider>(
-        std::make_unique<TestMetricCollector>(test_params));
+    metric_provider_ = std::make_unique<TestMetricProvider>(
+        std::make_unique<TestMetricCollector>(test_params), nullptr);
     metric_provider_->Init();
     task_environment_.RunUntilIdle();
   }
@@ -113,7 +158,7 @@
   // last.
   content::BrowserTaskEnvironment task_environment_;
 
-  std::unique_ptr<MetricProvider> metric_provider_;
+  std::unique_ptr<TestMetricProvider> metric_provider_;
 
   DISALLOW_COPY_AND_ASSIGN(MetricProviderTest);
 };
@@ -212,7 +257,8 @@
   EXPECT_TRUE(profile.has_ms_after_boot());
 }
 
-TEST_F(MetricProviderTest, EnableAndDisableRecording) {
+TEST_F(MetricProviderTest, DisableRecording) {
+  base::HistogramTester histogram_tester;
   metric_provider_->OnUserLoggedIn();
 
   // Upon disabling recording, we would expect no cached profiles after a
@@ -223,16 +269,239 @@
   std::vector<SampledProfile> stored_profiles;
   EXPECT_FALSE(metric_provider_->GetSampledProfiles(&stored_profiles));
   EXPECT_TRUE(stored_profiles.empty());
+  histogram_tester.ExpectUniqueSample(
+      "ChromeOS.CWP.RecordTest",
+      TestMetricProvider::RecordAttemptStatus::kRecordingDisabled, 1);
+}
+
+TEST_F(MetricProviderTest, EnableRecording) {
+  base::HistogramTester histogram_tester;
+  metric_provider_->OnUserLoggedIn();
 
   // Upon enabling recording, we would find a cached PERIODIC_COLLECTION profile
   // after a profiling interval.
   metric_provider_->EnableRecording();
   task_environment_.FastForwardBy(kPeriodicCollectionInterval);
 
+  std::vector<SampledProfile> stored_profiles;
   EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
   EXPECT_EQ(stored_profiles.size(), 1u);
   EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION,
             stored_profiles[0].trigger_event());
+  // When initializing the MetricProvider, we set the ProfileManager to nullptr.
+  histogram_tester.ExpectUniqueSample(
+      "ChromeOS.CWP.RecordTest",
+      TestMetricProvider::RecordAttemptStatus::kProfileManagerUnset, 1);
+}
+
+class MetricProviderSyncSettingsTest : public testing::Test {
+ public:
+  MetricProviderSyncSettingsTest()
+      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+
+  void SetUp() override {
+    CollectionParams test_params;
+    test_params.periodic_interval = kPeriodicCollectionInterval;
+
+    testing_profile_manager_ = std::make_unique<TestingProfileManager>(
+        TestingBrowserProcess::GetGlobal());
+    ASSERT_TRUE(testing_profile_manager_->SetUp());
+    metric_provider_ = std::make_unique<TestMetricProvider>(
+        std::make_unique<TestMetricCollector>(test_params),
+        testing_profile_manager_->profile_manager());
+    metric_provider_->Init();
+    task_environment_.RunUntilIdle();
+
+    perf_data_unchanged_ = GetExamplePerfDataProto();
+    // Perf data whose COMM event has its comm_md5_prefix redacted.
+    perf_data_redacted_ = GetExamplePerfDataProto();
+    perf_data_redacted_.mutable_events(1)
+        ->mutable_comm_event()
+        ->set_comm_md5_prefix(kRedactedCommMd5Prefix);
+  }
+
+  void TearDown() override {
+    metric_provider_.reset();
+    testing_profile_manager_.reset();
+  }
+
+ protected:
+  TestSyncService* GetSyncService(TestingProfile* profile) {
+    TestSyncService* sync_service = static_cast<TestSyncService*>(
+        ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+            profile, base::BindRepeating(&TestingSyncFactoryFunction)));
+    sync_service->SetFirstSetupComplete(true);
+    return sync_service;
+  }
+
+  void EnableOSAppSync(TestSyncService* sync_service) {
+    sync_service->GetUserSettings()->SetOsSyncFeatureEnabled(true);
+    sync_service->GetUserSettings()->SetSelectedOsTypes(
+        /*sync_all_os_types=*/false, {syncer::UserSelectableOsType::kOsApps});
+  }
+
+  void DisableOSAppSync(TestSyncService* sync_service) {
+    sync_service->GetUserSettings()->SetOsSyncFeatureEnabled(true);
+    sync_service->GetUserSettings()->SetSelectedOsTypes(
+        /*sync_all_os_types=*/false, {});
+  }
+
+  void EnableAppSync(TestSyncService* sync_service) {
+    sync_service->GetUserSettings()->SetSelectedTypes(
+        /*sync_everything=*/false, {syncer::UserSelectableType::kApps});
+  }
+
+  void DisableAppSync(TestSyncService* sync_service) {
+    sync_service->GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false,
+                                                      {});
+  }
+
+  content::BrowserTaskEnvironment task_environment_;
+
+  std::unique_ptr<TestingProfileManager> testing_profile_manager_;
+
+  std::unique_ptr<TestMetricProvider> metric_provider_;
+
+  base::test::ScopedFeatureList feature_list_;
+
+  PerfDataProto perf_data_unchanged_;
+
+  PerfDataProto perf_data_redacted_;
+
+  DISALLOW_COPY_AND_ASSIGN(MetricProviderSyncSettingsTest);
+};
+
+TEST_F(MetricProviderSyncSettingsTest, NoLoadedUserProfile) {
+  base::HistogramTester histogram_tester;
+  std::vector<SampledProfile> stored_profiles;
+  metric_provider_->OnUserLoggedIn();
+
+  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
+
+  EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_EQ(stored_profiles.size(), 1u);
+
+  const SampledProfile& profile = stored_profiles[0];
+  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
+  EXPECT_EQ(SerializeMessageToVector(perf_data_redacted_),
+            SerializeMessageToVector(profile.perf_data()));
+  histogram_tester.ExpectUniqueSample(
+      "ChromeOS.CWP.RecordTest",
+      TestMetricProvider::RecordAttemptStatus::kNoLoadedProfile, 1);
+}
+
+TEST_F(MetricProviderSyncSettingsTest, SplitSettingsAppSyncEnabled) {
+  base::HistogramTester histogram_tester;
+  std::vector<SampledProfile> stored_profiles;
+  metric_provider_->OnUserLoggedIn();
+  feature_list_.InitAndEnableFeature(chromeos::features::kSplitSettingsSync);
+
+  // Set up two testing profiles, both with OS App Sync enabled.
+  TestSyncService* sync_service1 =
+      GetSyncService(testing_profile_manager_->CreateTestingProfile("user1"));
+  TestSyncService* sync_service2 =
+      GetSyncService(testing_profile_manager_->CreateTestingProfile("user2"));
+  EnableOSAppSync(sync_service1);
+  EnableOSAppSync(sync_service2);
+
+  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
+
+  EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_EQ(stored_profiles.size(), 1u);
+
+  const SampledProfile& profile = stored_profiles[0];
+  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
+  EXPECT_EQ(SerializeMessageToVector(perf_data_unchanged_),
+            SerializeMessageToVector(profile.perf_data()));
+  histogram_tester.ExpectUniqueSample(
+      "ChromeOS.CWP.RecordTest",
+      TestMetricProvider::RecordAttemptStatus::kAppSyncEnabled, 1);
+}
+
+TEST_F(MetricProviderSyncSettingsTest, SplitSettingsAppSyncDisabled) {
+  base::HistogramTester histogram_tester;
+  std::vector<SampledProfile> stored_profiles;
+  metric_provider_->OnUserLoggedIn();
+  feature_list_.InitAndEnableFeature(chromeos::features::kSplitSettingsSync);
+
+  // Set up two testing profiles, one with OS App Sync enabled and the other
+  // disabled.
+  TestSyncService* sync_service1 =
+      GetSyncService(testing_profile_manager_->CreateTestingProfile("user1"));
+  TestSyncService* sync_service2 =
+      GetSyncService(testing_profile_manager_->CreateTestingProfile("user2"));
+  EnableOSAppSync(sync_service1);
+  DisableOSAppSync(sync_service2);
+
+  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
+
+  EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_EQ(stored_profiles.size(), 1u);
+
+  const SampledProfile& profile = stored_profiles[0];
+  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
+  EXPECT_EQ(SerializeMessageToVector(perf_data_redacted_),
+            SerializeMessageToVector(profile.perf_data()));
+  histogram_tester.ExpectUniqueSample(
+      "ChromeOS.CWP.RecordTest",
+      TestMetricProvider::RecordAttemptStatus::kAppSyncDisabled, 1);
+}
+
+TEST_F(MetricProviderSyncSettingsTest, UnifiedSettingsAppSyncEnabled) {
+  base::HistogramTester histogram_tester;
+  std::vector<SampledProfile> stored_profiles;
+  metric_provider_->OnUserLoggedIn();
+  feature_list_.InitAndDisableFeature(chromeos::features::kSplitSettingsSync);
+
+  // Set up two testing profiles, both with App Sync enabled.
+  TestSyncService* sync_service1 =
+      GetSyncService(testing_profile_manager_->CreateTestingProfile("user1"));
+  TestSyncService* sync_service2 =
+      GetSyncService(testing_profile_manager_->CreateTestingProfile("user2"));
+  EnableAppSync(sync_service1);
+  EnableAppSync(sync_service2);
+
+  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
+
+  EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_EQ(stored_profiles.size(), 1u);
+
+  const SampledProfile& profile = stored_profiles[0];
+  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
+  EXPECT_EQ(SerializeMessageToVector(perf_data_unchanged_),
+            SerializeMessageToVector(profile.perf_data()));
+  histogram_tester.ExpectUniqueSample(
+      "ChromeOS.CWP.RecordTest",
+      TestMetricProvider::RecordAttemptStatus::kAppSyncEnabled, 1);
+}
+
+TEST_F(MetricProviderSyncSettingsTest, UnifiedSettingsAppSyncDisabled) {
+  base::HistogramTester histogram_tester;
+  std::vector<SampledProfile> stored_profiles;
+  metric_provider_->OnUserLoggedIn();
+  feature_list_.InitAndDisableFeature(chromeos::features::kSplitSettingsSync);
+
+  // Set up two testing profiles, one with App Sync enabled and the other
+  // disabled.
+  TestSyncService* sync_service1 =
+      GetSyncService(testing_profile_manager_->CreateTestingProfile("user1"));
+  TestSyncService* sync_service2 =
+      GetSyncService(testing_profile_manager_->CreateTestingProfile("user2"));
+  EnableAppSync(sync_service1);
+  DisableAppSync(sync_service2);
+
+  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
+
+  EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_EQ(stored_profiles.size(), 1u);
+
+  const SampledProfile& profile = stored_profiles[0];
+  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
+  EXPECT_EQ(SerializeMessageToVector(perf_data_redacted_),
+            SerializeMessageToVector(profile.perf_data()));
+  histogram_tester.ExpectUniqueSample(
+      "ChromeOS.CWP.RecordTest",
+      TestMetricProvider::RecordAttemptStatus::kAppSyncDisabled, 1);
 }
 
 }  // namespace metrics
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos.cc b/chrome/browser/metrics/perf/profile_provider_chromeos.cc
index 9c09af4e..4ffd49a 100644
--- a/chrome/browser/metrics/perf/profile_provider_chromeos.cc
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos.cc
@@ -9,6 +9,7 @@
 #include "base/feature_list.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/perf/metric_provider.h"
 #include "chrome/browser/metrics/perf/perf_events_collector.h"
 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
@@ -58,8 +59,8 @@
   // Initialize the WindowedIncognitoMonitor on the UI thread.
   WindowedIncognitoMonitor::Init();
   // Register a perf events collector.
-  collectors_.push_back(
-      std::make_unique<MetricProvider>(std::make_unique<PerfCollector>()));
+  collectors_.push_back(std::make_unique<MetricProvider>(
+      std::make_unique<PerfCollector>(), g_browser_process->profile_manager()));
 }
 
 ProfileProvider::~ProfileProvider() {
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
index 501f562..40b6745 100644
--- a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
@@ -109,9 +109,9 @@
 
     collectors_.clear();
     collectors_.push_back(std::make_unique<MetricProvider>(
-        std::make_unique<TestMetricCollector<100>>(test_params)));
+        std::make_unique<TestMetricCollector<100>>(test_params), nullptr));
     collectors_.push_back(std::make_unique<MetricProvider>(
-        std::make_unique<TestMetricCollector<200>>(test_params)));
+        std::make_unique<TestMetricCollector<200>>(test_params), nullptr));
   }
 
   using ProfileProvider::collectors_;
diff --git a/chrome/browser/metrics/perf/profile_provider_unittest_main.cc b/chrome/browser/metrics/perf/profile_provider_unittest_main.cc
index c1e34e5..25fd072 100644
--- a/chrome/browser/metrics/perf/profile_provider_unittest_main.cc
+++ b/chrome/browser/metrics/perf/profile_provider_unittest_main.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/metrics/perf/collection_params.h"
 #include "chrome/browser/metrics/perf/metric_provider.h"
 #include "chrome/browser/metrics/perf/perf_events_collector.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -65,7 +66,7 @@
 
     collectors_.clear();
     auto metric_provider = std::make_unique<TestMetricProvider>(
-        std::make_unique<TestPerfCollector>(test_params));
+        std::make_unique<TestPerfCollector>(test_params), nullptr);
     metric_provider->set_cache_updated_callback(base::BindRepeating(
         &TestProfileProvider::OnProfileDone, base::Unretained(this)));
 
@@ -129,6 +130,10 @@
     chromeos::PowerManagerClient::InitializeFake();
     chromeos::LoginState::Initialize();
 
+    // The constructor of ProfileProvider uses g_browser_process thus requiring
+    // it to be not null, so initialize it here.
+    TestingBrowserProcess::CreateInstance();
+
     std::map<std::string, std::string> field_trial_params;
     // Only "cycles" event is supported.
     field_trial_params.insert(std::make_pair(
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.cc
index 7b7811df..8803878 100644
--- a/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.cc
+++ b/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.cc
@@ -77,17 +77,22 @@
     metadata.set_icon_url(*icon_url);
   }
   std::array<uint8_t, 6> bytes;
-  if (bluetooth_adapter &&
-      device::ParseBluetoothAddress(bluetooth_adapter->GetAddress(), bytes)) {
+  bool has_address =
+      bluetooth_adapter &&
+      device::ParseBluetoothAddress(bluetooth_adapter->GetAddress(), bytes);
+  if (has_address) {
     metadata.set_bluetooth_mac_address(std::string(bytes.begin(), bytes.end()));
   } else {
     NS_LOG(WARNING) << __func__
                     << ": No valid Bluetooth MAC available for private "
                     << "certificate metadata.";
     // TODO(https://crbug.com/1122641): Decide the best way to handle
-    // missing/invalid Bluetooth MAC addresses. Also, log a metric to track how
-    // often this happens.
+    // missing/invalid Bluetooth MAC addresses.
   }
+  base::UmaHistogramBoolean(
+      "Nearby.Share.Certificates.Manager."
+      "BluetoothMacAddressSetInPrivateCertificate",
+      has_address);
 
   return metadata;
 }
diff --git a/chrome/browser/nearby_sharing/common/BUILD.gn b/chrome/browser/nearby_sharing/common/BUILD.gn
index ed3d9ff7..cd94aa18 100644
--- a/chrome/browser/nearby_sharing/common/BUILD.gn
+++ b/chrome/browser/nearby_sharing/common/BUILD.gn
@@ -20,5 +20,8 @@
     "//chrome/browser/ui/webui/nearby_share/public/mojom",
     "//components/pref_registry",
     "//components/prefs",
+    "//net",
+    "//services/network/public/cpp",
+    "//services/network/public/mojom",
   ]
 }
diff --git a/chrome/browser/nearby_sharing/common/nearby_share_http_result.cc b/chrome/browser/nearby_sharing/common/nearby_share_http_result.cc
index bbbabc4..6009773 100644
--- a/chrome/browser/nearby_sharing/common/nearby_share_http_result.cc
+++ b/chrome/browser/nearby_sharing/common/nearby_share_http_result.cc
@@ -4,6 +4,12 @@
 
 #include "chrome/browser/nearby_sharing/common/nearby_share_http_result.h"
 
+#include "net/base/net_errors.h"
+#include "net/http/http_status_code.h"
+#include "services/network/public/cpp/cors/cors.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+
 NearbyShareHttpError NearbyShareHttpErrorForHttpResponseCode(
     int response_code) {
   if (response_code == 400)
@@ -40,6 +46,68 @@
   }
 }
 
+NearbyShareHttpStatus::NearbyShareHttpStatus(
+    const int net_error,
+    const network::mojom::URLResponseHead* head)
+    : net_error_code_(net_error) {
+  if (head && head->headers)
+    http_response_code_ = head->headers->response_code();
+
+  bool net_success = (net_error_code_ == net::OK ||
+                      net_error_code_ == net::ERR_HTTP_RESPONSE_CODE_FAILURE) &&
+                     http_response_code_;
+  bool http_success =
+      net_success && network::cors::IsOkStatus(*http_response_code_);
+
+  if (http_success) {
+    status_ = Status::kSuccess;
+  } else if (net_success) {
+    status_ = Status::kHttpFailure;
+  } else {
+    status_ = Status::kNetworkFailure;
+  }
+}
+
+NearbyShareHttpStatus::~NearbyShareHttpStatus() = default;
+
+bool NearbyShareHttpStatus::IsSuccess() const {
+  return status_ == Status::kSuccess;
+}
+
+int NearbyShareHttpStatus::GetResultCodeForMetrics() const {
+  switch (status_) {
+    case Status::kNetworkFailure:
+      return net_error_code_;
+    case Status::kSuccess:
+    case Status::kHttpFailure:
+      return *http_response_code_;
+  }
+}
+
+std::string NearbyShareHttpStatus::ToString() const {
+  std::string status;
+  switch (status_) {
+    case Status::kSuccess:
+      status = "kSuccess";
+      break;
+    case Status::kNetworkFailure:
+      status = "kNetworkFailure";
+      break;
+    case Status::kHttpFailure:
+      status = "kHttpFailure";
+      break;
+  }
+  std::string net_code = net::ErrorToString(net_error_code_);
+  std::string response_code =
+      http_response_code_.has_value()
+          ? net::GetHttpReasonPhrase(
+                static_cast<net::HttpStatusCode>(*http_response_code_))
+          : "[null]";
+
+  return "status=" + status + ", net_code=" + net_code +
+         ", response_code=" + response_code;
+}
+
 std::ostream& operator<<(std::ostream& stream,
                          const NearbyShareHttpResult& result) {
   switch (result) {
@@ -79,3 +147,9 @@
   stream << NearbyShareHttpErrorToResult(error);
   return stream;
 }
+
+std::ostream& operator<<(std::ostream& stream,
+                         const NearbyShareHttpStatus& status) {
+  stream << status.ToString();
+  return stream;
+}
diff --git a/chrome/browser/nearby_sharing/common/nearby_share_http_result.h b/chrome/browser/nearby_sharing/common/nearby_share_http_result.h
index 3b56b063..fc31f13a 100644
--- a/chrome/browser/nearby_sharing/common/nearby_share_http_result.h
+++ b/chrome/browser/nearby_sharing/common/nearby_share_http_result.h
@@ -6,6 +6,10 @@
 #define CHROME_BROWSER_NEARBY_SHARING_COMMON_NEARBY_SHARE_HTTP_RESULT_H_
 
 #include <ostream>
+#include <string>
+
+#include "base/optional.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 enum class NearbyShareHttpError {
   // Request could not be completed because the device is offline or has issues
@@ -46,12 +50,30 @@
   kMaxValue = kHttpErrorUnknown
 };
 
+class NearbyShareHttpStatus {
+ public:
+  NearbyShareHttpStatus(const int net_error,
+                        const network::mojom::URLResponseHead* head);
+  ~NearbyShareHttpStatus();
+
+  bool IsSuccess() const;
+  int GetResultCodeForMetrics() const;
+  std::string ToString() const;
+
+ private:
+  enum class Status { kSuccess, kNetworkFailure, kHttpFailure } status_;
+  int net_error_code_;
+  base::Optional<int> http_response_code_;
+};
+
 NearbyShareHttpError NearbyShareHttpErrorForHttpResponseCode(int response_code);
 NearbyShareHttpResult NearbyShareHttpErrorToResult(NearbyShareHttpError error);
 
 std::ostream& operator<<(std::ostream& stream,
-                         const NearbyShareHttpResult& error);
+                         const NearbyShareHttpResult& result);
 std::ostream& operator<<(std::ostream& stream,
                          const NearbyShareHttpError& error);
+std::ostream& operator<<(std::ostream& stream,
+                         const NearbyShareHttpStatus& status);
 
 #endif  // CHROME_BROWSER_NEARBY_SHARING_COMMON_NEARBY_SHARE_HTTP_RESULT_H_
diff --git a/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc b/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc
index 4a6ba7b9..a3707f4 100644
--- a/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc
+++ b/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc
@@ -4,12 +4,17 @@
 
 #include "chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.h"
 
+#include <sstream>
+
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/nearby_sharing/common/nearby_share_http_result.h"
 #include "chrome/browser/nearby_sharing/instantmessaging/constants.h"
 #include "chrome/browser/nearby_sharing/instantmessaging/proto/instantmessaging.pb.h"
 #include "chrome/browser/nearby_sharing/instantmessaging/token_fetcher.h"
+#include "chrome/browser/nearby_sharing/logging/logging.h"
 #include "net/base/load_flags.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -17,6 +22,7 @@
 #include "url/gurl.h"
 
 namespace {
+
 // TODO(crbug.com/1123164) - Add nearby sharing policy when available.
 const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
     net::DefineNetworkTrafficAnnotation("receive_messages_express", R"(
@@ -48,6 +54,31 @@
             }
           })");
 
+void LogReceiveResult(bool success, const network::SimpleURLLoader* loader) {
+  std::stringstream ss;
+  ss << "Instant messaging receive express "
+     << (success ? "succeeded." : "failed.");
+  base::UmaHistogramBoolean(
+      "Nearby.Share.InstantMessaging.ReceiveExpress.Result", success);
+  if (loader) {
+    NearbyShareHttpStatus http_status(loader->NetError(),
+                                      loader->ResponseInfo());
+    ss << " HTTP status: " << http_status;
+    if (!success) {
+      base::UmaHistogramSparse(
+          "Nearby.Share.InstantMessaging.ReceiveExpress.Result.FailureReason",
+          http_status.GetResultCodeForMetrics());
+    }
+  } else {
+    ss << " Missing URL loader.";
+  }
+  if (success) {
+    NS_LOG(VERBOSE) << ss.str();
+  } else {
+    NS_LOG(WARNING) << ss.str();
+  }
+}
+
 }  // namespace
 
 ReceiveMessagesExpress::ReceiveMessagesExpress(
@@ -132,6 +163,7 @@
 
 void ReceiveMessagesExpress::OnComplete(bool success) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  LogReceiveResult(success, url_loader_.get());
   if (!success_callback_.is_null())
     std::move(success_callback_).Run(success);
 
diff --git a/chrome/browser/nearby_sharing/instantmessaging/send_message_express.cc b/chrome/browser/nearby_sharing/instantmessaging/send_message_express.cc
index 0f40bb77..1e47aef 100644
--- a/chrome/browser/nearby_sharing/instantmessaging/send_message_express.cc
+++ b/chrome/browser/nearby_sharing/instantmessaging/send_message_express.cc
@@ -4,18 +4,24 @@
 
 #include "chrome/browser/nearby_sharing/instantmessaging/send_message_express.h"
 
+#include <sstream>
+
+#include "base/metrics/histogram_functions.h"
+#include "base/optional.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/nearby_sharing/common/nearby_share_http_result.h"
 #include "chrome/browser/nearby_sharing/instantmessaging/constants.h"
 #include "chrome/browser/nearby_sharing/instantmessaging/proto/instantmessaging.pb.h"
 #include "chrome/browser/nearby_sharing/instantmessaging/token_fetcher.h"
+#include "chrome/browser/nearby_sharing/logging/logging.h"
 #include "net/base/load_flags.h"
-#include "services/network/public/cpp/cors/cors.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "url/gurl.h"
 
 namespace {
+
 // 256 KB as max response size.
 constexpr int kMaxSendResponseSize = 256;
 
@@ -50,16 +56,24 @@
             }
           })");
 
-bool IsLoaderSuccessful(const network::SimpleURLLoader* loader) {
-  if (!loader || loader->NetError() != net::OK)
-    return false;
-
-  if (!loader->ResponseInfo() || !loader->ResponseInfo()->headers)
-    return false;
-
-  return network::cors::IsOkStatus(
-      loader->ResponseInfo()->headers->response_code());
+void LogSendResult(bool success, const NearbyShareHttpStatus& http_status) {
+  std::stringstream ss;
+  ss << "Instant messaging send express " << (success ? "succeeded" : "failed")
+     << ". HTTP status: " << http_status;
+  if (success) {
+    NS_LOG(VERBOSE) << ss.str();
+  } else {
+    NS_LOG(WARNING) << ss.str();
+  }
+  base::UmaHistogramBoolean("Nearby.Share.InstantMessaging.SendExpress.Result",
+                            success);
+  if (!success) {
+    base::UmaHistogramSparse(
+        "Nearby.Share.InstantMessaging.SendExpress.Result.FailureReason",
+        http_status.GetResultCodeForMetrics());
+  }
 }
+
 }  // namespace
 
 SendMessageExpress::SendMessageExpress(
@@ -122,9 +136,10 @@
     std::unique_ptr<network::SimpleURLLoader> url_loader,
     SuccessCallback callback,
     std::unique_ptr<std::string> response_body) {
-  // TODO(crbug.com/1123172) - Add metrics for success and failures, with error
-  // codes for failures.
-  bool success = response_body && !response_body->empty();
-  success &= IsLoaderSuccessful(url_loader.get());
+  NearbyShareHttpStatus http_status(url_loader->NetError(),
+                                    url_loader->ResponseInfo());
+  bool success =
+      http_status.IsSuccess() && response_body && !response_body->empty();
+  LogSendResult(success, http_status);
   std::move(callback).Run(success);
 }
diff --git a/chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.cc b/chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.cc
index 1a6928b..d872e46 100644
--- a/chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.cc
+++ b/chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.cc
@@ -51,7 +51,7 @@
 
   void SetObserver(Observer* observer) override;
   bool IsBlocked(const GURL& url) override;
-  std::vector<MostVisitedSitesSupervisor::Whitelist> GetWhitelists() override;
+  std::vector<MostVisitedSitesSupervisor::Allowlist> GetAllowlists() override;
   bool IsChildProfile() override;
 
   // SupervisedUserServiceObserver implementation.
@@ -91,15 +91,16 @@
          SupervisedUserURLFilter::FilteringBehavior::BLOCK;
 }
 
-std::vector<ntp_tiles::MostVisitedSitesSupervisor::Whitelist>
-SupervisorBridge::GetWhitelists() {
-  std::vector<MostVisitedSitesSupervisor::Whitelist> results;
+std::vector<ntp_tiles::MostVisitedSitesSupervisor::Allowlist>
+SupervisorBridge::GetAllowlists() {
+  std::vector<MostVisitedSitesSupervisor::Allowlist> results;
   SupervisedUserService* supervised_user_service =
       SupervisedUserServiceFactory::GetForProfile(profile_);
-  for (const auto& whitelist : supervised_user_service->allowlists()) {
-    results.emplace_back(Whitelist{
-        whitelist->title(), whitelist->entry_point(),
-        whitelist->large_icon_path(),
+  for (const auto& allowlist : supervised_user_service->allowlists()) {
+    results.emplace_back(Allowlist{
+        allowlist->title(),
+        allowlist->entry_point(),
+        allowlist->large_icon_path(),
     });
   }
   return results;
diff --git a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc
index 43eb504..11804c3f 100644
--- a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc
@@ -85,8 +85,10 @@
       internal::kHistogramFromGWSFirstImagePaint, 0);
   size_t document_created_entries_count =
       tester()->test_ukm_recorder().GetEntriesByName("DocumentCreated").size();
+  size_t unload_entries_count =
+      tester()->test_ukm_recorder().GetEntriesByName("Unload").size();
   EXPECT_EQ(0ul, tester()->test_ukm_recorder().entries_count() -
-                     document_created_entries_count);
+                     document_created_entries_count - unload_entries_count);
 }
 
 TEST_F(FromGWSPageLoadMetricsObserverTest, NonSearchPreviousCommittedUrl) {
@@ -106,8 +108,10 @@
       internal::kHistogramFromGWSFirstImagePaint, 0);
   size_t document_created_entries_count =
       tester()->test_ukm_recorder().GetEntriesByName("DocumentCreated").size();
+  size_t unload_entries_count =
+      tester()->test_ukm_recorder().GetEntriesByName("Unload").size();
   EXPECT_EQ(0ul, tester()->test_ukm_recorder().entries_count() -
-                     document_created_entries_count);
+                     document_created_entries_count - unload_entries_count);
 }
 
 TEST_F(FromGWSPageLoadMetricsObserverTest,
@@ -128,8 +132,10 @@
       internal::kHistogramFromGWSFirstImagePaint, 0);
   size_t document_created_entries_count =
       tester()->test_ukm_recorder().GetEntriesByName("DocumentCreated").size();
+  size_t unload_entries_count =
+      tester()->test_ukm_recorder().GetEntriesByName("Unload").size();
   EXPECT_EQ(0ul, tester()->test_ukm_recorder().entries_count() -
-                     document_created_entries_count);
+                     document_created_entries_count - unload_entries_count);
 }
 
 TEST_F(FromGWSPageLoadMetricsObserverTest,
@@ -152,8 +158,10 @@
       internal::kHistogramFromGWSFirstImagePaint, 0);
   size_t document_created_entries_count =
       tester()->test_ukm_recorder().GetEntriesByName("DocumentCreated").size();
+  size_t unload_entries_count =
+      tester()->test_ukm_recorder().GetEntriesByName("Unload").size();
   EXPECT_EQ(0ul, tester()->test_ukm_recorder().entries_count() -
-                     document_created_entries_count);
+                     document_created_entries_count - unload_entries_count);
 }
 
 TEST_F(FromGWSPageLoadMetricsObserverTest, SearchPreviousCommittedUrl1) {
@@ -587,8 +595,10 @@
 
   size_t document_created_entries_count =
       tester()->test_ukm_recorder().GetEntriesByName("DocumentCreated").size();
+  size_t unload_entries_count =
+      tester()->test_ukm_recorder().GetEntriesByName("Unload").size();
   EXPECT_EQ(0ul, tester()->test_ukm_recorder().entries_count() -
-                     document_created_entries_count);
+                     document_created_entries_count - unload_entries_count);
 }
 
 TEST_F(FromGWSPageLoadMetricsObserverTest,
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc
index b3ceb2c..c31bf56 100644
--- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc
@@ -163,12 +163,14 @@
   AssertNoInboxHistogramsLogged();
   AssertNoSearchHistogramsLogged();
   AssertNoSearchNoSWHistogramsLogged();
-  // Only a DocumentCreated entry is logged for creation of a blink::Document
-  // when the navigation committed;
-  EXPECT_EQ(1ul, tester()->test_ukm_recorder().entries_count());
+  // Only a DocumentCreated entry and an Unload entry is logged for creation of
+  // a blink::Document when the navigation committed.
+  EXPECT_EQ(2ul, tester()->test_ukm_recorder().entries_count());
   EXPECT_EQ(
       1ul,
       tester()->test_ukm_recorder().GetEntriesByName("DocumentCreated").size());
+  EXPECT_EQ(1ul,
+            tester()->test_ukm_recorder().GetEntriesByName("Unload").size());
 }
 
 TEST_F(ServiceWorkerPageLoadMetricsObserverTest, WithServiceWorker) {
diff --git a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc
index 6c480b1..4048cc1 100644
--- a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc
@@ -58,8 +58,9 @@
     mock_translate_metrics_logger_->LogTranslationStarted();
   }
 
-  void LogTranslationFinished(bool was_sucessful) override {
-    mock_translate_metrics_logger_->LogTranslationFinished(was_sucessful);
+  void LogTranslationFinished(
+      translate::TranslateErrors::Type error_type) override {
+    mock_translate_metrics_logger_->LogTranslationFinished(error_type);
   }
 
   void LogReversion() override {
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 6ba1468..00b63d3 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -120,6 +120,7 @@
 #include "ui/views/widget/any_widget_observer.h"
 #endif  // defined(TOOLKIT_VIEWS) && defined(USE_AURA)
 
+using content::AXInspectFactory;
 using content::WebContents;
 using extensions::ExtensionsAPIClient;
 using guest_view::GuestViewManager;
@@ -3110,14 +3111,13 @@
                          PDFExtensionAccessibilityTextExtractionTest,
                          testing::Bool());
 
-using AXTestPass = content::AccessibilityTreeFormatter::TestPass;
+using AXInspectType = AXInspectFactory::Type;
 
 class PDFExtensionAccessibilityTreeDumpTest
     : public PDFExtensionTest,
-      public ::testing::WithParamInterface<std::pair<bool, AXTestPass>> {
+      public ::testing::WithParamInterface<std::pair<bool, AXInspectType>> {
  public:
-  PDFExtensionAccessibilityTreeDumpTest()
-      : test_pass_(GetParam().second), test_helper_(test_pass_.name) {}
+  PDFExtensionAccessibilityTreeDumpTest() : test_helper_(GetParam().second) {}
   ~PDFExtensionAccessibilityTreeDumpTest() override = default;
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -3177,7 +3177,8 @@
 
     // Set up the tree formatter. Parse filters and other directives in the test
     // file.
-    std::unique_ptr<AXTreeFormatter> formatter = test_pass_.create_formatter();
+    std::unique_ptr<AXTreeFormatter> formatter =
+        AXInspectFactory::CreateFormatter(GetParam().second);
     std::vector<AXPropertyFilter> property_filters;
     formatter->AddDefaultFilters(&property_filters);
     AddDefaultFilters(&property_filters);
@@ -3264,15 +3265,14 @@
     property_filters->push_back(AXPropertyFilter(filter, type));
   }
 
-  content::AccessibilityTreeFormatter::TestPass test_pass_;
   content::DumpAccessibilityTestHelper test_helper_;
 };
 
 // Parameterize the tests so that each test-pass is run independently.
 struct DumpAccessibilityTreeTestPassToString {
   std::string operator()(
-      const ::testing::TestParamInfo<std::pair<bool, AXTestPass>>& i) const {
-    std::string result = i.param.second.name;
+      const ::testing::TestParamInfo<std::pair<bool, AXInspectType>>& i) const {
+    std::string result(i.param.second);
     return result + (i.param.first ? "_updateEnabled" : "_updateDisabled");
   }
 };
@@ -3280,10 +3280,11 @@
 // Constructs a list of accessibility tests, two for each accessibility tree
 // formatter testpasses: one when pdf update is enabled and the second one when
 // pdf update is disabled.
-const std::vector<std::pair<bool, AXTestPass>> GetAXTestPairValues() {
-  std::vector<std::pair<bool, AXTestPass>> values;
-  std::vector<AXTestPass> passes =
-      content::AccessibilityTreeFormatter::GetTestPasses();
+const std::vector<std::pair<bool, AXInspectFactory::Type>>
+GetAXTestPairValues() {
+  std::vector<std::pair<bool, AXInspectFactory::Type>> values;
+  std::vector<AXInspectFactory::Type> passes =
+      content::DumpAccessibilityTestHelper::TestPasses();
   for (auto pass : passes) {
     values.emplace_back(std::make_pair(true, pass));
     values.emplace_back(std::make_pair(false, pass));
diff --git a/chrome/browser/performance_manager/page_load_tracker_decorator_browsertest.cc b/chrome/browser/performance_manager/page_load_tracker_decorator_browsertest.cc
index b4a9e70b7..f99dfe6 100644
--- a/chrome/browser/performance_manager/page_load_tracker_decorator_browsertest.cc
+++ b/chrome/browser/performance_manager/page_load_tracker_decorator_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/process/process.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "chrome/browser/ui/browser.h"
@@ -11,30 +12,39 @@
 #include "components/performance_manager/performance_manager_impl.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "content/public/test/browser_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace performance_manager {
 
 namespace {
 
-// A class that waits for the IsLoading() property of a PageNode to transition
-// to a desired value. Generates an error if the first IsLoading() transitions
-// is not for the observed PageNode. Ignores IsLoading() transitions after the
-// first one.
-class PageIsLoadingObserver : public PageNode::ObserverDefaultImpl,
-                              public GraphOwnedDefaultImpl {
+using ::testing::AnyOf;
+using ::testing::ElementsAre;
+
+// A class that waits for the GetLoadingState() property of a PageNode to
+// transition to LoadingState::kLoadedIdle. Collects all intermediate states
+// observed in-between. Generates an error if transitions are observed for
+// another PageNode than |page_node|.
+class PageLoadingStateObserver : public PageNode::ObserverDefaultImpl,
+                                 public GraphOwnedDefaultImpl {
  public:
-  PageIsLoadingObserver(base::WeakPtr<PageNode> page_node,
-                        bool desired_is_loading)
-      : page_node_(page_node), desired_is_loading_(desired_is_loading) {
+  PageLoadingStateObserver(base::WeakPtr<PageNode> page_node,
+                           bool exit_if_already_loaded_idle)
+      : page_node_(page_node) {
     DCHECK(PerformanceManagerImpl::IsAvailable());
     PerformanceManagerImpl::CallOnGraphImpl(
         FROM_HERE,
-        base::BindLambdaForTesting([&](performance_manager::GraphImpl* graph) {
+        // |exit_if_already_loaded_idle| is captured by copy because the lambda
+        // can be executed after the constructor returns.
+        base::BindLambdaForTesting([&, exit_if_already_loaded_idle](
+                                       performance_manager::GraphImpl* graph) {
           EXPECT_TRUE(page_node_);
 
-          if (page_node_->IsLoading() == desired_is_loading_) {
-            run_loop_.Quit();
+          if (exit_if_already_loaded_idle &&
+              page_node_->GetLoadingState() ==
+                  PageNode::LoadingState::kLoadedIdle) {
+            QuitRunLoop();
           } else {
             graph_ = graph;
             graph_->AddPageNodeObserver(this);
@@ -42,32 +52,49 @@
         }));
   }
 
-  ~PageIsLoadingObserver() override = default;
+  ~PageLoadingStateObserver() override = default;
 
   void Wait() {
-    // The RunLoop is quit when |page_node_->IsLoading()| becomes equal to
-    // |desired_is_loading_|.
     run_loop_.Run();
   }
 
+  // Returns loading states observed before reaching LoadingState::kLoadedIdle.
+  // Can only be accessed safely after Wait() has returned.
+  const std::vector<PageNode::LoadingState>& observed_loading_states() const {
+    // If |graph_| is not nullptr, the RunLoop wasn't quit and accessing
+    // |observed_loading_states_| would be racy.
+    DCHECK(!graph_);
+    return observed_loading_states_;
+  }
+
  private:
-  // PageNodeObserver:
-  void OnIsLoadingChanged(const PageNode* page_node) override {
-    EXPECT_EQ(page_node_.get(), page_node);
-    EXPECT_EQ(page_node->IsLoading(), desired_is_loading_);
-    graph_->RemovePageNodeObserver(this);
+  void QuitRunLoop() {
+    graph_ = nullptr;
     run_loop_.Quit();
   }
 
-  // This RunLoop is quit when |page_node_->IsLoading()| is equal to
-  // |desired_is_loading_|.
+  // PageNodeObserver:
+  void OnLoadingStateChanged(const PageNode* page_node) override {
+    EXPECT_EQ(page_node_.get(), page_node);
+
+    if (page_node->GetLoadingState() == PageNode::LoadingState::kLoadedIdle) {
+      graph_->RemovePageNodeObserver(this);
+      QuitRunLoop();
+      return;
+    }
+
+    observed_loading_states_.push_back(page_node->GetLoadingState());
+  }
+
+  // This RunLoop is quit when |page_node_->GetLoadingState()| is equal to
+  // LoadingState::kLoadedIdle.
   base::RunLoop run_loop_;
 
   // The watched PageNode.
   const base::WeakPtr<PageNode> page_node_;
 
-  // Desired value for |page_node_->IsLoading()|.
-  const bool desired_is_loading_;
+  // Observed states before reaching kLoadedIdle.
+  std::vector<PageNode::LoadingState> observed_loading_states_;
 
   // Set when registering |this| as a PageNodeObserver. Used to unregister.
   GraphImpl* graph_ = nullptr;
@@ -82,35 +109,46 @@
 };
 
 // Integration test verifying that everything is hooked up in Chrome to update
-// PageNode::IsLoading() is updated on navigation. See
+// PageNode::GetLoadingState() is updated on navigation. See
 // PageLoadTrackerDecoratorTest for low level unit tests.
-IN_PROC_BROWSER_TEST_F(PageLoadTrackerDecoratorTest, PageNodeIsLoading) {
+IN_PROC_BROWSER_TEST_F(PageLoadTrackerDecoratorTest, PageNodeLoadingState) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   base::WeakPtr<PageNode> page_node =
       PerformanceManager::GetPageNodeForWebContents(
           browser()->tab_strip_model()->GetActiveWebContents());
 
-  // Wait until IsLoading() is false (the initial navigation may or may not be
-  // ongoing).
-  PageIsLoadingObserver observer1(page_node, false);
-  observer1.Wait();
+  // Wait until GetLoadingState() is LoadingState::kLoadedIdle (the initial
+  // navigation may or may not be ongoing).
+  {
+    PageLoadingStateObserver observer(page_node,
+                                      /* exit_if_already_loaded_idle=*/true);
+    observer.Wait();
+  }
 
-  // Create an Observer that will observe IsLoading() becoming true when the
-  // navigation below starts.
-  PageIsLoadingObserver observer2(page_node, true);
+  // Create an Observer that will observe GetLoadingState() becoming
+  // LoadingState::kLoadedIdle after the navigation below starts.
+  PageLoadingStateObserver observer(page_node,
+                                    /* exit_if_already_loaded_idle=*/false);
 
   // Navigate.
   browser()->OpenURL(content::OpenURLParams(
       embedded_test_server()->GetURL("/empty.html"), content::Referrer(),
       WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
 
-  // Wait until IsLoading() is true.
-  observer2.Wait();
+  // Wait until GetLoadingState() transitions to LoadingState::kLoadedIdle.
+  observer.Wait();
 
-  // Wait until IsLoading() is false.
-  PageIsLoadingObserver observer3(page_node, false);
-  observer3.Wait();
+  // States observed before reaching LoadingState::kLoadedIdle must follow one
+  // of the two expected sequenced (state can go through |kLoadingTimedOut| or
+  // not).
+  EXPECT_THAT(observer.observed_loading_states(),
+              AnyOf(ElementsAre(PageNode::LoadingState::kLoading,
+                                PageNode::LoadingState::kLoadedBusy),
+                    ElementsAre(PageNode::LoadingState::kLoading,
+                                PageNode::LoadingState::kLoadingTimedOut,
+                                PageNode::LoadingState::kLoading,
+                                PageNode::LoadingState::kLoadedBusy)));
 }
 
 }  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/policies/background_tab_loading_policy.cc b/chrome/browser/performance_manager/policies/background_tab_loading_policy.cc
index ad30487b..5e860d0 100644
--- a/chrome/browser/performance_manager/policies/background_tab_loading_policy.cc
+++ b/chrome/browser/performance_manager/policies/background_tab_loading_policy.cc
@@ -98,27 +98,50 @@
   graph->RemovePageNodeObserver(this);
 }
 
-void BackgroundTabLoadingPolicy::OnIsLoadingChanged(const PageNode* page_node) {
-  if (!page_node->IsLoading()) {
-    // Once the PageNode finishes loading, stop tracking it within this policy.
-    RemovePageNode(page_node);
+void BackgroundTabLoadingPolicy::OnLoadingStateChanged(
+    const PageNode* page_node) {
+  switch (page_node->GetLoadingState()) {
+    // Loading is complete or stalled.
+    case PageNode::LoadingState::kLoadingNotStarted:
+    case PageNode::LoadingState::kLoadedIdle:
+    case PageNode::LoadingState::kLoadingTimedOut:
 
-    // Since there is a free loading slot, load more tab if needed.
-    MaybeLoadSomeTabs();
-    return;
+    {
+      // Stop tracking the page within this policy.
+      RemovePageNode(page_node);
+
+      // Since there might be a free loading slot, attempt to load more tabs.
+      MaybeLoadSomeTabs();
+
+      return;
+    }
+
+    // Loading starts.
+    case PageNode::LoadingState::kLoading: {
+      // The PageNode started loading because of this policy or because of
+      // external factors (e.g. user-initiated). In either case, remove the
+      // PageNode from the set of PageNodes for which a load needs to be
+      // initiated and from the set of PageNodes for which a load has been
+      // initiated but hasn't started.
+      ErasePageNodeToLoadData(page_node);
+      base::Erase(page_nodes_load_initiated_, page_node);
+
+      // Keep track of all PageNodes that are loading, even when the load isn't
+      // initiated by this policy.
+      DCHECK(!base::Contains(page_nodes_loading_, page_node));
+      page_nodes_loading_.push_back(page_node);
+
+      return;
+    }
+
+    // Loading is progressing.
+    case PageNode::LoadingState::kLoadedBusy: {
+      // This PageNode should have been added to |page_nodes_loading_| when it
+      // transitioned to |kLoading|.
+      DCHECK(base::Contains(page_nodes_loading_, page_node));
+      return;
+    }
   }
-  // The PageNode started loading, either because of this policy or because of
-  // external factors (e.g. user-initiated). In either case, remove the PageNode
-  // from the set of PageNodes for which a load needs to be initiated and from
-  // the set of PageNodes for which a load has been initiated but hasn't
-  // started.
-  ErasePageNodeToLoadData(page_node);
-  base::Erase(page_nodes_load_initiated_, page_node);
-
-  // Keep track of all PageNodes that are loading, even when the load isn't
-  // initiated by this policy.
-  DCHECK(!base::Contains(page_nodes_loading_, page_node));
-  page_nodes_loading_.push_back(page_node);
 }
 
 void BackgroundTabLoadingPolicy::OnBeforePageNodeRemoved(
@@ -187,7 +210,7 @@
     const PageNode* node) const {
   base::Value dict(base::Value::Type::DICTIONARY);
   if (base::Contains(page_nodes_load_initiated_, node)) {
-    // Transient state between InitiateLoad() and OnIsLoadingChanged(),
+    // Transient state between InitiateLoad() and OnLoadingStateChanged(),
     // shouldn't be sticking around for long.
     dict.SetBoolKey("page_load_initiated", true);
   }
diff --git a/chrome/browser/performance_manager/policies/background_tab_loading_policy.h b/chrome/browser/performance_manager/policies/background_tab_loading_policy.h
index 111294f..e948b20 100644
--- a/chrome/browser/performance_manager/policies/background_tab_loading_policy.h
+++ b/chrome/browser/performance_manager/policies/background_tab_loading_policy.h
@@ -43,7 +43,7 @@
   void OnTakenFromGraph(Graph* graph) override;
 
   // PageNodeObserver implementation:
-  void OnIsLoadingChanged(const PageNode* page_node) override;
+  void OnLoadingStateChanged(const PageNode* page_node) override;
   void OnBeforePageNodeRemoved(const PageNode* page_node) override;
 
   // Schedules the PageNodes in |page_nodes| to be loaded when appropriate.
diff --git a/chrome/browser/performance_manager/policies/background_tab_loading_policy_unittest.cc b/chrome/browser/performance_manager/policies/background_tab_loading_policy_unittest.cc
index 04977fd..976ceb4 100644
--- a/chrome/browser/performance_manager/policies/background_tab_loading_policy_unittest.cc
+++ b/chrome/browser/performance_manager/policies/background_tab_loading_policy_unittest.cc
@@ -117,14 +117,14 @@
   testing::Mock::VerifyAndClear(loader());
 
   // Simulate load start of a PageNode that initiated load.
-  page_node_impl->SetIsLoading(true);
+  page_node_impl->SetLoadingState(PageNode::LoadingState::kLoading);
 
   // The policy should allow one more PageNode to load after a PageNode finishes
   // loading.
   EXPECT_CALL(*loader(), LoadPageNode(raw_page_nodes[2]));
 
   // Simulate load finish of a PageNode.
-  page_node_impl->SetIsLoading(false);
+  page_node_impl->SetLoadingState(PageNode::LoadingState::kLoadedIdle);
 }
 
 TEST_F(BackgroundTabLoadingPolicyTest, ShouldLoad_MaxTabsToRestore) {
@@ -256,28 +256,28 @@
   PageNodeImpl* page_node_impl = page_nodes[1].get();
 
   // Simulate load start of a PageNode that initiated load.
-  page_node_impl->SetIsLoading(true);
+  page_node_impl->SetLoadingState(PageNode::LoadingState::kLoading);
 
   // The policy should allow one more PageNode to load after a PageNode finishes
   // loading.
   EXPECT_CALL(*loader(), LoadPageNode(raw_page_nodes[0]));
 
   // Simulate load finish of a PageNode.
-  page_node_impl->SetIsLoading(false);
+  page_node_impl->SetLoadingState(PageNode::LoadingState::kLoadedIdle);
 
   testing::Mock::VerifyAndClear(loader());
 
   page_node_impl = page_nodes[0].get();
 
   // Simulate load start of a PageNode that initiated load.
-  page_node_impl->SetIsLoading(true);
+  page_node_impl->SetLoadingState(PageNode::LoadingState::kLoading);
 
   // The policy should allow one more PageNode to load after a PageNode finishes
   // loading.
   EXPECT_CALL(*loader(), LoadPageNode(raw_page_nodes[2]));
 
   // Simulate load finish of a PageNode.
-  page_node_impl->SetIsLoading(false);
+  page_node_impl->SetLoadingState(PageNode::LoadingState::kLoadedIdle);
 }
 
 TEST_F(BackgroundTabLoadingPolicyTest, OnMemoryPressure) {
@@ -314,11 +314,11 @@
   PageNodeImpl* page_node_impl = page_nodes[0].get();
 
   // Simulate load start of a PageNode that initiated load.
-  page_node_impl->SetIsLoading(true);
+  page_node_impl->SetLoadingState(PageNode::LoadingState::kLoading);
 
   // Simulate load finish of a PageNode and expect the policy to not start
   // another load.
-  page_node_impl->SetIsLoading(false);
+  page_node_impl->SetLoadingState(PageNode::LoadingState::kLoadedIdle);
 }
 
 }  // namespace policies
diff --git a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.cc b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.cc
index c74fd21..b2d1321 100644
--- a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.cc
+++ b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.cc
@@ -243,8 +243,10 @@
       GetSwapDeviceFreeSpaceBytes();
 }
 
-bool UserspaceSwapPolicy::IsPageNodeLoading(const PageNode* page_node) {
-  return page_node->IsLoading();
+bool UserspaceSwapPolicy::IsPageNodeLoadingOrBusy(const PageNode* page_node) {
+  const PageNode::LoadingState loading_state = page_node->GetLoadingState();
+  return loading_state == PageNode::LoadingState::kLoading ||
+         loading_state == PageNode::LoadingState::kLoadedBusy;
 }
 
 bool UserspaceSwapPolicy::IsPageNodeAudible(const PageNode* page_node) {
@@ -290,7 +292,7 @@
   // it.
   if (page_node) {
     // If we're loading, audible, or visible we will not swap.
-    if (IsPageNodeLoading(page_node) || IsPageNodeVisible(page_node) ||
+    if (IsPageNodeLoadingOrBusy(page_node) || IsPageNodeVisible(page_node) ||
         IsPageNodeAudible(page_node)) {
       return false;
     }
diff --git a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h
index cfe6a4d5..71a5f5d 100644
--- a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h
+++ b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h
@@ -67,7 +67,7 @@
       const ProcessNode* process_node);
   virtual bool IsPageNodeVisible(const PageNode* page_node);
   virtual bool IsPageNodeAudible(const PageNode* page_node);
-  virtual bool IsPageNodeLoading(const PageNode* page_node);
+  virtual bool IsPageNodeLoadingOrBusy(const PageNode* page_node);
   virtual base::TimeDelta GetTimeSinceLastVisibilityChange(
       const PageNode* page_node);
 
diff --git a/chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc b/chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc
index b2c6440..eb9995aa 100644
--- a/chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc
+++ b/chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc
@@ -64,6 +64,10 @@
   auto resource_request = std::make_unique<network::ResourceRequest>();
   resource_request->load_flags |= net::LOAD_PREFETCH;
   resource_request->url = prefetch_url_;
+  // Search prefetch URL Loaders should check |report_raw_headers| on the
+  // intercepted request to clear out the raw headers when |report_raw_headers|
+  // is false.
+  resource_request->report_raw_headers = true;
   resource_request->credentials_mode =
       network::mojom::CredentialsMode::kInclude;
   variations::AppendVariationsHeaderUnknownSignedIn(
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.cc
index eb4c097..7dba922 100644
--- a/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.cc
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.cc
@@ -104,6 +104,10 @@
     return;
   }
 
+  if (!request.report_raw_headers) {
+    head_->raw_request_response_info = nullptr;
+  }
+
   client_->OnReceiveResponse(std::move(head_));
   client_->OnStartLoadingResponseBody(std::move(consumer_handle));
 
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
index 1fcf5d8..2203c62 100644
--- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -8,7 +8,10 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
+#include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/devtools/devtools_window.h"
+#include "chrome/browser/devtools/devtools_window_testing.h"
 #include "chrome/browser/net/prediction_options.h"
 #include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h"
 #include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h"
@@ -34,6 +37,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browsing_data_filter_builder.h"
 #include "content/public/browser/browsing_data_remover.h"
+#include "content/public/common/content_client.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/browsing_data_remover_test_util.h"
@@ -44,6 +48,7 @@
 #include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "url/gurl.h"
 
 namespace {
@@ -250,6 +255,14 @@
     model->Add(std::make_unique<TemplateURL>(data));
   }
 
+  void OpenDevToolsWindow(content::WebContents* tab) {
+    window_ = DevToolsWindowTesting::OpenDevToolsWindowSync(tab, true);
+  }
+
+  void CloseDevToolsWindow() {
+    DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
+  }
+
  private:
   std::unique_ptr<net::test_server::HttpResponse> HandleSearchRequest(
       const net::test_server::HttpRequest& request) {
@@ -400,6 +413,8 @@
 
   // When set to true, serves a response that hangs after the start of the body.
   bool hang_requests_after_start_ = false;
+
+  DevToolsWindow* window_ = nullptr;
 };
 
 class SearchPrefetchServiceDisabledBrowserTest
@@ -530,6 +545,120 @@
   EXPECT_EQ(SearchPrefetchStatus::kCanBeServed, prefetch_status.value());
 }
 
+class HeaderObserverContentBrowserClient : public ChromeContentBrowserClient {
+ public:
+  HeaderObserverContentBrowserClient() = default;
+  ~HeaderObserverContentBrowserClient() override = default;
+
+  // ContentBrowserClient overrides:
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+  CreateURLLoaderThrottles(
+      const network::ResourceRequest& request,
+      content::BrowserContext* browser_context,
+      const base::RepeatingCallback<content::WebContents*()>& wc_getter,
+      content::NavigationUIData* navigation_ui_data,
+      int frame_tree_node_id) override;
+
+  bool had_raw_request_info() { return had_raw_request_info_; }
+
+  void set_had_raw_request_info(bool had_raw_request_info) {
+    had_raw_request_info_ = had_raw_request_info;
+  }
+
+ private:
+  bool had_raw_request_info_ = false;
+};
+
+// A delegate to cancel prefetch requests by setting |defer| to true.
+class HeaderObserverThrottle : public blink::URLLoaderThrottle {
+ public:
+  explicit HeaderObserverThrottle(HeaderObserverContentBrowserClient* client)
+      : client_(client) {}
+  ~HeaderObserverThrottle() override = default;
+
+  void WillProcessResponse(const GURL& response_url,
+                           network::mojom::URLResponseHead* response_head,
+                           bool* defer) override {
+    client_->set_had_raw_request_info(
+        !!response_head->raw_request_response_info);
+  }
+
+ private:
+  HeaderObserverContentBrowserClient* client_;
+};
+
+std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+HeaderObserverContentBrowserClient::CreateURLLoaderThrottles(
+    const network::ResourceRequest& request,
+    content::BrowserContext* browser_context,
+    const base::RepeatingCallback<content::WebContents*()>& wc_getter,
+    content::NavigationUIData* navigation_ui_data,
+    int frame_tree_node_id) {
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles =
+      ChromeContentBrowserClient::CreateURLLoaderThrottles(
+          request, browser_context, wc_getter, navigation_ui_data,
+          frame_tree_node_id);
+  throttles.push_back(std::make_unique<HeaderObserverThrottle>(this));
+  return throttles;
+}
+
+IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest,
+                       HeadersNotReportedFromNetwork) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "prefetch_content";
+
+  GURL prefetch_url = GetSearchServerQueryURL(search_terms);
+
+  EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+  auto prefetch_status =
+      search_prefetch_service->GetSearchPrefetchStatusForTesting(
+          base::ASCIIToUTF16(search_terms));
+  ASSERT_TRUE(prefetch_status.has_value());
+  EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value());
+
+  WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms));
+
+  HeaderObserverContentBrowserClient browser_client;
+  auto* old_client = content::SetBrowserClientForTesting(&browser_client);
+  ui_test_utils::NavigateToURL(browser(), prefetch_url);
+
+  EXPECT_FALSE(browser_client.had_raw_request_info());
+  content::SetBrowserClientForTesting(old_client);
+}
+
+IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest,
+                       HeadersReportedFromNetworkWithDevTools) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "prefetch_content";
+
+  GURL prefetch_url = GetSearchServerQueryURL(search_terms);
+
+  EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+  auto prefetch_status =
+      search_prefetch_service->GetSearchPrefetchStatusForTesting(
+          base::ASCIIToUTF16(search_terms));
+  ASSERT_TRUE(prefetch_status.has_value());
+  EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value());
+
+  WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms));
+
+  OpenDevToolsWindow(browser()->tab_strip_model()->GetActiveWebContents());
+
+  HeaderObserverContentBrowserClient browser_client;
+  auto* old_client = content::SetBrowserClientForTesting(&browser_client);
+  ui_test_utils::NavigateToURL(browser(), prefetch_url);
+
+  EXPECT_TRUE(browser_client.had_raw_request_info());
+  CloseDevToolsWindow();
+  content::SetBrowserClientForTesting(old_client);
+}
+
 IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest,
                        PrefetchRateLimiting) {
   auto* search_prefetch_service =
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
index 2c1e63fa..2c235112c1 100644
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
@@ -58,7 +58,7 @@
 }
 
 void StreamingSearchPrefetchURLLoader::SetUpForwardingClient(
-    const network::ResourceRequest& /* resource_request */,
+    const network::ResourceRequest& resource_request,
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
     mojo::PendingRemote<network::mojom::URLLoaderClient> forwarding_client) {
   DCHECK(!streaming_prefetch_request_);
@@ -70,6 +70,10 @@
                      weak_factory_.GetWeakPtr()));
   forwarding_client_.Bind(std::move(forwarding_client));
 
+  if (!resource_request.report_raw_headers) {
+    resource_response_->raw_request_response_info = nullptr;
+  }
+
   forwarding_client_->OnReceiveResponse(std::move(resource_response_));
 
   // Resume previously paused network service URLLoader.
diff --git a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc
index cc1517a3..d44249c0 100644
--- a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc
@@ -35,10 +35,10 @@
 TabManager::ResourceCoordinatorSignalObserver::
     ~ResourceCoordinatorSignalObserver() = default;
 
-void TabManager::ResourceCoordinatorSignalObserver::OnIsLoadingChanged(
+void TabManager::ResourceCoordinatorSignalObserver::OnLoadingStateChanged(
     const PageNode* page_node) {
   // Forward the notification over to the UI thread when the page stops loading.
-  if (!page_node->IsLoading()) {
+  if (page_node->GetLoadingState() == PageNode::LoadingState::kLoadedIdle) {
     content::GetUIThreadTaskRunner({})->PostTask(
         FROM_HERE, base::BindOnce(&OnPageStoppedLoadingOnUi,
                                   page_node->GetContentsProxy()));
diff --git a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h
index 42eab59..da8e548 100644
--- a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h
+++ b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h
@@ -34,7 +34,7 @@
 
   // PageNode::ObserverDefaultImpl:
   // This function run on the performance manager sequence.
-  void OnIsLoadingChanged(const PageNode* page_node) override;
+  void OnLoadingStateChanged(const PageNode* page_node) override;
 
   // GraphOwned implementation:
   void OnPassedToGraph(Graph* graph) override;
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ar.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ar.xtb
index f65988d9..b05e1ba5 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ar.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ar.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">المجموعة التالية</translation>
 <translation id="7813616274030162878">قائمة الوصول عبر مفتاح التحويل</translation>
 <translation id="7839679365527550018">الكلمة السابقة</translation>
+<translation id="7842115774595115751">تفعيل عناصر التحكُّم في التنقُّل</translation>
 <translation id="7846634333498149051">لوحة المفاتيح</translation>
 <translation id="7851816175263618915">بعض علامات الترقيم</translation>
 <translation id="7871691770940645922">عرض برايل الافتراضي</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_be.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_be.xtb
index 5d90307d..63298cc6 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_be.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_be.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">Наступная група</translation>
 <translation id="7813616274030162878">Меню доступу праз пераключальнікі</translation>
 <translation id="7839679365527550018">Папярэдняе слова</translation>
+<translation id="7842115774595115751">Уключыць элементы кіравання навігацыяй</translation>
 <translation id="7846634333498149051">Клавіятура</translation>
 <translation id="7851816175263618915">Некаторая пунктуацыя</translation>
 <translation id="7871691770940645922">Віртуальны дысплэй Брайля</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fi.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fi.xtb
index 180d5c6..1826a43 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fi.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fi.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">Seuraava ryhmä</translation>
 <translation id="7813616274030162878">Kytkimen käytön valikko</translation>
 <translation id="7839679365527550018">Edellinen sana</translation>
+<translation id="7842115774595115751">Ota siirtymispainikkeet käyttöön</translation>
 <translation id="7846634333498149051">Näppäimistö</translation>
 <translation id="7851816175263618915">Osa välimerkeistä</translation>
 <translation id="7871691770940645922">Virtuaalinen pistekirjoitusnäyttö</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fr-CA.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fr-CA.xtb
index e03f07a..a98fc99 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fr-CA.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fr-CA.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">Groupe suivant</translation>
 <translation id="7813616274030162878">Menu de Switch Access</translation>
 <translation id="7839679365527550018">Mot précédent</translation>
+<translation id="7842115774595115751">Activer les commandes de navigation</translation>
 <translation id="7846634333498149051">Clavier</translation>
 <translation id="7851816175263618915">Certains signes de ponctuation</translation>
 <translation id="7871691770940645922">Affichage braille virtuel</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_gl.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_gl.xtb
index d7ed393..e919855 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_gl.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_gl.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">Seguinte grupo</translation>
 <translation id="7813616274030162878">Menú de Acceso con interruptores</translation>
 <translation id="7839679365527550018">Palabra anterior</translation>
+<translation id="7842115774595115751">Activar controis de navegación</translation>
 <translation id="7846634333498149051">Teclado</translation>
 <translation id="7851816175263618915">Algúns signos de puntuación</translation>
 <translation id="7871691770940645922">Visualización de braille virtual</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_hu.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_hu.xtb
index 2a977813..7cd78a9 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_hu.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_hu.xtb
@@ -913,6 +913,7 @@
 <translation id="7810781339813764006">Következő csoport</translation>
 <translation id="7813616274030162878">A kapcsolóalapú hozzáférés menüje</translation>
 <translation id="7839679365527550018">Előző szó</translation>
+<translation id="7842115774595115751">Navigációs vezérlők engedélyezése</translation>
 <translation id="7846634333498149051">Billentyűzet</translation>
 <translation id="7851816175263618915">Bizonyos írásjelek</translation>
 <translation id="7871691770940645922">Virtuális Braille-kijelző</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_kn.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_kn.xtb
index a5dfcc0..a8e69db 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_kn.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_kn.xtb
@@ -913,6 +913,7 @@
 <translation id="7810781339813764006">ಮುಂದಿನ ಗುಂಪು</translation>
 <translation id="7813616274030162878">ಪ್ರವೇಶದ ಮೆನು ಬದಲಿಸಿ</translation>
 <translation id="7839679365527550018">ಹಿಂದಿನ ಪದ</translation>
+<translation id="7842115774595115751">ನ್ಯಾವಿಗೇಶನ್ ನಿಯಂತ್ರಣಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ</translation>
 <translation id="7846634333498149051">ಕೀಬೋರ್ಡ್</translation>
 <translation id="7851816175263618915">ಕೆಲವು ವಿರಾಮಚಿಹ್ನೆಗಳು</translation>
 <translation id="7871691770940645922">ವರ್ಚುವಲ್ ಬ್ರೈಲ್ ಡಿಸ್‌ಪ್ಲೇ</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ko.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ko.xtb
index d8d3ba4..81fe77b 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ko.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ko.xtb
@@ -913,6 +913,7 @@
 <translation id="7810781339813764006">다음 그룹</translation>
 <translation id="7813616274030162878">스위치 제어 메뉴</translation>
 <translation id="7839679365527550018">이전 단어</translation>
+<translation id="7842115774595115751">탐색 제어 기능 사용</translation>
 <translation id="7846634333498149051">키보드</translation>
 <translation id="7851816175263618915">일부 구두점만 읽음</translation>
 <translation id="7871691770940645922">가상 점자 디스플레이</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pa.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pa.xtb
index b7b68f11..f785fa6 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pa.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pa.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">ਅਗਲਾ ਸਮੂਹ</translation>
 <translation id="7813616274030162878">ਸਵਿੱਚ ਪਹੁੰਚ ਦਾ ਮੀਨੂ</translation>
 <translation id="7839679365527550018">ਪਿਛਲਾ ਸ਼ਬਦ</translation>
+<translation id="7842115774595115751">ਨੈਵੀਗੇਸ਼ਨ ਕੰਟਰੋਲ ਚਾਲੂ ਕਰੋ</translation>
 <translation id="7846634333498149051">ਕੀ-ਬੋਰਡ</translation>
 <translation id="7851816175263618915">ਕੁਝ ਵਿਸ਼ਰਾਮ ਚਿੰਨ੍ਹ</translation>
 <translation id="7871691770940645922">ਵਰਚੁਅਲ ਬ੍ਰੇਲ ਡਿਸਪਲੇ</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sk.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sk.xtb
index 7fc94385..7b235b7 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sk.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sk.xtb
@@ -913,6 +913,7 @@
 <translation id="7810781339813764006">Ďalšia skupina</translation>
 <translation id="7813616274030162878">Ponuka ovládania prepínačmi</translation>
 <translation id="7839679365527550018">Predchádzajúce slovo</translation>
+<translation id="7842115774595115751">Aktivovať navigáciu</translation>
 <translation id="7846634333498149051">Klávesnica</translation>
 <translation id="7851816175263618915">Čiastočná interpunkcia</translation>
 <translation id="7871691770940645922">Virtuálna Braillova obrazovka</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sq.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sq.xtb
index de908ba..8e6e327 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sq.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sq.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">Grupi tjetër</translation>
 <translation id="7813616274030162878">Menyja e "Qasjes me çelës"</translation>
 <translation id="7839679365527550018">Fjala e mëparshme</translation>
+<translation id="7842115774595115751">Aktivizo kontrollet e navigimit</translation>
 <translation id="7846634333498149051">Tastiera</translation>
 <translation id="7851816175263618915">Disa shenja pikësimi</translation>
 <translation id="7871691770940645922">Ekrani virtual Braille</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sv.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sv.xtb
index 6eeba63a..4a7b4762 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sv.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sv.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">Nästa grupp</translation>
 <translation id="7813616274030162878">Meny för brytarstyrning</translation>
 <translation id="7839679365527550018">Föregående ord</translation>
+<translation id="7842115774595115751">Aktivera navigeringskontroller</translation>
 <translation id="7846634333498149051">Tangentbord</translation>
 <translation id="7851816175263618915">Vissa skiljetecken</translation>
 <translation id="7871691770940645922">Virtuell punktskriftsskärm</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sw.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sw.xtb
index e2b158c..4979bac4 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sw.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sw.xtb
@@ -914,6 +914,7 @@
 <translation id="7810781339813764006">Kikundi Kinachofuata</translation>
 <translation id="7813616274030162878">Menyu ya Kufikia Kupitia Swichi</translation>
 <translation id="7839679365527550018">Neno Lililotangulia</translation>
+<translation id="7842115774595115751">Washa vidhibiti vya usogezaji</translation>
 <translation id="7846634333498149051">Kibodi</translation>
 <translation id="7851816175263618915">Baadhi ya vituo vya maandishi</translation>
 <translation id="7871691770940645922">Onyesho la Breli Pepe</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_tr.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_tr.xtb
index c267112..6a938f6 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_tr.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_tr.xtb
@@ -913,6 +913,7 @@
 <translation id="7810781339813764006">Sonraki Grup</translation>
 <translation id="7813616274030162878">Anahtar Erişimi Menüsü</translation>
 <translation id="7839679365527550018">Önceki Kelime</translation>
+<translation id="7842115774595115751">Gezinme kontrollerini etkinleştir</translation>
 <translation id="7846634333498149051">Klavye</translation>
 <translation id="7851816175263618915">Bazı noktalama işaretleri</translation>
 <translation id="7871691770940645922">Sanal Braille Ekranı</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ur.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ur.xtb
index d6bbd548..681c060 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ur.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ur.xtb
@@ -915,6 +915,7 @@
 <translation id="7810781339813764006">اگلا گروپ</translation>
 <translation id="7813616274030162878">سوئچ رسائی کا مینو</translation>
 <translation id="7839679365527550018">پچھلا لفظ</translation>
+<translation id="7842115774595115751">نیویگیشن کنٹرولز کو فعال کریں</translation>
 <translation id="7846634333498149051">کی بورڈ</translation>
 <translation id="7851816175263618915">کچھ رموز اوقاف</translation>
 <translation id="7871691770940645922">ورچوئل بریل ڈسپلے</translation>
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_dialog/oobe_dialog.html b/chrome/browser/resources/chromeos/login/components/oobe_dialog/oobe_dialog.html
index 1e75695e..4492636 100644
--- a/chrome/browser/resources/chromeos/login/components/oobe_dialog/oobe_dialog.html
+++ b/chrome/browser/resources/chromeos/login/components/oobe_dialog/oobe_dialog.html
@@ -80,9 +80,6 @@
     -->
     <style include="oobe-dialog-host cr-shared-style">
       :host {
-        --title-font-distance-to-baseline: 7px;
-        --subtitle-font-size: --oobe-default-font-size;
-        --subtitle-font-distance-to-baseline: 3px;
         --subtitle-line-height: 18px;
         @apply --oobe-default-font;
       }
@@ -194,10 +191,6 @@
         z-index: 1;
       }
 
-      :host #oobe-bottom[no-buttons-padding] {
-        padding: unset;
-      }
-
       #oobe-icon-div ::slotted(hd-iron-icon),
       #oobe-icon-div ::slotted(iron-icon) {
         --iron-icon-height: 32px;
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_dialog/oobe_dialog.js b/chrome/browser/resources/chromeos/login/components/oobe_dialog/oobe_dialog.js
index d6707da..beda40f52 100644
--- a/chrome/browser/resources/chromeos/login/components/oobe_dialog/oobe_dialog.js
+++ b/chrome/browser/resources/chromeos/login/components/oobe_dialog/oobe_dialog.js
@@ -41,14 +41,6 @@
     },
 
     /**
-     * Removes buttons padding.
-     */
-    noButtonsPadding: {
-      type: Boolean,
-      value: false,
-    },
-
-    /**
      * If true footer would be shrunk as much as possible to fit container.
      */
     footerShrinkable: {
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_enable_debugging.js b/chrome/browser/resources/chromeos/login/oobe_screen_enable_debugging.js
index 215347f9..c6dc2d6 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_enable_debugging.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_enable_debugging.js
@@ -87,7 +87,7 @@
    * network settings.
    */
   cancel() {
-    chrome.send('enableDebuggingOnCancel');
+    this.userActed('cancel');
   },
 
   /**
@@ -112,11 +112,11 @@
   },
 
   onHelpLinkClicked_() {
-    chrome.send('enableDebuggingOnLearnMore');
+    this.userActed('learnMore');
   },
 
   onRemoveButtonClicked_() {
-    chrome.send('enableDebuggingOnRemoveRootFSProtection');
+    this.userActed('removeRootFSProtection');
   },
 
   onEnableButtonClicked_() {
@@ -126,7 +126,7 @@
   },
 
   onOKButtonClicked_() {
-    chrome.send('enableDebuggingOnDone');
+    this.userActed('done');
   },
 
 });
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 9d7ab0f6..ca96e37 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -65,19 +65,23 @@
     "images/safe_browsing_banner.svg",
     "images/sync_banner_dark.svg",
     "images/sync_banner.svg",
+    "privacy_sandbox/privacy_sandbox.html",
     "settings.html",
   ]
   input_files_base_dir = rebase_path(".", "//")
 
+  grdp_files = [ "$target_gen_dir/privacy_sandbox/resources.grdp" ]
+  deps = [ "privacy_sandbox:build_grdp" ]
+
   if (optimize_webui) {
-    deps = [ ":build" ]
+    deps += [ ":build" ]
     manifest_files = [ "$target_gen_dir/$build_manifest" ]
     resource_path_rewrites = [
       "settings.rollup.js|settings.js",
       "lazy_load.rollup.js|lazy_load.js",
     ]
   } else {
-    deps = [
+    deps += [
       ":preprocess",
       ":preprocess_generated",
     ]
@@ -355,6 +359,7 @@
     "people_page:closure_compile",
     "prefs:closure_compile",
     "privacy_page:closure_compile",
+    "privacy_sandbox:closure_compile",
     "search_engines_page:closure_compile",
     "settings_page:closure_compile",
   ]
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html
index eb15380d..7866578 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html
@@ -110,7 +110,7 @@
             hidden="[[!confirmButtonVisible_]]"
             disabled="[[confirmButtonDisabled_]]"
             on-click="confirmButtonClick_">
-          $i18n{continue}
+          [[confirmButtonLabel_]]
         </cr-button>
         <cr-button id="doneButton" class="action-button"
             on-click="done_" hidden="[[!doneButtonVisible_]]">
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js
index 6293851..6e261a9e 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js
@@ -64,6 +64,9 @@
     confirmButtonVisible_: Boolean,
 
     /** @private */
+    confirmButtonLabel_: String,
+
+    /** @private */
     deleteInProgress_: Boolean,
 
     /**
@@ -104,6 +107,9 @@
   /** @private {string} */
   recentEnrollmentId_: '',
 
+  /** @private {boolean} */
+  showSetPINButton_: false,
+
   /** @override */
   attached() {
     afterNextRender(this, function() {
@@ -125,9 +131,11 @@
   /**
    * @private
    * @param {string} error
+   * @param {boolean=} requiresPINChange
    */
-  onError_(error) {
+  onError_(error, requiresPINChange = false) {
     this.errorMsg_ = error;
+    this.showSetPINButton_ = requiresPINChange;
     this.dialogPage_ = BioEnrollDialogPage.ERROR;
   },
 
@@ -175,6 +183,7 @@
         this.cancelButtonVisible_ = true;
         this.cancelButtonDisabled_ = false;
         this.confirmButtonVisible_ = true;
+        this.confirmButtonLabel_ = this.i18n('continue');
         this.confirmButtonDisabled_ = false;
         this.doneButtonVisible_ = false;
         this.$.pin.focus();
@@ -193,14 +202,16 @@
       case BioEnrollDialogPage.CHOOSE_NAME:
         this.cancelButtonVisible_ = false;
         this.confirmButtonVisible_ = true;
+        this.confirmButtonLabel_ = this.i18n('continue');
         this.confirmButtonDisabled_ = !this.recentEnrollmentName_.length;
         this.doneButtonVisible_ = false;
         this.$.enrollmentName.focus();
         break;
       case BioEnrollDialogPage.ERROR:
-        this.cancelButtonVisible_ = false;
-        this.confirmButtonVisible_ = false;
-        this.doneButtonVisible_ = true;
+        this.cancelButtonVisible_ = true;
+        this.confirmButtonVisible_ = this.showSetPINButton_;
+        this.confirmButtonLabel_ = this.i18n('securityKeysSetPinButton');
+        this.doneButtonVisible_ = false;
         break;
       default:
         assertNotReached();
@@ -303,6 +314,10 @@
       case BioEnrollDialogPage.CHOOSE_NAME:
         this.renameNewEnrollment_();
         break;
+      case BioEnrollDialogPage.ERROR:
+        this.$.dialog.close();
+        this.fire('bio-enroll-set-pin');
+        break;
       default:
         assertNotReached();
     }
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.js b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.js
index 8e9393d..56e5738 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.js
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.js
@@ -95,6 +95,9 @@
   /** @private {?Set<string>} */
   checkedCredentialIds_: null,
 
+  /** @private {boolean} */
+  showSetPINButton_: false,
+
   /** @override */
   attached() {
     this.$.dialog.showModal();
@@ -112,9 +115,11 @@
   /**
    * @private
    * @param {string} error
+   * @param {boolean=} requiresPINChange
    */
-  onError_(error) {
+  onError_(error, requiresPINChange = false) {
     this.errorMsg_ = error;
+    this.showSetPINButton_ = requiresPINChange;
     this.dialogPage_ = CredentialManagementDialogPage.ERROR;
   },
 
@@ -175,9 +180,10 @@
         this.closeButtonVisible_ = false;
         break;
       case CredentialManagementDialogPage.ERROR:
-        this.cancelButtonVisible_ = false;
-        this.confirmButtonVisible_ = false;
-        this.closeButtonVisible_ = true;
+        this.cancelButtonVisible_ = true;
+        this.confirmButtonLabel_ = this.i18n('securityKeysSetPinButton');
+        this.confirmButtonVisible_ = this.showSetPINButton_;
+        this.closeButtonVisible_ = false;
         break;
       default:
         assertNotReached();
@@ -194,6 +200,10 @@
       case CredentialManagementDialogPage.CREDENTIALS:
         this.deleteSelectedCredentials_();
         break;
+      case CredentialManagementDialogPage.ERROR:
+        this.$.dialog.close();
+        this.fire('credential-management-set-pin');
+        break;
       default:
         assertNotReached();
     }
@@ -274,10 +284,10 @@
     this.confirmButtonDisabled_ = true;
     this.deleteInProgress_ = true;
     this.browserProxy_.deleteCredentials(Array.from(this.checkedCredentialIds_))
-        .then((err) => {
+        .then((error) => {
           this.confirmButtonDisabled_ = false;
           this.deleteInProgress_ = false;
-          this.onError_(err);
+          this.onError_(error);
         });
   },
 });
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_subpage.html b/chrome/browser/resources/settings/privacy_page/security_keys_subpage.html
index f2c8057..a0b0c86 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_subpage.html
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_subpage.html
@@ -33,6 +33,7 @@
 
     <template is="dom-if" if="[[showCredentialManagementDialog_]]" restamp>
       <settings-security-keys-credential-management-dialog
+        on-credential-management-set-pin="onSetPIN_"
         on-close="onCredentialManagementDialogClosed_">
       </settings-security-keys-credential-management-dialog>
     </template>
@@ -44,6 +45,7 @@
 
     <template is="dom-if" if="[[showBioEnrollDialog_]]" restamp>
       <settings-security-keys-bio-enroll-dialog
+          on-bio-enroll-set-pin="onSetPIN_"
           on-close="onBioEnrollDialogClosed_">
       </settings-security-keys-bio-enroll-dialog>
     </template>
diff --git a/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn b/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn
new file mode 100644
index 0000000..aefd267
--- /dev/null
+++ b/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/html_to_js.gni")
+import("//ui/webui/resources/tools/generate_grd.gni")
+import("../settings.gni")
+
+generate_grd("build_grdp") {
+  grd_prefix = "privacy_sandbox"
+  out_grd = "$target_gen_dir/resources.grdp"
+  deps = [ ":web_components" ]
+  input_files_base_dir = rebase_path(target_gen_dir, root_build_dir)
+  input_files = [ "app.js" ]
+  resource_path_prefix = "privacy_sandbox"
+}
+
+js_type_check("closure_compile") {
+  is_polymer3 = true
+  closure_flags = settings_closure_flags
+  deps = [ ":app" ]
+}
+
+js_library("app") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
+html_to_js("web_components") {
+  js_files = [ "app.js" ]
+}
diff --git a/chrome/browser/resources/settings/privacy_sandbox/OWNERS b/chrome/browser/resources/settings/privacy_sandbox/OWNERS
new file mode 100644
index 0000000..8218569b
--- /dev/null
+++ b/chrome/browser/resources/settings/privacy_sandbox/OWNERS
@@ -0,0 +1,4 @@
+sauski@google.com
+
+# COMPONENT: UI>Settings>Privacy
+# TEAM: chrome-friendly-settings@google.com
diff --git a/chrome/browser/resources/settings/privacy_sandbox/app.html b/chrome/browser/resources/settings/privacy_sandbox/app.html
new file mode 100644
index 0000000..bb57b47
--- /dev/null
+++ b/chrome/browser/resources/settings/privacy_sandbox/app.html
@@ -0,0 +1,13 @@
+<style include="cr-shared-style">
+  #page-heading {
+    font-size: 2rem;
+    font-weight: 200;
+    margin: 0;
+    padding: 28px 0 14px 0;
+    text-align: center;
+  }
+</style>
+
+<div class="cr-centered-card-container">
+  <h1 id="page-heading">$i18n{privacySandboxPageHeading}</h1>
+</div>
diff --git a/chrome/browser/resources/settings/privacy_sandbox/app.js b/chrome/browser/resources/settings/privacy_sandbox/app.js
new file mode 100644
index 0000000..547f633a
--- /dev/null
+++ b/chrome/browser/resources/settings/privacy_sandbox/app.js
@@ -0,0 +1,12 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+import 'chrome://resources/cr_elements/shared_style_css.m.js';
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+Polymer({
+  is: 'privacy-sandbox-app',
+
+  _template: html`{__html_template__}`,
+
+});
diff --git a/chrome/browser/resources/settings/privacy_sandbox/privacy_sandbox.html b/chrome/browser/resources/settings/privacy_sandbox/privacy_sandbox.html
new file mode 100644
index 0000000..2b9ea9a
--- /dev/null
+++ b/chrome/browser/resources/settings/privacy_sandbox/privacy_sandbox.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+  <meta charset="utf-8">
+  <meta name="color-scheme" content="light dark">
+  <title>$i18n{privacySandboxTitle}</title>
+  <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
+  <style>
+    html {
+      background: var(--md-background-color);
+      height: 100%;
+    }
+
+    html,
+    body {
+      height: 100%;
+      margin: 0;
+    }
+  </style>
+</head>
+<body>
+  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+  <script type="module" src="privacy_sandbox/app.js"></script>
+  <privacy-sandbox-app></privacy-sandbox-app>
+</body>
+</html>
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
index f021402..b4b3748 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
@@ -21,6 +21,7 @@
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
     "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
+    "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
   ]
 }
 
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html
index a398124..3cf3204 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html
@@ -31,7 +31,13 @@
     font-weight: normal;
     line-height: 20px;
     margin-top: 18px;
-    outline: none;
+  }
+
+  /* The "not now" button is styled like a link, and uses FocusOutlineManager to
+   * only show outlines when focus was triggered by keyboard.
+   */
+  :host-context(html:not(.focus-outline-visible)) #notNowButton {
+      outline: none;
   }
 
   #signInButton {
@@ -62,12 +68,12 @@
   <h3>$i18n{profileTypeChoiceSubtitle}</h3>
 </div>
 <div id="actionContainer">
-  <cr-button id="signInButton" class="action-button fade-in"
-      on-click="onSignInClick_" disabled="[[loadSigninInProgess_]]">
+  <cr-button id="signInButton" class="action-button" on-click="onSignInClick_"
+      disabled="[[loadSigninInProgess_]]">
     $i18n{signInButtonLabel}
   </cr-button>
-  <button id="notNowButton" class="action-link fade-in"
-      on-click="onNotNowClick_" disabled="[[loadSigninInProgess_]]">
+  <button id="notNowButton" on-click="onNotNowClick_"
+      disabled="[[loadSigninInProgess_]]">
     $i18n{notNowButtonLabel}
   </button>
 </div>
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js
index 36dfc97a..7b9fb05 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js
@@ -7,6 +7,7 @@
 import './shared_css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
+import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js';
 import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
@@ -40,6 +41,7 @@
   ready() {
     this.addWebUIListener(
         'load-signin-failed', () => this.handleLoadSigninFailed_());
+    FocusOutlineManager.forDocument(document);
   },
 
   /** @private */
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 76d97c42..644abb63 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -4049,6 +4049,14 @@
       "views/toolbar/browser_actions_container.h",
       "views/toolbar/browser_app_menu_button.cc",
       "views/toolbar/browser_app_menu_button.h",
+      "views/toolbar/chrome_labs_bubble_view.cc",
+      "views/toolbar/chrome_labs_bubble_view.h",
+      "views/toolbar/chrome_labs_bubble_view_model.cc",
+      "views/toolbar/chrome_labs_bubble_view_model.h",
+      "views/toolbar/chrome_labs_button.cc",
+      "views/toolbar/chrome_labs_button.h",
+      "views/toolbar/chrome_labs_item_view.cc",
+      "views/toolbar/chrome_labs_item_view.h",
       "views/toolbar/extension_toolbar_menu_view.cc",
       "views/toolbar/extension_toolbar_menu_view.h",
       "views/toolbar/home_button.cc",
@@ -4164,6 +4172,7 @@
       "//device/vr/buildflags:buildflags",
       "//services/media_session/public/mojom",
       "//ui/base/dragdrop/mojom:mojom_shared",
+      "//ui/gfx/geometry",
       "//ui/views:buildflags",
     ]
 
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
index cac724bd..e2ed5a80 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
@@ -980,7 +980,7 @@
 <translation id="7798392620021911922"><ph name="TAB_COUNT" /> onglets sont restaurés</translation>
 <translation id="780301667611848630">Non merci</translation>
 <translation id="7810647596859435254">Ouvrir avec…</translation>
-<translation id="7815484226266492798">Longue capture d'écran</translation>
+<translation id="7815484226266492798">Capture d'écran pleine page</translation>
 <translation id="7821588508402923572">Vos économies de données s'affichent ici</translation>
 <translation id="7844171778363018843">Aucune donnée à synchroniser</translation>
 <translation id="7846296061357476882">Services Google</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
index 69ab6dc0..fe7bfc7 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
@@ -980,6 +980,7 @@
 <translation id="7798392620021911922"><ph name="TAB_COUNT" /> ટૅબ રિસ્ટોર કરી</translation>
 <translation id="780301667611848630">નહીં, આભાર</translation>
 <translation id="7810647596859435254">આની સાથે ખોલો…</translation>
+<translation id="7815484226266492798">લાંબો સ્ક્રીનશૉટ</translation>
 <translation id="7821588508402923572">તમારી ડેટા બચત અહીં દેખાશે</translation>
 <translation id="7844171778363018843">સિંક કરવા માટે કોઈ ડેટા પસંદ કર્યો નથી</translation>
 <translation id="7846296061357476882">Googleની સેવાઓ</translation>
@@ -1155,6 +1156,7 @@
 <translation id="9065203028668620118">ફેરફાર કરો</translation>
 <translation id="9065383040763568503">Chromeને મહત્ત્વનો ન લાગતો હોય તેવો સ્ટોર કરેલો ડેટા (દા.ત., કોઇ સાચવેલા સેટિંગ ન હોય તેવી અથવા વારંવાર મુલાકાત ન લેવાતી હોય તેવી સાઇટ)</translation>
 <translation id="9069543557624799859"><ph name="TIME" /> વાગ્યે ડાઉનલોડ શરૂ થશે.</translation>
+<translation id="9069999660519089861">વાંચ્યા વગરનું કોઈ પેજ નથી</translation>
 <translation id="9070377983101773829">વૉઇસ શોધ પ્રારંભ કરો</translation>
 <translation id="9074336505530349563">Google દ્વારા સૂચવેલ વ્યક્તિગત કરેલ કન્ટેન્ટ મેળવવા માટે, સાઇન ઇન કરો અને સિંક કરવાનું ચાલુ કરો</translation>
 <translation id="9086302186042011942">સમન્વય કરી રહ્યું છે</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_my.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_my.xtb
index 578606c..cb5afa08 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_my.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_my.xtb
@@ -371,7 +371,7 @@
 <translation id="363596933471559332">သိမ်းဆည်းထားသည့် အထောက်အထားများကို သုံးကာ ဝဘ်ဆိုက်များသို့ အလိုအလျောက် လက်မှတ်ထိုး ဝင်ပါသည်။ ၎င်းအင်္ဂါရပ်ကို ပိတ်ထားလျှင်၊ ထိုသို့ လုပ်ဆောင်နိုင်ချက်အား ပိတ်ထားပါက၊ သင်က ဝဘ်ဆိုက် တစ်ခုခုသို့ လက်မှတ်ထိုး ဝင်လိုတိုင်းမှာ အတည်ပြုရန် တောင်းဆိုပါလိမ့်မည်။</translation>
 <translation id="3653111872753786013"><ph name="WEBSITE_TITLE" />− <ph name="WEBSITE_URL" /></translation>
 <translation id="3658159451045945436">ပြင်ဆင်သတ်မှတ်ခြင်းသည် သင်ဝင်ကြည့်ခဲ့သည့် ဝဘ်ဆိုက်များစာရင်း အပါအဝင် သင်၏ ဒေတာ ချွေတာမှုမှတ်တမ်းကို ဖျက်လိုက်ပါမည်။</translation>
-<translation id="3687645719033307815">သင်သည် ဤစာမျက်နှာကို အစမ်းကြည့်ရှုနေခြင်း ဖြစ်သည်</translation>
+<translation id="3687645719033307815">သင်သည် ဤစာမျက်နှာ၏ အစမ်းပြသမှုကို ကြည့်ရှုနေခြင်း ဖြစ်သည်</translation>
 <translation id="3692944402865947621">သိုလှောင်ခန်းနေရာသို့ ချိတ်ဆက်၍မရသောကြောင့် <ph name="FILE_NAME" /> ကို ဒေါင်းလုဒ်လုပ်၍မရပါ။</translation>
 <translation id="3701167022068948696">ယခု ပြင်ဆင်ရန်</translation>
 <translation id="371230970611282515">အန္တရာယ်ရှိသည့် ဖြစ်ရပ်များ မဖြစ်ပွားမီ ခန့်မှန်းပြီး သင့်အား သတိပေးသည်။</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
index 37dfc2f..f22bad2 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
@@ -492,6 +492,7 @@
 <translation id="4587589328781138893">Sites</translation>
 <translation id="4594952190837476234">ଏହି ପୃଷ୍ଠା <ph name="CREATION_TIME" />ର ଅଟେ ଏବଂ ଅନ୍‌ଲାଇନ୍ ସଂସ୍କରଣ ଠାରୁ ଅଲଗା ହୋଇପାରେ।</translation>
 <translation id="4605958867780575332">କଢ଼ାଯାଇଥିବା ଆଇଟମ୍: <ph name="ITEM_TITLE" /></translation>
+<translation id="4614535611158687827">ପୃଷ୍ଠାଗୁଡ଼ିକୁ ପରବର୍ତ୍ତୀ ସମୟ ପାଇଁ ସେଭ୍ କରନ୍ତୁ ଏବଂ ଏକ ରିମାଇଣ୍ଡର୍ ପାଆନ୍ତୁ</translation>
 <translation id="4616150815774728855"><ph name="WEBAPK_NAME" /> ଖୋଲନ୍ତୁ</translation>
 <translation id="4634124774493850572">ପାସ୍‌ୱର୍ଡ ବ୍ୟବହାର କରନ୍ତୁ</translation>
 <translation id="4640331037679501949">{NUM_PASSWORDS,plural, =1{1ଟି ଚୋରି ହୋଇଯାଇଥିବା ପାସୱାର୍ଡ}other{#ଟି ଚୋରି ହୋଇଯାଇଥିବା ପାସୱାର୍ଡ}}</translation>
@@ -974,10 +975,12 @@
 <translation id="7774809984919390718">{PAYMENT_METHOD,plural, =1{<ph name="PAYMENT_METHOD_PREVIEW" />\u2026 ଓ <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ଅଧିକ}other{<ph name="PAYMENT_METHOD_PREVIEW" />\u2026 ଓ <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ଅଧିକ}}</translation>
 <translation id="7778840695157240389">ନୂଆ ଷ୍ଟୋରୀଗୁଡ଼ିକ ପାଇଁ ପରେ ପୁଣି ଦେଖନ୍ତୁ</translation>
 <translation id="7786595606756654269">Google Assistant ୱେବରେ ସନ୍ଧାନ କରିବାକୁ ଏବଂ ଆପଣ ଖୋଲିଥିବା ସାଇଟଗୁଡ଼ିକୁ ବ୍ୟସ୍ତ ରଖିବା ପାଇଁ ଏକ ଉନ୍ନତ ଭଏସ୍ ଅନୁଭୂତି ପ୍ରଦାନ କରେ। ଆପଣ Google Assistant ମାଧ୍ୟମରେ ବ୍ୟବହାର କରିଥିବା ସାଇଟଗୁଡ଼ିକର URL ଏବଂ ବିଷୟବସ୍ତୁକୁ Assistant ପ୍ରାପ୍ତ କରିବ।</translation>
+<translation id="7790349552933995572">ମୂଳସ୍କ୍ରିନ୍</translation>
 <translation id="7791543448312431591">ଯୋଡନ୍ତୁ</translation>
 <translation id="7798392620021911922"><ph name="TAB_COUNT" />ଟି ଟାବ୍ ରିଷ୍ଟୋର କରାଯାଇଛି</translation>
 <translation id="780301667611848630">ନାଁ, ଥାଉ</translation>
 <translation id="7810647596859435254">ଏଥିରେ ଖୋଲନ୍ତୁ…</translation>
+<translation id="7815484226266492798">ଲମ୍ବା ସ୍କ୍ରିନସଟ୍</translation>
 <translation id="7821588508402923572">ଆପଣଙ୍କର ଡାଟା ସେଭିଂ ଏଠାରେ ଦେଖାଯିବ</translation>
 <translation id="7844171778363018843">ସିଙ୍କ୍ କରିବାକୁ କୌଣସି ଡାଟା ଚୟନ କରାଯାଇନାହିଁ</translation>
 <translation id="7846296061357476882">Google ସେବାଗୁଡ଼ିକ</translation>
@@ -1153,6 +1156,7 @@
 <translation id="9065203028668620118">ସମ୍ପାଦନ</translation>
 <translation id="9065383040763568503">Chrome ଗୁରୁତ୍ୱପୂର୍ଣ୍ଣ ବୋଲି ମନେ କରୁନଥିବା ଷ୍ଟୋର୍ କରାଯାଇଥିବା ଡାଟା (ଉ.ଦା. ସେଭ୍ କରାଯାଇଥିବା କୌଣସି ସେଟିଂସ୍ ନଥିବା କିମ୍ବା ଆପଣ ପ୍ରାୟତଃ ଭିଜିଟ୍ କରୁନଥିବା ସାଇଟଗୁଡ଼ିକ)</translation>
 <translation id="9069543557624799859"><ph name="TIME" />ରେ ଡାଉନଲୋଡ୍ ଆରମ୍ଭ ହେବ।</translation>
+<translation id="9069999660519089861">ପଢ଼ାଯାଇନଥିବା କୌଣସି ପୃଷ୍ଠା ନାହିଁ</translation>
 <translation id="9070377983101773829">ଭଏସ୍ ସନ୍ଧାନ ଆରମ୍ଭ କରନ୍ତୁ</translation>
 <translation id="9074336505530349563">Google ଦ୍ୱାରା ପରାମର୍ଶ ଦିଆଯାଇଥିବା ବିଷୟବସ୍ତୁ ପ୍ରାପ୍ତ କରିବାକୁ ସାଇନ୍‍ ଇନ୍‌ କରନ୍ତୁ ଏବଂ ସିଙ୍କ୍‍ ଚାଲୁ କରନ୍ତୁ</translation>
 <translation id="9086302186042011942">ସିଙ୍କ୍ ହେଉଛି</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ur.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ur.xtb
index 6cde055..3f431fa 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ur.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ur.xtb
@@ -371,6 +371,7 @@
 <translation id="363596933471559332">اسٹور کردہ اسناد کا استعمال کر کے ویب سائٹس میں خود کار طور پر سائن ان کریں۔ خصوصیت آف ہونے پر، کسی ویب سائٹ میں سائن ان کرنے سے پہلے ہر بار آپ سے توثیق کرنے کو کہا جائے گا۔</translation>
 <translation id="3653111872753786013"><ph name="WEBSITE_TITLE" />: <ph name="WEBSITE_URL" /></translation>
 <translation id="3658159451045945436">ری سیٹ کرنے سے ملاحظہ کردہ سائٹس کی فہرست سمیت ڈیٹا بچت کی آپ کی سرگزشت صاف ہو جاتی ہے۔</translation>
+<translation id="3687645719033307815">آپ اس صفحہ کا پیش منظر دیکھ رہے ہیں</translation>
 <translation id="3692944402865947621">اسٹوریج کا مقام ناقابل رسائی ہونے کے سبب <ph name="FILE_NAME" /> ڈاؤن لوڈ کرنا ناکام ہو گیا۔</translation>
 <translation id="3701167022068948696">ابھی درست کریں</translation>
 <translation id="371230970611282515">خطرناک ایونٹس ہونے سے پہلے ان کی پیشین گوئی کرتا ہے اور آپ کو ان کے بارے میں متنبہ کرتا ہے۔</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb
index 518126c..f3d93311 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb
@@ -371,6 +371,7 @@
 <translation id="363596933471559332">使用存储的凭据自动登录网站。当该功能处于停用状态时,您每次都要通过验证才能登录网站。</translation>
 <translation id="3653111872753786013"><ph name="WEBSITE_TITLE" />:<ph name="WEBSITE_URL" /></translation>
 <translation id="3658159451045945436">这项重置操作会清空流量节省情况历史记录,包括曾访问过的网站的列表。</translation>
+<translation id="3687645719033307815">您正在查看此页面的预览视图</translation>
 <translation id="3692944402865947621">未能成功下载“<ph name="FILE_NAME" />”,因为无法访问它的存储位置。</translation>
 <translation id="3701167022068948696">立即修正</translation>
 <translation id="371230970611282515">预测危险事件并在此类事件发生前向您发出警告。</translation>
diff --git a/chrome/browser/ui/ash/clipboard_history_browsertest.cc b/chrome/browser/ui/ash/clipboard_history_browsertest.cc
index cd5bab4f..6c676c2c 100644
--- a/chrome/browser/ui/ash/clipboard_history_browsertest.cc
+++ b/chrome/browser/ui/ash/clipboard_history_browsertest.cc
@@ -279,6 +279,7 @@
   EXPECT_FALSE(GetHistoryItemViewForIndex(/*index=*/0)
                    ->delete_button_for_test()
                    ->GetVisible());
+  EXPECT_EQ(gfx::Size(256, 36), first_menu_item_view->size());
 
   // Move the mouse to the second menu item.
   const views::MenuItemView* second_menu_item_view =
diff --git a/chrome/browser/ui/signin_reauth_view_controller.cc b/chrome/browser/ui/signin_reauth_view_controller.cc
index 966638a..f97849154 100644
--- a/chrome/browser/ui/signin_reauth_view_controller.cc
+++ b/chrome/browser/ui/signin_reauth_view_controller.cc
@@ -29,8 +29,6 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "google_apis/gaia/gaia_urls.h"
-#include "third_party/blink/public/common/web_preferences/web_preferences.h"
-#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom.h"
 
 namespace {
 
@@ -311,15 +309,10 @@
           browser_, account_id_, access_point_);
   dialog_delegate_observer_.Add(dialog_delegate_);
 
-  // Gaia Reauth page doesn't support dark mode. Force the confirmation dialog
-  // to use the light mode as well to match the style.
-  auto* web_contents = dialog_delegate_->GetWebContents();
-  auto prefs = web_contents->GetOrCreateWebPreferences();
-  prefs.preferred_color_scheme = blink::mojom::PreferredColorScheme::kLight;
-  web_contents->SetWebPreferences(prefs);
-
-  SigninReauthUI* web_dialog_ui =
-      web_contents->GetWebUI()->GetController()->GetAs<SigninReauthUI>();
+  SigninReauthUI* web_dialog_ui = dialog_delegate_->GetWebContents()
+                                      ->GetWebUI()
+                                      ->GetController()
+                                      ->GetAs<SigninReauthUI>();
   web_dialog_ui->InitializeMessageHandlerWithReauthController(this);
 }
 
diff --git a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
index 4b8a11a..92c5b99 100644
--- a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
+++ b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/reauth_result.h"
 #include "chrome/browser/signin/signin_features.h"
@@ -19,6 +20,7 @@
 #include "chrome/browser/ui/signin_reauth_view_controller.h"
 #include "chrome/browser/ui/signin_view_controller.h"
 #include "chrome/browser/ui/webui/signin/login_ui_test_utils.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/signin/public/base/signin_metrics.h"
@@ -38,6 +40,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_response.h"
 #include "net/test/embedded_test_server/request_handler_util.h"
+#include "ui/base/ui_base_switches.h"
 
 using ::testing::ElementsAre;
 
@@ -541,3 +544,39 @@
       browser(), kReauthDialogTimeout));
   EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kUnexpectedResponse);
 }
+
+class SigninReauthViewControllerDarkModeBrowserTest
+    : public SigninReauthViewControllerBrowserTest {
+ public:
+  SigninReauthViewControllerDarkModeBrowserTest() {
+    scoped_feature_list_.InitAndEnableFeature(features::kWebUIDarkMode);
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(switches::kForceDarkMode);
+    SigninReauthViewControllerBrowserTest::SetUpCommandLine(command_line);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Tests the light mode is enforced for the reauth confirmation dialog even if
+// the dark mode is enabled.
+IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerDarkModeBrowserTest,
+                       ConfirmationDialogDarkModeDisabled) {
+  ShowReauthPrompt();
+  content::WebContents* confirmation_dialog_contents =
+      signin_reauth_view_controller()->GetWebContents();
+  content::TestNavigationObserver navigation_observer(
+      confirmation_dialog_contents);
+  navigation_observer.WaitForNavigationFinished();
+
+  bool prefers_dark_mode = true;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      confirmation_dialog_contents,
+      "window.domAutomationController.send("
+      "window.matchMedia('(prefers-color-scheme: dark)').matches)",
+      &prefers_dark_mode));
+  EXPECT_EQ(prefers_dark_mode, false);
+}
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 3513ba2..a4bd10c6 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -2057,121 +2057,137 @@
 
 // Checks the correct behavior of the profile picker on startup. This feature is
 // not available on ChromeOS.
-class StartupBrowserCreatorPickerTest : public InProcessBrowserTest {
+class StartupBrowserCreatorPickerTestBase : public InProcessBrowserTest {
  public:
-  StartupBrowserCreatorPickerTest() {
+  StartupBrowserCreatorPickerTestBase() {
     scoped_feature_list_.InitAndEnableFeature(features::kNewProfilePicker);
+    // This test configures command line params carefully. Make sure
+    // InProcessBrowserTest does _not_ add about:blank as a startup URL to the
+    // command line.
+    set_open_about_blank_on_browser_launch(false);
   }
-  StartupBrowserCreatorPickerTest(const StartupBrowserCreatorPickerTest&) =
-      delete;
-  StartupBrowserCreatorPickerTest& operator=(
-      const StartupBrowserCreatorPickerTest&) = delete;
-  ~StartupBrowserCreatorPickerTest() override = default;
+  StartupBrowserCreatorPickerTestBase(
+      const StartupBrowserCreatorPickerTestBase&) = delete;
+  StartupBrowserCreatorPickerTestBase& operator=(
+      const StartupBrowserCreatorPickerTestBase&) = delete;
+  ~StartupBrowserCreatorPickerTestBase() override = default;
 
- protected:
-  void StartWithTwoProfiles(const base::CommandLine& command_line) {
-    Profile* profile = browser()->profile();
+  void CreateMultipleProfiles() {
     ProfileManager* profile_manager = g_browser_process->profile_manager();
-    // Create another profile.
-    base::FilePath dest_path = profile_manager->user_data_dir();
-    dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile 1"));
-
-    Profile* other_profile = nullptr;
-    {
-      base::ScopedAllowBlockingForTesting allow_blocking;
-      other_profile = profile_manager->GetProfile(dest_path);
-    }
-    ASSERT_TRUE(other_profile);
-
-    StartupBrowserCreator launch;
-    ASSERT_TRUE(launch.Start(command_line, profile_manager->user_data_dir(),
-                             profile, {}));
+    // Create two additional profiles because the main test profile is created
+    // later in the startup process and so we need to have at least 2 fake
+    // profiles.
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    ASSERT_TRUE(
+        profile_manager->GetProfile(profile_manager->user_data_dir().Append(
+            FILE_PATH_LITERAL("New Profile 1"))));
+    ASSERT_TRUE(
+        profile_manager->GetProfile(profile_manager->user_data_dir().Append(
+            FILE_PATH_LITERAL("New Profile 2"))));
   }
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
+struct ProfilePickerSetup {
+  bool expected_to_show;
+  base::Optional<std::string> switch_name;
+  base::Optional<std::string> switch_value_ascii;
+  base::Optional<GURL> url_arg;
+  bool session_restore = false;
+};
+
+// Checks the correct behavior of the profile picker on startup. This feature is
+// not available on ChromeOS.
+class StartupBrowserCreatorPickerTest
+    : public StartupBrowserCreatorPickerTestBase,
+      public ::testing::WithParamInterface<ProfilePickerSetup> {
+ public:
+  StartupBrowserCreatorPickerTest() = default;
+  StartupBrowserCreatorPickerTest(const StartupBrowserCreatorPickerTest&) =
+      delete;
+  StartupBrowserCreatorPickerTest& operator=(
+      const StartupBrowserCreatorPickerTest&) = delete;
+  ~StartupBrowserCreatorPickerTest() override = default;
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    InProcessBrowserTest::SetUpCommandLine(command_line);
+
+    if (GetParam().url_arg) {
+      command_line->AppendArg(GetParam().url_arg->spec());
+    } else if (GetParam().switch_value_ascii) {
+      DCHECK(GetParam().switch_name);
+      command_line->AppendSwitchASCII(*GetParam().switch_name,
+                                      *GetParam().switch_value_ascii);
+    } else if (GetParam().switch_name) {
+      command_line->AppendSwitch(*GetParam().switch_name);
+    }
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Create a secondary profile in a separate PRE run because the existence of
+// profiles is checked during startup in the actual test.
+IN_PROC_BROWSER_TEST_P(StartupBrowserCreatorPickerTest, PRE_TestSetup) {
+  CreateMultipleProfiles();
+  // Need to close the browser window manually so that the real test does not
+  // treat it as session restore.
+  if (!GetParam().session_restore)
+    CloseAllBrowsers();
+}
+
+IN_PROC_BROWSER_TEST_P(StartupBrowserCreatorPickerTest, TestSetup) {
+  if (GetParam().expected_to_show) {
+    // Opens the picker and thus does not open any new browser window for the
+    // main profile.
+    EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
+  } else {
+    // The picker is skipped which means a browser window is opened on startup.
+    EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
+  }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    StartupBrowserCreatorPickerTest,
+    ::testing::Values(
 // Flaky: https://crbug.com/1126886
-#if defined(USE_OZONE) || defined(OS_WIN)
-#define MAYBE_OpensPicker DISABLED_OpensPicker
-#else
-#define MAYBE_OpensPicker OpensPicker
+#if !defined(USE_OZONE) && !defined(OS_WIN)
+        // Picker should be shown in normal multi-profile startup situation.
+        ProfilePickerSetup{/*expected_to_show=*/true},
 #endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorPickerTest, MAYBE_OpensPicker) {
-  ASSERT_EQ(1u, chrome::GetTotalBrowserCount());
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  StartWithTwoProfiles(command_line);
-
-  // Opens the picker and thus does not open any new browser window for the main
-  // profile.
-  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorPickerTest, SkipsPickerWithURL) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  GURL url("https://www.foo.com/");
-  command_line.AppendArg(url.spec());
-
-  StartWithTwoProfiles(command_line);
-
-  // Skips the picker and creates a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  EXPECT_TRUE(new_browser);
-  TabStripModel* tab_strip = new_browser->tab_strip_model();
-  ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ(url, tab_strip->GetWebContentsAt(0)->GetURL());
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorPickerTest,
-                       SkipsPickerWithIncognito) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendSwitch(switches::kIncognito);
-
-  StartWithTwoProfiles(command_line);
-
-  // Skips the picker and creates a new browser window.
-  Browser* new_browser = chrome::FindBrowserWithProfile(
-      browser()->profile()->GetPrimaryOTRProfile());
-  EXPECT_TRUE(new_browser);
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorPickerTest,
-                       SkipsPickerWithProfileDirectory) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendSwitch(switches::kProfileDirectory);
-
-  StartWithTwoProfiles(command_line);
-
-  // Skips the picker and creates a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  EXPECT_TRUE(new_browser);
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorPickerTest, SkipsPickerInAppMode) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendSwitch(switches::kApp);
-
-  StartWithTwoProfiles(command_line);
-
-  // Skips the picker and creates a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  EXPECT_TRUE(new_browser);
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorPickerTest, SkipsPickerWithAppId) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendSwitch(switches::kAppId);
-
-  StartWithTwoProfiles(command_line);
-
-  // Skips the picker and creates a new browser window.
-  Browser* new_browser = FindOneOtherBrowser(browser());
-  EXPECT_TRUE(new_browser);
-}
+        // Skip the picker for various command-line params and use the last used
+        // profile, instead.
+        ProfilePickerSetup{/*expected_to_show=*/false,
+                           /*switch_name=*/switches::kIncognito},
+        ProfilePickerSetup{/*expected_to_show=*/false,
+                           /*switch_name=*/switches::kApp},
+        ProfilePickerSetup{/*expected_to_show=*/false,
+                           /*switch_name=*/switches::kAppId},
+        // Skip the picker when a specific profile is requested (used e.g. by
+        // profile specific desktop shortcuts on Win).
+        ProfilePickerSetup{/*expected_to_show=*/false,
+                           /*switch_name=*/switches::kProfileDirectory,
+                           /*switch_value_ascii=*/"Custom Profile"},
+        // Skip the picker when a URL is provided on command-line (used by the
+        // OS when Chrome is the default web browser) and use the last used
+        // profile, instead.
+        ProfilePickerSetup{/*expected_to_show=*/false,
+                           /*switch_name=*/base::nullopt,
+                           /*switch_value_ascii=*/base::nullopt,
+                           /*url_arg=*/GURL("https://www.foo.com/")},
+        // Picker should be shown also in session restore.
+        ProfilePickerSetup{/*expected_to_show=*/true,
+                           /*switch_name=*/base::nullopt,
+                           /*switch_value_ascii=*/base::nullopt,
+                           /*url_arg=*/base::nullopt,
+                           /*session_restore=*/true}));
 
 class GuestStartupBrowserCreatorPickerTest
-    : public StartupBrowserCreatorPickerTest,
+    : public StartupBrowserCreatorPickerTestBase,
       public ::testing::WithParamInterface<bool> {
  public:
   GuestStartupBrowserCreatorPickerTest() {
@@ -2179,31 +2195,34 @@
         scoped_feature_list_, GetParam());
   }
 
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    InProcessBrowserTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitch(switches::kGuest);
+  }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
+// Create a secondary profile in a separate PRE run because the existence of
+// profiles is checked during startup in the actual test.
+IN_PROC_BROWSER_TEST_P(GuestStartupBrowserCreatorPickerTest,
+                       PRE_SkipsPickerWithGuest) {
+  CreateMultipleProfiles();
+  // Need to close the browser window manually so that the real test does not
+  // treat it as session restore.
+  CloseAllBrowsers();
+}
+
 IN_PROC_BROWSER_TEST_P(GuestStartupBrowserCreatorPickerTest,
                        SkipsPickerWithGuest) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendSwitch(switches::kGuest);
-
-  // The guest profile needs to get created before it gets opened.
-  Profile* guest_profile = nullptr;
-  {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    ProfileManager* profile_manager = g_browser_process->profile_manager();
-    guest_profile =
-        profile_manager->GetProfile(profile_manager->GetGuestProfilePath());
+  // The picker is skipped which means a browser window is opened on startup.
+  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
+  if (Profile::IsEphemeralGuestProfileEnabled()) {
+    EXPECT_TRUE(browser()->profile()->IsEphemeralGuestProfile());
+  } else {
+    EXPECT_TRUE(browser()->profile()->IsGuestSession());
   }
-
-  StartWithTwoProfiles(command_line);
-  // Skips the picker and creates a new browser window for the guest profile (by
-  // definition, it opens the OTR profile).
-  if (!Profile::IsEphemeralGuestProfileEnabled())
-    guest_profile = guest_profile->GetPrimaryOTRProfile();
-  Browser* new_browser = chrome::FindBrowserWithProfile(guest_profile);
-  EXPECT_TRUE(new_browser);
 }
 
 INSTANTIATE_TEST_SUITE_P(All,
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc
index f8ff53e..7584571f 100644
--- a/chrome/browser/ui/ui_features.cc
+++ b/chrome/browser/ui/ui_features.cc
@@ -8,6 +8,10 @@
 
 namespace features {
 
+// Enables Chrome Labs menu in the toolbar. See https://crbug.com/1145666
+const base::Feature kChromeLabs{"ChromeLabs",
+                                base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables showing the EV certificate details in the Page Info bubble.
 const base::Feature kEvDetailsInPageInfo{"EvDetailsInPageInfo",
                                          base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h
index a53e9f1c..676be7e3 100644
--- a/chrome/browser/ui/ui_features.h
+++ b/chrome/browser/ui/ui_features.h
@@ -20,6 +20,8 @@
 // All features in alphabetical order. The features should be documented
 // alongside the definition of their values in the .cc file.
 
+extern const base::Feature kChromeLabs;
+
 extern const base::Feature kEvDetailsInPageInfo;
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index eec1cbc..fc55e78 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -35,12 +35,12 @@
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/resize_utils.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/vector_icons.h"
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/window/non_client_view.h"
-#include "ui/views/window/window_resize_utils.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/ash_features.h"
@@ -290,30 +290,29 @@
 
     WindowQuadrant quadrant =
         GetCurrentWindowQuadrant(GetBounds(), controller_);
-    views::HitTest hit_test;
+    gfx::ResizeEdge resize_edge;
     switch (quadrant) {
       case OverlayWindowViews::WindowQuadrant::kBottomRight:
-        hit_test = views::HitTest::kTopLeft;
+        resize_edge = gfx::ResizeEdge::kTopLeft;
         break;
       case OverlayWindowViews::WindowQuadrant::kBottomLeft:
-        hit_test = views::HitTest::kTopRight;
+        resize_edge = gfx::ResizeEdge::kTopRight;
         break;
       case OverlayWindowViews::WindowQuadrant::kTopLeft:
-        hit_test = views::HitTest::kBottomRight;
+        resize_edge = gfx::ResizeEdge::kBottomRight;
         break;
       case OverlayWindowViews::WindowQuadrant::kTopRight:
-        hit_test = views::HitTest::kBottomLeft;
+        resize_edge = gfx::ResizeEdge::kBottomLeft;
         break;
     }
 
     // Update the window size to adhere to the aspect ratio.
     gfx::Size min_size = min_size_;
     gfx::Size max_size = max_size_;
-    views::WindowResizeUtils::SizeMinMaxToAspectRatio(aspect_ratio, &min_size,
-                                                      &max_size);
+    gfx::SizeMinMaxToAspectRatio(aspect_ratio, &min_size, &max_size);
     gfx::Rect window_rect(GetBounds().origin(), window_size);
-    views::WindowResizeUtils::SizeRectToAspectRatio(
-        hit_test, aspect_ratio, min_size, max_size, &window_rect);
+    gfx::SizeRectToAspectRatio(resize_edge, aspect_ratio, min_size, max_size,
+                               &window_rect);
     window_size.SetSize(window_rect.width(), window_rect.height());
 
     UpdateLayerBoundsWithLetterboxing(window_size);
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.cc b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.cc
new file mode 100644
index 0000000..c3249a4
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.cc
@@ -0,0 +1,180 @@
+// 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/ui/views/toolbar/chrome_labs_bubble_view.h"
+#include "base/bind.h"
+#include "chrome/browser/about_flags.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/ui/webui/flags_ui.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/flags_ui/pref_service_flags_storage.h"
+#include "ui/views/controls/button/md_text_button.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/flex_layout.h"
+
+namespace {
+
+ChromeLabsBubbleView* g_chrome_labs_bubble = nullptr;
+
+}  // namespace
+
+// TODO(elainechien): Add screenshots and strings for translation when UI is
+// finished.
+class ChromeLabsFooter : public views::View {
+ public:
+  ChromeLabsFooter() {
+    SetLayoutManager(std::make_unique<views::FlexLayout>())
+        ->SetOrientation(views::LayoutOrientation::kVertical);
+    AddChildView(views::Builder<views::Label>()
+                     .CopyAddressTo(&restart_label_)
+                     .SetText(base::ASCIIToUTF16(
+                         "Your changes will take effect the next time you "
+                         "relaunch Google Chrome."))
+                     .SetMultiLine(true)
+                     .Build());
+    AddChildView(views::Builder<views::MdTextButton>()
+                     .CopyAddressTo(&restart_button_)
+                     .SetCallback(base::BindRepeating(&chrome::AttemptRestart))
+                     .SetText(base::ASCIIToUTF16("Relaunch"))
+                     .Build());
+    restart_label_->SizeToFit(
+        restart_button_->CalculatePreferredSize().width());
+  }
+  // views::View
+  gfx::Size CalculatePreferredSize() const override {
+    int width = restart_button_->CalculatePreferredSize().width();
+    int height = GetHeightForWidth(width);
+    return gfx::Size(width, height);
+  }
+
+ private:
+  views::MdTextButton* restart_button_;
+  views::Label* restart_label_;
+};
+
+// static
+void ChromeLabsBubbleView::Show(views::View* anchor_view) {
+  g_chrome_labs_bubble = new ChromeLabsBubbleView(
+      anchor_view, std::make_unique<ChromeLabsBubbleViewModel>());
+  views::Widget* const widget =
+      BubbleDialogDelegateView::CreateBubble(g_chrome_labs_bubble);
+  widget->Show();
+}
+
+ChromeLabsBubbleView::ChromeLabsBubbleView(
+    views::View* anchor_view,
+    std::unique_ptr<ChromeLabsBubbleViewModel> model)
+    : BubbleDialogDelegateView(anchor_view,
+                               views::BubbleBorder::Arrow::TOP_RIGHT),
+      model_(std::move(model)) {
+  SetButtons(ui::DIALOG_BUTTON_NONE);
+  SetShowCloseButton(true);
+  SetTitle(base::ASCIIToUTF16("Chrome Labs"));
+  SetLayoutManager(std::make_unique<views::FlexLayout>())
+      ->SetOrientation(views::LayoutOrientation::kVertical)
+      .SetDefault(views::kMarginsKey, gfx::Insets(5));
+
+  // TODO(elainechien): ChromeOS specific logic for creating FlagsStorage
+  flags_storage_ = std::make_unique<flags_ui::PrefServiceFlagsStorage>(
+      g_browser_process->local_state());
+  flags_state_ = about_flags::GetCurrentFlagsState();
+
+  menu_item_container_ = AddChildView(std::make_unique<views::View>());
+  menu_item_container_->SetLayoutManager(std::make_unique<views::FlexLayout>())
+      ->SetOrientation(views::LayoutOrientation::kHorizontal)
+      .SetDefault(views::kMarginsKey, gfx::Insets(10));
+
+  // Create each lab item.
+  std::vector<std::string> lab_internal_names = model_->GetLabInfo();
+  for (const auto& internal_name : lab_internal_names) {
+    const flags_ui::FeatureEntry* entry =
+        flags_state_->FindFeatureEntryByName(internal_name);
+    DCHECK_EQ(entry->type, flags_ui::FeatureEntry::FEATURE_VALUE);
+    int default_index = GetIndexOfEnabledLabState(entry);
+    menu_item_container_->AddChildView(
+        CreateLabItem(internal_name, default_index, entry));
+  }
+  // TODO(elainechien): Build UI for 0 experiments case.
+  DCHECK(menu_item_container_->children().size() >= 1);
+
+  restart_prompt_ = AddChildView(std::make_unique<ChromeLabsFooter>());
+  restart_prompt_->SetVisible(about_flags::IsRestartNeededToCommitChanges());
+}
+
+std::unique_ptr<ChromeLabsItemView> ChromeLabsBubbleView::CreateLabItem(
+    std::string internal_name,
+    int default_index,
+    const flags_ui::FeatureEntry* entry) {
+  auto combobox_callback = [](ChromeLabsBubbleView* bubble_view,
+                              std::string internal_name,
+                              ChromeLabsItemView* item_view) {
+    int selected_index = item_view->GetSelectedIndex();
+    about_flags::SetFeatureEntryEnabled(
+        bubble_view->flags_storage_.get(),
+        internal_name + "@" + base::NumberToString(selected_index), true);
+    bubble_view->ShowRelaunchPrompt();
+  };
+
+  return std::make_unique<ChromeLabsItemView>(
+      internal_name, default_index, entry,
+      base::BindRepeating(combobox_callback, this, internal_name));
+}
+
+int ChromeLabsBubbleView::GetIndexOfEnabledLabState(
+    const flags_ui::FeatureEntry* entry) {
+  std::set<std::string> enabled_entries;
+  flags_state_->GetSanitizedEnabledFlags(flags_storage_.get(),
+                                         &enabled_entries);
+  for (int i = 0; i < entry->NumOptions(); i++) {
+    const std::string name = entry->NameForOption(i);
+    if (enabled_entries.count(name) > 0)
+      return i;
+  }
+  return 0;
+}
+
+void ChromeLabsBubbleView::ShowRelaunchPrompt() {
+  restart_prompt_->SetVisible(about_flags::IsRestartNeededToCommitChanges());
+  DCHECK_EQ(g_chrome_labs_bubble, this);
+  g_chrome_labs_bubble->SizeToContents();
+}
+
+ChromeLabsBubbleView::~ChromeLabsBubbleView() {
+  g_chrome_labs_bubble = nullptr;
+}
+
+// static
+bool ChromeLabsBubbleView::IsShowing() {
+  return g_chrome_labs_bubble != nullptr &&
+         g_chrome_labs_bubble->GetWidget() != nullptr;
+}
+
+// static
+void ChromeLabsBubbleView::Hide() {
+  if (IsShowing())
+    g_chrome_labs_bubble->GetWidget()->Close();
+}
+
+// static
+ChromeLabsBubbleView*
+ChromeLabsBubbleView::GetChromeLabsBubbleViewForTesting() {
+  return g_chrome_labs_bubble;
+}
+
+flags_ui::FlagsState* ChromeLabsBubbleView::GetFlagsStateForTesting() {
+  return flags_state_;
+}
+
+flags_ui::FlagsStorage* ChromeLabsBubbleView::GetFlagsStorageForTesting() {
+  return flags_storage_.get();
+}
+
+views::View* ChromeLabsBubbleView::GetMenuItemContainerForTesting() {
+  return menu_item_container_;
+}
+
+bool ChromeLabsBubbleView::IsRestartPromptVisibleForTesting() {
+  return restart_prompt_->GetVisible();
+}
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h
new file mode 100644
index 0000000..ec6464f5a
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h
@@ -0,0 +1,58 @@
+// 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_UI_VIEWS_TOOLBAR_CHROME_LABS_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUBBLE_VIEW_H_
+
+#include "chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h"
+#include "chrome/browser/ui/views/toolbar/chrome_labs_item_view.h"
+#include "components/flags_ui/feature_entry.h"
+#include "components/flags_ui/flags_state.h"
+#include "components/flags_ui/flags_storage.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+
+// TODO(elainechien): Use composition instead of inheritance.
+class ChromeLabsBubbleView : public views::BubbleDialogDelegateView {
+ public:
+  static void Show(views::View* anchor_view);
+
+  static bool IsShowing();
+
+  static void Hide();
+
+  ~ChromeLabsBubbleView() override;
+
+  // Getter functions for testing.
+  static ChromeLabsBubbleView* GetChromeLabsBubbleViewForTesting();
+  flags_ui::FlagsState* GetFlagsStateForTesting();
+  flags_ui::FlagsStorage* GetFlagsStorageForTesting();
+  views::View* GetMenuItemContainerForTesting();
+  bool IsRestartPromptVisibleForTesting();
+
+ private:
+  ChromeLabsBubbleView(views::View* anchor_view,
+                       std::unique_ptr<ChromeLabsBubbleViewModel> model);
+
+  std::unique_ptr<ChromeLabsItemView> CreateLabItem(
+      std::string internal_name,
+      int default_index,
+      const flags_ui::FeatureEntry* entry);
+
+  int GetIndexOfEnabledLabState(const flags_ui::FeatureEntry* entry);
+
+  void ShowRelaunchPrompt();
+
+  std::unique_ptr<flags_ui::FlagsStorage> flags_storage_;
+
+  flags_ui::FlagsState* flags_state_;
+
+  // This view will hold all the child lab items.
+  views::View* menu_item_container_;
+
+  std::unique_ptr<ChromeLabsBubbleViewModel> model_;
+
+  views::View* restart_prompt_;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.cc b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.cc
new file mode 100644
index 0000000..2e70fd23
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.cc
@@ -0,0 +1,25 @@
+// 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/ui/views/toolbar/chrome_labs_bubble_view_model.h"
+#include "base/strings/utf_string_conversions.h"
+
+ChromeLabsBubbleViewModel::ChromeLabsBubbleViewModel() {
+  SetUpLabs();
+}
+
+std::vector<std::string> ChromeLabsBubbleViewModel::GetLabInfo() const {
+  return lab_internal_names_;
+}
+
+// TODO(elainechien): Explore better ways to allow developers to add their
+// experiments.
+// Experiments featured in labs must have feature entries of type FEATURE_VALUE
+// (Default, Enabled, Disabled states). Experiments with multiple parameters may
+// be considered in the future.
+void ChromeLabsBubbleViewModel::SetUpLabs() {
+  lab_internal_names_.push_back("read-later");
+}
+
+ChromeLabsBubbleViewModel::~ChromeLabsBubbleViewModel() = default;
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h
new file mode 100644
index 0000000..a299f52
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_model.h
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUBBLE_VIEW_MODEL_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUBBLE_VIEW_MODEL_H_
+
+#include <vector>
+#include "base/strings/string16.h"
+
+class ChromeLabsBubbleViewModel {
+ public:
+  ChromeLabsBubbleViewModel();
+  ~ChromeLabsBubbleViewModel();
+
+  std::vector<std::string> GetLabInfo() const;
+
+ private:
+  void SetUpLabs();
+
+  std::vector<std::string> lab_internal_names_;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUBBLE_VIEW_MODEL_H_
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_unittest.cc b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_unittest.cc
new file mode 100644
index 0000000..4152591
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_bubble_view_unittest.cc
@@ -0,0 +1,164 @@
+// 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/ui/views/toolbar/chrome_labs_bubble_view.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/about_flags.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/test_with_browser_view.h"
+#include "chrome/browser/ui/views/toolbar/chrome_labs_button.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "components/flags_ui/flags_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/test/combobox_test_api.h"
+#include "ui/views/test/widget_test.h"
+
+class ChromeLabsBubbleTest : public TestWithBrowserView {
+ public:
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(features::kChromeLabs);
+    TestWithBrowserView::SetUp();
+    ChromeLabsButton* button = chrome_labs_button();
+    ChromeLabsBubbleView::Show(button);
+  }
+
+  void TearDown() override {
+    chrome_labs_bubble()->GetFlagsStateForTesting()->Reset();
+    TestWithBrowserView::TearDown();
+  }
+
+  ChromeLabsBubbleView* chrome_labs_bubble() {
+    return ChromeLabsBubbleView::GetChromeLabsBubbleViewForTesting();
+  }
+
+  ChromeLabsButton* chrome_labs_button() {
+    return browser_view()->toolbar()->chrome_labs_button();
+  }
+
+  views::View* chrome_labs_menu_item_container() {
+    return ChromeLabsBubbleView::GetChromeLabsBubbleViewForTesting()
+        ->GetMenuItemContainerForTesting();
+  }
+
+  flags_ui::FlagsState* flags_state() {
+    return ChromeLabsBubbleView::GetChromeLabsBubbleViewForTesting()
+        ->GetFlagsStateForTesting();
+  }
+
+  flags_ui::FlagsStorage* flags_storage() {
+    return ChromeLabsBubbleView::GetChromeLabsBubbleViewForTesting()
+        ->GetFlagsStorageForTesting();
+  }
+
+  ChromeLabsItemView* first_lab_item() {
+    views::View* menu_items = chrome_labs_menu_item_container();
+    return static_cast<ChromeLabsItemView*>(menu_items->children().front());
+  }
+
+  // Returns true if the option at index |option_index| is the enabled feature
+  // state.
+  bool IsSelected(int option_index, const flags_ui::FeatureEntry* entry) {
+    std::string internal_name = std::string(entry->internal_name) + "@" +
+                                base::NumberToString(option_index);
+    std::set<std::string> enabled_entries;
+    flags_state()->GetSanitizedEnabledFlags(flags_storage(), &enabled_entries);
+    for (int i = 0; i < entry->NumOptions(); i++) {
+      const std::string name = entry->NameForOption(i);
+      if (internal_name == name && enabled_entries.count(name) > 0) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Returns true if none of the entry's options have been enabled.
+  bool IsDefault(const flags_ui::FeatureEntry* entry) {
+    std::set<std::string> enabled_entries;
+    flags_state()->GetSanitizedEnabledFlags(flags_storage(), &enabled_entries);
+    for (int i = 0; i < entry->NumOptions(); i++) {
+      const std::string name = entry->NameForOption(i);
+      if (enabled_entries.count(name) > 0) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+class ChromeLabsFeatureTest : public ChromeLabsBubbleTest,
+                              public testing::WithParamInterface<int> {
+ public:
+  ChromeLabsFeatureTest() = default;
+};
+
+// This test checks that selecting an option through the combobox on a lab will
+// enable the corresponding option on the feature.
+TEST_P(ChromeLabsFeatureTest, ChangeSelectedOption) {
+  int row = GetParam();
+  ChromeLabsItemView* lab_item = first_lab_item();
+  views::Combobox* lab_item_combobox =
+      lab_item->GetLabStateComboboxForTesting();
+
+  lab_item_combobox->SetSelectedRow(row);
+
+  const flags_ui::FeatureEntry* feature_entry = lab_item->GetFeatureEntry();
+  EXPECT_TRUE(IsSelected(row, feature_entry));
+}
+
+// For FeatureEntries of type FEATURE_VALUE, the option at index 1 corresponds
+// to "Enabled" and the option at index 2 corresponds to "Disabled".
+INSTANTIATE_TEST_SUITE_P(All, ChromeLabsFeatureTest, testing::Values(1, 2));
+
+// This test checks that selecting row 0 will reset the feature to it's Default
+// state.
+TEST_F(ChromeLabsBubbleTest, ResetToDefault) {
+  ChromeLabsItemView* lab_item = first_lab_item();
+  views::Combobox* lab_item_combobox =
+      lab_item->GetLabStateComboboxForTesting();
+
+  // Selects an option and then attempts to reset the lab to Default by
+  // selecting 0.
+  const flags_ui::FeatureEntry* feature_entry = lab_item->GetFeatureEntry();
+  lab_item_combobox->SetSelectedRow(1);
+  EXPECT_FALSE(IsDefault(feature_entry));
+  lab_item_combobox->SetSelectedRow(0);
+  EXPECT_TRUE(IsDefault(feature_entry));
+}
+
+// This test checks that the restart prompt becomes visible when a lab state is
+// changed.
+TEST_F(ChromeLabsBubbleTest, RestartPromptShows) {
+  ChromeLabsBubbleView* bubble_view = chrome_labs_bubble();
+  ChromeLabsItemView* lab_item = first_lab_item();
+  views::Combobox* lab_item_combobox =
+      lab_item->GetLabStateComboboxForTesting();
+  EXPECT_FALSE(bubble_view->IsRestartPromptVisibleForTesting());
+  lab_item_combobox->SetSelectedRow(1);
+  EXPECT_TRUE(bubble_view->IsRestartPromptVisibleForTesting());
+  views::test::WidgetDestroyedWaiter destroyed_waiter(bubble_view->GetWidget());
+  ChromeLabsBubbleView::Hide();
+  destroyed_waiter.Wait();
+  ChromeLabsBubbleView::Show(chrome_labs_button());
+  ChromeLabsBubbleView* bubble_view_after_restart = chrome_labs_bubble();
+  EXPECT_TRUE(bubble_view_after_restart->IsRestartPromptVisibleForTesting());
+}
+
+// This test checks that the restart prompt does not show when the lab state has
+// not changed.
+// TODO(elainechien): This currently only works for default. This will be
+// changed to work for all states. See design doc in crbug/1145666.
+TEST_F(ChromeLabsBubbleTest, SelectDefaultTwiceNoRestart) {
+  ChromeLabsBubbleView* bubble_view = chrome_labs_bubble();
+  ChromeLabsItemView* lab_item = first_lab_item();
+  views::Combobox* lab_item_combobox =
+      lab_item->GetLabStateComboboxForTesting();
+  // Select default state when the originally instantiated state was already
+  // default.
+  lab_item_combobox->SetSelectedRow(0);
+  EXPECT_FALSE(bubble_view->IsRestartPromptVisibleForTesting());
+}
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_button.cc b/chrome/browser/ui/views/toolbar/chrome_labs_button.cc
new file mode 100644
index 0000000..9b26d71d
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_button.cc
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/toolbar/chrome_labs_button.h"
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h"
+#include "ui/views/controls/button/button_controller.h"
+
+ChromeLabsButton::ChromeLabsButton()
+    : ToolbarButton(base::BindRepeating(&ChromeLabsButton::ButtonPressed,
+                                        base::Unretained(this))) {
+  button_controller()->set_notify_action(
+      views::ButtonController::NotifyAction::kOnPress);
+}
+
+void ChromeLabsButton::UpdateIcon() {
+  // TODO(elainechien): Replace kHorizontalMenuIcon with Chrome Labs icon when
+  // available.
+  UpdateIconsWithStandardColors(kHorizontalMenuIcon);
+}
+
+const char* ChromeLabsButton::GetClassName() const {
+  return "ChromeLabsButton";
+}
+
+void ChromeLabsButton::ButtonPressed() {
+  if (ChromeLabsBubbleView::IsShowing()) {
+    ChromeLabsBubbleView::Hide();
+    return;
+  }
+  ChromeLabsBubbleView::Show(this);
+}
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_button.h b/chrome/browser/ui/views/toolbar/chrome_labs_button.h
new file mode 100644
index 0000000..09ef0724
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_button.h
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUTTON_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUTTON_H_
+
+#include "chrome/browser/ui/views/toolbar/toolbar_button.h"
+
+class ChromeLabsButton : public ToolbarButton {
+ public:
+  ChromeLabsButton();
+
+  // ToolbarButton:
+  void UpdateIcon() override;
+
+  // views::View:
+  const char* GetClassName() const override;
+
+ private:
+  void ButtonPressed();
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_BUTTON_H_
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc b/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc
new file mode 100644
index 0000000..725209d
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc
@@ -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.
+
+#include "chrome/browser/ui/views/toolbar/chrome_labs_button.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/test_with_browser_view.h"
+#include "chrome/browser/ui/views/toolbar/chrome_labs_bubble_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "ui/events/event_utils.h"
+#include "ui/views/test/button_test_api.h"
+#include "ui/views/test/widget_test.h"
+
+class ChromeLabsButtonTest : public TestWithBrowserView {
+ public:
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(features::kChromeLabs);
+    TestWithBrowserView::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(ChromeLabsButtonTest, ShowAndHideChromeLabsBubbleOnPress) {
+  ChromeLabsButton* labs_button =
+      browser_view()->toolbar()->chrome_labs_button();
+  EXPECT_FALSE(ChromeLabsBubbleView::IsShowing());
+  ui::MouseEvent e(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                   ui::EventTimeForNow(), 0, 0);
+  views::test::ButtonTestApi test_api(labs_button);
+  test_api.NotifyClick(e);
+  EXPECT_TRUE(ChromeLabsBubbleView::IsShowing());
+  views::test::WidgetDestroyedWaiter destroyed_waiter(
+      ChromeLabsBubbleView::GetChromeLabsBubbleViewForTesting()->GetWidget());
+  test_api.NotifyClick(e);
+  destroyed_waiter.Wait();
+  EXPECT_FALSE(ChromeLabsBubbleView::IsShowing());
+}
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_item_view.cc b/chrome/browser/ui/views/toolbar/chrome_labs_item_view.cc
new file mode 100644
index 0000000..6a7c0e9
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_item_view.cc
@@ -0,0 +1,58 @@
+// 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/ui/views/toolbar/chrome_labs_item_view.h"
+#include "ui/base/models/combobox_model.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/flex_layout.h"
+
+class LabsComboboxModel : public ui::ComboboxModel {
+ public:
+  explicit LabsComboboxModel(const flags_ui::FeatureEntry* feature_entry,
+                             int default_index)
+      : feature_entry_(feature_entry), default_index_(default_index) {}
+
+  // ui::ComboboxModel:
+  int GetItemCount() const override { return feature_entry_->NumOptions(); }
+
+  base::string16 GetItemAt(int index) const override {
+    // TODO(elainechien): remove white space for description
+    return feature_entry_->DescriptionForOption(index);
+  }
+
+  int GetDefaultIndex() const override { return default_index_; }
+
+ private:
+  const flags_ui::FeatureEntry* feature_entry_;
+  int default_index_;
+};
+
+ChromeLabsItemView::ChromeLabsItemView(
+    std::string internal_name,
+    int default_index,
+    const flags_ui::FeatureEntry* feature_entry,
+    base::RepeatingCallback<void(ChromeLabsItemView* item_view)>
+        combobox_callback)
+    : internal_name_(internal_name), feature_entry_(feature_entry) {
+  SetLayoutManager(std::make_unique<views::FlexLayout>())
+      ->SetOrientation(views::LayoutOrientation::kHorizontal)
+      .SetDefault(views::kMarginsKey, gfx::Insets(10));
+  AddChildView(views::Builder<views::Label>()
+                   .SetText(base::ASCIIToUTF16(feature_entry->visible_name))
+                   .Build());
+  AddChildView(views::Builder<views::Combobox>()
+                   .CopyAddressTo(&lab_state_combobox_)
+                   .SetOwnedModel(std::make_unique<LabsComboboxModel>(
+                       feature_entry_, default_index))
+                   .SetCallback(base::BindRepeating(combobox_callback, this))
+                   .Build());
+}
+
+int ChromeLabsItemView::GetSelectedIndex() {
+  return lab_state_combobox_->GetSelectedIndex();
+}
+
+const flags_ui::FeatureEntry* ChromeLabsItemView::GetFeatureEntry() {
+  return feature_entry_;
+}
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_item_view.h b/chrome/browser/ui/views/toolbar/chrome_labs_item_view.h
new file mode 100644
index 0000000..2de6eed8
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_item_view.h
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_ITEM_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_ITEM_VIEW_H_
+
+#include "base/callback.h"
+#include "components/flags_ui/feature_entry.h"
+#include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/view.h"
+
+class ChromeLabsItemView : public views::View {
+ public:
+  ChromeLabsItemView(
+      std::string internal_name,
+      int default_index,
+      const flags_ui::FeatureEntry* feature_entry,
+      base::RepeatingCallback<void(ChromeLabsItemView* item_view)>
+          combobox_callback);
+
+  int GetSelectedIndex();
+
+  views::Combobox* GetLabStateComboboxForTesting() {
+    return lab_state_combobox_;
+  }
+
+  const flags_ui::FeatureEntry* GetFeatureEntry();
+
+ private:
+  // Combobox with selected state of the lab.
+  views::Combobox* lab_state_combobox_;
+
+  std::string internal_name_;
+
+  const flags_ui::FeatureEntry* feature_entry_;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_CHROME_LABS_ITEM_VIEW_H_
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 89ec773..e370a877 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -52,6 +52,7 @@
 #include "chrome/browser/ui/views/toolbar/back_forward_button.h"
 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
 #include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
+#include "chrome/browser/ui/views/toolbar/chrome_labs_button.h"
 #include "chrome/browser/ui/views/toolbar/home_button.h"
 #include "chrome/browser/ui/views/toolbar/reload_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h"
@@ -270,6 +271,10 @@
   if (extensions_container)
     extensions_container_ = AddChildView(std::move(extensions_container));
 
+  if (base::FeatureList::IsEnabled(features::kChromeLabs)) {
+    chrome_labs_button_ = AddChildView(std::make_unique<ChromeLabsButton>());
+  }
+
   if (cast)
     cast_ = AddChildView(std::move(cast));
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 2cf0996..f8a88bb 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -46,6 +46,7 @@
 class Browser;
 class ExtensionsToolbarButton;
 class ExtensionsToolbarContainer;
+class ChromeLabsButton;
 class HomeButton;
 class MediaToolbarButtonView;
 class ReloadButton;
@@ -135,6 +136,7 @@
   // Accessors.
   Browser* browser() const { return browser_; }
   BrowserActionsContainer* browser_actions() const { return browser_actions_; }
+  ChromeLabsButton* chrome_labs_button() const { return chrome_labs_button_; }
   ExtensionsToolbarContainer* extensions_container() const {
     return extensions_container_;
   }
@@ -267,6 +269,7 @@
   LocationBarView* location_bar_ = nullptr;
   BrowserActionsContainer* browser_actions_ = nullptr;
   ExtensionsToolbarContainer* extensions_container_ = nullptr;
+  ChromeLabsButton* chrome_labs_button_ = nullptr;
   media_router::CastToolbarButton* cast_ = nullptr;
   ToolbarAccountIconContainerView* toolbar_account_icon_container_ = nullptr;
   AvatarToolbarButton* avatar_ = nullptr;
diff --git a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc
index 8268398..2914e51 100644
--- a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc
@@ -6,29 +6,15 @@
 
 #include <string>
 
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
 #include "chrome/browser/chromeos/login/screens/enable_debugging_screen.h"
-#include "chrome/browser/chromeos/login/ui/login_display_host.h"
-#include "chrome/browser/chromeos/login/ui/login_web_dialog.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
-#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/login/localized_values_builder.h"
 #include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
-#include "ui/base/l10n/l10n_util.h"
 
 namespace chromeos {
 
@@ -36,42 +22,30 @@
 
 EnableDebuggingScreenHandler::EnableDebuggingScreenHandler(
     JSCallsContainer* js_calls_container)
-    : BaseScreenHandler(kScreenId, js_calls_container) {}
+    : BaseScreenHandler(kScreenId, js_calls_container) {
+  set_user_acted_method_path("login.EnableDebuggingScreen.userActed");
+}
 
 EnableDebuggingScreenHandler::~EnableDebuggingScreenHandler() {
   if (screen_)
     screen_->OnViewDestroyed(this);
 }
 
-void EnableDebuggingScreenHandler::ShowWithParams() {
-  ShowScreen(kScreenId);
-
-  UpdateUIState(UI_STATE_WAIT);
-
-  DVLOG(1) << "Showing enable debugging screen.";
-
-  // Wait for cryptohomed before checking debugd. See http://crbug.com/440506.
-  chromeos::CryptohomeClient* client = chromeos::CryptohomeClient::Get();
-  client->WaitForServiceToBeAvailable(base::BindOnce(
-      &EnableDebuggingScreenHandler::OnCryptohomeDaemonAvailabilityChecked,
-      weak_ptr_factory_.GetWeakPtr()));
-}
-
 void EnableDebuggingScreenHandler::Show() {
   if (!page_is_ready()) {
     show_on_init_ = true;
     return;
   }
 
-  ShowWithParams();
+  DVLOG(1) << "Showing enable debugging screen.";
+  ShowScreen(kScreenId);
 }
 
-void EnableDebuggingScreenHandler::Hide() {
-  weak_ptr_factory_.InvalidateWeakPtrs();
-}
+void EnableDebuggingScreenHandler::Hide() {}
 
 void EnableDebuggingScreenHandler::SetDelegate(EnableDebuggingScreen* screen) {
   screen_ = screen;
+  BaseScreenHandler::SetBaseScreen(screen_);
   if (page_is_ready())
     Initialize();
 }
@@ -131,157 +105,18 @@
 }
 
 void EnableDebuggingScreenHandler::RegisterMessages() {
-  AddCallback("enableDebuggingOnCancel",
-              &EnableDebuggingScreenHandler::HandleOnCancel);
-  AddCallback("enableDebuggingOnDone",
-              &EnableDebuggingScreenHandler::HandleOnDone);
-  AddCallback("enableDebuggingOnLearnMore",
-              &EnableDebuggingScreenHandler::HandleOnLearnMore);
-  AddCallback("enableDebuggingOnRemoveRootFSProtection",
-              &EnableDebuggingScreenHandler::HandleOnRemoveRootFSProtection);
+  BaseScreenHandler::RegisterMessages();
   AddCallback("enableDebuggingOnSetup",
               &EnableDebuggingScreenHandler::HandleOnSetup);
 }
 
-void EnableDebuggingScreenHandler::HandleOnCancel() {
-  if (screen_)
-    screen_->OnExit(false);
-}
-
-void EnableDebuggingScreenHandler::HandleOnDone() {
-  if (screen_)
-    screen_->OnExit(true);
-}
-
-void EnableDebuggingScreenHandler::HandleOnRemoveRootFSProtection() {
-  UpdateUIState(UI_STATE_WAIT);
-  chromeos::DebugDaemonClient* client =
-      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
-  client->RemoveRootfsVerification(
-      base::BindOnce(&EnableDebuggingScreenHandler::OnRemoveRootfsVerification,
-                     weak_ptr_factory_.GetWeakPtr()));
-}
-
 void EnableDebuggingScreenHandler::HandleOnSetup(
     const std::string& password) {
-  UpdateUIState(UI_STATE_WAIT);
-  chromeos::DebugDaemonClient* client =
-      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
-  client->EnableDebuggingFeatures(
-      password,
-      base::BindOnce(&EnableDebuggingScreenHandler::OnEnableDebuggingFeatures,
-                     weak_ptr_factory_.GetWeakPtr()));
+  screen_->HandleSetup(password);
 }
 
-void EnableDebuggingScreenHandler::OnCryptohomeDaemonAvailabilityChecked(
-    bool service_is_available) {
-  DVLOG(1) << "Enable-debugging-screen: cryptohomed availability="
-           << service_is_available;
-  if (!service_is_available) {
-    LOG(ERROR) << "Crypthomed is not available.";
-    UpdateUIState(UI_STATE_ERROR);
-    return;
-  }
-
-  chromeos::DebugDaemonClient* client =
-      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
-  client->WaitForServiceToBeAvailable(base::BindOnce(
-      &EnableDebuggingScreenHandler::OnDebugDaemonServiceAvailabilityChecked,
-      weak_ptr_factory_.GetWeakPtr()));
-}
-
-void EnableDebuggingScreenHandler::OnDebugDaemonServiceAvailabilityChecked(
-    bool service_is_available) {
-  DVLOG(1) << "Enable-debugging-screen: debugd availability="
-           << service_is_available;
-  if (!service_is_available) {
-    LOG(ERROR) << "Debug daemon is not available.";
-    UpdateUIState(UI_STATE_ERROR);
-    return;
-  }
-
-  // Check the status of debugging features.
-  chromeos::DebugDaemonClient* client =
-      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
-  client->QueryDebuggingFeatures(
-      base::BindOnce(&EnableDebuggingScreenHandler::OnQueryDebuggingFeatures,
-                     weak_ptr_factory_.GetWeakPtr()));
-}
-
-// Removes rootfs verification, add flag to start with enable debugging features
-// screen and reboots the machine.
-void EnableDebuggingScreenHandler::OnRemoveRootfsVerification(bool success) {
-  if (!success) {
-    UpdateUIState(UI_STATE_ERROR);
-    return;
-  }
-
-  PrefService* prefs = g_browser_process->local_state();
-  prefs->SetBoolean(prefs::kDebuggingFeaturesRequested, true);
-  prefs->CommitPendingWrite();
-  chromeos::PowerManagerClient::Get()->RequestRestart(
-      power_manager::REQUEST_RESTART_OTHER,
-      "login debugging screen removing rootfs verification");
-}
-
-void EnableDebuggingScreenHandler::OnEnableDebuggingFeatures(bool success) {
-  if (!success) {
-    UpdateUIState(UI_STATE_ERROR);
-    return;
-  }
-
-  UpdateUIState(UI_STATE_DONE);
-}
-
-void EnableDebuggingScreenHandler::OnQueryDebuggingFeatures(bool success,
-                                                            int features_flag) {
-  DVLOG(1) << "Enable-debugging-screen: OnQueryDebuggingFeatures"
-           << ", success=" << success
-           << ", features=" << features_flag;
-  if (!success ||
-      features_flag == debugd::DevFeatureFlag::DEV_FEATURES_DISABLED) {
-    UpdateUIState(UI_STATE_ERROR);
-    return;
-  }
-
-  if ((features_flag &
-       debugd::DevFeatureFlag::DEV_FEATURE_ROOTFS_VERIFICATION_REMOVED) == 0) {
-    UpdateUIState(UI_STATE_REMOVE_PROTECTION);
-    return;
-  }
-
-  if ((features_flag & DebugDaemonClient::DEV_FEATURE_ALL_ENABLED) !=
-      DebugDaemonClient::DEV_FEATURE_ALL_ENABLED) {
-    UpdateUIState(UI_STATE_SETUP);
-  } else {
-    UpdateUIState(UI_STATE_DONE);
-  }
-}
-
-void EnableDebuggingScreenHandler::UpdateUIState(
-    EnableDebuggingScreenHandler::UIState state) {
-  if (state == UI_STATE_SETUP ||
-      state == UI_STATE_ERROR ||
-      state == UI_STATE_DONE) {
-    PrefService* prefs = g_browser_process->local_state();
-    prefs->ClearPref(prefs::kDebuggingFeaturesRequested);
-    prefs->CommitPendingWrite();
-  }
-
+void EnableDebuggingScreenHandler::UpdateUIState(UIState state) {
   CallJS("login.EnableDebuggingScreen.updateState", static_cast<int>(state));
 }
 
-void EnableDebuggingScreenHandler::HandleOnLearnMore() {
-  VLOG(1) << "Trying to view the help article about debugging features.";
-  const std::string help_content =
-      l10n_util::GetStringUTF8(IDS_ENABLE_DEBUGGING_HELP);
-  const GURL data_url = GURL("data:text/html;charset=utf-8," + help_content);
-
-  LoginWebDialog* dialog =
-      new LoginWebDialog(Profile::FromWebUI(web_ui()), NULL,
-                         LoginDisplayHost::default_host()->GetNativeWindow(),
-                         base::string16(), data_url);
-  dialog->Show();
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h
index 88dfc9a0..3da031fd 100644
--- a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h
@@ -8,8 +8,6 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 
 class PrefRegistrySimple;
@@ -24,11 +22,20 @@
  public:
   constexpr static StaticOobeScreenId kScreenId{"debugging"};
 
+  enum UIState {
+    UI_STATE_ERROR = -1,
+    UI_STATE_REMOVE_PROTECTION = 1,
+    UI_STATE_SETUP = 2,
+    UI_STATE_WAIT = 3,
+    UI_STATE_DONE = 4,
+  };
+
   virtual ~EnableDebuggingScreenView() {}
 
   virtual void Show() = 0;
   virtual void Hide() = 0;
   virtual void SetDelegate(EnableDebuggingScreen* screen) = 0;
+  virtual void UpdateUIState(UIState state) = 0;
 };
 
 // WebUI implementation of EnableDebuggingScreenView.
@@ -44,6 +51,7 @@
   void Show() override;
   void Hide() override;
   void SetDelegate(EnableDebuggingScreen* screen) override;
+  void UpdateUIState(UIState state) override;
 
   // BaseScreenHandler implementation:
   void DeclareLocalizedValues(
@@ -57,48 +65,14 @@
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
  private:
-  enum UIState {
-    UI_STATE_ERROR = -1,
-    UI_STATE_REMOVE_PROTECTION = 1,
-    UI_STATE_SETUP = 2,
-    UI_STATE_WAIT = 3,
-    UI_STATE_DONE = 4,
-  };
-
   // JS messages handlers.
-  void HandleOnCancel();
-  void HandleOnDone();
-  void HandleOnLearnMore();
-  void HandleOnRemoveRootFSProtection();
   void HandleOnSetup(const std::string& password);
 
-  void ShowWithParams();
-
-  // Callback for CryptohomeClient::WaitForServiceToBeAvailable
-  void OnCryptohomeDaemonAvailabilityChecked(bool service_is_available);
-
-  // Callback for DebugDaemonClient::WaitForServiceToBeAvailable
-  void OnDebugDaemonServiceAvailabilityChecked(bool service_is_available);
-
-  // Callback for DebugDaemonClient::EnableDebuggingFeatures().
-  void OnEnableDebuggingFeatures(bool success);
-
-  // Callback for DebugDaemonClient::QueryDebuggingFeatures().
-  void OnQueryDebuggingFeatures(bool success, int features_flag);
-
-  // Callback for DebugDaemonClient::RemoveRootfsVerification().
-  void OnRemoveRootfsVerification(bool success);
-
-  // Updates UI state.
-  void UpdateUIState(UIState state);
-
   EnableDebuggingScreen* screen_ = nullptr;
 
   // Keeps whether screen should be shown right after initialization.
   bool show_on_init_ = false;
 
-  base::WeakPtrFactory<EnableDebuggingScreenHandler> weak_ptr_factory_{this};
-
   DISALLOW_COPY_AND_ASSIGN(EnableDebuggingScreenHandler);
 };
 
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 52b0103..3d0cd67d 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -806,10 +806,6 @@
   core_handler_->ForwardAccelerator(accelerator_name);
 }
 
-void OobeUI::ResetSigninScreenHandlerDelegate() {
-  signin_screen_handler_->SetDelegate(nullptr);
-}
-
 gfx::NativeView OobeUI::GetNativeView() {
   return web_ui()->GetWebContents()->GetNativeView();
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index f25e721..b9c944d 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -94,9 +94,6 @@
   // Forwards an accelerator to the webui to be handled.
   void ForwardAccelerator(std::string accelerator_name);
 
-  // Resets the delegate set in ShowSigninScreen.
-  void ResetSigninScreenHandlerDelegate();
-
   gfx::NativeView GetNativeView();
 
   gfx::NativeWindow GetTopLevelNativeWindow();
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index f581f60..bcd9e6e8 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -862,9 +862,6 @@
   }
 }
 
-void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
-  SetDelegate(nullptr);
-}
 
 void SigninScreenHandler::ShowError(int login_attempts,
                                     const std::string& error_text,
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index 614c9c3..b133e444 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -65,7 +65,6 @@
   virtual void ClearUserPodPassword() = 0;
   virtual void OnUserImageChanged(const user_manager::User& user) = 0;
   virtual void OnPreferencesChanged() = 0;
-  virtual void ResetSigninScreenHandlerDelegate() = 0;
   virtual void ShowError(int login_attempts,
                          const std::string& error_text,
                          const std::string& help_link_text,
@@ -227,7 +226,6 @@
   void ClearUserPodPassword() override;
   void OnUserImageChanged(const user_manager::User& user) override;
   void OnPreferencesChanged() override;
-  void ResetSigninScreenHandlerDelegate() override;
   void ShowError(int login_attempts,
                  const std::string& error_text,
                  const std::string& help_link_text,
diff --git a/chrome/browser/ui/webui/discards/graph_dump_impl.h b/chrome/browser/ui/webui/discards/graph_dump_impl.h
index f4948cb..5a36658 100644
--- a/chrome/browser/ui/webui/discards/graph_dump_impl.h
+++ b/chrome/browser/ui/webui/discards/graph_dump_impl.h
@@ -124,7 +124,7 @@
   void OnIsAudibleChanged(
       const performance_manager::PageNode* page_node) override {}
   // Ignored.
-  void OnIsLoadingChanged(
+  void OnLoadingStateChanged(
       const performance_manager::PageNode* page_node) override {}
   // Ignored.
   void OnUkmSourceIdChanged(
diff --git a/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc b/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
index 934444f..0df9dce9 100644
--- a/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
+++ b/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
@@ -80,7 +80,7 @@
   switch (source) {
     case ntp_tiles::TileSource::TOP_SITES:
     case ntp_tiles::TileSource::SUGGESTIONS_SERVICE:
-    case ntp_tiles::TileSource::WHITELIST:
+    case ntp_tiles::TileSource::ALLOWLIST:
     case ntp_tiles::TileSource::HOMEPAGE:
       return true;
     case ntp_tiles::TileSource::POPULAR_BAKED_IN:
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 441dcb6..de0ef191 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1436,6 +1436,14 @@
   AddPersonalizationOptionsStrings(html_source);
 }
 
+void AddPrivacySandboxStrings(content::WebUIDataSource* html_source) {
+  static constexpr webui::LocalizedString kLocalizedStrings[] = {
+      {"privacySandboxTitle", IDS_SETTINGS_PRIVACY_SANDBOX_TITLE},
+      {"privacySandboxPageHeading", IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_HEADING},
+  };
+  AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
 void AddSafetyCheckStrings(content::WebUIDataSource* html_source) {
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
     {"safetyCheckSectionTitle", IDS_SETTINGS_SAFETY_CHECK_SECTION_TITLE},
@@ -2379,6 +2387,7 @@
       {"securityKeysTitle", IDS_SETTINGS_SECURITY_KEYS_TITLE},
       {"securityKeysTouchToContinue",
        IDS_SETTINGS_SECURITY_KEYS_TOUCH_TO_CONTINUE},
+      {"securityKeysSetPinButton", IDS_SETTINGS_SECURITY_KEYS_SET_PIN_BUTTON},
   };
   AddLocalizedStringsBulk(html_source, kSecurityKeysStrings);
   bool win_native_api_available = false;
@@ -2424,6 +2433,9 @@
   AddSearchStrings(html_source);
   AddSiteSettingsStrings(html_source, profile);
 
+  if (base::FeatureList::IsEnabled(features::kPrivacySandboxSettings))
+    AddPrivacySandboxStrings(html_source);
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   AddChromeOSUserStrings(html_source, profile);
 #else
diff --git a/chrome/browser/ui/webui/settings/settings_security_key_handler.cc b/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
index eacd547..245e320 100644
--- a/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
@@ -19,7 +19,6 @@
 #include "device/fido/bio/enrollment_handler.h"
 #include "device/fido/credential_management.h"
 #include "device/fido/credential_management_handler.h"
-#include "device/fido/fido_discovery_factory.h"
 #include "device/fido/pin.h"
 #include "device/fido/reset_request_handler.h"
 #include "device/fido/set_pin_request_handler.h"
@@ -53,6 +52,12 @@
 
 namespace settings {
 
+SecurityKeysHandlerBase::SecurityKeysHandlerBase() = default;
+SecurityKeysHandlerBase::SecurityKeysHandlerBase(
+    std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory)
+    : discovery_factory_(std::move(discovery_factory)) {}
+SecurityKeysHandlerBase::~SecurityKeysHandlerBase() = default;
+
 void SecurityKeysHandlerBase::OnJavascriptAllowed() {}
 
 void SecurityKeysHandlerBase::OnJavascriptDisallowed() {
@@ -285,8 +290,34 @@
 }
 
 SecurityKeysCredentialHandler::SecurityKeysCredentialHandler() = default;
+SecurityKeysCredentialHandler::SecurityKeysCredentialHandler(
+    std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory)
+    : SecurityKeysHandlerBase(std::move(discovery_factory)) {}
 SecurityKeysCredentialHandler::~SecurityKeysCredentialHandler() = default;
 
+void SecurityKeysCredentialHandler::HandleStart(const base::ListValue* args) {
+  DCHECK_EQ(State::kNone, state_);
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK_EQ(1u, args->GetSize());
+  DCHECK(!credential_management_);
+
+  AllowJavascript();
+  DCHECK(callback_id_.empty());
+  callback_id_ = args->GetList()[0].GetString();
+
+  state_ = State::kStart;
+  credential_management_ =
+      std::make_unique<device::CredentialManagementHandler>(
+          discovery_factory(), supported_transports(),
+          base::BindOnce(
+              &SecurityKeysCredentialHandler::OnCredentialManagementReady,
+              weak_factory_.GetWeakPtr()),
+          base::BindRepeating(&SecurityKeysCredentialHandler::OnGatherPIN,
+                              weak_factory_.GetWeakPtr()),
+          base::BindOnce(&SecurityKeysCredentialHandler::OnFinished,
+                         weak_factory_.GetWeakPtr()));
+}
+
 void SecurityKeysCredentialHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "securityKeyCredentialManagementStart",
@@ -316,38 +347,12 @@
   // Invalidate all existing WeakPtrs so that no stale callbacks occur.
   weak_factory_.InvalidateWeakPtrs();
   state_ = State::kNone;
-  discovery_factory_.reset();
   credential_management_.reset();
   callback_id_.clear();
   credential_management_provide_pin_cb_.Reset();
   DCHECK(!credential_management_provide_pin_cb_);
 }
 
-void SecurityKeysCredentialHandler::HandleStart(const base::ListValue* args) {
-  DCHECK_EQ(State::kNone, state_);
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK_EQ(1u, args->GetSize());
-  DCHECK(!credential_management_);
-  DCHECK(!discovery_factory_);
-
-  AllowJavascript();
-  DCHECK(callback_id_.empty());
-  callback_id_ = args->GetList()[0].GetString();
-
-  state_ = State::kStart;
-  discovery_factory_ = std::make_unique<device::FidoDiscoveryFactory>();
-  credential_management_ =
-      std::make_unique<device::CredentialManagementHandler>(
-          discovery_factory_.get(), supported_transports(),
-          base::BindOnce(
-              &SecurityKeysCredentialHandler::OnCredentialManagementReady,
-              weak_factory_.GetWeakPtr()),
-          base::BindRepeating(&SecurityKeysCredentialHandler::OnGatherPIN,
-                              weak_factory_.GetWeakPtr()),
-          base::BindOnce(&SecurityKeysCredentialHandler::OnFinished,
-                         weak_factory_.GetWeakPtr()));
-}
-
 void SecurityKeysCredentialHandler::HandlePIN(const base::ListValue* args) {
   DCHECK_EQ(State::kPIN, state_);
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -506,7 +511,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   int error;
-
+  bool requires_pin_change = false;
   switch (status) {
     case device::CredentialManagementStatus::kSoftPINBlock:
       error = IDS_SETTINGS_SECURITY_KEYS_PIN_SOFT_LOCK;
@@ -519,23 +524,53 @@
       error = IDS_SETTINGS_SECURITY_KEYS_NO_CREDENTIAL_MANAGEMENT;
       break;
     case device::CredentialManagementStatus::kNoPINSet:
+      requires_pin_change = true;
       error = IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_NO_PIN;
       break;
     case device::CredentialManagementStatus::kAuthenticatorResponseInvalid:
       error = IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_ERROR;
       break;
+    case device::CredentialManagementStatus::kForcePINChange:
+      requires_pin_change = true;
+      error = IDS_SETTINGS_SECURITY_KEYS_FORCE_PIN_CHANGE;
+      break;
     case device::CredentialManagementStatus::kSuccess:
       error = IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_REMOVED;
       break;
   }
 
   FireWebUIListener("security-keys-credential-management-finished",
-                    base::Value(l10n_util::GetStringUTF8(std::move(error))));
+                    base::Value(l10n_util::GetStringUTF8(error)),
+                    base::Value(requires_pin_change));
 }
 
 SecurityKeysBioEnrollmentHandler::SecurityKeysBioEnrollmentHandler() = default;
+SecurityKeysBioEnrollmentHandler::SecurityKeysBioEnrollmentHandler(
+    std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory)
+    : SecurityKeysHandlerBase(std::move(discovery_factory)) {}
 SecurityKeysBioEnrollmentHandler::~SecurityKeysBioEnrollmentHandler() = default;
 
+void SecurityKeysBioEnrollmentHandler::HandleStart(
+    const base::ListValue* args) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK_EQ(state_, State::kNone);
+  DCHECK_EQ(1u, args->GetSize());
+  DCHECK(callback_id_.empty());
+
+  AllowJavascript();
+  state_ = State::kStart;
+  callback_id_ = args->GetList()[0].GetString();
+  bio_ = std::make_unique<device::BioEnrollmentHandler>(
+      supported_transports(),
+      base::BindOnce(&SecurityKeysBioEnrollmentHandler::OnReady,
+                     weak_factory_.GetWeakPtr()),
+      base::BindOnce(&SecurityKeysBioEnrollmentHandler::OnError,
+                     weak_factory_.GetWeakPtr()),
+      base::BindRepeating(&SecurityKeysBioEnrollmentHandler::OnGatherPIN,
+                          weak_factory_.GetWeakPtr()),
+      discovery_factory());
+}
+
 void SecurityKeysBioEnrollmentHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "securityKeyBioEnrollStart",
@@ -577,35 +612,11 @@
 void SecurityKeysBioEnrollmentHandler::Close() {
   weak_factory_.InvalidateWeakPtrs();
   state_ = State::kNone;
-  discovery_factory_.reset();
   bio_.reset();
   callback_id_.clear();
-  discovery_factory_.reset();
   provide_pin_cb_.Reset();
 }
 
-void SecurityKeysBioEnrollmentHandler::HandleStart(
-    const base::ListValue* args) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK_EQ(state_, State::kNone);
-  DCHECK_EQ(1u, args->GetSize());
-  DCHECK(callback_id_.empty());
-
-  AllowJavascript();
-  state_ = State::kStart;
-  callback_id_ = args->GetList()[0].GetString();
-  discovery_factory_ = std::make_unique<device::FidoDiscoveryFactory>();
-  bio_ = std::make_unique<device::BioEnrollmentHandler>(
-      supported_transports(),
-      base::BindOnce(&SecurityKeysBioEnrollmentHandler::OnReady,
-                     weak_factory_.GetWeakPtr()),
-      base::BindOnce(&SecurityKeysBioEnrollmentHandler::OnError,
-                     weak_factory_.GetWeakPtr()),
-      base::BindRepeating(&SecurityKeysBioEnrollmentHandler::OnGatherPIN,
-                          weak_factory_.GetWeakPtr()),
-      discovery_factory_.get());
-}
-
 void SecurityKeysBioEnrollmentHandler::OnReady() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(bio_);
@@ -622,6 +633,7 @@
   state_ = State::kNone;
 
   int error;
+  bool requires_pin_change = false;
   switch (status) {
     case device::BioEnrollmentStatus::kSoftPINBlock:
       error = IDS_SETTINGS_SECURITY_KEYS_PIN_SOFT_LOCK;
@@ -633,18 +645,24 @@
       error = IDS_SETTINGS_SECURITY_KEYS_NO_BIOMETRIC_ENROLLMENT;
       break;
     case device::BioEnrollmentStatus::kNoPINSet:
-      error = IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_NO_PIN;
+      requires_pin_change = true;
+      error = IDS_SETTINGS_SECURITY_KEYS_BIO_NO_PIN;
       break;
     case device::BioEnrollmentStatus::kAuthenticatorResponseInvalid:
       error = IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_ERROR;
       break;
+    case device::BioEnrollmentStatus::kForcePINChange:
+      requires_pin_change = true;
+      error = IDS_SETTINGS_SECURITY_KEYS_FORCE_PIN_CHANGE;
+      break;
     case device::BioEnrollmentStatus::kSuccess:
       error = IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_REMOVED;
       break;
   }
 
   FireWebUIListener("security-keys-bio-enroll-error",
-                    base::Value(l10n_util::GetStringUTF8(error)));
+                    base::Value(l10n_util::GetStringUTF8(error)),
+                    base::Value(requires_pin_change));
 
   // If |callback_id_| is not empty, there is an ongoing operation,
   // which means there is an unresolved Promise. Reject it so that
diff --git a/chrome/browser/ui/webui/settings/settings_security_key_handler.h b/chrome/browser/ui/webui/settings/settings_security_key_handler.h
index d719f1ae..b29ea5f 100644
--- a/chrome/browser/ui/webui/settings/settings_security_key_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_security_key_handler.h
@@ -12,9 +12,9 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
-#include "device/fido/fido_constants.h"
-
 #include "device/fido/bio/enrollment.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_discovery_factory.h"
 
 namespace base {
 class ListValue;
@@ -22,7 +22,6 @@
 
 namespace device {
 struct AggregatedEnumerateCredentialsResponse;
-class FidoDiscoveryFactory;
 class CredentialManagementHandler;
 enum class CredentialManagementStatus;
 class SetPINRequestHandler;
@@ -40,14 +39,25 @@
   SecurityKeysHandlerBase& operator=(const SecurityKeysHandlerBase&) = delete;
 
  protected:
-  SecurityKeysHandlerBase() = default;
+  SecurityKeysHandlerBase();
+  explicit SecurityKeysHandlerBase(
+      std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory);
+  ~SecurityKeysHandlerBase() override;
 
   // Subclasses must implement close to invalidate all pending callbacks.
   virtual void Close() = 0;
 
+  // Returns the discovery factory to be used for the request.
+  device::FidoDiscoveryFactory* discovery_factory() {
+    return discovery_factory_.get();
+  }
+
  private:
   void OnJavascriptAllowed() override;
   void OnJavascriptDisallowed() override;
+
+  std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory_ =
+      std::make_unique<device::FidoDiscoveryFactory>();
 };
 
 // SecurityKeysPINHandler processes messages from the "Create a PIN" dialog of
@@ -130,6 +140,11 @@
   SecurityKeysCredentialHandler();
   ~SecurityKeysCredentialHandler() override;
 
+ protected:
+  explicit SecurityKeysCredentialHandler(
+      std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory);
+  void HandleStart(const base::ListValue* args);
+
  private:
   enum class State {
     kNone,
@@ -143,7 +158,6 @@
   void RegisterMessages() override;
   void Close() override;
 
-  void HandleStart(const base::ListValue* args);
   void HandlePIN(const base::ListValue* args);
   void HandleEnumerate(const base::ListValue* args);
   void HandleDelete(const base::ListValue* args);
@@ -164,7 +178,6 @@
   State state_ = State::kNone;
   base::OnceCallback<void(std::string)> credential_management_provide_pin_cb_;
 
-  std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory_;
   std::unique_ptr<device::CredentialManagementHandler> credential_management_;
 
   std::string callback_id_;
@@ -180,6 +193,11 @@
   SecurityKeysBioEnrollmentHandler();
   ~SecurityKeysBioEnrollmentHandler() override;
 
+ protected:
+  explicit SecurityKeysBioEnrollmentHandler(
+      std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory);
+  void HandleStart(const base::ListValue* args);
+
  private:
   enum class State {
     kNone,
@@ -195,7 +213,6 @@
   void RegisterMessages() override;
   void Close() override;
 
-  void HandleStart(const base::ListValue* args);
   void OnReady();
   void OnError(device::BioEnrollmentStatus status);
   void OnGatherPIN(uint32_t min_pin_length,
@@ -229,7 +246,6 @@
   State state_ = State::kNone;
   std::string callback_id_;
   base::OnceCallback<void(std::string)> provide_pin_cb_;
-  std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory_;
   std::unique_ptr<device::BioEnrollmentHandler> bio_;
   base::WeakPtrFactory<SecurityKeysBioEnrollmentHandler> weak_factory_{this};
 };
diff --git a/chrome/browser/ui/webui/settings/settings_security_key_handler_unittest.cc b/chrome/browser/ui/webui/settings/settings_security_key_handler_unittest.cc
new file mode 100644
index 0000000..8db5713
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/settings_security_key_handler_unittest.cc
@@ -0,0 +1,144 @@
+// 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/ui/webui/settings/settings_security_key_handler.h"
+
+#include <memory>
+
+#include "chrome/grit/generated_resources.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/test/test_web_ui.h"
+#include "device/fido/fake_fido_discovery.h"
+#include "device/fido/fido_discovery_factory.h"
+#include "device/fido/fido_types.h"
+#include "device/fido/virtual_fido_device_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace settings {
+
+namespace {
+
+class TestSecurityKeysCredentialHandler : public SecurityKeysCredentialHandler {
+ public:
+  explicit TestSecurityKeysCredentialHandler(content::TestWebUI* web_ui)
+      : SecurityKeysCredentialHandler(
+            std::make_unique<device::test::VirtualFidoDeviceFactory>()) {
+    set_web_ui(web_ui);
+    AllowJavascriptForTesting();
+  }
+
+  using SecurityKeysCredentialHandler::HandleStart;
+
+  device::test::VirtualFidoDeviceFactory* GetDiscoveryFactory() {
+    return static_cast<device::test::VirtualFidoDeviceFactory*>(
+        discovery_factory());
+  }
+};
+
+class TestSecurityKeysBioEnrollmentHandler
+    : public SecurityKeysBioEnrollmentHandler {
+ public:
+  explicit TestSecurityKeysBioEnrollmentHandler(content::TestWebUI* web_ui)
+      : SecurityKeysBioEnrollmentHandler(
+            std::make_unique<device::test::VirtualFidoDeviceFactory>()) {
+    set_web_ui(web_ui);
+    AllowJavascriptForTesting();
+  }
+
+  using SecurityKeysBioEnrollmentHandler::HandleStart;
+
+  device::test::VirtualFidoDeviceFactory* GetDiscoveryFactory() {
+    return static_cast<device::test::VirtualFidoDeviceFactory*>(
+        discovery_factory());
+  }
+};
+
+}  // namespace
+
+class SecurityKeysCredentialHandlerTest
+    : public ChromeRenderViewHostTestHarness {
+ protected:
+  void SetUp() override {
+    ChromeRenderViewHostTestHarness::SetUp();
+    web_ui_ = std::make_unique<content::TestWebUI>();
+    web_ui_->set_web_contents(web_contents());
+    handler_ =
+        std::make_unique<TestSecurityKeysCredentialHandler>(web_ui_.get());
+    web_ui_->ClearTrackedCalls();
+  }
+
+  std::unique_ptr<TestSecurityKeysCredentialHandler> handler_;
+  std::unique_ptr<content::TestWebUI> web_ui_;
+};
+
+TEST_F(SecurityKeysCredentialHandlerTest, TestForcePINChange) {
+  handler_->GetDiscoveryFactory()->mutable_state()->force_pin_change = true;
+  handler_->GetDiscoveryFactory()->mutable_state()->pin = "1234";
+  device::VirtualCtap2Device::Config config;
+  config.pin_support = true;
+  config.pin_uv_auth_token_support = true;
+  config.min_pin_length_support = true;
+  config.credential_management_support = true;
+  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
+  handler_->GetDiscoveryFactory()->SetCtap2Config(config);
+
+  std::string callback_id("start_callback_id");
+  base::ListValue args;
+  args.Append(callback_id);
+  handler_->HandleStart(&args);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(web_ui_->call_data()[0]->arg1()->GetString(),
+            "security-keys-credential-management-finished");
+  EXPECT_EQ(
+      web_ui_->call_data()[0]->arg2()->GetString(),
+      l10n_util::GetStringUTF8(IDS_SETTINGS_SECURITY_KEYS_FORCE_PIN_CHANGE));
+  EXPECT_EQ(web_ui_->call_data()[0]->arg3()->GetBool(), true);
+}
+
+class SecurityKeysBioEnrollmentHandlerTest
+    : public ChromeRenderViewHostTestHarness {
+ protected:
+  void SetUp() override {
+    ChromeRenderViewHostTestHarness::SetUp();
+    web_ui_ = std::make_unique<content::TestWebUI>();
+    web_ui_->set_web_contents(web_contents());
+    handler_ =
+        std::make_unique<TestSecurityKeysBioEnrollmentHandler>(web_ui_.get());
+    web_ui_->ClearTrackedCalls();
+  }
+
+  std::unique_ptr<TestSecurityKeysBioEnrollmentHandler> handler_;
+  std::unique_ptr<content::TestWebUI> web_ui_;
+};
+
+TEST_F(SecurityKeysBioEnrollmentHandlerTest, TestForcePINChange) {
+  handler_->GetDiscoveryFactory()->mutable_state()->force_pin_change = true;
+  handler_->GetDiscoveryFactory()->mutable_state()->pin = "1234";
+  device::VirtualCtap2Device::Config config;
+  config.internal_uv_support = true;
+  config.bio_enrollment_support = true;
+  config.pin_support = true;
+  config.pin_uv_auth_token_support = true;
+  config.min_pin_length_support = true;
+  config.credential_management_support = true;
+  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
+  handler_->GetDiscoveryFactory()->SetCtap2Config(config);
+
+  std::string callback_id("start_callback_id");
+  base::ListValue args;
+  args.Append(callback_id);
+  handler_->HandleStart(&args);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(web_ui_->call_data()[0]->arg1()->GetString(),
+            "security-keys-bio-enroll-error");
+  EXPECT_EQ(
+      web_ui_->call_data()[0]->arg2()->GetString(),
+      l10n_util::GetStringUTF8(IDS_SETTINGS_SECURITY_KEYS_FORCE_PIN_CHANGE));
+  EXPECT_EQ(web_ui_->call_data()[0]->arg3()->GetBool(), true);
+}
+
+}  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index fb737ba2..49f21b6 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -346,6 +346,11 @@
       profile, std::make_unique<FaviconSource>(
                    profile, chrome::FaviconUrlFormat::kFavicon2));
 
+  // Privacy Sandbox
+  if (base::FeatureList::IsEnabled(features::kPrivacySandboxSettings)) {
+    html_source->AddResourcePath(
+        "privacySandbox", IDR_SETTINGS_PRIVACY_SANDBOX_PRIVACY_SANDBOX_HTML);
+  }
   TryShowHatsSurveyWithTimeout();
 }
 
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index a2964ee6..9de087f 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1606802354-d1c692a560ec6fde56aef2f398f74e894835d223.profdata
+chrome-linux-master-1606845551-c0991c25d04e0fb7cdc34afe442412c8219bff33.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 5b3d3fa..83df8f2 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1606802354-31ea8b5273cb9879cfc7599870323fbd7fd3af58.profdata
+chrome-mac-master-1606845551-f7436cdc1d8a17c203d7167ce8ba0cc00b1d3773.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 5977438f..853a58d 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1606759191-849e6110591039c862ea10277c9aceb1aa0b28d5.profdata
+chrome-win32-master-1606802354-2e3be99fee27d60bc23828ee78c917e6dcb3614e.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 8cc1983..aba139f 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1606780634-4bcba867177e99782f7fa7f8d4c0822ffa36a5f3.profdata
+chrome-win64-master-1606834243-e828e7c1abf6992c40e6e24872b0e913b727a4f7.profdata
diff --git a/chrome/common/google_url_loader_throttle.cc b/chrome/common/google_url_loader_throttle.cc
index c1870b0f..ce40f00 100644
--- a/chrome/common/google_url_loader_throttle.cc
+++ b/chrome/common/google_url_loader_throttle.cc
@@ -12,6 +12,7 @@
 #include "components/google/core/common/google_util.h"
 #include "net/base/url_util.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
+#include "services/network/public/mojom/x_frame_options.mojom.h"
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "extensions/common/extension_urls.h"
@@ -152,15 +153,21 @@
     const GURL& response_url,
     network::mojom::URLResponseHead* response_head,
     bool* defer) {
-  // Built-in additional protection for the chrome web store origin.
+  // Built-in additional protection for the chrome web store origin by ensuring
+  // that the X-Frame-Options protection mechanism is set to either DENY or
+  // SAMEORIGIN.
   GURL webstore_url(extension_urls::GetWebstoreLaunchURL());
   if (response_url.SchemeIsHTTPOrHTTPS() &&
       response_url.DomainIs(webstore_url.host_piece())) {
-    if (response_head && response_head->headers &&
-        !response_head->headers->HasHeaderValue("x-frame-options", "deny") &&
-        !response_head->headers->HasHeaderValue("x-frame-options",
-                                                "sameorigin")) {
-      response_head->headers->AddHeader("x-frame-options", "sameorigin");
+    // TODO(mkwst): Consider shifting this to a NavigationThrottle rather than
+    // relying on implicit ordering between this check and the time at which
+    // ParsedHeaders is created.
+    CHECK(response_head);
+    CHECK(response_head->parsed_headers);
+    if (response_head->parsed_headers->xfo !=
+        network::mojom::XFrameOptionsValue::kDeny) {
+      response_head->parsed_headers->xfo =
+          network::mojom::XFrameOptionsValue::kSameOrigin;
     }
   }
 }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index e166f7a4..f65a001d 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4398,6 +4398,9 @@
       "../browser/badging/test_badge_manager_delegate.cc",
       "../browser/badging/test_badge_manager_delegate.h",
 
+      # Device API isn't supported on Android.
+      "../browser/device_api/device_service_unittest.cc",
+
       # Bookmark export/import are handled via the BookmarkColumns
       # ContentProvider.
       "../browser/bookmarks/bookmark_html_writer_unittest.cc",
@@ -4668,6 +4671,7 @@
       "../browser/ui/webui/settings/safety_check_handler_unittest.cc",
       "../browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc",
       "../browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc",
+      "../browser/ui/webui/settings/settings_security_key_handler_unittest.cc",
       "../browser/ui/webui/settings/site_settings_handler_unittest.cc",
       "../browser/ui/webui/settings/site_settings_helper_unittest.cc",
       "../browser/ui/webui/settings_utils_unittest.cc",
@@ -6068,6 +6072,8 @@
       "../browser/ui/views/tabs/tab_strip_layout_unittest.cc",
       "../browser/ui/views/tabs/tab_strip_unittest.cc",
       "../browser/ui/views/tabs/tab_unittest.cc",
+      "../browser/ui/views/toolbar/chrome_labs_bubble_view_unittest.cc",
+      "../browser/ui/views/toolbar/chrome_labs_button_unittest.cc",
       "../browser/ui/views/toolbar/reload_button_unittest.cc",
       "../browser/ui/views/toolbar/toolbar_action_view_unittest.cc",
       "../browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java
index 5f9f1a5..102a846 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java
@@ -53,9 +53,9 @@
         siteSuggestions.add(new SiteSuggestion("0 TOP_SITES",
                 new GURL(testServer.getURL(TEST_PAGE) + "#0"), "", TileTitleSource.TITLE_TAG,
                 TileSource.TOP_SITES, TileSectionType.PERSONALIZED, new Date()));
-        siteSuggestions.add(new SiteSuggestion("1 WHITELIST",
+        siteSuggestions.add(new SiteSuggestion("1 ALLOWLIST",
                 new GURL(testServer.getURL(TEST_PAGE) + "#1"), "/test.png", TileTitleSource.UNKNOWN,
-                TileSource.WHITELIST, TileSectionType.PERSONALIZED, new Date()));
+                TileSource.ALLOWLIST, TileSectionType.PERSONALIZED, new Date()));
         siteSuggestions.add(new SiteSuggestion("2 TOP_SITES",
                 new GURL(testServer.getURL(TEST_PAGE) + "#2"), "", TileTitleSource.TITLE_TAG,
                 TileSource.TOP_SITES, TileSectionType.PERSONALIZED, new Date()));
diff --git a/chrome/test/data/extensions/api_test/enterprise_platform_keys/basic.js b/chrome/test/data/extensions/api_test/enterprise_platform_keys/background.js
similarity index 96%
rename from chrome/test/data/extensions/api_test/enterprise_platform_keys/basic.js
rename to chrome/test/data/extensions/api_test/enterprise_platform_keys/background.js
index fd3f9d4..be4e015 100644
--- a/chrome/test/data/extensions/api_test/enterprise_platform_keys/basic.js
+++ b/chrome/test/data/extensions/api_test/enterprise_platform_keys/background.js
@@ -4,7 +4,12 @@
 
 'use strict';
 
-var systemTokenEnabled = (location.href.indexOf("systemTokenEnabled") != -1);
+// The message sent from a browsertest to the background script in case the
+// system token is enabled.
+const SYSTEM_TOKEN_ENABLED_MESSAGE = 'System token enabled.';
+// The message sent from a browsertest to the background script in case the
+// system token is disabled.
+const SYSTEM_TOKEN_DISABLED_MESSAGE = 'System token disabled.';
 
 var assertEq = chrome.test.assertEq;
 var assertTrue = chrome.test.assertTrue;
@@ -292,7 +297,7 @@
 /**
  * Runs preparations before the actual tests. Calls |callback| with |userToken|.
  */
-function beforeTests(callback) {
+function beforeTests(systemTokenEnabled, callback) {
   assertTrue(!!chrome.enterprise, "No enterprise namespace.");
   assertTrue(!!chrome.enterprise.platformKeys, "No platformKeys namespace.");
   assertTrue(!!chrome.enterprise.platformKeys.getTokens,
@@ -876,4 +881,20 @@
   chrome.test.runTests(testsIndependentOfKeys.concat(testsNotParameterized));
 }
 
-beforeTests(runTests);
+// |waitForSystemTokenStateMessage()| waits for the browser test to send a
+// message with the state of the system token to run tests accordingly. The
+// browser test logic can be found at:
+// c/b/e/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
+function waitForSystemTokenStateMessage(systemTokenStateMessage) {
+  if (systemTokenStateMessage == SYSTEM_TOKEN_ENABLED_MESSAGE) {
+    beforeTests(/*systemTokenEnabled=*/ true, runTests);
+  } else if (systemTokenStateMessage == SYSTEM_TOKEN_DISABLED_MESSAGE) {
+    beforeTests(/*systemTokenEnabled=*/ false, runTests);
+  } else {
+    // No background script tests should run.
+    succeed();
+  }
+}
+
+chrome.test.sendMessage(
+    'Waiting for system token state message', waitForSystemTokenStateMessage);
diff --git a/chrome/test/data/extensions/api_test/enterprise_platform_keys/basic.html b/chrome/test/data/extensions/api_test/enterprise_platform_keys/basic.html
deleted file mode 100644
index 569a748..0000000
--- a/chrome/test/data/extensions/api_test/enterprise_platform_keys/basic.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!--
- * Copyright 2014 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.
--->
-<script src="basic.js"></script>
diff --git a/chrome/test/data/extensions/api_test/enterprise_platform_keys/manifest.json b/chrome/test/data/extensions/api_test/enterprise_platform_keys/manifest.json
index a302425..83c5fb4 100644
--- a/chrome/test/data/extensions/api_test/enterprise_platform_keys/manifest.json
+++ b/chrome/test/data/extensions/api_test/enterprise_platform_keys/manifest.json
@@ -4,6 +4,9 @@
   "name": "Basic tests",
   "version": "0.1",
   "manifest_version": 2,
+  "background": {
+    "scripts": ["background.js"]
+  },
   "permissions": [
     "enterprise.platformKeys"
   ]
diff --git a/chrome/test/data/extensions/test_certificate_provider/extension.crx b/chrome/test/data/extensions/test_certificate_provider/extension.crx
deleted file mode 100644
index effa0f8..0000000
--- a/chrome/test/data/extensions/test_certificate_provider/extension.crx
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/extensions/test_certificate_provider/update_manifest.xml b/chrome/test/data/extensions/test_certificate_provider/update_manifest.xml
deleted file mode 100644
index 7b1fec1..0000000
--- a/chrome/test/data/extensions/test_certificate_provider/update_manifest.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-  This update manifest points to the ./extension.crx file.
-  "mock.http" is a placeholder that gets substituted with the test server
-  address in runtime.
--->
-<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
-  <app appid='ecmhnokcdiianioonpgakiooenfnonid'>
-    <updatecheck
-        codebase='http://mock.http/extensions/test_certificate_provider/extension.crx'
-        version='1.0' />
-   </app>
-</gupdate>
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
index fd60841..42dd4bfa 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
@@ -121,7 +121,7 @@
       assertEquals(
           getNameText(),
           loadTimeData.getStringF(
-              'routineNameText',
+              'routineEntryText',
               loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should be empty if the test is not started.
@@ -138,7 +138,7 @@
       assertEquals(
           getNameText(),
           loadTimeData.getStringF(
-              'routineNameText',
+              'routineEntryText',
               loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should be running.
@@ -158,7 +158,7 @@
       assertEquals(
           getNameText(),
           loadTimeData.getStringF(
-              'routineNameText',
+              'routineEntryText',
               loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should show the passed result.
@@ -178,7 +178,7 @@
       assertEquals(
           getNameText(),
           loadTimeData.getStringF(
-              'routineNameText',
+              'routineEntryText',
               loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should show the passed result.
@@ -203,7 +203,7 @@
       assertEquals(
           getNameText(),
           loadTimeData.getStringF(
-              'routineNameText',
+              'routineEntryText',
               loadTimeData.getString('batteryChargeRoutineText')));
 
       // Status should show the passed result.
diff --git a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
index 6cb5818..fc825d3 100644
--- a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
@@ -23,6 +23,8 @@
   let scanProgress;
   /** @type {!HTMLElement} */
   let scannedImages;
+  /** @type {!HTMLElement} */
+  let cancelingProgress;
 
   setup(() => {
     scanPreview = /** @type {!ScanPreviewElement} */ (
@@ -38,6 +40,8 @@
         /** @type {!HTMLElement} */ (scanPreview.$$('#scanProgress'));
     scannedImages =
         /** @type {!HTMLElement} */ (scanPreview.$$('#scannedImages'));
+    cancelingProgress =
+        /** @type {!HTMLElement} */ (scanPreview.$$('#cancelingProgress'));
   });
 
   teardown(() => {
@@ -52,14 +56,16 @@
    * @param {boolean} isHelperTextVisible
    * @param {boolean} isScanProgressVisible
    * @param {boolean} isScannedImagesVisible
+   * @param {boolean} isCancelingProgressVisible
    */
   function assertVisible(
       isHelpOrProgressVisible, isHelperTextVisible, isScanProgressVisible,
-      isScannedImagesVisible) {
+      isScannedImagesVisible, isCancelingProgressVisible) {
     assertEquals(isHelpOrProgressVisible, isVisible(helpOrProgress));
     assertEquals(isHelperTextVisible, isVisible(helperText));
     assertEquals(isScanProgressVisible, isVisible(scanProgress));
     assertEquals(isScannedImagesVisible, isVisible(scannedImages));
+    assertEquals(isCancelingProgressVisible, isVisible(cancelingProgress));
   }
 
   test('initializeScanPreview', () => {
@@ -86,37 +92,50 @@
     flush();
     assertVisible(
         /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true,
-        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false);
+        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
+        /*isCancelingProgressVisible*/ false);
 
     scanPreview.appState = AppState.GOT_SCANNERS;
     flush();
     assertVisible(
         /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true,
-        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false);
+        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
+        /*isCancelingProgressVisible*/ false);
 
     scanPreview.appState = AppState.GETTING_CAPS;
     flush();
     assertVisible(
         /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true,
-        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false);
+        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
+        /*isCancelingProgressVisible*/ false);
 
     scanPreview.appState = AppState.READY;
     flush();
     assertVisible(
         /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ true,
-        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false);
+        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
+        /*isCancelingProgressVisible*/ false);
 
     scanPreview.appState = AppState.SCANNING;
     flush();
     assertVisible(
         /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ false,
-        /*isScanProgressVisible*/ true, /*isScannedImagesVisible*/ false);
+        /*isScanProgressVisible*/ true, /*isScannedImagesVisible*/ false,
+        /*isCancelingProgressVisible*/ false);
+
+    scanPreview.appState = AppState.CANCELING;
+    flush();
+    assertVisible(
+        /*isHelpOrProgressVisible*/ true, /*isHelperTextVisible*/ false,
+        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ false,
+        /*isCancelingProgressVisible*/ true);
 
     scanPreview.objectUrls = ['image'];
     scanPreview.appState = AppState.DONE;
     flush();
     assertVisible(
         /*isHelpOrProgressVisible*/ false, /*isHelperTextVisible*/ false,
-        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ true);
+        /*isScanProgressVisible*/ false, /*isScannedImagesVisible*/ true,
+        /*isCancelingProgressVisible*/ false);
   });
 }
diff --git a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
index 99a75ba..a29f80bc 100644
--- a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
@@ -553,6 +553,8 @@
           return fakeScanService_.whenCalled('cancelScan');
         })
         .then(() => {
+          // Cancel button should be disabled while canceling is in progress.
+          assertTrue(cancelButton.disabled);
           // Simulate cancel completing successfully.
           return fakeScanService_.simulateCancelComplete(true);
         })
@@ -610,6 +612,8 @@
           return fakeScanService_.whenCalled('cancelScan');
         })
         .then(() => {
+          // Cancel button should be disabled while canceling is in progress.
+          assertTrue(cancelButton.disabled);
           // Simulate cancel failing.
           return fakeScanService_.simulateCancelComplete(false);
         })
diff --git a/chrome/test/data/webui/settings/security_keys_subpage_test.js b/chrome/test/data/webui/settings/security_keys_subpage_test.js
index cfed44a..fc68cfa 100644
--- a/chrome/test/data/webui/settings/security_keys_subpage_test.js
+++ b/chrome/test/data/webui/settings/security_keys_subpage_test.js
@@ -628,11 +628,35 @@
     assertShown(allDivs, dialog, 'initial');
     startResolver.resolve([currentMinPinLength]);
 
-    const errorString = 'foo bar baz';
+    const error = 'foo bar baz';
     webUIListenerCallback(
-        'security-keys-credential-management-finished', errorString);
+        'security-keys-credential-management-finished', error);
     assertShown(allDivs, dialog, 'error');
-    assertTrue(dialog.$.error.textContent.trim().includes(errorString));
+    assertTrue(dialog.$.error.textContent.trim().includes(error));
+  });
+
+  test('PINChangeError', async function() {
+    const startResolver = new PromiseResolver();
+    browserProxy.setResponseFor(
+        'startCredentialManagement', startResolver.promise);
+
+    document.body.appendChild(dialog);
+    await browserProxy.whenCalled('startCredentialManagement');
+    assertShown(allDivs, dialog, 'initial');
+    startResolver.resolve([currentMinPinLength]);
+
+    const error = 'foo bar baz';
+    webUIListenerCallback(
+        'security-keys-credential-management-finished', error,
+        true /* requiresPINChange */);
+    assertShown(allDivs, dialog, 'error');
+    assertFalse(dialog.$.confirmButton.hidden);
+    assertFalse(dialog.$.confirmButton.disabled);
+    assertTrue(dialog.$.error.textContent.trim().includes(error));
+
+    const setPinEvent = eventToPromise('credential-management-set-pin', dialog);
+    dialog.$.confirmButton.click();
+    await setPinEvent;
   });
 
   test('Credentials', async function() {
@@ -754,10 +778,33 @@
     assertShown(allDivs, dialog, 'initial');
     resolver.resolve([currentMinPinLength]);
 
-    const errorString = 'foo bar baz';
-    webUIListenerCallback('security-keys-bio-enroll-error', errorString);
+    const error = 'foo bar baz';
+    webUIListenerCallback('security-keys-bio-enroll-error', error);
     assertShown(allDivs, dialog, 'error');
-    assertTrue(dialog.$.error.textContent.trim().includes(errorString));
+    assertTrue(dialog.$.confirmButton.hidden);
+    assertTrue(dialog.$.error.textContent.trim().includes(error));
+  });
+
+  test('PINChangeError', async function() {
+    const resolver = new PromiseResolver();
+    browserProxy.setResponseFor('startBioEnroll', resolver.promise);
+
+    document.body.appendChild(dialog);
+    await browserProxy.whenCalled('startBioEnroll');
+    assertShown(allDivs, dialog, 'initial');
+    resolver.resolve([currentMinPinLength]);
+
+    const error = 'something about setting a new PIN';
+    webUIListenerCallback(
+        'security-keys-bio-enroll-error', error, true /* requiresPINChange */);
+    assertShown(allDivs, dialog, 'error');
+    assertFalse(dialog.$.confirmButton.hidden);
+    assertFalse(dialog.$.confirmButton.disabled);
+    assertTrue(dialog.$.error.textContent.trim().includes(error));
+
+    const setPinEvent = eventToPromise('bio-enroll-set-pin', dialog);
+    dialog.$.confirmButton.click();
+    await setPinEvent;
   });
 
   test('Enrollments', async function() {
diff --git a/chromecast/app/cast_test_launcher.cc b/chromecast/app/cast_test_launcher.cc
index f2dc921..fdef3c1 100644
--- a/chromecast/app/cast_test_launcher.cc
+++ b/chromecast/app/cast_test_launcher.cc
@@ -14,6 +14,10 @@
 #include "ipc/ipc_channel.h"
 #include "mojo/core/embedder/embedder.h"
 
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#endif  // defined(OS_WIN)
+
 namespace chromecast {
 namespace shell {
 
@@ -48,6 +52,13 @@
   size_t parallel_jobs = base::NumParallelJobs(/*cores_per_job=*/2);
   if (parallel_jobs == 0U)
     return 1;
+
+#if defined(OS_WIN)
+  // Load and pin user32.dll to avoid having to load it once tests start while
+  // on the main thread loop where blocking calls are disallowed.
+  base::win::PinUser32();
+#endif  // OS_WIN
+
   chromecast::shell::CastTestLauncherDelegate launcher_delegate;
   mojo::core::Init();
   content::ForceInProcessNetworkService(true);
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 6a4e707..5903109e 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -19,25 +19,36 @@
   flags = [ "ENABLE_CAST_AUDIO_MANAGER_MIXER=$enable_cast_audio_manager_mixer" ]
 }
 
-cast_source_set("prefs") {
+group("prefs") {
+  public_deps = [ ":prefs_base" ]
+
+  if (chromecast_branding == "public") {
+    public_deps += [ ":prefs_simple" ]
+  }
+}
+
+cast_source_set("prefs_base") {
   sources = [
     "pref_service_helper.cc",
     "pref_service_helper.h",
   ]
 
-  if (chromecast_branding == "public") {
-    sources += [ "pref_service_helper_simple.cc" ]
-  }
+  public_deps = [ "//components/prefs" ]
 
   deps = [
     "//base",
     "//chromecast:chromecast_buildflags",
     "//chromecast/base",
     "//components/cdm/browser",
-    "//components/prefs",
   ]
 }
 
+cast_source_set("prefs_simple") {
+  sources = [ "pref_service_helper_simple.cc" ]
+
+  public_deps = [ ":prefs_base" ]
+}
+
 cast_source_set("feature_list") {
   sources = [
     "cast_feature_list_creator.cc",
@@ -64,7 +75,18 @@
   ]
 }
 
-cast_source_set("browser") {
+group("browser") {
+  public_deps = [ ":browser_base" ]
+
+  if (chromecast_branding == "public") {
+    public_deps += [
+      ":simple_client",
+      ":simple_main_parts",
+    ]
+  }
+}
+
+cast_source_set("browser_base") {
   sources = [
     "application_media_capabilities.cc",
     "application_media_capabilities.h",
@@ -154,13 +176,6 @@
     "webui/constants.h",
   ]
 
-  if (chromecast_branding == "public") {
-    sources += [
-      "cast_browser_main_parts_simple.cc",
-      "cast_content_browser_client_simple.cc",
-    ]
-  }
-
   public_deps = [
     ":feature_list",
     ":prefs",
@@ -493,6 +508,20 @@
   }
 }
 
+cast_source_set("simple_main_parts") {
+  sources = [ "cast_browser_main_parts_simple.cc" ]
+
+  public_deps = [ ":browser_base" ]
+}
+
+cast_source_set("simple_client") {
+  sources = [ "cast_content_browser_client_simple.cc" ]
+
+  public_deps = [ ":browser_base" ]
+
+  deps = [ "//base" ]
+}
+
 # Lightweight target for Cast interfaces that wrap //content/public/browser.
 # This target should only include interfaces which are required for unit tests.
 cast_source_set("public") {
diff --git a/chromecast/renderer/BUILD.gn b/chromecast/renderer/BUILD.gn
index c6fa39a..590acec 100644
--- a/chromecast/renderer/BUILD.gn
+++ b/chromecast/renderer/BUILD.gn
@@ -24,7 +24,15 @@
   ]
 }
 
-cast_source_set("renderer") {
+group("renderer") {
+  public_deps = [ ":renderer_base" ]
+
+  if (chromecast_branding == "public") {
+    public_deps += [ ":simple_client" ]
+  }
+}
+
+cast_source_set("renderer_base") {
   sources = [
     "activity_filtering_websocket_handshake_throttle.cc",
     "activity_filtering_websocket_handshake_throttle.h",
@@ -47,39 +55,38 @@
     "queryable_data_store.h",
   ]
 
-  public_deps = [ "//chromecast/renderer/media" ]
-
-  if (chromecast_branding == "public") {
-    sources += [ "cast_content_renderer_client_simple.cc" ]
-  }
+  public_deps = [
+    "//chromecast:chromecast_buildflags",
+    "//chromecast/common/mojom",
+    "//content/public/renderer",
+    "//media",
+    "//mojo/public/cpp/bindings",
+    "//v8",
+  ]
 
   deps = [
     "//base",
-    "//chromecast:chromecast_buildflags",
     "//chromecast/base",
     "//chromecast/common",
     "//chromecast/common:activity_url_filter",
     "//chromecast/common:queryable_data",
     "//chromecast/common/media",
-    "//chromecast/common/mojom",
     "//chromecast/crash",
     "//chromecast/media",
     "//chromecast/media/base:media_codec_support",
+    "//chromecast/renderer/media",
     "//components/media_control/renderer",
     "//components/network_hints/renderer",
     "//components/on_load_script_injector/renderer",
     "//content/public/common",
-    "//content/public/renderer",
     "//crypto",
     "//gin",
     "//ipc",
-    "//media",
     "//media/remoting:remoting_constants",
     "//media/remoting:remoting_renderer",
     "//net",
     "//services/network/public/cpp:cpp",
     "//services/service_manager/public/cpp",
-    "//v8",
   ]
 
   if (!is_android) {
@@ -87,11 +94,6 @@
       "memory_pressure_observer_impl.cc",
       "memory_pressure_observer_impl.h",
     ]
-
-    deps += [
-      "//chromecast/common/mojom",
-      "//mojo/public/cpp/bindings",
-    ]
   } else {
     deps += [ "//chromecast/media/audio:cast_audio_device_factory" ]
   }
@@ -120,3 +122,12 @@
     ]
   }
 }
+
+cast_source_set("simple_client") {
+  sources = [ "cast_content_renderer_client_simple.cc" ]
+
+  public_deps = [
+    ":renderer_base",
+    "//base",
+  ]
+}
diff --git a/chromecast/utility/BUILD.gn b/chromecast/utility/BUILD.gn
index e6a48f9..48eed4a 100644
--- a/chromecast/utility/BUILD.gn
+++ b/chromecast/utility/BUILD.gn
@@ -4,7 +4,15 @@
 
 import("//chromecast/chromecast.gni")
 
-cast_source_set("utility") {
+group("utility") {
+  public_deps = [ ":utility_base" ]
+
+  if (chromecast_branding == "public") {
+    public_deps += [ ":simple_client" ]
+  }
+}
+
+cast_source_set("utility_base") {
   sources = [
     "cast_content_utility_client.cc",
     "cast_content_utility_client.h",
@@ -17,8 +25,10 @@
     "//mojo/public/cpp/system",
     "//services/service_manager/public/mojom",
   ]
+}
 
-  if (chromecast_branding == "public") {
-    sources += [ "cast_content_utility_client_simple.cc" ]
-  }
+cast_source_set("simple_client") {
+  sources = [ "cast_content_utility_client_simple.cc" ]
+
+  public_deps = [ ":utility_base" ]
 }
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 55cc657e..11a161d3 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -588,6 +588,9 @@
       <message name="IDS_SCANNING_APP_SCAN_CANCELED_TOAST_TEXT" desc="The message displayed when a scan job is successfully canceled.">
         Scanning has been canceled
       </message>
+      <message name="IDS_SCANNING_APP_CANCELING_SCANNING_TEXT" desc="The text displayed in the scan preview to indicate a scan job is being canceled.">
+        Canceling scanning
+      </message>
 
       <!-- Diagnostics App -->
       <!-- TODO(michaelcheco): Update with finalized copies of the strings -->
@@ -727,6 +730,51 @@
       <message name="IDS_DISCHARGE_TEST_RESULT" desc="The result text for discharging routine." translateable="false">
         Discharged <ph name="RATE">$1<ex>10%</ex></ph> in <ph name="NUM_SECONDS">$1<ex>10</ex></ph> seconds.
       </message>
+      <message name="IDS_DIAGNOSTICS_TEST_FAILURE_TEXT" desc="The text displayed when a test fails." translateable="true">
+        Test failed
+      </message>
+      <message name="IDS_DIAGNOSTICS_TEST_SUCCESS_TEXT" desc="The text displayed when a test passes." translateable="true">
+        Test succeeded
+      </message>
+      <message name="IDS_DIAGNOSTICS_TEST_RUNNING_BADGE_TEXT" desc="The text displayed to indicate that a test is running." translateable="true">
+        RUNNING
+      </message>
+      <message name="IDS_DIAGNOSTICS_TEST_FAILURE_BADGE_TEXT" desc="The text displayed to indicate that a test failed." translateable="true">
+        FAILED
+      </message>
+      <message name="IDS_DIAGNOSTICS_TEST_SUCCESS_BADGE_TEXT" desc="The text displayed to indicate that a test passed." translateable="true">
+        SUCCESS
+      </message>
+      <message name="IDS_DIAGNOSTICS_TEST_RUNNING_TEXT" desc="The text displayed while a test is running." translateable="true">
+        Test running
+      </message>
+      <message name="IDS_DIAGNOSTICS_HIDE_REPORT_TEXT" desc="The text for the button that closes the test summary report." translateable="true">
+        Hide Report
+      </message>
+      <message name="IDS_DIAGNOSTICS_SEE_REPORT_TEXT" desc="The text for the button that shows the test summary report" translateable="true">
+        See Report
+      </message>
+      <message name="IDS_DIANOSTICS_ROUTINE_ENTRY_TEXT" desc="The text that shows the name of a test." translateable="true">
+        <ph name="TEST_NAME">$1<ex>Stress</ex></ph> Test
+      </message>
+      <message name="IDS_DIAGNOSTICS_CHARGE_RUN_TESTS_BUTTON_TEXT" desc="The text for the button used to run the battery charge test." translateable="true">
+        Run Charge test
+      </message>
+      <message name="IDS_DIAGNOSTICS_DISCHARGE_RUN_TESTS_BUTTON_TEXT" desc="The text for the button used to run the battery discharge test." translateable="true">
+        Run Discharge test
+      </message>
+      <message name="IDS_DIAGNOSTICS_CPU_RUN_TESTS_BUTTON_TEXT" desc="The text for the button used to run the CPU tests." translateable="true">
+        Run CPU test
+      </message>
+      <message name="IDS_DIAGNOSTICS_MEMORY_RUN_TESTS_BUTTON_TEXT" desc="The text for the button used to run the memory test." translateable="true">
+        Run Memory test
+      </message>
+      <message name="IDS_DIAGNOSTICS_RUN_AGAIN_BUTTON_TEXT" desc="The text for the button used to rerun a test." translateable="true">
+        Run again
+      </message>
+      <message name="IDS_DIAGNOSTICS_STOP_TEST_BUTTON_TEXT" desc="The text for the button used to stop a test." translateable="true">
+        Stop test
+      </message>
 
       <!-- Quick Answers -->
       <message name="IDS_QUICK_ANSWERS_DEFINITION_TITLE_TEXT" desc="The title text format string used for Quick Answers definition result card. The first placeholder contains the source query text and the second placeholder contains the phonetics.">
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_CHARGE_RUN_TESTS_BUTTON_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_CHARGE_RUN_TESTS_BUTTON_TEXT.png.sha1
new file mode 100644
index 0000000..70d5e3d
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_CHARGE_RUN_TESTS_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@
+48460b87e4f31104b05ed47bcd467b43dc203605
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_CPU_RUN_TESTS_BUTTON_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_CPU_RUN_TESTS_BUTTON_TEXT.png.sha1
new file mode 100644
index 0000000..323539c
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_CPU_RUN_TESTS_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@
+2272adacc5b8d94ebe466cedb6eacc161aa45086
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DISCHARGE_RUN_TESTS_BUTTON_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DISCHARGE_RUN_TESTS_BUTTON_TEXT.png.sha1
new file mode 100644
index 0000000..2870b088
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DISCHARGE_RUN_TESTS_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@
+c881f00f58577bf59aac45e0998934031b31c1be
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HIDE_REPORT_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HIDE_REPORT_TEXT.png.sha1
new file mode 100644
index 0000000..8e33f78
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HIDE_REPORT_TEXT.png.sha1
@@ -0,0 +1 @@
+29f7c4c9cd69276dea9875b9963de8f252d7f50b
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_MEMORY_RUN_TESTS_BUTTON_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_MEMORY_RUN_TESTS_BUTTON_TEXT.png.sha1
new file mode 100644
index 0000000..323539c
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_MEMORY_RUN_TESTS_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@
+2272adacc5b8d94ebe466cedb6eacc161aa45086
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_RUN_AGAIN_BUTTON_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_RUN_AGAIN_BUTTON_TEXT.png.sha1
new file mode 100644
index 0000000..2955cb1
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_RUN_AGAIN_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@
+68820f706ca59b90b200be0a0bb4cddcfb9ecf86
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_SEE_REPORT_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_SEE_REPORT_TEXT.png.sha1
new file mode 100644
index 0000000..d138fdf
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_SEE_REPORT_TEXT.png.sha1
@@ -0,0 +1 @@
+30b792e1ff8f17d862664cee9e14d8f728d0cca2
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_STOP_TEST_BUTTON_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_STOP_TEST_BUTTON_TEXT.png.sha1
new file mode 100644
index 0000000..e72b3a30
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_STOP_TEST_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@
+3f4504a25fc3b4b712570c0744416217d48c9a60
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_FAILURE_BADGE_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_FAILURE_BADGE_TEXT.png.sha1
new file mode 100644
index 0000000..8e33f78
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_FAILURE_BADGE_TEXT.png.sha1
@@ -0,0 +1 @@
+29f7c4c9cd69276dea9875b9963de8f252d7f50b
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_FAILURE_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_FAILURE_TEXT.png.sha1
new file mode 100644
index 0000000..9ac7590
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_FAILURE_TEXT.png.sha1
@@ -0,0 +1 @@
+a05eca9f186972d5185c7e6a9d52358df10fc81a
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_RUNNING_BADGE_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_RUNNING_BADGE_TEXT.png.sha1
new file mode 100644
index 0000000..15dfc62
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_RUNNING_BADGE_TEXT.png.sha1
@@ -0,0 +1 @@
+c9429a03c4c6ca3db130068cdf88ddd16bf3ce89
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_RUNNING_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_RUNNING_TEXT.png.sha1
new file mode 100644
index 0000000..15dfc62
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_RUNNING_TEXT.png.sha1
@@ -0,0 +1 @@
+c9429a03c4c6ca3db130068cdf88ddd16bf3ce89
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_SUCCESS_BADGE_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_SUCCESS_BADGE_TEXT.png.sha1
new file mode 100644
index 0000000..15dfc62
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_SUCCESS_BADGE_TEXT.png.sha1
@@ -0,0 +1 @@
+c9429a03c4c6ca3db130068cdf88ddd16bf3ce89
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_SUCCESS_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_SUCCESS_TEXT.png.sha1
new file mode 100644
index 0000000..5599011
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_SUCCESS_TEXT.png.sha1
@@ -0,0 +1 @@
+2344539e12cd23784212566dca050ee51b5e5be7
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_ROUTINE_ENTRY_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_ROUTINE_ENTRY_TEXT.png.sha1
new file mode 100644
index 0000000..8e33f78
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_ROUTINE_ENTRY_TEXT.png.sha1
@@ -0,0 +1 @@
+29f7c4c9cd69276dea9875b9963de8f252d7f50b
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_CANCELING_SCANNING_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_CANCELING_SCANNING_TEXT.png.sha1
new file mode 100644
index 0000000..3a191639
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_CANCELING_SCANNING_TEXT.png.sha1
@@ -0,0 +1 @@
+209056995bbc15942d75ea539ef44749d1d14cd1
\ No newline at end of file
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_ar.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_ar.xtb
index f68618e..93c0f1dc 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_ar.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_ar.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">هل تريد فعلاً إزالة <ph name="FILE" />؟</translation>
 <translation id="3750315947605636967">يتم حاليًا استخدام الكاميرا من قِبَل تطبيق آخر.</translation>
 <translation id="3810838688059735925">الفيديوهات</translation>
+<translation id="3838931309141338733">مسح الرمز الشريطي ضوئيًا</translation>
 <translation id="4000398125663085899">سيتم الآن حفظ الصور والفيديوهات الجديدة في مجلد في تطبيق "الملفات": ملفاتي &gt; الكاميرا.</translation>
 <translation id="4118525110028899586">إيقاف التسجيل مؤقتًا</translation>
 <translation id="4279490309300973883">النسخ المطابق</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_be.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_be.xtb
index a24ce2b7..8af6009 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_be.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_be.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Сапраўды выдаліць файл "<ph name="FILE" />"?</translation>
 <translation id="3750315947605636967">Камера выкарыстоўваецца іншай праграмай</translation>
 <translation id="3810838688059735925">Відэа</translation>
+<translation id="3838931309141338733">Сканіраваць штрыхкод</translation>
 <translation id="4000398125663085899">Новыя фота і відэа цяпер будуць захоўвацца ў папцы ў праграме "Файлы": "Мае файлы &gt; Камера"</translation>
 <translation id="4118525110028899586">Прыпыніць запіс</translation>
 <translation id="4279490309300973883">Адлюстраванне</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_fi.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_fi.xtb
index b797ac8..8fff74b5 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_fi.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_fi.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Haluatko varmasti, että <ph name="FILE" /> poistetaan?</translation>
 <translation id="3750315947605636967">Toinen sovellus käyttää kameraasi</translation>
 <translation id="3810838688059735925">Video</translation>
+<translation id="3838931309141338733">Skannaa viivakoodi</translation>
 <translation id="4000398125663085899">Uudet kuvat ja videot tallennetaan nyt kansioon Tiedostot-sovelluksessa: Omat tiedostot &gt; Kamera</translation>
 <translation id="4118525110028899586">Keskeytä tallennus</translation>
 <translation id="4279490309300973883">Peilaus päällä</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_fr-CA.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_fr-CA.xtb
index d507b30..e202395d2 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_fr-CA.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_fr-CA.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Voulez-vous vraiment supprimer <ph name="FILE" />?</translation>
 <translation id="3750315947605636967">Une autre application utilise votre caméra</translation>
 <translation id="3810838688059735925">Vidéo</translation>
+<translation id="3838931309141338733">Numériser le code-barres</translation>
 <translation id="4000398125663085899">Les nouvelles photos et vidéos seront maintenant enregistrées dans un dossier de l'application Fichiers : Mes fichiers &gt; Caméra</translation>
 <translation id="4118525110028899586">Interrompre l'enregistrement</translation>
 <translation id="4279490309300973883">Mise en miroir</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_gl.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_gl.xtb
index 4dd0397b..caa67f90 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_gl.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_gl.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Seguro que queres eliminar <ph name="FILE" />?</translation>
 <translation id="3750315947605636967">Outra aplicación está usando a cámara</translation>
 <translation id="3810838688059735925">Vídeo</translation>
+<translation id="3838931309141338733">Escanear código de barras</translation>
 <translation id="4000398125663085899">Agora as fotos e os vídeos novos gardaranse nun cartafol da aplicación Ficheiros: Os meus ficheiros &gt; Cámara</translation>
 <translation id="4118525110028899586">Pór gravación en pausa</translation>
 <translation id="4279490309300973883">Proxección</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_hu.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_hu.xtb
index 059cf8d..00c5689 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_hu.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_hu.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Biztosan eltávolítja a következő fájlt: <ph name="FILE" />?</translation>
 <translation id="3750315947605636967">A kamerát egy másik alkalmazás használja</translation>
 <translation id="3810838688059735925">Videó</translation>
+<translation id="3838931309141338733">Vonalkód beolvasása</translation>
 <translation id="4000398125663085899">Az új fotók és videók mostantól a Fájlok alkalmazás egyik mappájába lesznek mentve: Saját fájlok &gt; Kamera</translation>
 <translation id="4118525110028899586">Felvétel szüneteltetése</translation>
 <translation id="4279490309300973883">Tükrözés</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_kn.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_kn.xtb
index 88e23b3..b99d2be 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_kn.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_kn.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">ನೀವು ನಿಜವಾಗಿಯೂ <ph name="FILE" /> ತೆಗೆದುಹಾಕಲು ಬಯಸುವಿರಾ?</translation>
 <translation id="3750315947605636967">ಬೇರೊಂದು ಆ್ಯಪ್ ನಿಮ್ಮ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುತ್ತಿದೆ</translation>
 <translation id="3810838688059735925">ವೀಡಿಯೊ</translation>
+<translation id="3838931309141338733">ಬಾರ್‌ಕೋಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ</translation>
 <translation id="4000398125663085899">ಹೊಸ ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಈಗ Files ಆ್ಯಪ್‌ನಲ್ಲಿರುವ ಫೋಲ್ಡರ್‌ಗೆ ಉಳಿಸಲಾಗುತ್ತದೆ: ನನ್ನ ಫೈಲ್‌ಗಳು &gt; ಕ್ಯಾಮರಾ</translation>
 <translation id="4118525110028899586">ರೆಕಾರ್ಡಿಂಗ್ ವಿರಾಮಗೊಳಿಸಿ</translation>
 <translation id="4279490309300973883">ಪ್ರತಿಬಿಂಬಿಸುವಿಕೆ</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_ko.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_ko.xtb
index 6ebc7e07..fcb5e8e2 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_ko.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_ko.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032"><ph name="FILE" /> 파일을 삭제하시겠습니까?</translation>
 <translation id="3750315947605636967">다른 앱에서 카메라를 사용 중입니다.</translation>
 <translation id="3810838688059735925">동영상</translation>
+<translation id="3838931309141338733">바코드 스캔</translation>
 <translation id="4000398125663085899">이제 새로운 사진과 동영상이 Files 앱의 내 파일 &gt; 카메라 폴더에 저장됩니다.</translation>
 <translation id="4118525110028899586">녹화 일시중지</translation>
 <translation id="4279490309300973883">미러링</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_pa.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_pa.xtb
index 767750a..5e67df50 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_pa.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_pa.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">ਕੀ ਤੁਸੀਂ ਪੱਕਾ <ph name="FILE" /> ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?</translation>
 <translation id="3750315947605636967">ਤੁਹਾਡਾ ਕੈਮਰਾ ਕਿਸੇ ਹੋਰ ਐਪ ਵੱਲੋਂ ਵਰਤਿਆ ਜਾ ਰਿਹਾ ਹੈ</translation>
 <translation id="3810838688059735925">ਵੀਡਿਓ</translation>
+<translation id="3838931309141338733">ਬਾਰਕੋਡ ਸਕੈਨ ਕਰੋ</translation>
 <translation id="4000398125663085899">ਨਵੀਆਂ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਨੂੰ ਹੁਣ Files ਐਪ ਵਿੱਚ ਕਿਸੇ ਫੋਲਡਰ: ਮੇਰੀਆਂ ਫ਼ਾਈਲਾਂ &gt; ਕੈਮਰੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਵੇਗਾ</translation>
 <translation id="4118525110028899586">ਰਿਕਾਰਡਿੰਗ ਰੋਕੋ</translation>
 <translation id="4279490309300973883">ਪ੍ਰਤਿਬਿੰਬੀਕਰਨ</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_sk.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_sk.xtb
index 676fc27..425f02e 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_sk.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_sk.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Naozaj chcete odstrániť <ph name="FILE" />?</translation>
 <translation id="3750315947605636967">Fotoaparát používa iná aplikácia</translation>
 <translation id="3810838688059735925">Video</translation>
+<translation id="3838931309141338733">Skenovať čiarový kód</translation>
 <translation id="4000398125663085899">Nové fotky a videá sa budú odteraz ukladať do priečinka v aplikácii Súbory: Moje súbory &gt; Kamera</translation>
 <translation id="4118525110028899586">Pozastaviť nahrávanie</translation>
 <translation id="4279490309300973883">Zrkadlenie</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_sq.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_sq.xtb
index 6d4fc617..27c0372 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_sq.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_sq.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Vërtet dëshiron të heqësh <ph name="FILE" />?</translation>
 <translation id="3750315947605636967">Kamera jote po përdoret nga një aplikacion tjetër</translation>
 <translation id="3810838688059735925">Video</translation>
+<translation id="3838931309141338733">Skano bardkodin</translation>
 <translation id="4000398125663085899">Fotografitë dhe videot e reja tani do të ruhen në një dosje në aplikacionin "Skedarët": Skedarët e mi &gt; Kamera</translation>
 <translation id="4118525110028899586">Vendose në pauzë regjistrimin</translation>
 <translation id="4279490309300973883">Pasqyrim</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_sv.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_sv.xtb
index 24b83bb..edbe5e17 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_sv.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_sv.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Vill du ta bort <ph name="FILE" />?</translation>
 <translation id="3750315947605636967">Kameran används av en annan app</translation>
 <translation id="3810838688059735925">Video</translation>
+<translation id="3838931309141338733">Läs av streckkod</translation>
 <translation id="4000398125663085899">Nu sparas foton och videor i en ny mapp i appen Filer under Mina filer &gt; Kamera</translation>
 <translation id="4118525110028899586">Pausa inspelning</translation>
 <translation id="4279490309300973883">Spegling</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_sw.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_sw.xtb
index 14ec91a0..8231df4b 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_sw.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_sw.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">Una uhakika ungependa kuondoa <ph name="FILE" />?</translation>
 <translation id="3750315947605636967">Kamera yako inatumiwa na programu nyingine</translation>
 <translation id="3810838688059735925">Video</translation>
+<translation id="3838931309141338733">Changanua msimbo wa mistari</translation>
 <translation id="4000398125663085899">Picha na video mpya sasa zitahifadhiwa kwenye folda katika programu ya Faili: Faili zangu &gt; Kamera</translation>
 <translation id="4118525110028899586">Sitisha kurekodi</translation>
 <translation id="4279490309300973883">Kuakisi</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_tr.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_tr.xtb
index e89929e..5684924 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_tr.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_tr.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032"><ph name="FILE" /> dosyasını kaldırmak istediğinizden emin misiniz?</translation>
 <translation id="3750315947605636967">Kameranız başka bir uygulama tarafından kullanılıyor</translation>
 <translation id="3810838688059735925">Video</translation>
+<translation id="3838931309141338733">Barkodu tara</translation>
 <translation id="4000398125663085899">Artık yeni fotoğraflar ve videolar, Dosyalar uygulamasında bir klasöre kaydedilecek: Dosyalarım &gt; Kamera</translation>
 <translation id="4118525110028899586">Kaydı duraklat</translation>
 <translation id="4279490309300973883">Yansıtılıyor</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_ur.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_ur.xtb
index 1a6bc802..dc2fb42 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_ur.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_ur.xtb
@@ -32,6 +32,7 @@
 <translation id="3569311554794739032">کیا آپ واقعی <ph name="FILE" /> کو ہٹانا چاہتے ہیں؟</translation>
 <translation id="3750315947605636967">کوئی دوسری ایپ آپ کا کیمرا استعمال کر رہی ہے</translation>
 <translation id="3810838688059735925">ویڈیو</translation>
+<translation id="3838931309141338733">بارکوڈ اسکین کریں</translation>
 <translation id="4000398125663085899">نئی تصاویر اور ویڈیوز کو فائلز ایپ میں ایک فولڈر میں محفوظ کیا جائے گا: میری فائلیں &gt; کیمرا۔</translation>
 <translation id="4118525110028899586">ریکارڈنگ موقوف کریں</translation>
 <translation id="4279490309300973883">مررنگ</translation>
diff --git a/chromeos/components/diagnostics_ui/diagnostics_ui.cc b/chromeos/components/diagnostics_ui/diagnostics_ui.cc
index 9df2233..0397af8 100644
--- a/chromeos/components/diagnostics_ui/diagnostics_ui.cc
+++ b/chromeos/components/diagnostics_ui/diagnostics_ui.cc
@@ -70,6 +70,7 @@
       {"deviceInfo", IDS_DIAGNOSTICS_DEVICE_INFO_TEXT},
       {"diagnosticsTitle", IDS_DIAGNOSTICS_TITLE},
       {"dischargeTestResultText", IDS_DISCHARGE_TEST_RESULT},
+      {"hideReportText", IDS_DIAGNOSTICS_HIDE_REPORT_TEXT},
       {"learnMore", IDS_DIANOSTICS_LEARN_MORE_LABEL},
       {"memoryAvailable", IDS_DIAGNOSTICS_MEMORY_AVAILABLE_LABEL},
       {"memoryRoutineText", IDS_DIAGNOSTICS_MEMORY_ROUTINE_TEXT},
@@ -77,8 +78,24 @@
       {"percentageLabel", IDS_DIAGNOSTICS_PERCENTAGE_LABEL},
       {"powerTime", IDS_DIAGNOSTICS_POWER_TIME_LABEL},
       {"remainingCharge", IDS_DIAGNOSTICS_REMAINING_CHARGE_LABEL},
+      {"routineEntryText", IDS_DIANOSTICS_ROUTINE_ENTRY_TEXT},
       {"routineNameText", IDS_DIANOSTICS_ROUTINE_NAME_TEXT},
+      {"runAgainButtonText", IDS_DIAGNOSTICS_RUN_AGAIN_BUTTON_TEXT},
+      {"runBatteryChargeTestText",
+       IDS_DIAGNOSTICS_CHARGE_RUN_TESTS_BUTTON_TEXT},
+      {"runBatteryDischargeTestText",
+       IDS_DIAGNOSTICS_DISCHARGE_RUN_TESTS_BUTTON_TEXT},
+      {"runCpuTestText", IDS_DIAGNOSTICS_CPU_RUN_TESTS_BUTTON_TEXT},
+      {"runMemoryTestText", IDS_DIAGNOSTICS_MEMORY_RUN_TESTS_BUTTON_TEXT},
+      {"seeReportText", IDS_DIAGNOSTICS_HIDE_REPORT_TEXT},
       {"sessionLog", IDS_DIAGNOSTICS_SESSION_LOG_LABEL},
+      {"stopTestButtonText", IDS_DIAGNOSTICS_STOP_TEST_BUTTON_TEXT},
+      {"testFailure", IDS_DIAGNOSTICS_TEST_FAILURE_TEXT},
+      {"testFailedBadgeText", IDS_DIAGNOSTICS_TEST_FAILURE_BADGE_TEXT},
+      {"testRunning", IDS_DIAGNOSTICS_TEST_RUNNING_TEXT},
+      {"testRunningBadgeText", IDS_DIAGNOSTICS_TEST_RUNNING_BADGE_TEXT},
+      {"testSuccess", IDS_DIAGNOSTICS_TEST_SUCCESS_TEXT},
+      {"testSucceededBadgeText", IDS_DIAGNOSTICS_TEST_SUCCESS_BADGE_TEXT},
       {"totalMemory", IDS_DIAGNOSTICS_TOTAL_MEMORY_LABEL},
       {"usedMemory", IDS_DIAGNOSTICS_USED_MEMORY_LABEL},
   };
diff --git a/chromeos/components/diagnostics_ui/resources/battery_status_card.html b/chromeos/components/diagnostics_ui/resources/battery_status_card.html
index 2dfc092a..13578ab 100644
--- a/chromeos/components/diagnostics_ui/resources/battery_status_card.html
+++ b/chromeos/components/diagnostics_ui/resources/battery_status_card.html
@@ -28,6 +28,9 @@
   </data-point>
 
   <routine-section slot="routines" routines="[[routines_]]"
-    is-test-running="{{isTestRunning}}">
+    is-test-running="{{isTestRunning}}"
+    run-tests-button-text="[[getRunTestsButtonText_(
+      batteryChargeStatus_.powerAdapterStatus
+    )]]">
   </routine-section>
 </diagnostics-card>
diff --git a/chromeos/components/diagnostics_ui/resources/battery_status_card.js b/chromeos/components/diagnostics_ui/resources/battery_status_card.js
index 7d3598d..70c7950 100644
--- a/chromeos/components/diagnostics_ui/resources/battery_status_card.js
+++ b/chromeos/components/diagnostics_ui/resources/battery_status_card.js
@@ -191,4 +191,13 @@
     return loadTimeData.getStringF(
         'currentNowText', this.batteryChargeStatus_.currentNowMilliamps);
   },
+
+  /** @protected */
+  getRunTestsButtonText_() {
+    return loadTimeData.getString(
+        this.batteryChargeStatus_.powerAdapterStatus ===
+                chromeos.diagnostics.mojom.ExternalPowerSource.kDisconnected ?
+            'runBatteryDischargeTestText' :
+            'runBatteryChargeTestText')
+  }
 });
diff --git a/chromeos/components/diagnostics_ui/resources/cpu_card.html b/chromeos/components/diagnostics_ui/resources/cpu_card.html
index cf12f48..48aad3c 100644
--- a/chromeos/components/diagnostics_ui/resources/cpu_card.html
+++ b/chromeos/components/diagnostics_ui/resources/cpu_card.html
@@ -26,6 +26,7 @@
     value="">
 </data-point>
   <routine-section slot="routines" routines="[[routines_]]"
-    is-test-running="{{isTestRunning}}">
+    is-test-running="{{isTestRunning}}"
+    run-tests-button-text="[[i18n('runCpuTestText')]]">
   </routine-section>
 </diagnostics-card>
diff --git a/chromeos/components/diagnostics_ui/resources/memory_card.html b/chromeos/components/diagnostics_ui/resources/memory_card.html
index 5924eff..7e5cb38 100644
--- a/chromeos/components/diagnostics_ui/resources/memory_card.html
+++ b/chromeos/components/diagnostics_ui/resources/memory_card.html
@@ -9,6 +9,7 @@
     max="[[memoryUsage_.totalMemoryKib]]">
   </percent-bar-chart>
   <routine-section slot="routines" routines="[[routines_]]"
-    is-test-running="{{isTestRunning}}">
+    is-test-running="{{isTestRunning}}"
+    run-tests-button-text="[[i18n('runMemoryTestText')]]">
   </routine-section>
 </diagnostics-card>
diff --git a/chromeos/components/diagnostics_ui/resources/routine_result_entry.html b/chromeos/components/diagnostics_ui/resources/routine_result_entry.html
index 2d248649..87c91fd 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_result_entry.html
+++ b/chromeos/components/diagnostics_ui/resources/routine_result_entry.html
@@ -7,7 +7,6 @@
 </style>
 
 <div class="entryRow">
-  <!-- TODO(zentaro): Create mapping to localized strings. -->
   <div id="routine">[[routineType_]]</div>
   <text-badge id="status" badge-type="[[getBadgeType_(item.progress, item.result)]]"
   		value="[[getBadgeText_(item.progress, item.result)]]"
diff --git a/chromeos/components/diagnostics_ui/resources/routine_result_entry.js b/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
index dcc5afc..9780de7f 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
+++ b/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
@@ -70,7 +70,7 @@
    * @return {string}
    */
   getRunningRoutineString_(routine) {
-    return loadTimeData.getStringF('routineNameText', getRoutineType(routine));
+    return loadTimeData.getStringF('routineEntryText', getRoutineType(routine));
   },
 
   /**
@@ -98,25 +98,23 @@
    * @protected
    */
   getBadgeText_() {
-    // TODO(joonbug): Localize this string.
     if (this.item.progress === ExecutionProgress.kRunning) {
-      return 'RUNNING';
+      return loadTimeData.getString('testRunningBadgeText');
     }
 
     if (this.item.result &&
         this.getSimpleResult_(this.item.result) ===
             chromeos.diagnostics.mojom.StandardRoutineResult.kTestPassed) {
-      return 'SUCCESS';
+      return loadTimeData.getString('testSucceededBadgeText');
     }
 
-    return 'FAILED';
+    return loadTimeData.getString('testFailedBadgeText');
   },
 
   /**
    * @protected
    */
   getBadgeType_() {
-    // TODO(joonbug): Localize this string.
     if (this.item.progress === ExecutionProgress.kRunning) {
       return BadgeType.DEFAULT;
     }
diff --git a/chromeos/components/diagnostics_ui/resources/routine_section.html b/chromeos/components/diagnostics_ui/resources/routine_section.html
index 3e429c1..350a8604 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_section.html
+++ b/chromeos/components/diagnostics_ui/resources/routine_section.html
@@ -10,8 +10,7 @@
 <div id="routineSection">
   <cr-button id="runTestsButton" class="action-button" on-click="onRunTestsClicked_"
       disabled="[[isTestRunning]]">
-    <!-- TODO(zentaro): Localize this string. -->
-    Run Tests
+    [[runTestsButtonText]]
   </cr-button>
   <cr-button id="toggleReportButton" class="action-button" on-click="onToggleReportClicked_"
       hidden="[[isResultAndStatusHidden_(executionStatus_)]]">
diff --git a/chromeos/components/diagnostics_ui/resources/routine_section.js b/chromeos/components/diagnostics_ui/resources/routine_section.js
index 2af7677b..83d6498e 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_section.js
+++ b/chromeos/components/diagnostics_ui/resources/routine_section.js
@@ -84,6 +84,12 @@
       type: Boolean,
       value: true,
     },
+
+    /** @type {string} */
+    runTestsButtonText: {
+      type: String,
+      value: '',
+    },
   },
 
   /** @private */
@@ -160,8 +166,8 @@
 
   /** @protected */
   getReportToggleButtonText_() {
-    // TODO(joonbug): Localize this string.
-    return this.isReportListHidden_ ? 'See Report' : 'Hide Report';
+    return loadTimeData.getString(
+        this.isReportListHidden_ ? 'seeReportText' : 'hideReportText');
   },
 
   /** @protected */
@@ -177,11 +183,12 @@
 
   /** @protected */
   getBadgeText_() {
-    // TODO(joonbug): Localize this string.
     if (this.executionStatus_ === ExecutionProgress.kRunning) {
-      return 'Test running';
+      return loadTimeData.getString('testRunning');
     }
-    return this.hasTestFailure_ ? 'FAILED' : 'SUCCESS';
+    return loadTimeData.getString(
+        this.hasTestFailure_ ? 'testFailedBadgeText' :
+                               'testSucceededBadgeText');
   },
 
   /** @protected */
@@ -189,7 +196,8 @@
     if (this.executionStatus_ === ExecutionProgress.kRunning) {
       return this.currentTestName_;
     }
-    return this.hasTestFailure_ ? 'Test failed' : 'Test succeeded';
+    return loadTimeData.getString(
+        this.hasTestFailure_ ? 'testFailure' : 'testSuccess');
   },
 
   /** @override */
diff --git a/chromeos/components/scanning/resources/scan_preview.html b/chromeos/components/scanning/resources/scan_preview.html
index 57ef859e..96a652e 100644
--- a/chromeos/components/scanning/resources/scan_preview.html
+++ b/chromeos/components/scanning/resources/scan_preview.html
@@ -18,12 +18,14 @@
     height: calc(1.2941 * var(--left-panel-width));
   }
 
-  #progressText {
+  #progressText,
+  #cancelingText {
     @apply --scanning-progress-text-font;
     color: var(--scanning-progress-text-color);
   }
 
-  #scanProgress {
+  #scanProgress,
+  #cancelingProgress {
     margin: auto;
     text-align: center;
     width: 60%;
@@ -57,13 +59,21 @@
   }
 
   paper-progress {
-    --paper-progress-active-color: var(--google-blue-600);
-    --paper-progress-container-color: var(--google-blue-200);
     border-radius: 4px;
     height: 4px;
     margin-top: 12px;
     width: 256px;
   }
+
+  #scanProgressBar {
+    --paper-progress-active-color: var(--google-blue-600);
+    --paper-progress-container-color: var(--google-blue-200);
+  }
+
+  #cancelingProgressBar {
+    --paper-progress-active-color: var(--google-grey-refresh-500);
+    --paper-progress-container-color: var(--google-grey-200);
+  }
 </style>
 <div class="preview">
   <div id="helpOrProgress" class="preview-item"
@@ -73,7 +83,12 @@
     </div>
     <div id="scanProgress" hidden$="[[!showScanProgress_]]">
       <span id="progressText">[[getProgressTextString_(pageNumber)]]</span>
-      <paper-progress value="[[progressPercent]]"></paper-progress>
+      <paper-progress id="scanProgressBar" value="[[progressPercent]]">
+      </paper-progress>
+    </div>
+    <div id="cancelingProgress" hidden$="[[!showCancelingProgress_]]">
+      <span id="cancelingText">[[i18n('cancelingScanningText')]]</span>
+      <paper-progress id="cancelingProgressBar" indeterminate></paper-progress>
     </div>
   </div>
   <div id="scannedImages" hidden$="[[!showScannedImages_]]">
diff --git a/chromeos/components/scanning/resources/scan_preview.js b/chromeos/components/scanning/resources/scan_preview.js
index 7bf0ef9b..5b500149 100644
--- a/chromeos/components/scanning/resources/scan_preview.js
+++ b/chromeos/components/scanning/resources/scan_preview.js
@@ -59,6 +59,12 @@
       type: Boolean,
       value: false,
     },
+
+    /** @private {boolean} */
+    showCancelingProgress_: {
+      type: Boolean,
+      value: false,
+    },
   },
 
   /**
@@ -84,8 +90,10 @@
   onAppStateChange_() {
     this.showScannedImages_ =
         this.appState === AppState.DONE && this.objectUrls.length > 0;
+    this.showScanProgress_ =
+        this.appState === AppState.SCANNING || this.appState === AppState.DONE;
+    this.showCancelingProgress_ = this.appState === AppState.CANCELING;
     this.showHelperText_ =
-        this.appState !== AppState.SCANNING && this.appState !== AppState.DONE;
-    this.showScanProgress_ = !this.showHelperText_;
+        !this.showScanProgress_ && !this.showCancelingProgress_;
   },
 });
diff --git a/chromeos/components/scanning/resources/scanning_app.html b/chromeos/components/scanning/resources/scanning_app.html
index 56792bbf..cacda44 100644
--- a/chromeos/components/scanning/resources/scanning_app.html
+++ b/chromeos/components/scanning/resources/scanning_app.html
@@ -164,7 +164,8 @@
             [[i18n('scanButtonText')]]
           </cr-button>
           <cr-button id="cancelButton" on-click="onCancelClick_"
-              hidden$="[[!showCancelButton_]]">
+              hidden$="[[!showCancelButton_]]"
+              disabled$="[[cancelButtonDisabled_]]">
             [[i18n('cancelButtonText')]]
           </cr-button>
         </div>
diff --git a/chromeos/components/scanning/resources/scanning_app.js b/chromeos/components/scanning/resources/scanning_app.js
index 19df781..360459f 100644
--- a/chromeos/components/scanning/resources/scanning_app.js
+++ b/chromeos/components/scanning/resources/scanning_app.js
@@ -174,6 +174,12 @@
       value: false,
     },
 
+    /** @private {boolean} */
+    cancelButtonDisabled_: {
+      type: Boolean,
+      value: false,
+    },
+
     /**
      * The file path of the last scanned page of a successful scan job. Used to
      * open the Files app with the correct file highlighted.
@@ -240,7 +246,9 @@
    * @param {number} progressPercent
    */
   onPageProgress(pageNumber, progressPercent) {
-    assert(this.appState_ === AppState.SCANNING);
+    assert(
+        this.appState_ === AppState.SCANNING ||
+        this.appState_ === AppState.CANCELING);
     this.pageNumber_ = pageNumber;
     this.progressPercent_ = progressPercent;
   },
@@ -250,7 +258,9 @@
    * @param {!Array<number>} pageData
    */
   onPageComplete(pageData) {
-    assert(this.appState_ === AppState.SCANNING);
+    assert(
+        this.appState_ === AppState.SCANNING ||
+        this.appState_ === AppState.CANCELING);
     const blob = new Blob([Uint8Array.from(pageData)], {'type': 'image/png'});
     this.push('objectUrls_', URL.createObjectURL(blob));
   },
@@ -278,6 +288,7 @@
   onCancelComplete(success) {
     // If the cancel request fails, continue showing the scan progress page.
     if (!success) {
+      this.setAppState_(AppState.SCANNING);
       this.showToast_('cancelFailedToastText');
       return;
     }
@@ -444,6 +455,7 @@
   /** @private */
   onCancelClick_() {
     assert(this.appState_ === AppState.SCANNING);
+    this.setAppState_(AppState.CANCELING);
     this.scanService_.cancelScan();
   },
 
@@ -480,13 +492,21 @@
         assert(
             this.appState_ === AppState.GETTING_CAPS ||
             this.appState_ === AppState.SCANNING ||
-            this.appState_ === AppState.DONE);
+            this.appState_ === AppState.DONE ||
+            this.appState_ === AppState.CANCELING);
         this.clearObjectUrls_();
         break;
       case (AppState.SCANNING):
-        assert(this.appState_ === AppState.READY);
+        assert(
+            this.appState_ === AppState.READY ||
+            this.appState_ === AppState.CANCELING);
         break;
       case (AppState.DONE):
+        assert(
+            this.appState_ === AppState.SCANNING ||
+            this.appState_ === AppState.CANCELING);
+        break;
+      case (AppState.CANCELING):
         assert(this.appState_ === AppState.SCANNING);
         break;
     }
@@ -498,7 +518,9 @@
   onAppStateChange_() {
     this.scannersLoaded_ = this.appState_ !== AppState.GETTING_SCANNERS;
     this.settingsDisabled_ = this.appState_ !== AppState.READY;
-    this.showCancelButton_ = this.appState_ === AppState.SCANNING;
+    this.showCancelButton_ = this.appState_ === AppState.SCANNING ||
+        this.appState_ === AppState.CANCELING;
+    this.cancelButtonDisabled_ = this.appState_ === AppState.CANCELING;
     this.showDoneSection_ = this.appState_ === AppState.DONE;
   },
 
diff --git a/chromeos/components/scanning/resources/scanning_app_types.js b/chromeos/components/scanning/resources/scanning_app_types.js
index 1dded9f..985a6b71 100644
--- a/chromeos/components/scanning/resources/scanning_app_types.js
+++ b/chromeos/components/scanning/resources/scanning_app_types.js
@@ -13,6 +13,7 @@
   READY: 3,
   SCANNING: 4,
   DONE: 5,
+  CANCELING: 6,
 };
 
 /**
diff --git a/chromeos/components/scanning/resources/scanning_shared_css.html b/chromeos/components/scanning/resources/scanning_shared_css.html
index cf1588c5..31ff00ee 100644
--- a/chromeos/components/scanning/resources/scanning_shared_css.html
+++ b/chromeos/components/scanning/resources/scanning_shared_css.html
@@ -10,6 +10,11 @@
       background-color: var(--cros-bg-color);
     }
 
+    select {
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+
     /* TODO(michaelcheco): Update once responsiveness spec is finalized. */
     @media (min-width:600px) and (max-width: 767px) {
       :host {
diff --git a/chromeos/components/scanning/scanning_ui.cc b/chromeos/components/scanning/scanning_ui.cc
index 4f111bd6..194836a 100644
--- a/chromeos/components/scanning/scanning_ui.cc
+++ b/chromeos/components/scanning/scanning_ui.cc
@@ -57,6 +57,7 @@
       {"blackAndWhiteOptionText", IDS_SCANNING_APP_BLACK_AND_WHITE_OPTION_TEXT},
       {"cancelButtonText", IDS_SCANNING_APP_CANCEL_BUTTON_TEXT},
       {"cancelFailedToastText", IDS_SCANNING_APP_CANCEL_FAILED_TOAST_TEXT},
+      {"cancelingScanningText", IDS_SCANNING_APP_CANCELING_SCANNING_TEXT},
       {"colorModeDropdownLabel", IDS_SCANNING_APP_COLOR_MODE_DROPDOWN_LABEL},
       {"colorOptionText", IDS_SCANNING_APP_COLOR_OPTION_TEXT},
       {"defaultSourceOptionText", IDS_SCANNING_APP_DEFAULT_SOURCE_OPTION_TEXT},
diff --git a/chromeos/components/tether/active_host.cc b/chromeos/components/tether/active_host.cc
index 5343b02..91f25e2 100644
--- a/chromeos/components/tether/active_host.cc
+++ b/chromeos/components/tether/active_host.cc
@@ -118,13 +118,13 @@
                 tether_network_guid, wifi_network_guid);
 }
 
-void ActiveHost::GetActiveHost(const ActiveHostCallback& active_host_callback) {
+void ActiveHost::GetActiveHost(ActiveHostCallback active_host_callback) {
   ActiveHostStatus status = GetActiveHostStatus();
 
   if (status == ActiveHostStatus::DISCONNECTED) {
-    active_host_callback.Run(status, base::nullopt /* active_host */,
-                             "" /* tether_network_guid */,
-                             "" /* wifi_network_guid */);
+    std::move(active_host_callback)
+        .Run(status, base::nullopt /* active_host */,
+             "" /* tether_network_guid */, "" /* wifi_network_guid */);
     return;
   }
 
@@ -132,9 +132,9 @@
   DCHECK(!active_host_device_id.empty());
 
   tether_host_fetcher_->FetchTetherHost(
-      active_host_device_id,
-      base::Bind(&ActiveHost::OnTetherHostFetched,
-                 weak_ptr_factory_.GetWeakPtr(), active_host_callback));
+      active_host_device_id, base::BindOnce(&ActiveHost::OnTetherHostFetched,
+                                            weak_ptr_factory_.GetWeakPtr(),
+                                            std::move(active_host_callback)));
 }
 
 ActiveHost::ActiveHostStatus ActiveHost::GetActiveHostStatus() const {
@@ -188,14 +188,14 @@
   pref_service_->Set(prefs::kWifiNetworkGuid, base::Value(wifi_network_guid));
 
   // Now, send an active host changed update.
-  GetActiveHost(base::Bind(&ActiveHost::SendActiveHostChangedUpdate,
-                           weak_ptr_factory_.GetWeakPtr(), old_status,
-                           old_device_id, old_tether_network_guid,
-                           old_wifi_network_guid));
+  GetActiveHost(base::BindOnce(&ActiveHost::SendActiveHostChangedUpdate,
+                               weak_ptr_factory_.GetWeakPtr(), old_status,
+                               old_device_id, old_tether_network_guid,
+                               old_wifi_network_guid));
 }
 
 void ActiveHost::OnTetherHostFetched(
-    const ActiveHostCallback& active_host_callback,
+    ActiveHostCallback active_host_callback,
     base::Optional<multidevice::RemoteDeviceRef> active_host) {
   if (GetActiveHostDeviceId().empty() || !active_host) {
     DCHECK(GetActiveHostStatus() == ActiveHostStatus::DISCONNECTED);
@@ -204,33 +204,35 @@
 
     // If the active host became disconnected while the tether host was being
     // fetched, forward this information to the callback.
-    active_host_callback.Run(
-        ActiveHostStatus::DISCONNECTED, base::nullopt /* active_host */,
-        "" /* wifi_network_guid */, "" /* tether_network_guid */);
+    std::move(active_host_callback)
+        .Run(ActiveHostStatus::DISCONNECTED, base::nullopt /* active_host */,
+             "" /* wifi_network_guid */, "" /* tether_network_guid */);
     return;
   }
 
   if (GetActiveHostDeviceId() != active_host->GetDeviceId()) {
     // If the active host has changed while the tether host was being fetched,
     // perform the fetch again.
-    GetActiveHost(active_host_callback);
+    GetActiveHost(std::move(active_host_callback));
     return;
   }
 
   if (GetActiveHostStatus() == ActiveHostStatus::CONNECTING) {
     DCHECK(!GetTetherNetworkGuid().empty());
     DCHECK(GetWifiNetworkGuid().empty());
-    active_host_callback.Run(ActiveHostStatus::CONNECTING, active_host,
-                             GetTetherNetworkGuid() /* tether_network_guid */,
-                             "" /* wifi_network_guid */);
+    std::move(active_host_callback)
+        .Run(ActiveHostStatus::CONNECTING, active_host,
+             GetTetherNetworkGuid() /* tether_network_guid */,
+             "" /* wifi_network_guid */);
     return;
   }
 
   DCHECK(GetActiveHostStatus() == ActiveHostStatus::CONNECTED);
   DCHECK(!GetTetherNetworkGuid().empty());
   DCHECK(!GetWifiNetworkGuid().empty());
-  active_host_callback.Run(ActiveHostStatus::CONNECTED, active_host,
-                           GetTetherNetworkGuid(), GetWifiNetworkGuid());
+  std::move(active_host_callback)
+      .Run(ActiveHostStatus::CONNECTED, active_host, GetTetherNetworkGuid(),
+           GetWifiNetworkGuid());
 }
 
 void ActiveHost::SendActiveHostChangedUpdate(
diff --git a/chromeos/components/tether/active_host.h b/chromeos/components/tether/active_host.h
index 361544c8..a1a20f8 100644
--- a/chromeos/components/tether/active_host.h
+++ b/chromeos/components/tether/active_host.h
@@ -111,12 +111,12 @@
   //                   parameters will be "".
   //     CONNECTING: The callback's |wifi_network_guid| parameter will be "".
   //     CONNECTED: All four parameters  will be present.
-  using ActiveHostCallback = base::Callback<void(
+  using ActiveHostCallback = base::OnceCallback<void(
       ActiveHostStatus active_host_status,
       base::Optional<multidevice::RemoteDeviceRef> active_host,
       const std::string& tether_network_guid,
       const std::string& wifi_network_guid)>;
-  virtual void GetActiveHost(const ActiveHostCallback& active_host_callback);
+  virtual void GetActiveHost(ActiveHostCallback active_host_callback);
 
   // Synchronous getter methods which do not return a full RemoteDevice object.
   virtual ActiveHostStatus GetActiveHostStatus() const;
@@ -147,7 +147,7 @@
                      const std::string& wifi_network_guid);
 
   void OnTetherHostFetched(
-      const ActiveHostCallback& active_host_callback,
+      ActiveHostCallback active_host_callback,
       base::Optional<multidevice::RemoteDeviceRef> active_host);
 
   TetherHostFetcher* tether_host_fetcher_;
diff --git a/chromeos/components/tether/fake_active_host.cc b/chromeos/components/tether/fake_active_host.cc
index e17c2b3..cbbd750 100644
--- a/chromeos/components/tether/fake_active_host.cc
+++ b/chromeos/components/tether/fake_active_host.cc
@@ -46,7 +46,7 @@
 }
 
 void FakeActiveHost::GetActiveHost(
-    const ActiveHost::ActiveHostCallback& active_host_callback) {
+    ActiveHost::ActiveHostCallback active_host_callback) {
   base::Optional<multidevice::RemoteDeviceRef> remote_device;
   if (GetActiveHostStatus() != ActiveHost::ActiveHostStatus::DISCONNECTED) {
     // Convert the active host ID to a public key.
@@ -58,8 +58,9 @@
         multidevice::RemoteDeviceRefBuilder().SetPublicKey(public_key).Build());
   }
 
-  active_host_callback.Run(GetActiveHostStatus(), remote_device,
-                           GetTetherNetworkGuid(), GetWifiNetworkGuid());
+  std::move(active_host_callback)
+      .Run(GetActiveHostStatus(), remote_device, GetTetherNetworkGuid(),
+           GetWifiNetworkGuid());
 }
 
 ActiveHost::ActiveHostStatus FakeActiveHost::GetActiveHostStatus() const {
diff --git a/chromeos/components/tether/fake_active_host.h b/chromeos/components/tether/fake_active_host.h
index a49ed57..5f58d0ae 100644
--- a/chromeos/components/tether/fake_active_host.h
+++ b/chromeos/components/tether/fake_active_host.h
@@ -31,7 +31,7 @@
                               const std::string& tether_network_guid,
                               const std::string& wifi_network_guid) override;
   void GetActiveHost(
-      const ActiveHost::ActiveHostCallback& active_host_callback) override;
+      ActiveHost::ActiveHostCallback active_host_callback) override;
   ActiveHostStatus GetActiveHostStatus() const override;
   std::string GetActiveHostDeviceId() const override;
   std::string GetTetherNetworkGuid() const override;
diff --git a/chromeos/components/tether/fake_tether_host_fetcher.cc b/chromeos/components/tether/fake_tether_host_fetcher.cc
index b376accf..ff33c7c 100644
--- a/chromeos/components/tether/fake_tether_host_fetcher.cc
+++ b/chromeos/components/tether/fake_tether_host_fetcher.cc
@@ -28,14 +28,15 @@
 }
 
 void FakeTetherHostFetcher::FetchAllTetherHosts(
-    const TetherHostFetcher::TetherHostListCallback& callback) {
-  ProcessFetchAllTetherHostsRequest(tether_hosts_, callback);
+    TetherHostFetcher::TetherHostListCallback callback) {
+  ProcessFetchAllTetherHostsRequest(tether_hosts_, std::move(callback));
 }
 
 void FakeTetherHostFetcher::FetchTetherHost(
     const std::string& device_id,
-    const TetherHostFetcher::TetherHostCallback& callback) {
-  ProcessFetchSingleTetherHostRequest(device_id, tether_hosts_, callback);
+    TetherHostFetcher::TetherHostCallback callback) {
+  ProcessFetchSingleTetherHostRequest(device_id, tether_hosts_,
+                                      std::move(callback));
 }
 
 }  // namespace tether
diff --git a/chromeos/components/tether/fake_tether_host_fetcher.h b/chromeos/components/tether/fake_tether_host_fetcher.h
index 2532de3..0894ed8e 100644
--- a/chromeos/components/tether/fake_tether_host_fetcher.h
+++ b/chromeos/components/tether/fake_tether_host_fetcher.h
@@ -32,10 +32,9 @@
   // TetherHostFetcher:
   bool HasSyncedTetherHosts() override;
   void FetchAllTetherHosts(
-      const TetherHostFetcher::TetherHostListCallback& callback) override;
-  void FetchTetherHost(
-      const std::string& device_id,
-      const TetherHostFetcher::TetherHostCallback& callback) override;
+      TetherHostFetcher::TetherHostListCallback callback) override;
+  void FetchTetherHost(const std::string& device_id,
+                       TetherHostFetcher::TetherHostCallback callback) override;
 
  private:
   multidevice::RemoteDeviceRefList tether_hosts_;
diff --git a/chromeos/components/tether/tether_host_fetcher.cc b/chromeos/components/tether/tether_host_fetcher.cc
index 0c681f7..664d250 100644
--- a/chromeos/components/tether/tether_host_fetcher.cc
+++ b/chromeos/components/tether/tether_host_fetcher.cc
@@ -27,23 +27,23 @@
 
 void TetherHostFetcher::ProcessFetchAllTetherHostsRequest(
     const multidevice::RemoteDeviceRefList& remote_device_list,
-    const TetherHostListCallback& callback) {
-  callback.Run(remote_device_list);
+    TetherHostListCallback callback) {
+  std::move(callback).Run(remote_device_list);
 }
 
 void TetherHostFetcher::ProcessFetchSingleTetherHostRequest(
     const std::string& device_id,
     const multidevice::RemoteDeviceRefList& remote_device_list,
-    const TetherHostCallback& callback) {
+    TetherHostCallback callback) {
   for (auto remote_device : remote_device_list) {
     if (remote_device.GetDeviceId() == device_id) {
-      callback.Run(
+      std::move(callback).Run(
           base::make_optional<multidevice::RemoteDeviceRef>(remote_device));
       return;
     }
   }
 
-  callback.Run(base::nullopt);
+  std::move(callback).Run(base::nullopt);
 }
 
 void TetherHostFetcher::NotifyTetherHostsUpdated() {
diff --git a/chromeos/components/tether/tether_host_fetcher.h b/chromeos/components/tether/tether_host_fetcher.h
index eb3c68b..213880d 100644
--- a/chromeos/components/tether/tether_host_fetcher.h
+++ b/chromeos/components/tether/tether_host_fetcher.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "base/callback_forward.h"
+#include "base/callback.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/optional.h"
@@ -40,23 +40,23 @@
 
   // Fetches all tether hosts.
   using TetherHostListCallback =
-      base::Callback<void(const multidevice::RemoteDeviceRefList&)>;
-  virtual void FetchAllTetherHosts(const TetherHostListCallback& callback) = 0;
+      base::OnceCallback<void(const multidevice::RemoteDeviceRefList&)>;
+  virtual void FetchAllTetherHosts(TetherHostListCallback callback) = 0;
 
   // Fetches the tether host with the ID |device_id|.
   using TetherHostCallback =
-      base::Callback<void(base::Optional<multidevice::RemoteDeviceRef>)>;
+      base::OnceCallback<void(base::Optional<multidevice::RemoteDeviceRef>)>;
   virtual void FetchTetherHost(const std::string& device_id,
-                               const TetherHostCallback& callback) = 0;
+                               TetherHostCallback callback) = 0;
 
  protected:
   void ProcessFetchAllTetherHostsRequest(
       const multidevice::RemoteDeviceRefList& remote_device_list,
-      const TetherHostListCallback& callback);
+      TetherHostListCallback callback);
   void ProcessFetchSingleTetherHostRequest(
       const std::string& device_id,
       const multidevice::RemoteDeviceRefList& remote_device_list,
-      const TetherHostCallback& callback);
+      TetherHostCallback callback);
 
   void NotifyTetherHostsUpdated();
 
diff --git a/chromeos/components/tether/tether_host_fetcher_impl.cc b/chromeos/components/tether/tether_host_fetcher_impl.cc
index 4336b11..dc161c6 100644
--- a/chromeos/components/tether/tether_host_fetcher_impl.cc
+++ b/chromeos/components/tether/tether_host_fetcher_impl.cc
@@ -58,15 +58,15 @@
 }
 
 void TetherHostFetcherImpl::FetchAllTetherHosts(
-    const TetherHostListCallback& callback) {
-  ProcessFetchAllTetherHostsRequest(current_remote_device_list_, callback);
+    TetherHostListCallback callback) {
+  ProcessFetchAllTetherHostsRequest(current_remote_device_list_,
+                                    std::move(callback));
 }
 
-void TetherHostFetcherImpl::FetchTetherHost(
-    const std::string& device_id,
-    const TetherHostCallback& callback) {
+void TetherHostFetcherImpl::FetchTetherHost(const std::string& device_id,
+                                            TetherHostCallback callback) {
   ProcessFetchSingleTetherHostRequest(device_id, current_remote_device_list_,
-                                      callback);
+                                      std::move(callback));
 }
 
 void TetherHostFetcherImpl::OnNewDevicesSynced() {
diff --git a/chromeos/components/tether/tether_host_fetcher_impl.h b/chromeos/components/tether/tether_host_fetcher_impl.h
index d1e72a8..e85c64d 100644
--- a/chromeos/components/tether/tether_host_fetcher_impl.h
+++ b/chromeos/components/tether/tether_host_fetcher_impl.h
@@ -55,9 +55,9 @@
 
   // TetherHostFetcher:
   bool HasSyncedTetherHosts() override;
-  void FetchAllTetherHosts(const TetherHostListCallback& callback) override;
+  void FetchAllTetherHosts(TetherHostListCallback callback) override;
   void FetchTetherHost(const std::string& device_id,
-                       const TetherHostCallback& callback) override;
+                       TetherHostCallback callback) override;
 
   // device_sync::DeviceSyncClient::Observer:
   void OnNewDevicesSynced() override;
diff --git a/chromeos/components/tether/tether_host_fetcher_impl_unittest.cc b/chromeos/components/tether/tether_host_fetcher_impl_unittest.cc
index dbe7646..3d46826e 100644
--- a/chromeos/components/tether/tether_host_fetcher_impl_unittest.cc
+++ b/chromeos/components/tether/tether_host_fetcher_impl_unittest.cc
@@ -90,8 +90,8 @@
   void VerifyAllTetherHosts(
       const multidevice::RemoteDeviceRefList expected_list) {
     tether_host_fetcher_->FetchAllTetherHosts(
-        base::Bind(&TetherHostFetcherImplTest::OnTetherHostListFetched,
-                   base::Unretained(this)));
+        base::BindOnce(&TetherHostFetcherImplTest::OnTetherHostListFetched,
+                       base::Unretained(this)));
     EXPECT_EQ(expected_list, last_fetched_list_);
   }
 
@@ -100,8 +100,8 @@
       base::Optional<multidevice::RemoteDeviceRef> expected_device) {
     tether_host_fetcher_->FetchTetherHost(
         device_id,
-        base::Bind(&TetherHostFetcherImplTest::OnSingleTetherHostFetched,
-                   base::Unretained(this)));
+        base::BindOnce(&TetherHostFetcherImplTest::OnSingleTetherHostFetched,
+                       base::Unretained(this)));
     if (expected_device)
       EXPECT_EQ(expected_device, last_fetched_single_host_);
     else
diff --git a/chromeos/dbus/tpm_manager/fake_tpm_manager_client.cc b/chromeos/dbus/tpm_manager/fake_tpm_manager_client.cc
index f68d00ad..96055ed 100644
--- a/chromeos/dbus/tpm_manager/fake_tpm_manager_client.cc
+++ b/chromeos/dbus/tpm_manager/fake_tpm_manager_client.cc
@@ -66,6 +66,14 @@
                     ::tpm_manager::ClearStoredOwnerPasswordReply());
 }
 
+void FakeTpmManagerClient::AddObserver(Observer* observer) {
+  NOTIMPLEMENTED();
+}
+
+void FakeTpmManagerClient::RemoveObserver(Observer* observer) {
+  NOTIMPLEMENTED();
+}
+
 TpmManagerClient::TestInterface* FakeTpmManagerClient::GetTestInterface() {
   return this;
 }
diff --git a/chromeos/dbus/tpm_manager/fake_tpm_manager_client.h b/chromeos/dbus/tpm_manager/fake_tpm_manager_client.h
index 4cbb435..4f7e5c1 100644
--- a/chromeos/dbus/tpm_manager/fake_tpm_manager_client.h
+++ b/chromeos/dbus/tpm_manager/fake_tpm_manager_client.h
@@ -39,6 +39,8 @@
   void ClearStoredOwnerPassword(
       const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
       ClearStoredOwnerPasswordCallback callback) override;
+  void AddObserver(Observer* observer) override;
+  void RemoveObserver(Observer* observer) override;
 
   TpmManagerClient::TestInterface* GetTestInterface() override;
 
diff --git a/chromeos/dbus/tpm_manager/tpm_manager_client.cc b/chromeos/dbus/tpm_manager/tpm_manager_client.cc
index 556b44d4..f6f0645 100644
--- a/chromeos/dbus/tpm_manager/tpm_manager_client.cc
+++ b/chromeos/dbus/tpm_manager/tpm_manager_client.cc
@@ -14,6 +14,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chromeos/dbus/constants/dbus_switches.h"
@@ -51,6 +52,14 @@
   return true;
 }
 
+void OnSignalConnected(const std::string& interface_name,
+                       const std::string& signal_name,
+                       bool success) {
+  DCHECK_EQ(interface_name, ::tpm_manager::kTpmManagerInterface);
+  LOG_IF(DFATAL, !success) << "Failed to connect to D-Bus signal; interface: "
+                           << interface_name << "; signal: " << signal_name;
+}
+
 // "Real" implementation of TpmManagerClient taking to the TpmManager daemon
 // on the Chrome OS side.
 class TpmManagerClientImpl : public TpmManagerClient {
@@ -96,10 +105,18 @@
                     std::move(callback));
   }
 
+  void AddObserver(Observer* observer) override {
+    observer_list_.AddObserver(observer);
+  }
+  void RemoveObserver(Observer* observer) override {
+    observer_list_.RemoveObserver(observer);
+  }
+
   void Init(dbus::Bus* bus) {
     proxy_ = bus->GetObjectProxy(
         ::tpm_manager::kTpmManagerServiceName,
         dbus::ObjectPath(::tpm_manager::kTpmManagerServicePath));
+    ConnectToOwnershipTakenSignal();
   }
 
  private:
@@ -156,9 +173,29 @@
     std::move(callback).Run(reply_proto);
   }
 
+  // Called when receiving ownership taken signal.
+  void OnOwnershipTakenSignal(dbus::Signal*) {
+    for (auto& observer : observer_list_) {
+      observer.OnOwnershipTaken();
+    }
+  }
+
+  // Connects to ownership taken signal.
+  void ConnectToOwnershipTakenSignal() {
+    proxy_->ConnectToSignal(
+        ::tpm_manager::kTpmManagerInterface,
+        ::tpm_manager::kOwnershipTakenSignal,
+        base::BindRepeating(&TpmManagerClientImpl::OnOwnershipTakenSignal,
+                            weak_factory_.GetWeakPtr()),
+        base::BindOnce(&OnSignalConnected));
+  }
+
   // D-Bus proxy for the TpmManager daemon, not owned.
   dbus::ObjectProxy* proxy_ = nullptr;
 
+  // The observer list of ownership taken signal.
+  base::ObserverList<Observer> observer_list_;
+
   base::WeakPtrFactory<TpmManagerClientImpl> weak_factory_{this};
 };
 
diff --git a/chromeos/dbus/tpm_manager/tpm_manager_client.h b/chromeos/dbus/tpm_manager/tpm_manager_client.h
index bc8c8df..7d5fa7f1 100644
--- a/chromeos/dbus/tpm_manager/tpm_manager_client.h
+++ b/chromeos/dbus/tpm_manager/tpm_manager_client.h
@@ -7,6 +7,7 @@
 
 #include "base/callback.h"
 #include "base/component_export.h"
+#include "base/observer_list_types.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
 
 namespace dbus {
@@ -23,6 +24,13 @@
 // definitions of the D-Bus methods and their arguments.
 class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) TpmManagerClient {
  public:
+  class Observer : public base::CheckedObserver {
+   public:
+    virtual void OnOwnershipTaken() = 0;
+  };
+
+ public:
+  // Callbacks of the D-Bus methods.
   using GetTpmNonsensitiveStatusCallback = base::OnceCallback<void(
       const ::tpm_manager::GetTpmNonsensitiveStatusReply&)>;
   using GetVersionInfoCallback =
@@ -95,6 +103,11 @@
       const ::tpm_manager::ClearStoredOwnerPasswordRequest& request,
       ClearStoredOwnerPasswordCallback callback) = 0;
 
+  // Adds an observer.
+  virtual void AddObserver(Observer* observer) = 0;
+  // Removes an observer.
+  virtual void RemoveObserver(Observer* observer) = 0;
+
   // Returns an interface for testing (fake only), or returns nullptr.
   virtual TestInterface* GetTestInterface() = 0;
 
diff --git a/chromeos/dbus/tpm_manager/tpm_manager_client_unittest.cc b/chromeos/dbus/tpm_manager/tpm_manager_client_unittest.cc
index bc2d91e..c9a9a46b 100644
--- a/chromeos/dbus/tpm_manager/tpm_manager_client_unittest.cc
+++ b/chromeos/dbus/tpm_manager/tpm_manager_client_unittest.cc
@@ -12,6 +12,7 @@
 #include "dbus/mock_bus.h"
 #include "dbus/mock_object_proxy.h"
 #include "dbus/object_path.h"
+#include "dbus/object_proxy.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/tpm_manager/dbus-constants.h"
@@ -19,6 +20,7 @@
 using ::testing::_;
 using ::testing::Invoke;
 using ::testing::Return;
+using ::testing::SaveArg;
 
 namespace chromeos {
 
@@ -31,6 +33,19 @@
   std::move(callback).Run(response.get());
 }
 
+// The observer class used for testing to watch the invocation of the signal
+// callbacks.
+class TestObserver : public TpmManagerClient::Observer {
+ public:
+  // TpmManagerClient::Observer.
+  void OnOwnershipTaken() override { ++signal_count_; }
+
+  int signal_count() const { return signal_count_; }
+
+ private:
+  int signal_count_ = 0;
+};
+
 }  // namespace
 
 class TpmManagerClientTest : public testing::Test {
@@ -59,17 +74,33 @@
     EXPECT_CALL(*proxy_.get(), DoCallMethod(_, _, _))
         .WillRepeatedly(Invoke(this, &TpmManagerClientTest::OnCallMethod));
 
+    EXPECT_CALL(*proxy_,
+                DoConnectToSignal(::tpm_manager::kTpmManagerInterface,
+                                  ::tpm_manager::kOwnershipTakenSignal, _, _))
+        .WillOnce(SaveArg<2>(&ownership_taken_signal_callback_));
     TpmManagerClient::Initialize(bus_.get());
 
     // Execute callbacks posted by `client_->Init()`.
     base::RunLoop().RunUntilIdle();
 
+    ASSERT_FALSE(ownership_taken_signal_callback_.is_null());
+
     client_ = TpmManagerClient::Get();
   }
 
   void TearDown() override { TpmManagerClient::Shutdown(); }
 
  protected:
+  void EmitOwnershipTakenSignal() {
+    ::tpm_manager::OwnershipTakenSignal ownership_taken_signal;
+    dbus::Signal signal(::tpm_manager::kTpmManagerInterface,
+                        ::tpm_manager::kOwnershipTakenSignal);
+    dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(
+        ownership_taken_signal);
+    // Emit signal.
+    ASSERT_FALSE(ownership_taken_signal_callback_.is_null());
+    ownership_taken_signal_callback_.Run(&signal);
+  }
   base::test::SingleThreadTaskEnvironment task_environment_;
 
   // Mock bus and proxy for simulating calls.
@@ -123,6 +154,8 @@
         FROM_HERE, base::BindOnce(RunResponseCallback, std::move(*callback),
                                   std::move(response)));
   }
+
+  dbus::ObjectProxy::SignalCallback ownership_taken_signal_callback_;
 };
 
 TEST_F(TpmManagerClientTest, GetTpmNonsensitiveStatus) {
@@ -276,6 +309,21 @@
   EXPECT_EQ(expected_clear_password_reply_.status(), result_reply.status());
 }
 
+TEST_F(TpmManagerClientTest, OnwershipTakenSignal) {
+  TestObserver observer;
+  ASSERT_EQ(observer.signal_count(), 0);
+
+  client_->AddObserver(&observer);
+  EmitOwnershipTakenSignal();
+
+  EXPECT_EQ(observer.signal_count(), 1);
+
+  client_->RemoveObserver(&observer);
+  EmitOwnershipTakenSignal();
+
+  EXPECT_EQ(observer.signal_count(), 1);
+}
+
 TEST_F(TpmManagerClientTest, ClearStoredOwnerPasswordDBusFailure) {
   shall_message_parsing_fail_ = true;
   ::tpm_manager::ClearStoredOwnerPasswordReply result_reply;
diff --git a/chromeos/strings/chromeos_strings_ar.xtb b/chromeos/strings/chromeos_strings_ar.xtb
index 663a0b9..60cbacbb 100644
--- a/chromeos/strings/chromeos_strings_ar.xtb
+++ b/chromeos/strings/chromeos_strings_ar.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="ar">
 <translation id="1018656279737460067">تم الإلغاء</translation>
+<translation id="1059913517121127803">تعذَّر إجراء عملية المسح الضوئي.</translation>
 <translation id="1071587090247825784">تم العثور على جدار ناري.</translation>
 <translation id="1075811647922107217">حجم الصفحة</translation>
 <translation id="1175697296044146566">تتم إدارة جهاز <ph name="DEVICE_TYPE" /> هذا من خلال <ph name="MANAGER" />.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">اختيار مجلّد في تطبيق "الملفات"...</translation>
 <translation id="4890353053343094602">اختيار كلمة مرور جديدة فورًا</translation>
 <translation id="4917889632206600977">توقّفت الطابعة - نفد الورق</translation>
+<translation id="4921665434385737356">تم شحن <ph name="RATE" /> خلال <ph name="NUM_SECONDS" /> ثانية.</translation>
 <translation id="4932733599132424254">التاريخ</translation>
 <translation id="4985509611418653372">تشغيل</translation>
 <translation id="5168185087976003268">حالة البطارية</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">تأكيد كلمة المرور الجديدة</translation>
 <translation id="7805768142964895445">الحالة</translation>
 <translation id="7855434858642800953">تم حفظ الملف الذي تم مسحه ضوئيًا.</translation>
+<translation id="7928373994957558460">عرض مكان الملف</translation>
 <translation id="7936303884198020182">لم يتم العثور على خوادم الأسماء.</translation>
 <translation id="8041089156583427627">إرسال تعليقات</translation>
 <translation id="808894953321890993">تغيير كلمة المرور</translation>
diff --git a/chromeos/strings/chromeos_strings_be.xtb b/chromeos/strings/chromeos_strings_be.xtb
index e8fc6d7..2748446 100644
--- a/chromeos/strings/chromeos_strings_be.xtb
+++ b/chromeos/strings/chromeos_strings_be.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="be">
 <translation id="1018656279737460067">Скасавана</translation>
+<translation id="1059913517121127803">Не ўдалося запусціць сканіраванне</translation>
 <translation id="1071587090247825784">Выяўлены брандмаўар</translation>
 <translation id="1075811647922107217">Памер старонкі</translation>
 <translation id="1175697296044146566">Гэтай прыладай <ph name="DEVICE_TYPE" /> кіруе <ph name="MANAGER" /></translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Выбраць папку ў праграме "Файлы"...</translation>
 <translation id="4890353053343094602">Неадкладна задайце новы</translation>
 <translation id="4917889632206600977">Спынена: скончылася папера</translation>
+<translation id="4921665434385737356">Зараджана: <ph name="RATE" /> за <ph name="NUM_SECONDS" /> с.</translation>
 <translation id="4932733599132424254">Дата</translation>
 <translation id="4985509611418653372">Запусціць</translation>
 <translation id="5168185087976003268">Стан акумулятара</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">Пацвердзіце новы пароль</translation>
 <translation id="7805768142964895445">Стан</translation>
 <translation id="7855434858642800953">Файл адсканіраванага відарыса захаваны!</translation>
+<translation id="7928373994957558460">Паказаць месцазнаходжанне файла</translation>
 <translation id="7936303884198020182">Серверы даменных імён не знойдзены</translation>
 <translation id="8041089156583427627">Адправіць водгук</translation>
 <translation id="808894953321890993">Змяніць пароль</translation>
diff --git a/chromeos/strings/chromeos_strings_fi.xtb b/chromeos/strings/chromeos_strings_fi.xtb
index a5acb0f4..766d671 100644
--- a/chromeos/strings/chromeos_strings_fi.xtb
+++ b/chromeos/strings/chromeos_strings_fi.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="fi">
 <translation id="1018656279737460067">Peruutettu</translation>
+<translation id="1059913517121127803">Skannauksen aloittaminen ei onnistunut</translation>
 <translation id="1071587090247825784">Palomuuri havaittu</translation>
 <translation id="1075811647922107217">Sivun koko</translation>
 <translation id="1175697296044146566">Laitetta (<ph name="DEVICE_TYPE" />) ylläpitää <ph name="MANAGER" />.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Valitse kansio Tiedostot-sovelluksesta…</translation>
 <translation id="4890353053343094602">Valitse uusi välittömästi</translation>
 <translation id="4917889632206600977">Pysähtynyt – Paperi loppu</translation>
+<translation id="4921665434385737356"><ph name="RATE" /> ladattiin <ph name="NUM_SECONDS" /> sekunnissa.</translation>
 <translation id="4932733599132424254">Päiväys</translation>
 <translation id="4985509611418653372">Suorita</translation>
 <translation id="5168185087976003268">Akun toiminta</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">Vahvista uusi salasana</translation>
 <translation id="7805768142964895445">Tila</translation>
 <translation id="7855434858642800953">Skannattu tiedosto tallennettu!</translation>
+<translation id="7928373994957558460">Näytä tiedoston sijainti</translation>
 <translation id="7936303884198020182">Nimipalvelimia ei löydy</translation>
 <translation id="8041089156583427627">Lähetä palautetta</translation>
 <translation id="808894953321890993">Vaihda salasana</translation>
diff --git a/chromeos/strings/chromeos_strings_fr-CA.xtb b/chromeos/strings/chromeos_strings_fr-CA.xtb
index b811b13b..ea212a18 100644
--- a/chromeos/strings/chromeos_strings_fr-CA.xtb
+++ b/chromeos/strings/chromeos_strings_fr-CA.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="fr-CA">
 <translation id="1018656279737460067">Annulé</translation>
+<translation id="1059913517121127803">Impossible de démarrer la numérisation</translation>
 <translation id="1071587090247825784">Pare-feu détecté</translation>
 <translation id="1075811647922107217">Taille de la page</translation>
 <translation id="1175697296044146566">Ce <ph name="DEVICE_TYPE" /> est géré par <ph name="MANAGER" />.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Sélectionner un dossier dans l'application Fichiers…</translation>
 <translation id="4890353053343094602">Choisissez-en un immédiatement</translation>
 <translation id="4917889632206600977">Tâche arrêtée : à court de papier</translation>
+<translation id="4921665434385737356">L'appareil s'est rechargé de <ph name="RATE" /> en <ph name="NUM_SECONDS" /> secondes.</translation>
 <translation id="4932733599132424254">Date</translation>
 <translation id="4985509611418653372">Exécuter</translation>
 <translation id="5168185087976003268">État de la pile</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">Confirmez le nouveau mot de passe</translation>
 <translation id="7805768142964895445">État</translation>
 <translation id="7855434858642800953">Fichier numérisé enregistré!</translation>
+<translation id="7928373994957558460">Afficher le lieu du fichier</translation>
 <translation id="7936303884198020182">Aucun serveur de nom n'a été trouvé</translation>
 <translation id="8041089156583427627">Envoyer des commentaires</translation>
 <translation id="808894953321890993">Changer le mot de passe</translation>
diff --git a/chromeos/strings/chromeos_strings_gl.xtb b/chromeos/strings/chromeos_strings_gl.xtb
index 88868f3..56da926c 100644
--- a/chromeos/strings/chromeos_strings_gl.xtb
+++ b/chromeos/strings/chromeos_strings_gl.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="gl">
 <translation id="1018656279737460067">Cancelados</translation>
+<translation id="1059913517121127803">Non se puido iniciar o escaneo</translation>
 <translation id="1071587090247825784">Detectouse un firewall</translation>
 <translation id="1075811647922107217">Tamaño da páxina</translation>
 <translation id="1175697296044146566">Este dispositivo (<ph name="DEVICE_TYPE" />) está xestionado por <ph name="MANAGER" />.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Seleccionar cartafol na aplicación Ficheiros…</translation>
 <translation id="4890353053343094602">Escolle un novo inmediatamente</translation>
 <translation id="4917889632206600977">Detívose (esgotouse o papel)</translation>
+<translation id="4921665434385737356">Cargouse un <ph name="RATE" /> en <ph name="NUM_SECONDS" /> segundos.</translation>
 <translation id="4932733599132424254">Data</translation>
 <translation id="4985509611418653372">Executar</translation>
 <translation id="5168185087976003268">Estado da batería</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">Confirmar contrasinal novo</translation>
 <translation id="7805768142964895445">Estado</translation>
 <translation id="7855434858642800953">Gardouse o ficheiro escaneado</translation>
+<translation id="7928373994957558460">Mostrar localización do ficheiro</translation>
 <translation id="7936303884198020182">Non se atoparon servidores de nomes</translation>
 <translation id="8041089156583427627">Enviar comentarios</translation>
 <translation id="808894953321890993">Cambiar contrasinal</translation>
diff --git a/chromeos/strings/chromeos_strings_hu.xtb b/chromeos/strings/chromeos_strings_hu.xtb
index 2365682..72dfcff 100644
--- a/chromeos/strings/chromeos_strings_hu.xtb
+++ b/chromeos/strings/chromeos_strings_hu.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="hu">
 <translation id="1018656279737460067">Megszakítva</translation>
+<translation id="1059913517121127803">Nem sikerült elindítani a szkennelést</translation>
 <translation id="1071587090247825784">Tűzfal észlelve</translation>
 <translation id="1075811647922107217">Oldal mérete</translation>
 <translation id="1175697296044146566">Ezt a(z) <ph name="DEVICE_TYPE" /> eszközt a(z) <ph name="MANAGER" /> kezeli.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Mappa kiválasztása a Fájlok alkalmazásban…</translation>
 <translation id="4890353053343094602">Azonnal válasszon új jelszót</translation>
 <translation id="4917889632206600977">Leállt – Kifogyott a papír</translation>
+<translation id="4921665434385737356"><ph name="RATE" /> töltöttség <ph name="NUM_SECONDS" /> másodperc alatt.</translation>
 <translation id="4932733599132424254">Dátum</translation>
 <translation id="4985509611418653372">Futtatás</translation>
 <translation id="5168185087976003268">Akkumulátor egészsége</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">Új jelszó megerősítése</translation>
 <translation id="7805768142964895445">Állapot</translation>
 <translation id="7855434858642800953">Sikerült a beolvasott fájl mentése</translation>
+<translation id="7928373994957558460">Fájl helyének megjelenítése</translation>
 <translation id="7936303884198020182">Nem találhatók névszerverek</translation>
 <translation id="8041089156583427627">Visszajelzés küldése</translation>
 <translation id="808894953321890993">Jelszó módosítása</translation>
diff --git a/chromeos/strings/chromeos_strings_it.xtb b/chromeos/strings/chromeos_strings_it.xtb
index f9a0942..c8ddf30 100644
--- a/chromeos/strings/chromeos_strings_it.xtb
+++ b/chromeos/strings/chromeos_strings_it.xtb
@@ -122,7 +122,7 @@
 <translation id="54609108002486618">Gestito</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />: <ph name="PROBLEMS" /></translation>
 <translation id="5551702563755460533">Scopri di più nel Centro assistenza</translation>
-<translation id="5719918614880940190">Questo valore indica l'utilizzo della CPU e aggrega tutti i punteggi</translation>
+<translation id="5719918614880940190">Questo valore indica l'utilizzo della CPU e aggrega tutti i core</translation>
 <translation id="5832805196449965646">Aggiungi persona</translation>
 <translation id="5895138241574237353">Riavvia</translation>
 <translation id="5982592372228113572">(<ph name="BOARD_NAME" />, versione <ph name="MILESTONE_VERSION" />)</translation>
diff --git a/chromeos/strings/chromeos_strings_km.xtb b/chromeos/strings/chromeos_strings_km.xtb
index b40c1c8..b7dd7b41 100644
--- a/chromeos/strings/chromeos_strings_km.xtb
+++ b/chromeos/strings/chromeos_strings_km.xtb
@@ -121,7 +121,7 @@
 <translation id="54609108002486618">បាន​គ្រប់គ្រង</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />៖ <ph name="PROBLEMS" /></translation>
 <translation id="5551702563755460533">ស្វែងយល់បន្ថែម​នៅក្នុង​មជ្ឈមណ្ឌលជំនួយ</translation>
-<translation id="5719918614880940190">វាវាស់ស្ទង់ការប្រើប្រាស់ CPU ហើយគឺជាការវាស់ស្ទង់ការប្រើប្រាស់សរុបនៃស្នូលទាំងអស់</translation>
+<translation id="5719918614880940190">សកម្មភាពនេះវាស់ស្ទង់ការប្រើប្រាស់ CPU ហើយគឺជាការវាស់ស្ទង់ការប្រើប្រាស់សរុបនៃស្នូលទាំងអស់</translation>
 <translation id="5832805196449965646">បន្ថែមបុគ្គល</translation>
 <translation id="5895138241574237353">ចាប់ផ្តើមឡើងវិញ</translation>
 <translation id="5982592372228113572">(<ph name="BOARD_NAME" />, កំណែ <ph name="MILESTONE_VERSION" />)</translation>
diff --git a/chromeos/strings/chromeos_strings_kn.xtb b/chromeos/strings/chromeos_strings_kn.xtb
index bac23ba..12ff367 100644
--- a/chromeos/strings/chromeos_strings_kn.xtb
+++ b/chromeos/strings/chromeos_strings_kn.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="kn">
 <translation id="1018656279737460067">ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ</translation>
+<translation id="1059913517121127803">ಸ್ಕ್ಯಾನ್ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ</translation>
 <translation id="1071587090247825784">ಫೈರ್‌ವಾಲ್ ಅನ್ನು ಪತ್ತೆಹಚ್ಚಲಾಗಿದೆ</translation>
 <translation id="1075811647922107217">ಪುಟದ ಗಾತ್ರ</translation>
 <translation id="1175697296044146566">ಈ <ph name="DEVICE_TYPE" />, <ph name="MANAGER" /> ಇಂದ ನಿರ್ವಹಿಸಲ್ಪಡುತ್ತದೆ.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Files ಆ್ಯಪ್‌ನಲ್ಲಿ ಫೋಲ್ಡರ್ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಿ...</translation>
 <translation id="4890353053343094602">ಹೊಸದೊಂದನ್ನು ತತ್‌ಕ್ಷಣ ಆಯ್ಕೆಮಾಡಿ</translation>
 <translation id="4917889632206600977">ನಿಲ್ಲಿಸಲಾಗಿದೆ - ಪೇಪರ್ ಖಾಲಿಯಾಗಿದೆ</translation>
+<translation id="4921665434385737356"><ph name="NUM_SECONDS" /> ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ <ph name="RATE" /> ಶುಲ್ಕವನ್ನು ವಿಧಿಸಲಾಗಿದೆ.</translation>
 <translation id="4932733599132424254">ದಿನಾಂಕ</translation>
 <translation id="4985509611418653372">ರನ್‌ ಮಾಡಿ</translation>
 <translation id="5168185087976003268">ಬ್ಯಾಟರಿ ಬಾಳಿಕೆ:</translation>
@@ -163,6 +165,7 @@
 <translation id="7690294790491645610">ಹೊಸ ಪಾಸ್‌ವರ್ಡ್ ಖಚಿತಪಡಿಸಿ</translation>
 <translation id="7805768142964895445">ಸ್ಥಿತಿ</translation>
 <translation id="7855434858642800953">ಸ್ಕ್ಯಾನ್ ಮಾಡಿದ ಫೈಲ್‌ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ!</translation>
+<translation id="7928373994957558460">ಫೈಲ್ ಸ್ಥಳವನ್ನು ತೋರಿಸಿ</translation>
 <translation id="7936303884198020182">ಹೆಸರು ಇಲ್ಲದ ಸರ್ವರ್‌ಗಳು ಕಂಡುಬಂದಿವೆ.</translation>
 <translation id="8041089156583427627">ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸಿ</translation>
 <translation id="808894953321890993">ಪಾಸ್‌ವರ್ಡ್ ಬದಲಿಸಿ</translation>
diff --git a/chromeos/strings/chromeos_strings_ko.xtb b/chromeos/strings/chromeos_strings_ko.xtb
index 5aec470d..3e937c6 100644
--- a/chromeos/strings/chromeos_strings_ko.xtb
+++ b/chromeos/strings/chromeos_strings_ko.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="ko">
 <translation id="1018656279737460067">취소됨</translation>
+<translation id="1059913517121127803">스캔을 시작할 수 없음</translation>
 <translation id="1071587090247825784">방화벽 감지됨</translation>
 <translation id="1075811647922107217">페이지 크기</translation>
 <translation id="1175697296044146566">이 <ph name="DEVICE_TYPE" /> 기기는 <ph name="MANAGER" />에서 관리합니다.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">파일 앱에서 폴더 선택…</translation>
 <translation id="4890353053343094602">지금 바로 새 비밀번호를 선택하세요.</translation>
 <translation id="4917889632206600977">중지됨 - 용지 부족</translation>
+<translation id="4921665434385737356"><ph name="NUM_SECONDS" />초 동안 <ph name="RATE" /> 충전했습니다.</translation>
 <translation id="4932733599132424254">날짜</translation>
 <translation id="4985509611418653372">실행</translation>
 <translation id="5168185087976003268">배터리 상태</translation>
@@ -120,7 +122,7 @@
 <translation id="54609108002486618">관리</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />: <ph name="PROBLEMS" /></translation>
 <translation id="5551702563755460533">고객센터에서 자세히 알아보기</translation>
-<translation id="5719918614880940190">CPU 사용량을 측정하며, 모든 코어에서 집계한 값임</translation>
+<translation id="5719918614880940190">CPU 사용량을 측정하며, 모든 코어에서 집계한 값입니다.</translation>
 <translation id="5832805196449965646">사용자 추가</translation>
 <translation id="5895138241574237353">다시 시작</translation>
 <translation id="5982592372228113572">(<ph name="BOARD_NAME" />, 버전 <ph name="MILESTONE_VERSION" />)</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">새 비밀번호 확인</translation>
 <translation id="7805768142964895445">상태</translation>
 <translation id="7855434858642800953">스캔한 파일이 저장되었습니다.</translation>
+<translation id="7928373994957558460">파일 위치 표시</translation>
 <translation id="7936303884198020182">네임서버를 찾을 수 없습니다.</translation>
 <translation id="8041089156583427627">의견 보내기</translation>
 <translation id="808894953321890993">비밀번호 변경</translation>
diff --git a/chromeos/strings/chromeos_strings_mk.xtb b/chromeos/strings/chromeos_strings_mk.xtb
index 3ac78fa..520246c 100644
--- a/chromeos/strings/chromeos_strings_mk.xtb
+++ b/chromeos/strings/chromeos_strings_mk.xtb
@@ -41,7 +41,7 @@
 <translation id="2364498172489649528">Помина</translation>
 <translation id="2375079107209812402">Преостануваат <ph name="ATTEMPTS_LEFT" /> обиди</translation>
 <translation id="2391082728065870591">Испрати извештај со повратни информации</translation>
-<translation id="2461822463642141190">Тековна</translation>
+<translation id="2461822463642141190">Моментално</translation>
 <translation id="2463748424736466148">{ATTEMPTS_LEFT,plural, =1{<ph name="ERROR_MESSAGE" /> Уште {0} обид}one{<ph name="ERROR_MESSAGE" /> Уште {0} обиди}other{<ph name="ERROR_MESSAGE" /> Уште {0} обиди}}</translation>
 <translation id="249323605434939166"><ph name="QUERY_TEXT" /> · <ph name="SOURCE_LANGUAGE_NAME" /></translation>
 <translation id="2517472476991765520">Скенирај</translation>
@@ -194,7 +194,7 @@
 <translation id="8910721771319628100">Стандардната мрежа е над прагот за латентност</translation>
 <translation id="8919837981463578619">Неуспешно - недостасува фиоката</translation>
 <translation id="8928727111548978589">Неуспешно - нема хартија</translation>
-<translation id="9088306295921699330">Тековно користење</translation>
+<translation id="9088306295921699330">Моментално користење</translation>
 <translation id="910415269708673980">Освежете го билетот за <ph name="PRINCIPAL_NAME" /></translation>
 <translation id="9106415115617144481">Се скенира страницата <ph name="PAGE_NUMBER" /></translation>
 <translation id="9111102763498581341">Отклучи</translation>
diff --git a/chromeos/strings/chromeos_strings_my.xtb b/chromeos/strings/chromeos_strings_my.xtb
index b6cc691..b391545 100644
--- a/chromeos/strings/chromeos_strings_my.xtb
+++ b/chromeos/strings/chromeos_strings_my.xtb
@@ -27,7 +27,7 @@
 <translation id="1662989795263954667">ရပ်သွားသည် - မင်ကုန်နေသည်</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">DNS Resolver ရှိသည်</translation>
-<translation id="1743558184855585519">ကန့်သတ်အရေအတွက်သို့ ရောက်သွားသောအခါ ဘက်ထရီကို အသုံးပြုပြီးပြီဟု သတ်မှတ်လိုက်သည်</translation>
+<translation id="1743558184855585519">ကန့်သတ်ပမာဏသို့ ရောက်သွားသောအခါ ဘက်ထရီကုန်ပြီဟု သတ်မှတ်လိုက်သည်</translation>
 <translation id="1905710495812624430">အများဆုံးခွင့်ပြုပေးထားသည့် အခေါက်အရေအတွက်ထက် ကျော်လွန်သွားပါပြီ။</translation>
 <translation id="1930797645656624981">Chrome OS လက်ကွက်ဝန်ဆောင်မှု</translation>
 <translation id="1947737735496445907">ပုံနှိပ်ထုတ်ပြီးပြီ</translation>
diff --git a/chromeos/strings/chromeos_strings_or.xtb b/chromeos/strings/chromeos_strings_or.xtb
index 8ae245e..e35221ab 100644
--- a/chromeos/strings/chromeos_strings_or.xtb
+++ b/chromeos/strings/chromeos_strings_or.xtb
@@ -32,6 +32,7 @@
 <translation id="1930797645656624981">Chrome OS ଇନ୍‍ପୁଟ୍ ପଦ୍ଧତି ସେବା</translation>
 <translation id="1947737735496445907">ପ୍ରିଣ୍ଟ କରାଯାଇଛି</translation>
 <translation id="1979103255016296513">ପାସ୍‌ୱାର୍ଡ ପରିବର୍ତ୍ତନର ସମୟ ବିଳମ୍ବ ହୋଇଯାଇଛି</translation>
+<translation id="1980044825731880088">CPU ସ୍ପିଡ୍</translation>
 <translation id="2080070583977670716">ଅଧିକ ସେଟିଂ</translation>
 <translation id="2141644705054017895"><ph name="PERCENTAGE_VALUE" />%</translation>
 <translation id="2161394479394250669">ପ୍ରିଣ୍ଟ କାର୍ଯ୍ୟକୁ ବାତିଲ୍ କରନ୍ତୁ</translation>
@@ -40,6 +41,7 @@
 <translation id="2364498172489649528">ପାସ୍ କରିଛି</translation>
 <translation id="2375079107209812402"><ph name="ATTEMPTS_LEFT" />ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି</translation>
 <translation id="2391082728065870591">ମତାମତ ରିପୋର୍ଟ ପଠାନ୍ତୁ</translation>
+<translation id="2461822463642141190">ବର୍ତ୍ତମାନର</translation>
 <translation id="2463748424736466148">{ATTEMPTS_LEFT,plural, =1{<ph name="ERROR_MESSAGE" /> {0}ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି}other{<ph name="ERROR_MESSAGE" />{0}ଟି ପ୍ରଚେଷ୍ଟା ବାକି ଅଛି}}</translation>
 <translation id="249323605434939166"><ph name="QUERY_TEXT" /> · <ph name="SOURCE_LANGUAGE_NAME" /></translation>
 <translation id="2517472476991765520">ସ୍କାନ୍ କରନ୍ତୁ</translation>
@@ -48,6 +50,7 @@
 <translation id="2872961005593481000">ବନ୍ଦ କରନ୍ତୁ</translation>
 <translation id="3008341117444806826">ରିଫ୍ରେଶ୍ କରନ୍ତୁ</translation>
 <translation id="3009958530611748826">ଏଥିରେ ସେଭ୍ କରିବାକୁ ଏକ ଫୋଲ୍ଡର୍ ଚୟନ କରନ୍ତୁ</translation>
+<translation id="3054177598518735801"><ph name="CURRENT_VALUE" />mA</translation>
 <translation id="3083667275341675831">ସଂଯୋଗ ଡାଏଗ୍ନୋଷ୍ଟିକ୍ସ</translation>
 <translation id="3091839911843451378">ବିଫଳ ହୋଇଛି - ପ୍ରିଣ୍ଟର୍ ବନ୍ଦ ହୋଇଯାଇଛି</translation>
 <translation id="3188257591659621405">ମୋ ଫାଇଲ୍‌ଗୁଡ଼ିକ</translation>
@@ -102,6 +105,7 @@
 <translation id="4921665434385737356"><ph name="NUM_SECONDS" /> ସେକେଣ୍ଡରେ <ph name="RATE" /> ଚାର୍ଜ ହୋଇଛି</translation>
 <translation id="4932733599132424254">ତାରିଖ</translation>
 <translation id="4985509611418653372">ଚଲାନ୍ତୁ</translation>
+<translation id="5168185087976003268">ବ୍ୟାଟେରୀ ହେଲ୍ଥ</translation>
 <translation id="520299634122159966">କୌଣସି ସ୍କାନର୍ ଉପଲବ୍ଧ ନାହିଁ</translation>
 <translation id="5212543919916444558">ଆପଣଙ୍କର ସ୍କ୍ରିନ୍‌ରେ ମୁଁ କିଛି ଖୋଜିପାଇଲି ନାହିଁ ଯାହାଦ୍ୱାରା ମୁଁ ଆପଣଙ୍କୁ ସାହାଯ୍ୟ କରିପାରିବି।
 ମୋତେ ଯାହା କିଛି ପଚାରିବା ପାଇଁ ମାଇକ୍‌ ଟାପ୍‌ କରି ଦେଖନ୍ତୁ।</translation>
@@ -117,9 +121,11 @@
 <translation id="5457599981699367932">ଅତିଥି ହିସାବରେ ବ୍ରାଉଜ୍ କରନ୍ତୁ</translation>
 <translation id="54609108002486618">ପରିଚାଳିତ ହେଉଛି</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />: <ph name="PROBLEMS" /></translation>
+<translation id="5551702563755460533">ସହାୟତା କେନ୍ଦ୍ରରେ ଅଧିକ ଜାଣନ୍ତୁ</translation>
 <translation id="5719918614880940190">ଏହା CPUର ବ୍ୟବହାରକୁ ମାପେ ଏବଂ ସମସ୍ତ କୋରର ଏକତ୍ରୀକରଣ ଅଟେ</translation>
 <translation id="5832805196449965646">ଲୋକଙ୍କୁ ଯୋଗ କରନ୍ତୁ</translation>
 <translation id="5895138241574237353">ପୁନଃଆରମ୍ଭ</translation>
+<translation id="5982592372228113572">(<ph name="BOARD_NAME" />, ସଂସ୍କରଣ <ph name="MILESTONE_VERSION" />)</translation>
 <translation id="6040143037577758943">ବନ୍ଦ</translation>
 <translation id="6048107060512778456">ବିଫଳ ହୋଇଛି - କାଗଜ ଅଟକି ଯାଇଛି</translation>
 <translation id="6050189528197190982">ଗ୍ରେସ୍କେଲ୍</translation>
@@ -188,6 +194,7 @@
 <translation id="8910721771319628100">ଡିଫଲ୍ଟ ନେଟୱାର୍କ ଲାଟେନ୍ସି ସୀମାର ଉପରେ ଅଛି</translation>
 <translation id="8919837981463578619">ବିଫଳ ହୋଇଛି - ଟ୍ରେ ଅନୁପଲବ୍ଧ ଅଛି</translation>
 <translation id="8928727111548978589">ବିଫଳ ହୋଇଛି - କାଗଜ ଶେଷ ହୋଇଯାଇଛି</translation>
+<translation id="9088306295921699330">ବର୍ତ୍ତମାନର ବ୍ୟବହାର</translation>
 <translation id="910415269708673980"><ph name="PRINCIPAL_NAME" /> ପାଇଁ ଟିକେଟ୍ ରିଫ୍ରେଶ୍ କରନ୍ତୁ</translation>
 <translation id="9106415115617144481">ପୃଷ୍ଠା <ph name="PAGE_NUMBER" />କୁ ସ୍କାନ୍ କରାଯାଉଛି</translation>
 <translation id="9111102763498581341">ଅନ୍‌ଲକ୍ କରନ୍ତୁ</translation>
diff --git a/chromeos/strings/chromeos_strings_pa.xtb b/chromeos/strings/chromeos_strings_pa.xtb
index be1dc45..48c15850 100644
--- a/chromeos/strings/chromeos_strings_pa.xtb
+++ b/chromeos/strings/chromeos_strings_pa.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="pa">
 <translation id="1018656279737460067">ਰੱਦ ਕੀਤਾ</translation>
+<translation id="1059913517121127803">ਸਕੈਨ ਕਰਨਾ ਸ਼ੁਰੂ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ</translation>
 <translation id="1071587090247825784">Firewall ਦਾ ਪਤਾ ਲੱਗਾ</translation>
 <translation id="1075811647922107217">ਪੰਨੇ ਦਾ ਆਕਾਰ</translation>
 <translation id="1195447618553298278">ਅਗਿਆਤ ਗੜਬੜ।</translation>
@@ -98,6 +99,7 @@
 <translation id="4832079907277790330">Files ਐਪ ਵਿੱਚ ਫੋਲਡਰ ਨੂੰ ਚੁਣੋ...</translation>
 <translation id="4890353053343094602">ਛੇਤੀ ਇੱਕ ਨਵਾਂ ਪਾਸਵਰਡ ਚੁਣੋ</translation>
 <translation id="4917889632206600977">ਬੰਦ ਹੋ ਗਿਆ - ਕਾਗਜ਼ ਖਤਮ ਹੋ ਗਏ</translation>
+<translation id="4921665434385737356"><ph name="NUM_SECONDS" /> ਸਕਿੰਟਾਂ ਵਿੱਚ <ph name="RATE" /> ਚਾਰਜ ਹੋਈ।</translation>
 <translation id="4932733599132424254">ਤਾਰੀਖ</translation>
 <translation id="4985509611418653372">ਚਲਾਓ</translation>
 <translation id="5168185087976003268">ਬੈਟਰੀ ਦੀ ਸਥਿਤੀ</translation>
@@ -158,6 +160,7 @@
 <translation id="7690294790491645610">ਨਵੇਂ ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</translation>
 <translation id="7805768142964895445">ਸਥਿਤੀ</translation>
 <translation id="7855434858642800953">ਸਕੈਨ ਕੀਤੀ ਫ਼ਾਈਲ ਨੂੰ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ!</translation>
+<translation id="7928373994957558460">ਫ਼ਾਈਲ ਦਾ ਟਿਕਾਣਾ ਦਿਖਾਓ</translation>
 <translation id="7936303884198020182">ਕੋਈ ਨਾਮ ਸਰਵਰ ਨਹੀਂ ਮਿਲਿਆ</translation>
 <translation id="8041089156583427627">ਵਿਚਾਰ ਭੇਜੋ</translation>
 <translation id="808894953321890993">ਪਾਸਵਰਡ ਬਦਲੋ</translation>
diff --git a/chromeos/strings/chromeos_strings_sk.xtb b/chromeos/strings/chromeos_strings_sk.xtb
index 412a94d..116dd8b5 100644
--- a/chromeos/strings/chromeos_strings_sk.xtb
+++ b/chromeos/strings/chromeos_strings_sk.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="sk">
 <translation id="1018656279737460067">Zrušené</translation>
+<translation id="1059913517121127803">Skenovanie sa nepodarilo spustiť</translation>
 <translation id="1071587090247825784">Bol zistený firewall</translation>
 <translation id="1075811647922107217">Veľkosť stránky</translation>
 <translation id="1175697296044146566">Toto zariadenie <ph name="DEVICE_TYPE" /> spravuje <ph name="MANAGER" />.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Vybrať priečinok v aplikácii Súbory…</translation>
 <translation id="4890353053343094602">Okamžite si zvoľte nové heslo</translation>
 <translation id="4917889632206600977">Zastavené – minul sa papier</translation>
+<translation id="4921665434385737356">Nabité na <ph name="RATE" /> za <ph name="NUM_SECONDS" /> s.</translation>
 <translation id="4932733599132424254">Dátum</translation>
 <translation id="4985509611418653372">Spustiť</translation>
 <translation id="5168185087976003268">Stav batérie</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">Potvrďte nové heslo</translation>
 <translation id="7805768142964895445">Stav</translation>
 <translation id="7855434858642800953">Naskenovaný súbor bol uložený.</translation>
+<translation id="7928373994957558460">Zobraziť umiestnenie súboru</translation>
 <translation id="7936303884198020182">Nenašli sa žiadne servery DNS</translation>
 <translation id="8041089156583427627">Odoslať spätnú väzbu</translation>
 <translation id="808894953321890993">Zmeniť heslo</translation>
diff --git a/chromeos/strings/chromeos_strings_sq.xtb b/chromeos/strings/chromeos_strings_sq.xtb
index 8e358a0..b7751b4 100644
--- a/chromeos/strings/chromeos_strings_sq.xtb
+++ b/chromeos/strings/chromeos_strings_sq.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="sq">
 <translation id="1018656279737460067">Anuluar</translation>
+<translation id="1059913517121127803">Skanimi nuk mund të nisej</translation>
 <translation id="1071587090247825784">U zbulua mur mbrojtës</translation>
 <translation id="1075811647922107217">Madhësia e faqes</translation>
 <translation id="1175697296044146566">Kjo pajisje <ph name="DEVICE_TYPE" /> menaxhohet nga <ph name="MANAGER" />.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Zgjidh dosjen në aplikacionin "Skedarët"...</translation>
 <translation id="4890353053343094602">Zgjidh një të re menjëherë</translation>
 <translation id="4917889632206600977">Ndaloi - Nuk ka letër</translation>
+<translation id="4921665434385737356">U karikua <ph name="RATE" /> në <ph name="NUM_SECONDS" /> sekonda.</translation>
 <translation id="4932733599132424254">Data</translation>
 <translation id="4985509611418653372">Ekzekuto</translation>
 <translation id="5168185087976003268">Integriteti i baterisë</translation>
@@ -163,6 +165,7 @@
 <translation id="7690294790491645610">Konfirmo fjalëkalimin e ri</translation>
 <translation id="7805768142964895445">Statusi</translation>
 <translation id="7855434858642800953">Skedari i skanuar u ruajt!</translation>
+<translation id="7928373994957558460">Shfaq vendndodhjen e skedarit</translation>
 <translation id="7936303884198020182">Nuk u gjetën serverë DNS</translation>
 <translation id="8041089156583427627">Dërgo komentet</translation>
 <translation id="808894953321890993">Ndrysho fjalëkalimin</translation>
diff --git a/chromeos/strings/chromeos_strings_sv.xtb b/chromeos/strings/chromeos_strings_sv.xtb
index 1f32e63..3e5a768 100644
--- a/chromeos/strings/chromeos_strings_sv.xtb
+++ b/chromeos/strings/chromeos_strings_sv.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="sv">
 <translation id="1018656279737460067">Avbröts</translation>
+<translation id="1059913517121127803">Det gick inte att börja söka</translation>
 <translation id="1071587090247825784">Brandvägg hittades</translation>
 <translation id="1075811647922107217">Sidstorlek</translation>
 <translation id="1175697296044146566">Denna <ph name="DEVICE_TYPE" /> hanteras av <ph name="MANAGER" />.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Välj en fil i appen Filer</translation>
 <translation id="4890353053343094602">Välj ett nytt omedelbart</translation>
 <translation id="4917889632206600977">Har stoppats – slut på papper</translation>
+<translation id="4921665434385737356">Har laddat <ph name="RATE" /> på <ph name="NUM_SECONDS" /> sekunder.</translation>
 <translation id="4932733599132424254">Datum</translation>
 <translation id="4985509611418653372">Kör</translation>
 <translation id="5168185087976003268">Batterinivå</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">Bekräfta det nya lösenordet</translation>
 <translation id="7805768142964895445">Status</translation>
 <translation id="7855434858642800953">Den skannade filen har sparats.</translation>
+<translation id="7928373994957558460">Visa filplats</translation>
 <translation id="7936303884198020182">Inga namnservrar hittades</translation>
 <translation id="8041089156583427627">Skicka feedback</translation>
 <translation id="808894953321890993">Ändra lösenord</translation>
diff --git a/chromeos/strings/chromeos_strings_sw.xtb b/chromeos/strings/chromeos_strings_sw.xtb
index 3039c65..9a425e3c 100644
--- a/chromeos/strings/chromeos_strings_sw.xtb
+++ b/chromeos/strings/chromeos_strings_sw.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="sw">
 <translation id="1018656279737460067">Imeghairiwa</translation>
+<translation id="1059913517121127803">Imeshindwa kuanza kuchanganua</translation>
 <translation id="1071587090247825784">Kinga mtandao imetambuliwa</translation>
 <translation id="1075811647922107217">Ukubwa wa ukurasa</translation>
 <translation id="1175697296044146566"><ph name="DEVICE_TYPE" /> hii inasimamiwa na <ph name="MANAGER" />.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Chagua folda katika programu ya Faili...</translation>
 <translation id="4890353053343094602">Chagua nenosiri jipya mara moja</translation>
 <translation id="4917889632206600977">Imesimama - Karatasi zimeisha</translation>
+<translation id="4921665434385737356">Imechaji <ph name="RATE" /> baada ya sekunde <ph name="NUM_SECONDS" />.</translation>
 <translation id="4932733599132424254">Tarehe</translation>
 <translation id="4985509611418653372">Tekeleza</translation>
 <translation id="5168185087976003268">Muda wa kudumu wa betri</translation>
@@ -163,6 +165,7 @@
 <translation id="7690294790491645610">Thibitisha nenosiri jipya</translation>
 <translation id="7805768142964895445">Hali</translation>
 <translation id="7855434858642800953">Faili iliyochanganuliwa imehifadhiwa!</translation>
+<translation id="7928373994957558460">Onyesha faili ilipo</translation>
 <translation id="7936303884198020182">Hakuna seva za majina zilizopatikana</translation>
 <translation id="8041089156583427627">Tuma Maoni</translation>
 <translation id="808894953321890993">Badilisha nenosiri</translation>
diff --git a/chromeos/strings/chromeos_strings_tr.xtb b/chromeos/strings/chromeos_strings_tr.xtb
index febab52..3124d03 100644
--- a/chromeos/strings/chromeos_strings_tr.xtb
+++ b/chromeos/strings/chromeos_strings_tr.xtb
@@ -2,6 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="tr">
 <translation id="1018656279737460067">İptal Edildi</translation>
+<translation id="1059913517121127803">Tarama işlemi başlatılamadı</translation>
 <translation id="1071587090247825784">Güvenlik duvarı algılandı</translation>
 <translation id="1075811647922107217">Sayfa boyutu</translation>
 <translation id="1175697296044146566">Bu <ph name="DEVICE_TYPE" />, <ph name="MANAGER" /> tarafından yönetiliyor.</translation>
@@ -101,6 +102,7 @@
 <translation id="4832079907277790330">Dosyalar uygulamasında klasör seç...</translation>
 <translation id="4890353053343094602">Hemen yeni bir tane seçin</translation>
 <translation id="4917889632206600977">Durduruldu - Kağıt bitti</translation>
+<translation id="4921665434385737356"><ph name="NUM_SECONDS" /> saniyede <ph name="RATE" /> şarj oldu</translation>
 <translation id="4932733599132424254">Tarih</translation>
 <translation id="4985509611418653372">Çalıştır</translation>
 <translation id="5168185087976003268">Pil gücü</translation>
@@ -164,6 +166,7 @@
 <translation id="7690294790491645610">Yeni şifreyi doğrula</translation>
 <translation id="7805768142964895445">Durum</translation>
 <translation id="7855434858642800953">Taranan dosya kaydedildi</translation>
+<translation id="7928373994957558460">Dosya konumunu göster</translation>
 <translation id="7936303884198020182">Alan adı sunucusu bulunamadı</translation>
 <translation id="8041089156583427627">Görüş bildirin</translation>
 <translation id="808894953321890993">Şifreyi değiştir</translation>
diff --git a/chromeos/strings/chromeos_strings_ur.xtb b/chromeos/strings/chromeos_strings_ur.xtb
index aee1d46a..1361216 100644
--- a/chromeos/strings/chromeos_strings_ur.xtb
+++ b/chromeos/strings/chromeos_strings_ur.xtb
@@ -2,8 +2,10 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="ur">
 <translation id="1018656279737460067">منسوخ کردہ</translation>
+<translation id="1059913517121127803">اسکین کرنا شروع نہیں کیا جا سکا</translation>
 <translation id="1071587090247825784">فائروال کا پتا چلا</translation>
 <translation id="1075811647922107217">صفحہ کا سائز</translation>
+<translation id="1175697296044146566"><ph name="MANAGER" /> اس <ph name="DEVICE_TYPE" /> کا نظم کرتا ہے۔</translation>
 <translation id="1195447618553298278">نامعلوم خرابی۔</translation>
 <translation id="1204296502688602597">‏DNS تاخیر</translation>
 <translation id="1238612778414822719">‏HTTPS تاخیر</translation>
@@ -25,6 +27,7 @@
 <translation id="1662989795263954667">رک گیا - سیاہی ختم ہو گئی</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">‏DNS ریزولور دستیاب ہے</translation>
+<translation id="1743558184855585519">بیٹری کو حد تک پہنچ جانے کے بعد استعمال کردہ مانا جاتا ہے</translation>
 <translation id="1905710495812624430">زیادہ سے زیادہ مجاز کوششوں سے تجاوز کرگیا۔</translation>
 <translation id="1930797645656624981">‏Chrome OS اندراج کے طریقہ کی سروس</translation>
 <translation id="1947737735496445907">پرنٹ ہو گیا</translation>
@@ -42,6 +45,7 @@
 <translation id="2463748424736466148">{ATTEMPTS_LEFT,plural, =1{<ph name="ERROR_MESSAGE" /> {0} کوشش باقی ہے}other{<ph name="ERROR_MESSAGE" /> {0} کوششیں باقی ہیں}}</translation>
 <translation id="249323605434939166"><ph name="QUERY_TEXT" /> · <ph name="SOURCE_LANGUAGE_NAME" /></translation>
 <translation id="2517472476991765520">اسکین کریں</translation>
+<translation id="2570743873672969996"><ph name="TEST_NAME" /> ٹیسٹ چل رہا ہے...</translation>
 <translation id="2805756323405976993">اطلاقات</translation>
 <translation id="2872961005593481000">بند کریں</translation>
 <translation id="3008341117444806826">ریفریش کریں</translation>
@@ -98,6 +102,7 @@
 <translation id="4832079907277790330">فائلز ایپ میں فولڈر منتخب کریں...</translation>
 <translation id="4890353053343094602">فوری طور پر نیا پاس ورڈ منتخب کریں</translation>
 <translation id="4917889632206600977">رک گیا - کاغذ ختم ہو گیا</translation>
+<translation id="4921665434385737356"><ph name="NUM_SECONDS" /> سیکنڈ میں <ph name="RATE" /> چارج کیا گیا۔</translation>
 <translation id="4932733599132424254">تاریخ</translation>
 <translation id="4985509611418653372">چلائیں</translation>
 <translation id="5168185087976003268">بیٹری کی صحت</translation>
@@ -116,6 +121,7 @@
 <translation id="54609108002486618">نظم کردہ</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />: <ph name="PROBLEMS" /></translation>
 <translation id="5551702563755460533">مرکز امداد میں مزید جانیں</translation>
+<translation id="5719918614880940190">‏اس سے CPU استعمال کی پیمائش ہوتی ہے اور یہ سبھی کورز کا مجموعہ ہے</translation>
 <translation id="5832805196449965646">شخص کو شامل کریں</translation>
 <translation id="5895138241574237353">دوبارہ شروع کریں</translation>
 <translation id="5982592372228113572">(<ph name="BOARD_NAME" />، ورژن <ph name="MILESTONE_VERSION" />)</translation>
@@ -151,6 +157,7 @@
 <translation id="7177485034254901881">یہ <ph name="DEVICE_TYPE" /> <ph name="MANAGER" /> کے زیر انتظام ہے۔ منتظمین دور سے آلے کو کنفیگر کر سکتے ہیں۔</translation>
 <translation id="7274587244503383581"><ph name="PRINTED_PAGES_NUMBER" />/<ph name="TOTAL_PAGES_NUMBER" /></translation>
 <translation id="7359657277149375382">فائل کی قسم</translation>
+<translation id="7441459999606975924">استعمال کے ساتھ بیٹریز کی استعداد کم ہوتی ہے</translation>
 <translation id="7561454561030345039">یہ کارروائی آپ کے منتظم کے زیر انتظام ہے</translation>
 <translation id="7569444139234840525"><ph name="QUERY_TEXT" /> · /<ph name="PHONETICS" />/</translation>
 <translation id="7648838807254605802">‏زیادہ HTTPS تاخیر</translation>
@@ -158,6 +165,7 @@
 <translation id="7690294790491645610">نئے پاس ورڈ کی توثیق کریں</translation>
 <translation id="7805768142964895445">صورتحال</translation>
 <translation id="7855434858642800953">اسکین کردہ فائل محفوظ ہو گئی!</translation>
+<translation id="7928373994957558460">فائل کا مقام دکھائیں</translation>
 <translation id="7936303884198020182">کوئی نام سرور نہیں ملا</translation>
 <translation id="8041089156583427627">تاثرات بھیجیں</translation>
 <translation id="808894953321890993">پاس ورڈ تبدیل کریں</translation>
@@ -170,6 +178,8 @@
 <translation id="8347227221149377169">پرنٹ جابز</translation>
 <translation id="8352772353338965963">متعدد سائن ان میں ایک اکاؤنٹ شامل کریں۔ سبھی سائن ان کردہ اکاؤنٹس تک پاس ورڈ کے بغیر رسائی کی جا سکتی ہے لہذا یہ خصوصیت صرف بھروسہ مند اکاؤنٹس کے ساتھ استعمال کی جانی چاہیے۔</translation>
 <translation id="8364946094152050673">نام سرورز خالی ہیں</translation>
+<translation id="8395584934117017006">یہ <ph name="DEVICE_TYPE" /> انٹرپرائز کے زیر انتظام ہے</translation>
+<translation id="8398927464629426868">آلے کی فی الحال چارج ہونے یا چارج ختم ہونے کی شرح</translation>
 <translation id="8475690821716466388">‏WiFi نیٹ ورک کمزور پروٹوکول WEP PSK کے ساتھ محفوظ ہے</translation>
 <translation id="8477551185774834963">‏DNS تاخیر قابل اجازت حد سے تھوڑی سی زیادہ ہے</translation>
 <translation id="871560550817059752">ناکام ہو گیا - سیاہی ختم ہو گئی</translation>
diff --git a/chromeos/strings/chromeos_strings_zh-CN.xtb b/chromeos/strings/chromeos_strings_zh-CN.xtb
index babd306..e638a65a 100644
--- a/chromeos/strings/chromeos_strings_zh-CN.xtb
+++ b/chromeos/strings/chromeos_strings_zh-CN.xtb
@@ -5,6 +5,7 @@
 <translation id="1059913517121127803">无法启动扫描</translation>
 <translation id="1071587090247825784">检测到防火墙</translation>
 <translation id="1075811647922107217">页面大小</translation>
+<translation id="1175697296044146566">此 <ph name="DEVICE_TYPE" /> 由 <ph name="MANAGER" /> 管理。</translation>
 <translation id="1195447618553298278">未知错误。</translation>
 <translation id="1204296502688602597">DNS 延迟时间</translation>
 <translation id="1238612778414822719">HTTPS 延迟</translation>
@@ -26,6 +27,7 @@
 <translation id="1662989795263954667">已停止 - 墨水已用完</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">存在 DNS 解析器</translation>
+<translation id="1743558184855585519">电池达到循环计数上限后,就会被视为已耗尽</translation>
 <translation id="1905710495812624430">已超过允许的尝试次数上限。</translation>
 <translation id="1930797645656624981">Chrome 操作系统输入法服务</translation>
 <translation id="1947737735496445907">已打印</translation>
@@ -43,6 +45,7 @@
 <translation id="2463748424736466148">{ATTEMPTS_LEFT,plural, =1{<ph name="ERROR_MESSAGE" />剩余尝试次数:{0}}other{<ph name="ERROR_MESSAGE" />剩余尝试次数:{0}}}</translation>
 <translation id="249323605434939166"><ph name="QUERY_TEXT" /> · <ph name="SOURCE_LANGUAGE_NAME" /></translation>
 <translation id="2517472476991765520">扫描</translation>
+<translation id="2570743873672969996">正在运行<ph name="TEST_NAME" />测试…</translation>
 <translation id="2805756323405976993">应用</translation>
 <translation id="2872961005593481000">关机</translation>
 <translation id="3008341117444806826">刷新</translation>
@@ -119,6 +122,7 @@
 <translation id="54609108002486618">托管</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />:<ph name="PROBLEMS" /></translation>
 <translation id="5551702563755460533">前往帮助中心了解详情</translation>
+<translation id="5719918614880940190">此指标旨在衡量 CPU 使用情况,是所有核心指标的汇总数据</translation>
 <translation id="5832805196449965646">添加用户</translation>
 <translation id="5895138241574237353">重新启动</translation>
 <translation id="5982592372228113572">(<ph name="BOARD_NAME" />,版本 <ph name="MILESTONE_VERSION" />)</translation>
@@ -154,6 +158,7 @@
 <translation id="7177485034254901881">此 <ph name="DEVICE_TYPE" /> 由 <ph name="MANAGER" /> 管理。管理员可能会远程配置此设备。</translation>
 <translation id="7274587244503383581"><ph name="PRINTED_PAGES_NUMBER" />/<ph name="TOTAL_PAGES_NUMBER" /></translation>
 <translation id="7359657277149375382">文件类型</translation>
+<translation id="7441459999606975924">电池容量会随使用时长的增加而减少</translation>
 <translation id="7561454561030345039">此操作由您的管理员管理</translation>
 <translation id="7569444139234840525"><ph name="QUERY_TEXT" /> · /<ph name="PHONETICS" />/</translation>
 <translation id="7648838807254605802">HTTPS 延迟较高</translation>
@@ -174,6 +179,8 @@
 <translation id="8347227221149377169">打印任务</translation>
 <translation id="8352772353338965963">为多帐号登录添加帐号。用户无需使用密码即可访问所有已登录的帐号,因此您应仅通过受信任的帐号使用此功能。</translation>
 <translation id="8364946094152050673">未指定域名服务器</translation>
+<translation id="8395584934117017006">此 <ph name="DEVICE_TYPE" /> 由企业管理</translation>
+<translation id="8398927464629426868">设备当前的充电或放电速度</translation>
 <translation id="8475690821716466388">Wi-Fi 网络采用了防护能力较弱的 WEP PSK 协议</translation>
 <translation id="8477551185774834963">DNS 延迟时间略微超出了允许的阈值</translation>
 <translation id="871560550817059752">失败 - 墨水已用完</translation>
diff --git a/chromeos/strings/chromeos_strings_zh-TW.xtb b/chromeos/strings/chromeos_strings_zh-TW.xtb
index 590efb65..fbc09ce 100644
--- a/chromeos/strings/chromeos_strings_zh-TW.xtb
+++ b/chromeos/strings/chromeos_strings_zh-TW.xtb
@@ -50,7 +50,7 @@
 <translation id="2872961005593481000">關閉</translation>
 <translation id="3008341117444806826">更新</translation>
 <translation id="3009958530611748826">選取要儲存掃描檔的資料夾</translation>
-<translation id="3054177598518735801"><ph name="CURRENT_VALUE" />mA</translation>
+<translation id="3054177598518735801"><ph name="CURRENT_VALUE" /> mA</translation>
 <translation id="3083667275341675831">連線診斷工具</translation>
 <translation id="3091839911843451378">失敗 - 已停止</translation>
 <translation id="3188257591659621405">我的檔案</translation>
@@ -105,7 +105,7 @@
 <translation id="4921665434385737356"><ph name="NUM_SECONDS" /> 秒內已充電 <ph name="RATE" />。</translation>
 <translation id="4932733599132424254">日期</translation>
 <translation id="4985509611418653372">執行</translation>
-<translation id="5168185087976003268">電池壽命:</translation>
+<translation id="5168185087976003268">電池壽命</translation>
 <translation id="520299634122159966">沒有可用的掃描器</translation>
 <translation id="5212543919916444558">系統在你的畫面上找不到任何能提供協助的內容。
 請輕觸麥克風圖示,直接說出你的問題。</translation>
diff --git a/components/arc/session/arc_property_util_expand_property_contents_fuzzer.cc b/components/arc/session/arc_property_util_expand_property_contents_fuzzer.cc
index d055a7a..18d1e53 100644
--- a/components/arc/session/arc_property_util_expand_property_contents_fuzzer.cc
+++ b/components/arc/session/arc_property_util_expand_property_contents_fuzzer.cc
@@ -16,12 +16,20 @@
 #include "components/arc/test/fake_cros_config.h"
 #include "testing/libfuzzer/libfuzzer_exports.h"
 
+namespace {
+constexpr size_t kMaxInputSize = 256 * 1024;
+}
+
 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
   base::CommandLine::Init(*argc, *argv);
   return 0;
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  // Limit the input size to avoid timing out on ClusterFuzz.
+  if (size > kMaxInputSize)
+    return 0;
+
   FuzzedDataProvider data_provider(data, size);
 
   std::string content = data_provider.ConsumeRandomLengthString(size);
diff --git a/components/arc/session/arc_vm_client_adapter_unittest.cc b/components/arc/session/arc_vm_client_adapter_unittest.cc
index 990fa1bc..03a332b 100644
--- a/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -22,10 +22,10 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
-#include "base/system/sys_info.h"
 #include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/test/bind.h"
+#include "base/test/scoped_chromeos_version_info.h"
 #include "base/test/scoped_run_loop_timeout.h"
 #include "base/time/time.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
@@ -1189,7 +1189,7 @@
 }
 
 TEST_F(ArcVmClientAdapterTest, ChromeOsChannelStable) {
-  base::SysInfo::SetChromeOSVersionInfoForTest(
+  base::test::ScopedChromeOSVersionInfo info(
       "CHROMEOS_RELEASE_TRACK=stable-channel", base::Time::Now());
 
   StartParams start_params(GetPopulatedStartParams());
@@ -1199,13 +1199,11 @@
   EXPECT_TRUE(
       base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
                      "androidboot.chromeos_channel=stable"));
-
-  base::SysInfo::ResetChromeOSVersionInfoForTest();
 }
 
 TEST_F(ArcVmClientAdapterTest, ChromeOsChannelUnknown) {
-  base::SysInfo::SetChromeOSVersionInfoForTest("CHROMEOS_RELEASE_TRACK=invalid",
-                                               base::Time::Now());
+  base::test::ScopedChromeOSVersionInfo info("CHROMEOS_RELEASE_TRACK=invalid",
+                                             base::Time::Now());
 
   StartParams start_params(GetPopulatedStartParams());
   SetValidUserInfo();
@@ -1214,8 +1212,6 @@
   EXPECT_TRUE(
       base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
                      "androidboot.chromeos_channel=unknown"));
-
-  base::SysInfo::ResetChromeOSVersionInfoForTest();
 }
 
 // Tests that the binary translation type is set to None when no library is
diff --git a/components/autofill/core/browser/autofill_handler.cc b/components/autofill/core/browser/autofill_handler.cc
index 58dbf5bd..ad21872a 100644
--- a/components/autofill/core/browser/autofill_handler.cc
+++ b/components/autofill/core/browser/autofill_handler.cc
@@ -13,7 +13,9 @@
 #include "components/autofill/core/common/autofill_internals/log_message.h"
 #include "components/autofill/core/common/autofill_internals/logging_scope.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
+#include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/autofill_tick_clock.h"
+#include "google_apis/google_api_keys.h"
 #include "ui/gfx/geometry/rect_f.h"
 
 namespace autofill {
@@ -43,11 +45,7 @@
 // Returns true if |live_form| does not match |cached_form|, assuming that
 // |live_form|'s language is |live_form_language|.
 bool CachedFormNeedsUpdate(const FormData& live_form,
-                           const LanguageCode& live_form_language,
                            const FormStructure& cached_form) {
-  if (cached_form.current_page_language() != live_form_language)
-    return true;
-
   if (live_form.fields.size() != cached_form.field_count())
     return true;
 
@@ -59,13 +57,34 @@
   return false;
 }
 
+std::string GetAPIKeyForUrl(version_info::Channel channel) {
+  // First look if we can get API key from command line flag.
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kAutofillAPIKey))
+    return command_line.GetSwitchValueASCII(switches::kAutofillAPIKey);
+
+  // Get the API key from Chrome baked keys.
+  if (channel == version_info::Channel::STABLE)
+    return google_apis::GetAPIKey();
+  return google_apis::GetNonStableAPIKey();
+}
+
 }  // namespace
 
 using base::TimeTicks;
 
-AutofillHandler::AutofillHandler(AutofillDriver* driver,
-                                 LogManager* log_manager)
-    : driver_(driver), log_manager_(log_manager) {}
+AutofillHandler::AutofillHandler(
+    AutofillDriver* driver,
+    LogManager* log_manager,
+    AutofillDownloadManagerState enable_download_manager,
+    version_info::Channel channel)
+    : driver_(driver), log_manager_(log_manager) {
+  if (enable_download_manager == ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {
+    download_manager_ = std::make_unique<AutofillDownloadManager>(
+        driver, this, GetAPIKeyForUrl(channel), log_manager);
+  }
+}
 
 AutofillHandler::~AutofillHandler() = default;
 
@@ -215,7 +234,7 @@
       FindCachedFormByRendererId(form.unique_renderer_id);
   if (cached_form) {
     DCHECK(cached_form);
-    if (!CachedFormNeedsUpdate(form, GetPageLanguage(), *cached_form)) {
+    if (!CachedFormNeedsUpdate(form, *cached_form)) {
       // There is no data to return if there are no auto-fillable fields.
       if (!cached_form->autofill_count())
         return false;
diff --git a/components/autofill/core/browser/autofill_handler.h b/components/autofill/core/browser/autofill_handler.h
index 874daab..4af6543 100644
--- a/components/autofill/core/browser/autofill_handler.h
+++ b/components/autofill/core/browser/autofill_handler.h
@@ -20,6 +20,7 @@
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/version_info/channel.h"
 
 namespace gfx {
 class RectF;
@@ -143,6 +144,10 @@
 
   AutofillDriver* driver() { return driver_; }
 
+  AutofillDownloadManager* download_manager() {
+    return download_manager_.get();
+  }
+
 #ifdef UNIT_TEST
   // A public wrapper that calls |mutable_form_structures| for testing purposes
   // only.
@@ -158,7 +163,10 @@
 #endif
 
  protected:
-  AutofillHandler(AutofillDriver* driver, LogManager* log_manager);
+  AutofillHandler(AutofillDriver* driver,
+                  LogManager* log_manager,
+                  AutofillDownloadManagerState enable_download_manager,
+                  version_info::Channel channel);
 
   virtual void OnFormSubmittedImpl(const FormData& form,
                                    bool known_success,
@@ -221,6 +229,11 @@
     return &form_structures_;
   }
 
+  // Exposed for testing.
+  void set_download_manager(AutofillDownloadManager* manager) {
+    download_manager_.reset(manager);
+  }
+
  private:
   // AutofillDownloadManager::Observer:
   void OnLoadedServerPredictions(
@@ -239,6 +252,10 @@
   // Our copy of the form data.
   std::map<FormRendererId, std::unique_ptr<FormStructure>> form_structures_;
 
+  // Handles queries and uploads to Autofill servers. Will be nullptr if
+  // the download manager functionality is disabled.
+  std::unique_ptr<AutofillDownloadManager> download_manager_;
+
   // Will be not null only for |SaveCardBubbleViewsFullFormBrowserTest|.
   ObserverForTest* observer_for_testing_ = nullptr;
 
diff --git a/components/autofill/core/browser/autofill_handler_proxy.cc b/components/autofill/core/browser/autofill_handler_proxy.cc
index e7ea4a96a..3643899 100644
--- a/components/autofill/core/browser/autofill_handler_proxy.cc
+++ b/components/autofill/core/browser/autofill_handler_proxy.cc
@@ -13,7 +13,11 @@
 AutofillHandlerProxy::AutofillHandlerProxy(AutofillDriver* driver,
                                            LogManager* log_manager,
                                            AutofillProvider* provider)
-    : AutofillHandler(driver, log_manager), provider_(provider) {}
+    : AutofillHandler(driver,
+                      log_manager,
+                      DISABLE_AUTOFILL_DOWNLOAD_MANAGER,
+                      version_info::Channel::UNKNOWN),
+      provider_(provider) {}
 
 AutofillHandlerProxy::~AutofillHandlerProxy() {}
 
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index d0dc0dbf9..6a207bb 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -78,7 +78,6 @@
 #include "components/autofill/core/common/autofill_internals/logging_scope.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
 #include "components/autofill/core/common/autofill_prefs.h"
-#include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/autofill_tick_clock.h"
 #include "components/autofill/core/common/autofill_util.h"
 #include "components/autofill/core/common/form_data.h"
@@ -91,8 +90,6 @@
 #include "components/security_interstitials/core/pref_names.h"
 #include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/version_info/channel.h"
-#include "google_apis/google_api_keys.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/rect.h"
@@ -189,19 +186,6 @@
   }
 }
 
-std::string GetAPIKeyForUrl(version_info::Channel channel) {
-  // First look if we can get API key from command line flag.
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kAutofillAPIKey))
-    return command_line.GetSwitchValueASCII(switches::kAutofillAPIKey);
-
-  // Get the API key from Chrome baked keys.
-  if (channel == version_info::Channel::STABLE)
-    return google_apis::GetAPIKey();
-  return google_apis::GetNonStableAPIKey();
-}
-
 ValuePatternsMetric GetValuePattern(const base::string16& value) {
   if (IsUPIVirtualPaymentAddress(value))
     return ValuePatternsMetric::kUpiVpa;
@@ -1561,7 +1545,7 @@
 
 void AutofillManager::UploadFormData(const FormStructure& submitted_form,
                                      bool observed_submission) {
-  if (!download_manager_)
+  if (!download_manager())
     return;
 
   // Check if the form is among the forms that were recently auto-filled.
@@ -1582,7 +1566,7 @@
     non_empty_types.insert(CREDIT_CARD_VERIFICATION_CODE);
   }
 
-  download_manager_->StartUploadRequest(
+  download_manager()->StartUploadRequest(
       submitted_form, was_autofilled, non_empty_types,
       /*login_form_signature=*/std::string(), observed_submission,
       client_->GetPrefs());
@@ -1632,7 +1616,10 @@
     const std::string app_locale,
     AutofillDownloadManagerState enable_download_manager,
     std::unique_ptr<CreditCardAccessManager> cc_access_manager)
-    : AutofillHandler(driver, client->GetLogManager()),
+    : AutofillHandler(driver,
+                      client->GetLogManager(),
+                      enable_download_manager,
+                      client->GetChannel()),
       client_(client),
       log_manager_(client_->GetLogManager()),
       app_locale_(app_locale),
@@ -1661,11 +1648,6 @@
                                     : std::make_unique<CreditCardAccessManager>(
                                           driver, client_, personal_data_,
                                           credit_card_form_event_logger_.get());
-  if (enable_download_manager == ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {
-    version_info::Channel channel = client_->GetChannel();
-    download_manager_.reset(new AutofillDownloadManager(
-        driver, this, GetAPIKeyForUrl(channel), client_->GetLogManager()));
-  }
   CountryNames::SetLocaleString(app_locale_);
   offer_manager_ = client_->GetAutofillOfferManager();
 }
@@ -2138,8 +2120,8 @@
   LogAutofillTypePredictionsAvailable(log_manager_, queryable_forms);
 
   // Query the server if at least one of the forms was parsed.
-  if (!queryable_forms.empty() && download_manager_) {
-    download_manager_->StartQueryRequest(queryable_forms);
+  if (!queryable_forms.empty() && download_manager()) {
+    download_manager()->StartQueryRequest(queryable_forms);
   }
 }
 
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 4e07e12..b8a5eda 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -177,10 +177,6 @@
 
   AutofillClient* client() { return client_; }
 
-  AutofillDownloadManager* download_manager() {
-    return download_manager_.get();
-  }
-
   CreditCardAccessManager* credit_card_access_manager() {
     return credit_card_access_manager_.get();
   }
@@ -377,11 +373,6 @@
   }
 
   // Exposed for testing.
-  void set_download_manager(AutofillDownloadManager* manager) {
-    download_manager_.reset(manager);
-  }
-
-  // Exposed for testing.
   bool is_rich_query_enabled() const { return is_rich_query_enabled_; }
 
   // Exposed for testing.
@@ -648,10 +639,6 @@
 
   base::circular_deque<std::string> autofilled_form_signatures_;
 
-  // Handles queries and uploads to Autofill servers. Will be NULL if
-  // the download manager functionality is disabled.
-  std::unique_ptr<AutofillDownloadManager> download_manager_;
-
   // Handles single-field autocomplete form data.
   // May be NULL.  NULL indicates OTR.
   base::WeakPtr<AutocompleteHistoryManager> autocomplete_history_manager_;
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 6b16cbc..c665e0d 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -7583,7 +7583,8 @@
         version_info::Channel::UNKNOWN}) {
     SCOPED_TRACE(::testing::Message()
                  << "Channel " << static_cast<int>(channel));
-    EXPECT_CALL(autofill_client_, GetChannel()).WillOnce(Return(channel));
+    // One more call is from TestAutofillManager constructor.
+    EXPECT_CALL(autofill_client_, GetChannel()).WillRepeatedly(Return(channel));
     TestAutofillManager test_instance(autofill_driver_.get(), &autofill_client_,
                                       &personal_data_,
                                       autocomplete_history_manager_.get());
@@ -7618,7 +7619,8 @@
     SCOPED_TRACE(::testing::Message()
                  << "Channel " << static_cast<int>(channel));
     EXPECT_FALSE(AutofillManager::IsRichQueryEnabled(channel));
-    EXPECT_CALL(autofill_client_, GetChannel()).WillOnce(Return(channel));
+    // One more call is from TestAutofillManager constructor.
+    EXPECT_CALL(autofill_client_, GetChannel()).WillRepeatedly(Return(channel));
     TestAutofillManager test_instance(autofill_driver_.get(), &autofill_client_,
                                       &personal_data_,
                                       autocomplete_history_manager_.get());
diff --git a/components/autofill_assistant/browser/features.cc b/components/autofill_assistant/browser/features.cc
index 899f459..f4440f9 100644
--- a/components/autofill_assistant/browser/features.cc
+++ b/components/autofill_assistant/browser/features.cc
@@ -19,6 +19,11 @@
 const base::Feature kAutofillAssistantDirectActions{
     "AutofillAssistantDirectActions", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Controls whether to disable onboarding flow for Autofill Assistant
+const base::Feature kAutofillAssistantDisableOnboardingFlow{
+    "AutofillAssistantDisableOnboardingFlow",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kAutofillAssistantProactiveHelp{
     "AutofillAssistantProactiveHelp", base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -27,5 +32,13 @@
 const base::Feature kAutofillAssistantWithTabHelper{
     "AutofillAssistantWithTabHelper", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// By default, proactive help is only offered if MSBB is turned on. This feature
+// flag allows disabling the link. Proactive help can still be offered to users
+// so long as no communication to a remote backend is required. Specifically,
+// base64-injected trigger scripts can be shown even in the absence of MSBB.
+const base::Feature kAutofillAssistantDisableProactiveHelpTiedToMSBB{
+    "AutofillAssistantDisableProactiveHelpTiedToMSBB",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/features.h b/components/autofill_assistant/browser/features.h
index d8cd5cb..8821243 100644
--- a/components/autofill_assistant/browser/features.h
+++ b/components/autofill_assistant/browser/features.h
@@ -16,8 +16,10 @@
 extern const base::Feature kAutofillAssistant;
 extern const base::Feature kAutofillAssistantChromeEntry;
 extern const base::Feature kAutofillAssistantDirectActions;
+extern const base::Feature kAutofillAssistantDisableOnboardingFlow;
 extern const base::Feature kAutofillAssistantProactiveHelp;
 extern const base::Feature kAutofillAssistantWithTabHelper;
+extern const base::Feature kAutofillAssistantDisableProactiveHelpTiedToMSBB;
 
 }  // namespace features
 }  // namespace autofill_assistant
diff --git a/components/data_reduction_proxy/DIR_METADATA b/components/data_reduction_proxy/DIR_METADATA
new file mode 100644
index 0000000..e548f97
--- /dev/null
+++ b/components/data_reduction_proxy/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals>Network>DataProxy"
+}
diff --git a/components/data_reduction_proxy/OWNERS b/components/data_reduction_proxy/OWNERS
index ce288ae1..4b104a29c 100644
--- a/components/data_reduction_proxy/OWNERS
+++ b/components/data_reduction_proxy/OWNERS
@@ -14,7 +14,6 @@
 per-file *_messages*.h=set noparent
 per-file *_messages*.h=file://ipc/SECURITY_OWNERS
 
-# COMPONENT: Internals>Network>DataProxy
 
 # Leave ASCII Art in comments
 ################################################################################
diff --git a/components/data_use_measurement/DIR_METADATA b/components/data_use_measurement/DIR_METADATA
new file mode 100644
index 0000000..3d3ad077
--- /dev/null
+++ b/components/data_use_measurement/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals>Network>DataUse"
+}
diff --git a/components/data_use_measurement/OWNERS b/components/data_use_measurement/OWNERS
index 9bcf864..2783dea 100644
--- a/components/data_use_measurement/OWNERS
+++ b/components/data_use_measurement/OWNERS
@@ -1,3 +1 @@
 file://components/data_reduction_proxy/OWNERS
-
-# COMPONENT: Internals>Network>DataUse
diff --git a/components/dbus/DIR_METADATA b/components/dbus/DIR_METADATA
new file mode 100644
index 0000000..06e78af
--- /dev/null
+++ b/components/dbus/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "OS>Systems"
+}
diff --git a/components/dbus/OWNERS b/components/dbus/OWNERS
index 4d3121d..6f555f868e 100644
--- a/components/dbus/OWNERS
+++ b/components/dbus/OWNERS
@@ -1,3 +1 @@
 file://dbus/OWNERS
-
-# COMPONENT: OS>Systems
diff --git a/components/device_event_log/DIR_METADATA b/components/device_event_log/DIR_METADATA
new file mode 100644
index 0000000..4bb577e
--- /dev/null
+++ b/components/device_event_log/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals>Logging"
+}
diff --git a/components/device_event_log/OWNERS b/components/device_event_log/OWNERS
index baa95df..d313f84 100644
--- a/components/device_event_log/OWNERS
+++ b/components/device_event_log/OWNERS
@@ -1,4 +1,2 @@
 stevenjb@chromium.org
 reillyg@chromium.org
-
-# COMPONENT: Internals>Logging
\ No newline at end of file
diff --git a/components/discardable_memory/DIR_METADATA b/components/discardable_memory/DIR_METADATA
new file mode 100644
index 0000000..14b5edb5
--- /dev/null
+++ b/components/discardable_memory/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals"
+}
diff --git a/components/discardable_memory/OWNERS b/components/discardable_memory/OWNERS
index 44e9f3a..2285adf9 100644
--- a/components/discardable_memory/OWNERS
+++ b/components/discardable_memory/OWNERS
@@ -1,3 +1 @@
 penghuang@chromium.org
-
-# COMPONENT: Internals
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager.h b/components/discardable_memory/client/client_discardable_shared_memory_manager.h
index f949718..3de1d29 100644
--- a/components/discardable_memory/client/client_discardable_shared_memory_manager.h
+++ b/components/discardable_memory/client/client_discardable_shared_memory_manager.h
@@ -34,14 +34,14 @@
 // discardable memory segments through the browser process.
 class DISCARDABLE_MEMORY_EXPORT ClientDiscardableSharedMemoryManager
     : public base::DiscardableMemoryAllocator,
-      public base::trace_event::MemoryDumpProvider {
+      public base::trace_event::MemoryDumpProvider,
+      public base::RefCountedThreadSafe<ClientDiscardableSharedMemoryManager> {
  public:
   ClientDiscardableSharedMemoryManager(
       mojo::PendingRemote<mojom::DiscardableSharedMemoryManager> manager,
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> periodic_purge_task_runner =
           nullptr);
-  ~ClientDiscardableSharedMemoryManager() override;
 
   // Overridden from base::DiscardableMemoryAllocator:
   std::unique_ptr<base::DiscardableMemory> AllocateLockedDiscardableMemory(
@@ -96,6 +96,8 @@
   // These fields are only protected for testing, they would otherwise be
   // private. Everything else should be either public or private.
  protected:
+  friend class base::RefCountedThreadSafe<ClientDiscardableSharedMemoryManager>;
+  ~ClientDiscardableSharedMemoryManager() override;
   ClientDiscardableSharedMemoryManager(
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> periodic_purge_task_runner);
@@ -134,7 +136,9 @@
     bool is_locked() const EXCLUSIVE_LOCKS_REQUIRED(manager_->GetLock());
 
     friend class ClientDiscardableSharedMemoryManager;
-    ClientDiscardableSharedMemoryManager* const manager_;
+    // We need to ensure that |manager_| outlives |this|, to avoid a
+    // use-after-free.
+    scoped_refptr<ClientDiscardableSharedMemoryManager> const manager_;
     std::unique_ptr<DiscardableSharedMemoryHeap::Span> span_;
     // Set to an invalid base::TimeTicks when |this| is Lock()-ed, and to
     // |TimeTicks::Now()| each time |this| is Unlock()-ed.
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc b/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc
index 5dc8114..002e627 100644
--- a/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc
+++ b/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc
@@ -48,8 +48,6 @@
             base::MakeRefCounted<TestSingleThreadTaskRunner>(),
             periodic_purge_task_runner) {}
 
-  ~TestClientDiscardableSharedMemoryManager() override = default;
-
   std::unique_ptr<base::DiscardableSharedMemory>
   AllocateLockedDiscardableSharedMemory(size_t size, int32_t id) override {
     auto shared_memory = std::make_unique<base::DiscardableSharedMemory>();
@@ -73,15 +71,18 @@
     base::AutoLock lock(lock_);
     return timer_ == nullptr;
   }
+
+ private:
+  ~TestClientDiscardableSharedMemoryManager() override = default;
 };
 
 class ClientDiscardableSharedMemoryManagerTest : public testing::Test {
  public:
   void SetUp() override {
     client_ =
-        std::make_unique<TestClientDiscardableSharedMemoryManager>(nullptr);
+        base::MakeRefCounted<TestClientDiscardableSharedMemoryManager>(nullptr);
   }
-  std::unique_ptr<TestClientDiscardableSharedMemoryManager> client_;
+  scoped_refptr<TestClientDiscardableSharedMemoryManager> client_;
   const size_t page_size_ = base::GetPageSize();
 };
 
@@ -92,7 +93,7 @@
       : task_env_(base::test::TaskEnvironment::MainThreadType::UI,
                   base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
   void SetUp() override {
-    client_ = std::make_unique<TestClientDiscardableSharedMemoryManager>(
+    client_ = base::MakeRefCounted<TestClientDiscardableSharedMemoryManager>(
         task_env_.GetMainThreadTaskRunner());
   }
   base::test::TaskEnvironment task_env_;
diff --git a/components/dom_distiller/DIR_METADATA b/components/dom_distiller/DIR_METADATA
new file mode 100644
index 0000000..e745659
--- /dev/null
+++ b/components/dom_distiller/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+  component: "UI>Browser>ReaderMode"
+}
+
+team_email: "dom-distiller-eng@google.com"
diff --git a/components/dom_distiller/OWNERS b/components/dom_distiller/OWNERS
index f500ab38..d3c1ffb 100644
--- a/components/dom_distiller/OWNERS
+++ b/components/dom_distiller/OWNERS
@@ -2,6 +2,3 @@
 mdjones@chromium.org
 nyquist@chromium.org
 wychen@chromium.org
-
-# COMPONENT: UI>Browser>ReaderMode
-# TEAM: dom-distiller-eng@google.com
diff --git a/components/dom_distiller_strings_grdp/DIR_METADATA b/components/dom_distiller_strings_grdp/DIR_METADATA
new file mode 100644
index 0000000..472473b
--- /dev/null
+++ b/components/dom_distiller_strings_grdp/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>ReaderMode"
+}
diff --git a/components/dom_distiller_strings_grdp/OWNERS b/components/dom_distiller_strings_grdp/OWNERS
index 1b6f4e1a..9db3893 100644
--- a/components/dom_distiller_strings_grdp/OWNERS
+++ b/components/dom_distiller_strings_grdp/OWNERS
@@ -1,2 +1 @@
 file://components/dom_distiller/OWNERS
-# COMPONENT: UI>Browser>ReaderMode
diff --git a/components/domain_reliability/DIR_METADATA b/components/domain_reliability/DIR_METADATA
new file mode 100644
index 0000000..cb1a69b4
--- /dev/null
+++ b/components/domain_reliability/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+  component: "Internals>Network>ReportingAndNEL"
+}
+
+team_email: "net-dev@chromium.org"
diff --git a/components/domain_reliability/OWNERS b/components/domain_reliability/OWNERS
index 6016d30..2206787 100644
--- a/components/domain_reliability/OWNERS
+++ b/components/domain_reliability/OWNERS
@@ -1,5 +1,2 @@
 file://net/OWNERS
 file://net/network_error_logging/OWNERS
-
-# COMPONENT: Internals>Network>ReportingAndNEL
-# TEAM: net-dev@chromium.org
diff --git a/components/drive/DIR_METADATA b/components/drive/DIR_METADATA
new file mode 100644
index 0000000..5b8d7cd
--- /dev/null
+++ b/components/drive/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Platform>Apps>FileManager"
+}
diff --git a/components/drive/OWNERS b/components/drive/OWNERS
index fa173c2..540a62f 100644
--- a/components/drive/OWNERS
+++ b/components/drive/OWNERS
@@ -5,4 +5,3 @@
 kinaba@chromium.org
 slangley@chromium.org
 yoshiki@chromium.org
-# COMPONENT: Platform>Apps>FileManager
diff --git a/components/enterprise/browser/reporting/report_generator.cc b/components/enterprise/browser/reporting/report_generator.cc
index ab701ab..38d710ae 100644
--- a/components/enterprise/browser/reporting/report_generator.cc
+++ b/components/enterprise/browser/reporting/report_generator.cc
@@ -56,7 +56,10 @@
     basic_request->set_allocated_os_report(GetOSReport().release());
     basic_request->set_allocated_browser_device_identifier(
         policy::GetBrowserDeviceIdentifier().release());
-#endif
+#if defined(OS_IOS)
+    basic_request->set_device_model(policy::GetDeviceModel());
+#endif  // defined(OS_IOS)
+#endif  // defined(OS_CHROMEOS)
   }
 
   browser_report_generator_.Generate(
diff --git a/components/feed/feed_feature_list.cc b/components/feed/feed_feature_list.cc
index 3554fe7f..d535500d 100644
--- a/components/feed/feed_feature_list.cc
+++ b/components/feed/feed_feature_list.cc
@@ -33,10 +33,6 @@
 const base::Feature kReportFeedUserActions{"ReportFeedUserActions",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Determines whether conditions should be reached before enabling the upload of
-// click and view actions in the feed (e.g., the user needs to view X cards).
-// For example, This is needed when the notice card is at the second position in
-// the feed.
 const base::Feature kInterestFeedV1ClicksAndViewsConditionalUpload{
     "InterestFeedV1ClickAndViewActionsConditionalUpload",
     base::FEATURE_DISABLED_BY_DEFAULT};
@@ -44,12 +40,9 @@
     "InterestFeedV2ClickAndViewActionsConditionalUpload",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Feature that allows the client to automatically dismiss the notice card based
-// on the clicks and views on the notice card.
 const base::Feature kInterestFeedNoticeCardAutoDismiss{
     "InterestFeedNoticeCardAutoDismiss", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Used for A:B testing of a bug fix (crbug.com/1151391).
 const base::Feature kInterestFeedSpinnerAlwaysAnimate{
     "InterestFeedSpinnerAlwaysAnimate", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/components/feed/feed_feature_list.h b/components/feed/feed_feature_list.h
index 4cca493..d7f0a16b 100644
--- a/components/feed/feed_feature_list.h
+++ b/components/feed/feed_feature_list.h
@@ -28,11 +28,18 @@
 // for personalization. Also enables the feed header menu to manage the feed.
 extern const base::Feature kReportFeedUserActions;
 
+// Determines whether conditions should be reached before enabling the upload of
+// click and view actions in the feed (e.g., the user needs to view X cards).
+// For example, this is needed when the notice card is at the second position in
+// the feed.
 extern const base::Feature kInterestFeedV1ClicksAndViewsConditionalUpload;
 extern const base::Feature kInterestFeedV2ClicksAndViewsConditionalUpload;
 
+// Feature that allows the client to automatically dismiss the notice card based
+// on the clicks and views on the notice card.
 extern const base::Feature kInterestFeedNoticeCardAutoDismiss;
 
+// Used for A:B testing of a bug fix (crbug.com/1151391).
 extern const base::Feature kInterestFeedSpinnerAlwaysAnimate;
 
 // Feature that allows users to keep up with and consume web content.
diff --git a/components/flags_ui/flags_state.h b/components/flags_ui/flags_state.h
index cab1448..5e2ecd9 100644
--- a/components/flags_ui/flags_state.h
+++ b/components/flags_ui/flags_state.h
@@ -96,6 +96,16 @@
                               const char* enable_features_flag_name,
                               const char* disable_features_flag_name);
 
+  // Returns the FeatureEntry named |internal_name|. Returns null if no entry is
+  // matched.
+  const FeatureEntry* FindFeatureEntryByName(
+      const std::string& internal_name) const;
+
+  // Gets sanitized entries from |flags_storage|, filtering out any entries that
+  // don't exist in |feature_entries_|, and updates |flags_storage|.
+  void GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
+                                std::set<std::string>* result) const;
+
   // Reads the state from |flags_storage| and fills |switches| with the set of
   // switches corresponding to enabled entries and |features| with the set of
   // strings corresponding to enabled/disabled base::Feature states. Feature
@@ -214,10 +224,6 @@
       const std::set<std::string>& enabled_entries,
       int platform_mask) const;
 
-  // Gets sanitized entries from |flags_storage|, filtering out any entries that
-  // don't exist in |feature_entries_|, and updates |flags_storage|.
-  void GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
-                                std::set<std::string>* result) const;
 
   // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't
   // enabled on the current platform.
@@ -234,10 +240,6 @@
       std::set<std::string>* enabled_entries,
       std::map<std::string, SwitchEntry>* name_to_switch_map) const;
 
-  // Returns the FeatureEntry named |internal_name|. Returns null if no entry is
-  // matched.
-  const FeatureEntry* FindFeatureEntryByName(
-      const std::string& internal_name) const;
 
   // Returns whether there is a FeatureEntry named by |name| in
   // |feature_entries_| that:
diff --git a/components/history/DIR_METADATA b/components/history/DIR_METADATA
new file mode 100644
index 0000000..e5d3d0b
--- /dev/null
+++ b/components/history/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>History"
+}
\ No newline at end of file
diff --git a/components/history/OWNERS b/components/history/OWNERS
index 3a86eb84..a5e53e0 100644
--- a/components/history/OWNERS
+++ b/components/history/OWNERS
@@ -1,2 +1 @@
-sky@chromium.org
-# COMPONENT: UI>Browser>History
+sky@chromium.org
\ No newline at end of file
diff --git a/components/history/core/browser/sync/DIR_METADATA b/components/history/core/browser/sync/DIR_METADATA
new file mode 100644
index 0000000..62ecc04
--- /dev/null
+++ b/components/history/core/browser/sync/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Services>Sync"
+}
\ No newline at end of file
diff --git a/components/history/core/browser/sync/OWNERS b/components/history/core/browser/sync/OWNERS
index ef97383..261ab18 100644
--- a/components/history/core/browser/sync/OWNERS
+++ b/components/history/core/browser/sync/OWNERS
@@ -1,3 +1 @@
 file://components/sync/OWNERS
-
-# COMPONENT: Services>Sync
diff --git a/components/history/ios/DIR_METADATA b/components/history/ios/DIR_METADATA
new file mode 100644
index 0000000..2e5e0d0
--- /dev/null
+++ b/components/history/ios/DIR_METADATA
@@ -0,0 +1,4 @@
+monorail {
+  component: "Mobile>iOSWeb"
+}
+team_email: "ios-directory-owners@chromium.org"
\ No newline at end of file
diff --git a/components/history/ios/OWNERS b/components/history/ios/OWNERS
index 8836311c..e69de29 100644
--- a/components/history/ios/OWNERS
+++ b/components/history/ios/OWNERS
@@ -1,2 +0,0 @@
-# COMPONENT: Mobile>iOSWeb
-# TEAM: ios-directory-owners@chromium.org
diff --git a/components/javascript_dialogs/DIR_METADATA b/components/javascript_dialogs/DIR_METADATA
new file mode 100644
index 0000000..e3d54cf
--- /dev/null
+++ b/components/javascript_dialogs/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Blink>WindowDialog"
+}
diff --git a/components/javascript_dialogs/OWNERS b/components/javascript_dialogs/OWNERS
index 9c92ae3..704db9f 100644
--- a/components/javascript_dialogs/OWNERS
+++ b/components/javascript_dialogs/OWNERS
@@ -1,2 +1 @@
 avi@chromium.org
-# COMPONENT: Blink>WindowDialog
diff --git a/components/javascript_dialogs/views/DIR_METADATA b/components/javascript_dialogs/views/DIR_METADATA
new file mode 100644
index 0000000..2cf1ad6
--- /dev/null
+++ b/components/javascript_dialogs/views/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals>Views>Desktop"
+}
diff --git a/components/javascript_dialogs/views/OWNERS b/components/javascript_dialogs/views/OWNERS
index 82163ec..e69de29 100644
--- a/components/javascript_dialogs/views/OWNERS
+++ b/components/javascript_dialogs/views/OWNERS
@@ -1 +0,0 @@
-# COMPONENT: Internals>Views>Desktop
diff --git a/components/javascript_dialogs_strings_grdp/DIR_METADATA b/components/javascript_dialogs_strings_grdp/DIR_METADATA
new file mode 100644
index 0000000..e3d54cf
--- /dev/null
+++ b/components/javascript_dialogs_strings_grdp/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Blink>WindowDialog"
+}
diff --git a/components/javascript_dialogs_strings_grdp/OWNERS b/components/javascript_dialogs_strings_grdp/OWNERS
index 8872cb4..086dc673 100644
--- a/components/javascript_dialogs_strings_grdp/OWNERS
+++ b/components/javascript_dialogs_strings_grdp/OWNERS
@@ -1,2 +1 @@
 file://components/javascript_dialogs/OWNERS
-# COMPONENT: Blink>WindowDialog
diff --git a/components/js_injection/DIR_METADATA b/components/js_injection/DIR_METADATA
new file mode 100644
index 0000000..6e8bcf2c
--- /dev/null
+++ b/components/js_injection/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+  component: "Mobile>WebView"
+}
+
+team_email: "android-webview-dev@chromium.org"
diff --git a/components/js_injection/OWNERS b/components/js_injection/OWNERS
index e13cff5..5dfb9a2 100644
--- a/components/js_injection/OWNERS
+++ b/components/js_injection/OWNERS
@@ -1,5 +1,2 @@
 ctzsm@chromium.org
 sky@chromium.org
-
-# TEAM: android-webview-dev@chromium.org
-# COMPONENT: Mobile>WebView
diff --git a/components/keep_alive_registry/DIR_METADATA b/components/keep_alive_registry/DIR_METADATA
new file mode 100644
index 0000000..14b5edb5
--- /dev/null
+++ b/components/keep_alive_registry/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals"
+}
diff --git a/components/keep_alive_registry/OWNERS b/components/keep_alive_registry/OWNERS
index 21960ede..87d51bb 100644
--- a/components/keep_alive_registry/OWNERS
+++ b/components/keep_alive_registry/OWNERS
@@ -1,3 +1,2 @@
 benwells@chromium.org
 michaelpg@chromium.org
-# COMPONENT: Internals
diff --git a/components/keyed_service/DIR_METADATA b/components/keyed_service/DIR_METADATA
new file mode 100644
index 0000000..14b5edb5
--- /dev/null
+++ b/components/keyed_service/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals"
+}
diff --git a/components/keyed_service/OWNERS b/components/keyed_service/OWNERS
index 88763f9..4775ae5b 100644
--- a/components/keyed_service/OWNERS
+++ b/components/keyed_service/OWNERS
@@ -1,3 +1,2 @@
 blundell@chromium.org
 hnakashima@chromium.org
-# COMPONENT: Internals
diff --git a/components/language/DIR_METADATA b/components/language/DIR_METADATA
new file mode 100644
index 0000000..45f3f52
--- /dev/null
+++ b/components/language/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+  component: "UI>Browser>Language"
+}
+
+team_email: "language@chromium.org"
diff --git a/components/language/OWNERS b/components/language/OWNERS
index e2c41dc..eaa050d 100644
--- a/components/language/OWNERS
+++ b/components/language/OWNERS
@@ -5,6 +5,3 @@
 megjablon@chromium.org
 renjieliu@chromium.org
 sclittle@chromium.org
-
-# TEAM: language@chromium.org
-# COMPONENT: UI>Browser>Language
diff --git a/components/language_usage_metrics/DIR_METADATA b/components/language_usage_metrics/DIR_METADATA
new file mode 100644
index 0000000..3c135cd
--- /dev/null
+++ b/components/language_usage_metrics/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>Language"
+}
diff --git a/components/language_usage_metrics/OWNERS b/components/language_usage_metrics/OWNERS
index 29abffbbe..bb5c3afc 100644
--- a/components/language_usage_metrics/OWNERS
+++ b/components/language_usage_metrics/OWNERS
@@ -1,2 +1 @@
 file://components/translate/OWNERS
-# COMPONENT: UI>Browser>Language
diff --git a/components/leveldb_proto/DIR_METADATA b/components/leveldb_proto/DIR_METADATA
new file mode 100644
index 0000000..f8e9454
--- /dev/null
+++ b/components/leveldb_proto/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+  component: "Internals>Storage>LevelDBProto"
+}
+
+team_email: "chromium-reviews@chromium.org"
diff --git a/components/leveldb_proto/OWNERS b/components/leveldb_proto/OWNERS
index e0e56f97..a49f7f93e 100644
--- a/components/leveldb_proto/OWNERS
+++ b/components/leveldb_proto/OWNERS
@@ -1,5 +1,2 @@
 nyquist@chromium.org
 ssid@chromium.org
-
-# COMPONENT: Internals>Storage>LevelDBProto
-# TEAM: chromium-reviews@chromium.org
diff --git a/components/link_header_util/DIR_METADATA b/components/link_header_util/DIR_METADATA
new file mode 100644
index 0000000..af30f87
--- /dev/null
+++ b/components/link_header_util/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+  component: "Blink>Loader"
+}
+
+team_email: "loading-dev@chromium.org"
diff --git a/components/link_header_util/OWNERS b/components/link_header_util/OWNERS
index 5b89858..a0fb178 100644
--- a/components/link_header_util/OWNERS
+++ b/components/link_header_util/OWNERS
@@ -4,6 +4,3 @@
 # The Link: header can be parsed at high privilege, so please include a security
 # reviewer as well:
 file://base/SECURITY_OWNERS
-
-# TEAM: loading-dev@chromium.org
-# COMPONENT: Blink>Loader
diff --git a/components/location/DIR_METADATA b/components/location/DIR_METADATA
new file mode 100644
index 0000000..53a76af
--- /dev/null
+++ b/components/location/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Blink>Location"
+}
diff --git a/components/location/OWNERS b/components/location/OWNERS
index 966eb95..5140571 100644
--- a/components/location/OWNERS
+++ b/components/location/OWNERS
@@ -1,3 +1,2 @@
 jyasskin@chromium.org
 tedchoc@chromium.org
-# COMPONENT: Blink>Location
diff --git a/components/login/DIR_METADATA b/components/login/DIR_METADATA
new file mode 100644
index 0000000..ad3c5e1
--- /dev/null
+++ b/components/login/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Shell>OOBE"
+}
diff --git a/components/login/OWNERS b/components/login/OWNERS
index f9350fc..b280edc9 100644
--- a/components/login/OWNERS
+++ b/components/login/OWNERS
@@ -1,4 +1,3 @@
 achuith@chromium.org
 alemate@chromium.org
 xiyuan@chromium.org
-# COMPONENT: UI>Shell>OOBE
diff --git a/components/lookalikes/DIR_METADATA b/components/lookalikes/DIR_METADATA
new file mode 100644
index 0000000..b302215
--- /dev/null
+++ b/components/lookalikes/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>Interstitials"
+}
diff --git a/components/lookalikes/OWNERS b/components/lookalikes/OWNERS
index 1d70c9f..f050018fa 100644
--- a/components/lookalikes/OWNERS
+++ b/components/lookalikes/OWNERS
@@ -1,3 +1 @@
 file://chrome/browser/lookalikes/OWNERS
-
-# COMPONENT: UI>Browser>Interstitials
diff --git a/components/mirroring/service/rtp_stream.h b/components/mirroring/service/rtp_stream.h
index 35ef727c..eff804f 100644
--- a/components/mirroring/service/rtp_stream.h
+++ b/components/mirroring/service/rtp_stream.h
@@ -46,13 +46,13 @@
   // The following are for hardware video encoding.
 
   virtual void CreateVideoEncodeAccelerator(
-      const media::cast::ReceiveVideoEncodeAcceleratorCallback& callback) = 0;
+      media::cast::ReceiveVideoEncodeAcceleratorCallback callback) = 0;
 
   // TODO(crbug.com/1015472): Remove this interface. Instead, create the shared
   // memory in external video encoder through mojo::ScopedSharedBufferHandle.
   virtual void CreateVideoEncodeMemory(
       size_t size,
-      const media::cast::ReceiveVideoEncodeMemoryCallback& callback) = 0;
+      media::cast::ReceiveVideoEncodeMemoryCallback callback) = 0;
 };
 
 // Receives video frames and submits the data to media::cast::VideoSender. It
diff --git a/components/mirroring/service/rtp_stream_unittest.cc b/components/mirroring/service/rtp_stream_unittest.cc
index a6202c2..d0052fac22 100644
--- a/components/mirroring/service/rtp_stream_unittest.cc
+++ b/components/mirroring/service/rtp_stream_unittest.cc
@@ -38,11 +38,10 @@
   void OnError(const std::string& message) override {}
   void RequestRefreshFrame() override {}
   void CreateVideoEncodeAccelerator(
-      const media::cast::ReceiveVideoEncodeAcceleratorCallback& callback)
-      override {}
+      media::cast::ReceiveVideoEncodeAcceleratorCallback callback) override {}
   void CreateVideoEncodeMemory(
       size_t size,
-      const media::cast::ReceiveVideoEncodeMemoryCallback& callback) override {}
+      media::cast::ReceiveVideoEncodeMemoryCallback callback) override {}
 
   base::WeakPtr<RtpStreamClient> GetWeakPtr() {
     return weak_factory_.GetWeakPtr();
diff --git a/components/mirroring/service/session.cc b/components/mirroring/service/session.cc
index 45fcad49..96956e9 100644
--- a/components/mirroring/service/session.cc
+++ b/components/mirroring/service/session.cc
@@ -529,7 +529,7 @@
 }
 
 void Session::CreateVideoEncodeAccelerator(
-    const media::cast::ReceiveVideoEncodeAcceleratorCallback& callback) {
+    media::cast::ReceiveVideoEncodeAcceleratorCallback callback) {
   if (callback.is_null())
     return;
   std::unique_ptr<media::VideoEncodeAccelerator> mojo_vea;
@@ -545,12 +545,13 @@
     mojo_vea.reset(new media::MojoVideoEncodeAccelerator(std::move(vea),
                                                          supported_profiles_));
   }
-  callback.Run(base::ThreadTaskRunnerHandle::Get(), std::move(mojo_vea));
+  std::move(callback).Run(base::ThreadTaskRunnerHandle::Get(),
+                          std::move(mojo_vea));
 }
 
 void Session::CreateVideoEncodeMemory(
     size_t size,
-    const media::cast::ReceiveVideoEncodeMemoryCallback& callback) {
+    media::cast::ReceiveVideoEncodeMemoryCallback callback) {
   DVLOG(1) << __func__;
 
   base::UnsafeSharedMemoryRegion buf =
@@ -559,7 +560,7 @@
   if (!buf.IsValid())
     LOG(WARNING) << "Browser failed to allocate shared memory.";
 
-  callback.Run(std::move(buf));
+  std::move(callback).Run(std::move(buf));
 }
 
 void Session::OnTransportStatusChanged(CastTransportStatus status) {
diff --git a/components/mirroring/service/session.h b/components/mirroring/service/session.h
index 63f7daf..b5c501cc 100644
--- a/components/mirroring/service/session.h
+++ b/components/mirroring/service/session.h
@@ -75,11 +75,10 @@
   void OnError(const std::string& message) override;
   void RequestRefreshFrame() override;
   void CreateVideoEncodeAccelerator(
-      const media::cast::ReceiveVideoEncodeAcceleratorCallback& callback)
-      override;
+      media::cast::ReceiveVideoEncodeAcceleratorCallback callback) override;
   void CreateVideoEncodeMemory(
       size_t size,
-      const media::cast::ReceiveVideoEncodeMemoryCallback& callback) override;
+      media::cast::ReceiveVideoEncodeMemoryCallback callback) override;
 
   // Callbacks by media::cast::CastTransport::Client.
   void OnTransportStatusChanged(media::cast::CastTransportStatus status);
diff --git a/components/ntp_tiles/metrics.cc b/components/ntp_tiles/metrics.cc
index 567baf3d..32cf11a 100644
--- a/components/ntp_tiles/metrics.cc
+++ b/components/ntp_tiles/metrics.cc
@@ -25,7 +25,7 @@
 const char kHistogramServerName[] = "server";
 const char kHistogramPopularName[] = "popular_fetched";
 const char kHistogramBakedInName[] = "popular_baked_in";
-const char kHistogramWhitelistName[] = "whitelist";
+const char kHistogramAllowlistName[] = "allowlist";
 const char kHistogramHomepageName[] = "homepage";
 const char kHistogramCustomLinksName[] = "custom_links";
 const char kHistogramExploreName[] = "explore";
@@ -50,8 +50,8 @@
       return kHistogramBakedInName;
     case TileSource::POPULAR:
       return kHistogramPopularName;
-    case TileSource::WHITELIST:
-      return kHistogramWhitelistName;
+    case TileSource::ALLOWLIST:
+      return kHistogramAllowlistName;
     case TileSource::SUGGESTIONS_SERVICE:
       return kHistogramServerName;
     case TileSource::HOMEPAGE:
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index c6bff3b..a553f9b 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -176,7 +176,7 @@
       return popular_sites_ != nullptr;
     case TileSource::HOMEPAGE:
       return homepage_client_ != nullptr;
-    case TileSource::WHITELIST:
+    case TileSource::ALLOWLIST:
       return supervisor_ != nullptr;
     case TileSource::CUSTOM_LINKS:
       return custom_links_ != nullptr;
@@ -456,11 +456,11 @@
                      top_sites_weak_ptr_factory_.GetWeakPtr()));
 }
 
-base::FilePath MostVisitedSites::GetWhitelistLargeIconPath(const GURL& url) {
+base::FilePath MostVisitedSites::GetAllowlistLargeIconPath(const GURL& url) {
   if (supervisor_) {
-    for (const auto& whitelist : supervisor_->GetWhitelists()) {
-      if (AreURLsEquivalent(whitelist.entry_point, url))
-        return whitelist.large_icon_path;
+    for (const auto& allowlist : supervisor_->GetAllowlists()) {
+      if (AreURLsEquivalent(allowlist.entry_point, url))
+        return allowlist.large_icon_path;
     }
   }
   return base::FilePath();
@@ -489,7 +489,7 @@
         custom_links_ ? GenerateShortTitle(visited.title) : visited.title;
     tile.url = visited.url;
     tile.source = TileSource::TOP_SITES;
-    tile.whitelist_icon_path = GetWhitelistLargeIconPath(visited.url);
+    tile.allowlist_icon_path = GetAllowlistLargeIconPath(visited.url);
     // MostVisitedURL.title is either the title or the URL which is treated
     // exactly as the title. Differentiating here is not worth the overhead.
     tile.title_source = TileTitleSource::TITLE_TAG;
@@ -589,7 +589,7 @@
     tile.source = TileSource::SUGGESTIONS_SERVICE;
     // The title is an aggregation of multiple history entries of one site.
     tile.title_source = TileTitleSource::INFERRED;
-    tile.whitelist_icon_path = GetWhitelistLargeIconPath(url);
+    tile.allowlist_icon_path = GetAllowlistLargeIconPath(url);
     tile.favicon_url = GURL(suggestion_pb.favicon_url());
     tile.data_generation_time = profile_timestamp;
 
@@ -604,41 +604,41 @@
   InitiateNotificationForNewTiles(std::move(tiles));
 }
 
-NTPTilesVector MostVisitedSites::CreateWhitelistEntryPointTiles(
+NTPTilesVector MostVisitedSites::CreateAllowlistEntryPointTiles(
     const std::set<std::string>& used_hosts,
     size_t num_actual_tiles) {
   if (!supervisor_) {
     return NTPTilesVector();
   }
 
-  NTPTilesVector whitelist_tiles;
-  for (const auto& whitelist : supervisor_->GetWhitelists()) {
-    if (whitelist_tiles.size() + num_actual_tiles >= GetMaxNumSites())
+  NTPTilesVector allowlist_tiles;
+  for (const auto& allowlist : supervisor_->GetAllowlists()) {
+    if (allowlist_tiles.size() + num_actual_tiles >= GetMaxNumSites())
       break;
 
     // Skip blocked sites.
-    if (top_sites_ && top_sites_->IsBlocked(whitelist.entry_point))
+    if (top_sites_ && top_sites_->IsBlocked(allowlist.entry_point))
       continue;
 
     // Skip tiles already present.
-    if (used_hosts.find(whitelist.entry_point.host()) != used_hosts.end())
+    if (used_hosts.find(allowlist.entry_point.host()) != used_hosts.end())
       continue;
 
-    // Skip whitelist entry points that are manually blocked.
-    if (supervisor_->IsBlocked(whitelist.entry_point))
+    // Skip allowlist entry points that are manually blocked.
+    if (supervisor_->IsBlocked(allowlist.entry_point))
       continue;
 
     NTPTile tile;
-    tile.title = whitelist.title;
-    tile.url = whitelist.entry_point;
-    tile.source = TileSource::WHITELIST;
+    tile.title = allowlist.title;
+    tile.url = allowlist.entry_point;
+    tile.source = TileSource::ALLOWLIST;
     // User-set. Might be the title but we cannot be sure.
     tile.title_source = TileTitleSource::UNKNOWN;
-    tile.whitelist_icon_path = whitelist.large_icon_path;
-    whitelist_tiles.push_back(std::move(tile));
+    tile.allowlist_icon_path = allowlist.large_icon_path;
+    allowlist_tiles.push_back(std::move(tile));
   }
 
-  return whitelist_tiles;
+  return allowlist_tiles;
 }
 
 std::map<SectionType, NTPTilesVector>
@@ -851,9 +851,9 @@
   }
   AddToHostsAndTotalCount(personal_tiles, &used_hosts, &num_actual_tiles);
 
-  NTPTilesVector whitelist_tiles =
-      CreateWhitelistEntryPointTiles(used_hosts, num_actual_tiles);
-  AddToHostsAndTotalCount(whitelist_tiles, &used_hosts, &num_actual_tiles);
+  NTPTilesVector allowlist_tiles =
+      CreateAllowlistEntryPointTiles(used_hosts, num_actual_tiles);
+  AddToHostsAndTotalCount(allowlist_tiles, &used_hosts, &num_actual_tiles);
 
   std::map<SectionType, NTPTilesVector> sections =
       CreatePopularSitesSections(used_hosts, num_actual_tiles);
@@ -861,7 +861,7 @@
                           &num_actual_tiles);
 
   NTPTilesVector new_tiles =
-      MergeTiles(std::move(personal_tiles), std::move(whitelist_tiles),
+      MergeTiles(std::move(personal_tiles), std::move(allowlist_tiles),
                  std::move(sections[SectionType::PERSONALIZED]), explore_tile);
 
   SaveTilesAndNotify(std::move(new_tiles), std::move(sections));
@@ -891,13 +891,13 @@
 // static
 NTPTilesVector MostVisitedSites::MergeTiles(
     NTPTilesVector personal_tiles,
-    NTPTilesVector whitelist_tiles,
+    NTPTilesVector allowlist_tiles,
     NTPTilesVector popular_tiles,
     base::Optional<NTPTile> explore_tile) {
   NTPTilesVector merged_tiles;
   std::move(personal_tiles.begin(), personal_tiles.end(),
             std::back_inserter(merged_tiles));
-  std::move(whitelist_tiles.begin(), whitelist_tiles.end(),
+  std::move(allowlist_tiles.begin(), allowlist_tiles.end(),
             std::back_inserter(merged_tiles));
   std::move(popular_tiles.begin(), popular_tiles.end(),
             std::back_inserter(merged_tiles));
diff --git a/components/ntp_tiles/most_visited_sites.h b/components/ntp_tiles/most_visited_sites.h
index 85e1096..a2f5403 100644
--- a/components/ntp_tiles/most_visited_sites.h
+++ b/components/ntp_tiles/most_visited_sites.h
@@ -50,7 +50,7 @@
 // Shim interface for SupervisedUserService.
 class MostVisitedSitesSupervisor {
  public:
-  struct Whitelist {
+  struct Allowlist {
     base::string16 title;
     GURL entry_point;
     base::FilePath large_icon_path;
@@ -76,7 +76,7 @@
   virtual bool IsBlocked(const GURL& url) = 0;
 
   // Explicitly-specified sites to show on NTP.
-  virtual std::vector<Whitelist> GetWhitelists() = 0;
+  virtual std::vector<Allowlist> GetAllowlists() = 0;
 
   // If true, be conservative about suggesting sites from outside sources.
   virtual bool IsChildProfile() = 0;
@@ -225,7 +225,7 @@
   // Workhorse for SaveNewTilesAndNotify. Implemented as a separate static and
   // public method for ease of testing.
   static NTPTilesVector MergeTiles(NTPTilesVector personal_tiles,
-                                   NTPTilesVector whitelist_tiles,
+                                   NTPTilesVector allowlist_tiles,
                                    NTPTilesVector popular_tiles,
                                    base::Optional<NTPTile> explore_tile);
 
@@ -257,8 +257,8 @@
   // returned no data.
   void InitiateTopSitesQuery();
 
-  // If there's a whitelist entry point for the URL, return the large icon path.
-  base::FilePath GetWhitelistLargeIconPath(const GURL& url);
+  // If there's a allowlist entry point for the URL, return the large icon path.
+  base::FilePath GetAllowlistLargeIconPath(const GURL& url);
 
   // Callback for when data is available from TopSites.
   void OnMostVisitedURLsAvailable(
@@ -278,8 +278,8 @@
   void BuildCurrentTilesGivenSuggestionsProfile(
       const suggestions::SuggestionsProfile& suggestions_profile);
 
-  // Creates whitelist entry point suggestions whose hosts weren't used yet.
-  NTPTilesVector CreateWhitelistEntryPointTiles(
+  // Creates allowlist entry point suggestions whose hosts weren't used yet.
+  NTPTilesVector CreateAllowlistEntryPointTiles(
       const std::set<std::string>& used_hosts,
       size_t num_actual_tiles);
 
@@ -307,7 +307,7 @@
   // |SaveTilesAndNotify| in the end.
   void InitiateNotificationForNewTiles(NTPTilesVector new_tiles);
 
-  // Takes the personal tiles, creates and merges in whitelist and popular tiles
+  // Takes the personal tiles, creates and merges in allowlist and popular tiles
   // if appropriate. Calls |SaveTilesAndNotify| at the end.
   void MergeMostVisitedTiles(NTPTilesVector personal_tiles);
 
diff --git a/components/ntp_tiles/most_visited_sites_unittest.cc b/components/ntp_tiles/most_visited_sites_unittest.cc
index 440a7ed..cc1e4f79 100644
--- a/components/ntp_tiles/most_visited_sites_unittest.cc
+++ b/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -2190,7 +2190,7 @@
   // Without any popular tiles, the result after merge should be the personal
   // tiles.
   EXPECT_THAT(MostVisitedSites::MergeTiles(std::move(personal_tiles),
-                                           /*whitelist_tiles=*/NTPTilesVector(),
+                                           /*allowlist_tiles=*/NTPTilesVector(),
                                            /*popular_tiles=*/NTPTilesVector(),
                                            /*explore_tile=*/base::nullopt),
               ElementsAre(MatchesTile("Site 1", "https://www.site1.com/",
@@ -2214,7 +2214,7 @@
   // tiles.
   EXPECT_THAT(
       MostVisitedSites::MergeTiles(/*personal_tiles=*/NTPTilesVector(),
-                                   /*whitelist_tiles=*/NTPTilesVector(),
+                                   /*allowlist_tiles=*/NTPTilesVector(),
                                    /*popular_tiles=*/std::move(popular_tiles),
                                    /*explore_tile=*/base::nullopt),
       ElementsAre(
@@ -2239,7 +2239,7 @@
   };
   EXPECT_THAT(
       MostVisitedSites::MergeTiles(std::move(personal_tiles),
-                                   /*whitelist_tiles=*/NTPTilesVector(),
+                                   /*allowlist_tiles=*/NTPTilesVector(),
                                    /*popular_tiles=*/std::move(popular_tiles),
                                    /*explore_tiles=*/explore_tile),
       ElementsAre(
diff --git a/components/ntp_tiles/ntp_tile.cc b/components/ntp_tiles/ntp_tile.cc
index 0df7832f..299e821 100644
--- a/components/ntp_tiles/ntp_tile.cc
+++ b/components/ntp_tiles/ntp_tile.cc
@@ -16,7 +16,7 @@
 bool operator==(const NTPTile& a, const NTPTile& b) {
   return (a.title == b.title) && (a.url == b.url) && (a.source == b.source) &&
          (a.title_source == b.title_source) &&
-         (a.whitelist_icon_path == b.whitelist_icon_path) &&
+         (a.allowlist_icon_path == b.allowlist_icon_path) &&
          (a.favicon_url == b.favicon_url) &&
          (a.from_most_visited == b.from_most_visited);
 }
diff --git a/components/ntp_tiles/ntp_tile.h b/components/ntp_tiles/ntp_tile.h
index 21caea35..dc53589 100644
--- a/components/ntp_tiles/ntp_tile.h
+++ b/components/ntp_tiles/ntp_tile.h
@@ -24,10 +24,10 @@
   TileTitleSource title_source;
   TileSource source;
 
-  // Empty unless whitelists are enabled and this site is in a whitelist.
-  // However, may be non-empty even if |source| is not |WHITELIST|, if this tile
+  // Empty unless allowlists are enabled and this site is in an allowlist.
+  // However, may be non-empty even if |source| is not |ALLOWLIST|, if this tile
   // is also available from another, higher-priority source.
-  base::FilePath whitelist_icon_path;
+  base::FilePath allowlist_icon_path;
 
   // This won't be empty, but might 404 etc.
   GURL favicon_url;
diff --git a/components/ntp_tiles/tile_source.h b/components/ntp_tiles/tile_source.h
index 9376b08..53cac00 100644
--- a/components/ntp_tiles/tile_source.h
+++ b/components/ntp_tiles/tile_source.h
@@ -22,8 +22,8 @@
   POPULAR_BAKED_IN,
   // Tile is a custom link.
   CUSTOM_LINKS,
-  // Tile is on a custodian-managed whitelist.
-  WHITELIST,
+  // Tile is on a custodian-managed allowlist.
+  ALLOWLIST,
   // Tile containing the user-set home page is replacing the home page button.
   HOMEPAGE,
   // Tile comes from explore sites list.
diff --git a/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc b/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
index 945bc87d..6fdf0fb 100644
--- a/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
+++ b/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
@@ -99,7 +99,7 @@
     disabled.SetBoolean("suggestionsService", false);
     disabled.SetBoolean("popular", false);
     disabled.SetBoolean("customLinks", false);
-    disabled.SetBoolean("whitelist", false);
+    disabled.SetBoolean("allowlist", false);
     client_->CallJavascriptFunction(
         "chrome.ntp_tiles_internals.receiveSourceInfo", disabled);
     SendTiles(NTPTilesVector(), FaviconResultMap());
@@ -209,8 +209,8 @@
                    most_visited_sites_->DoesSourceExist(TileSource::TOP_SITES));
   value.SetBoolean("customLinks", most_visited_sites_->DoesSourceExist(
                                       TileSource::CUSTOM_LINKS));
-  value.SetBoolean("whitelist",
-                   most_visited_sites_->DoesSourceExist(TileSource::WHITELIST));
+  value.SetBoolean("allowlist",
+                   most_visited_sites_->DoesSourceExist(TileSource::ALLOWLIST));
 
   if (most_visited_sites_->DoesSourceExist(TileSource::SUGGESTIONS_SERVICE)) {
     value.SetString("suggestionsService.status", suggestions_status_);
@@ -256,8 +256,8 @@
     entry->SetString("title", tile.title);
     entry->SetString("url", tile.url.spec());
     entry->SetInteger("source", static_cast<int>(tile.source));
-    entry->SetString("whitelistIconPath",
-                     tile.whitelist_icon_path.LossyDisplayName());
+    entry->SetString("allowlistIconPath",
+                     tile.allowlist_icon_path.LossyDisplayName());
     if (tile.source == TileSource::CUSTOM_LINKS) {
       entry->SetBoolean("fromMostVisited", tile.from_most_visited);
     }
diff --git a/components/ntp_tiles/webui/resources/ntp_tiles_internals.html b/components/ntp_tiles/webui/resources/ntp_tiles_internals.html
index ef7da4b..ac8fe67 100644
--- a/components/ntp_tiles/webui/resources/ntp_tiles_internals.html
+++ b/components/ntp_tiles/webui/resources/ntp_tiles_internals.html
@@ -97,9 +97,9 @@
           <td class="value" jsdisplay="!$this">no</td>
         </tr>
       </tbody>
-      <tbody jsselect="whitelist">
+      <tbody jsselect="allowlist">
         <tr>
-          <th colspan="2">WHITELIST</th>
+          <th colspan="2">ALLOWLIST</th>
         </tr>
         <tr>
           <td class="detail">enabled</td>
@@ -128,7 +128,7 @@
           <td class="value" jsdisplay="source == 2">POPULAR</td>
           <td class="value" jsdisplay="source == 3">POPULAR_BAKED_IN</td>
           <td class="value" jsdisplay="source == 4">CUSTOM_LINKS</td>
-          <td class="value" jsdisplay="source == 5">WHITELIST</td>
+          <td class="value" jsdisplay="source == 5">ALLOWLIST</td>
           <td class="value" jsdisplay="source == 6">HOMEPAGE</td>
           <td class="value" jsdisplay="source &gt; 6">???</td>
         </tr>
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java b/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java
index 565f679..9998945 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java
@@ -143,13 +143,13 @@
     void notifyPaymentUiOfPendingApps(List<PaymentApp> pendingApps);
 
     /**
-     * Skips the app selector UI whether it is currently opened or not, and if applicable, invokes a
-     * payment app.
+     * Called when these conditions are satisfied: (1) show() has been called, (2) payment apps
+     * are all queried, and (3) PaymentDetails is finalized.
      * @return The error if it fails; null otherwise.
      * @param isUserGestureShow Whether PaymentRequest.show() was invoked with a user gesture.
      */
     @Nullable
-    default String triggerPaymentAppUiSkipIfApplicable(boolean isUserGestureShow) {
+    default String onShowCalledAndAppsQueriedAndDetailsFinalized(boolean isUserGestureShow) {
         return null;
     }
 
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
index e5c7965..4189cc61 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
@@ -749,23 +749,11 @@
         mBrowserPaymentRequest.notifyPaymentUiOfPendingApps(mPendingApps);
         mPendingApps.clear();
         if (mIsShowCalled) {
-            PaymentNotShownError notShownError = ensureHasSupportedPaymentMethods();
+            PaymentNotShownError notShownError = onShowCalledAndAppsQueried();
             if (notShownError != null) {
                 onShowFailed(notShownError);
                 return;
             }
-            String error = mBrowserPaymentRequest.showAppSelector(mIsShowWaitingForUpdatedDetails,
-                    mSpec.getRawTotal(), mSpec.getPaymentOptions(), mIsUserGestureShow);
-            if (error != null) {
-                onShowFailed(error);
-                return;
-            }
-        }
-
-        String error = triggerPaymentAppUiSkipIfApplicable();
-        if (error != null) {
-            onShowFailed(error);
-            return;
         }
 
         if (mIsCanMakePaymentResponsePending) {
@@ -777,6 +765,33 @@
         }
     }
 
+    @Nullable
+    private PaymentNotShownError onShowCalledAndAppsQueried() {
+        assert mIsShowCalled;
+        assert mIsFinishedQueryingPaymentApps;
+        assert mBrowserPaymentRequest != null;
+
+        PaymentNotShownError ensureError = ensureHasSupportedPaymentMethods();
+        if (ensureError != null) return ensureError;
+
+        String showError = mBrowserPaymentRequest.showAppSelector(mIsShowWaitingForUpdatedDetails,
+                mSpec.getRawTotal(), mSpec.getPaymentOptions(), mIsUserGestureShow);
+        if (showError != null) {
+            return new PaymentNotShownError(
+                    NotShownReason.OTHER, showError, PaymentErrorReason.NOT_SUPPORTED);
+        }
+
+        if (mIsShowWaitingForUpdatedDetails) return null;
+        String error = mBrowserPaymentRequest.onShowCalledAndAppsQueriedAndDetailsFinalized(
+                mIsUserGestureShow);
+        if (error != null) {
+            return new PaymentNotShownError(
+                    NotShownReason.OTHER, error, PaymentErrorReason.NOT_SUPPORTED);
+        }
+
+        return null;
+    }
+
     private void onShowFailed(String error) {
         onShowFailed(NotShownReason.OTHER, error, PaymentErrorReason.USER_CANCEL);
     }
@@ -1035,34 +1050,12 @@
         mJourneyLogger.setTriggerTime();
 
         if (mIsFinishedQueryingPaymentApps) {
-            PaymentNotShownError notShownError = ensureHasSupportedPaymentMethods();
+            PaymentNotShownError notShownError = onShowCalledAndAppsQueried();
             if (notShownError != null) {
                 onShowFailed(notShownError);
                 return;
             }
-            String error = mBrowserPaymentRequest.showAppSelector(mIsShowWaitingForUpdatedDetails,
-                    mSpec.getRawTotal(), mSpec.getPaymentOptions(), mIsUserGestureShow);
-            if (error != null) {
-                onShowFailed(error);
-                return;
-            }
         }
-
-        String error = triggerPaymentAppUiSkipIfApplicable();
-        if (error != null) {
-            onShowFailed(error);
-            return;
-        }
-    }
-
-    // Return the error if failed, null if success.
-    @Nullable
-    private String triggerPaymentAppUiSkipIfApplicable() {
-        if (mHasClosed || !mIsFinishedQueryingPaymentApps || !mIsShowCalled
-                || mIsShowWaitingForUpdatedDetails) {
-            return null;
-        }
-        return mBrowserPaymentRequest.triggerPaymentAppUiSkipIfApplicable(mIsUserGestureShow);
     }
 
     /**
@@ -1158,6 +1151,7 @@
 
     private String continueShow(@Nullable PaymentDetails details) {
         assert mIsShowWaitingForUpdatedDetails;
+        assert mBrowserPaymentRequest != null;
         // mSpec.updateWith() can be used only when mSpec has not been destroyed.
         assert !mSpec.isDestroyed();
 
@@ -1173,7 +1167,10 @@
         mIsShowWaitingForUpdatedDetails = false;
         String error = mBrowserPaymentRequest.continueShow(mIsFinishedQueryingPaymentApps);
         if (error != null) return error;
-        return triggerPaymentAppUiSkipIfApplicable();
+
+        if (!mIsFinishedQueryingPaymentApps) return null;
+        return mBrowserPaymentRequest.onShowCalledAndAppsQueriedAndDetailsFinalized(
+                mIsUserGestureShow);
     }
 
     /**
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java
index f0bcb51..bf2f8041 100644
--- a/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java
+++ b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java
@@ -540,10 +540,10 @@
         PaymentRequestService service = defaultBuilder().build();
         show(service);
         Mockito.verify(mBrowserPaymentRequest, Mockito.never())
-                .triggerPaymentAppUiSkipIfApplicable(Mockito.anyBoolean());
+                .onShowCalledAndAppsQueriedAndDetailsFinalized(Mockito.anyBoolean());
         queryPaymentApps();
         Mockito.verify(mBrowserPaymentRequest, Mockito.times(1))
-                .triggerPaymentAppUiSkipIfApplicable(Mockito.anyBoolean());
+                .onShowCalledAndAppsQueriedAndDetailsFinalized(Mockito.anyBoolean());
     }
 
     @Test
@@ -552,13 +552,28 @@
         PaymentRequestService service = defaultBuilder().build();
         service.show(mIsUserGestureDefaultValue, true);
         Mockito.verify(mBrowserPaymentRequest, Mockito.never())
-                .triggerPaymentAppUiSkipIfApplicable(Mockito.anyBoolean());
+                .onShowCalledAndAppsQueriedAndDetailsFinalized(Mockito.anyBoolean());
         queryPaymentApps();
         Mockito.verify(mBrowserPaymentRequest, Mockito.never())
-                .triggerPaymentAppUiSkipIfApplicable(Mockito.anyBoolean());
-        service.updateWith(getDefaultPaymentDetailsUpdate());
+                .onShowCalledAndAppsQueriedAndDetailsFinalized(Mockito.anyBoolean());
+        updateWith(service);
         Mockito.verify(mBrowserPaymentRequest, Mockito.times(1))
-                .triggerPaymentAppUiSkipIfApplicable(Mockito.anyBoolean());
+                .onShowCalledAndAppsQueriedAndDetailsFinalized(Mockito.anyBoolean());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testQueryFinishCanTriggerUiSkipped() {
+        PaymentRequestService service = defaultBuilder().build();
+        service.show(mIsUserGestureDefaultValue, true);
+        Mockito.verify(mBrowserPaymentRequest, Mockito.never())
+                .onShowCalledAndAppsQueriedAndDetailsFinalized(Mockito.anyBoolean());
+        updateWith(service);
+        Mockito.verify(mBrowserPaymentRequest, Mockito.never())
+                .onShowCalledAndAppsQueriedAndDetailsFinalized(Mockito.anyBoolean());
+        queryPaymentApps();
+        Mockito.verify(mBrowserPaymentRequest, Mockito.times(1))
+                .onShowCalledAndAppsQueriedAndDetailsFinalized(Mockito.anyBoolean());
     }
 
     @Test
diff --git a/components/performance_manager/decorators/page_load_tracker_decorator.cc b/components/performance_manager/decorators/page_load_tracker_decorator.cc
index 288dcb6..e453186 100644
--- a/components/performance_manager/decorators/page_load_tracker_decorator.cc
+++ b/components/performance_manager/decorators/page_load_tracker_decorator.cc
@@ -6,6 +6,8 @@
 
 #include <algorithm>
 
+#include "base/compiler_specific.h"
+#include "base/notreached.h"
 #include "components/performance_manager/graph/frame_node_impl.h"
 #include "components/performance_manager/graph/graph_impl.h"
 #include "components/performance_manager/graph/node_attached_data_impl.h"
@@ -50,10 +52,12 @@
 // static
 const char* ToString(LoadIdleState state) {
   switch (state) {
-    case LoadIdleState::kLoadingNotStarted:
-      return "kLoadingNotStarted";
-    case LoadIdleState::kLoading:
-      return "kLoading";
+    case LoadIdleState::kLoadingWaitingForResponse:
+      return "kLoadingWaitingForResponse";
+    case LoadIdleState::kLoadingWaitingForResponseTimedOut:
+      return "kLoadingWaitingForResponseTimedOut";
+    case LoadIdleState::kLoadingDidReceiveResponse:
+      return "kLoadingDidReceiveResponse";
     case LoadIdleState::kLoadedNotIdling:
       return "kLoadedNotIdling";
     case LoadIdleState::kLoadedAndIdling:
@@ -68,8 +72,8 @@
 }  // namespace
 
 // static
+constexpr base::TimeDelta PageLoadTrackerDecorator::kWaitingForResponseTimeout;
 constexpr base::TimeDelta PageLoadTrackerDecorator::kLoadedAndIdlingTimeout;
-// static
 constexpr base::TimeDelta PageLoadTrackerDecorator::kWaitingForIdleTimeout;
 
 PageLoadTrackerDecorator::PageLoadTrackerDecorator() {
@@ -104,7 +108,8 @@
 
   base::Value ret(base::Value::Type::DICTIONARY);
   ret.SetStringKey("load_idle_state", ToString(data->load_idle_state()));
-  ret.SetBoolKey("loading_received_response", data->loading_received_response_);
+  ret.SetBoolKey("is_loading", data->is_loading_);
+  ret.SetBoolKey("received_response", data->received_response_);
 
   return ret;
 }
@@ -114,16 +119,49 @@
   UpdateLoadIdleStateProcess(ProcessNodeImpl::FromNode(process_node));
 }
 
-void PageLoadTrackerDecorator::DidReceiveResponse(PageNodeImpl* page_node) {
+// static
+void PageLoadTrackerDecorator::DidStartLoading(PageNodeImpl* page_node) {
   auto* data = DataImpl::GetOrCreate(page_node);
-  DCHECK(!data->loading_received_response_);
-  data->loading_received_response_ = true;
+
+  // Typically, |data| is a newly created DataImpl. However, if a load starts
+  // before the page reaches an idle state following the previous load, |data|
+  // may indicate that the page is |kLoadedNotIdling| or |kLoadedAndIdling|.
+  // In all cases, restart the state machine at |kLoadingWaitingForResponse|
+  // and clear the |loading_started_| timestamp.
+  DCHECK_NE(data->load_idle_state(),
+            LoadIdleState::kLoadingWaitingForResponseTimedOut);
+  DCHECK_NE(data->load_idle_state(), LoadIdleState::kLoadingDidReceiveResponse);
+  DCHECK_NE(data->load_idle_state(), LoadIdleState::kLoadedAndIdle);
+  DCHECK(data);
+  DCHECK(!data->is_loading_);
+  DCHECK(!data->received_response_);
+  data->is_loading_ = true;
+  data->SetLoadIdleState(page_node, LoadIdleState::kLoadingWaitingForResponse);
+  data->loading_started_ = base::TimeTicks();
   UpdateLoadIdleStatePage(page_node);
 }
 
+// static
+void PageLoadTrackerDecorator::DidReceiveResponse(PageNodeImpl* page_node) {
+  auto* data = DataImpl::Get(page_node);
+
+  DCHECK(data);
+  DCHECK(data->is_loading_);
+  DCHECK(!data->received_response_);
+  data->received_response_ = true;
+
+  UpdateLoadIdleStatePage(page_node);
+}
+
+// static
 void PageLoadTrackerDecorator::DidStopLoading(PageNodeImpl* page_node) {
-  auto* data = DataImpl::GetOrCreate(page_node);
-  data->loading_received_response_ = false;
+  auto* data = DataImpl::Get(page_node);
+
+  DCHECK(data);
+  DCHECK(data->is_loading_);
+  data->is_loading_ = false;
+  data->received_response_ = false;
+
   UpdateLoadIdleStatePage(page_node);
 }
 
@@ -163,13 +201,17 @@
   if (data == nullptr)
     return;
 
-  // This is the terminal state, so should never occur.
-  DCHECK_NE(LoadIdleState::kLoadedAndIdle, data->load_idle_state());
-
   // Cancel any ongoing timers. A new timer will be set if necessary.
-  data->idling_timer_.Stop();
+  data->timer_.Stop();
   const base::TimeTicks now = base::TimeTicks::Now();
 
+  // If this is a new load, set the start time.
+  if (data->loading_started_.is_null()) {
+    DCHECK_EQ(data->load_idle_state(),
+              LoadIdleState::kLoadingWaitingForResponse);
+    data->loading_started_ = now;
+  }
+
   // Determine if the overall timeout has fired.
   if ((data->load_idle_state() == LoadIdleState::kLoadedNotIdling ||
        data->load_idle_state() == LoadIdleState::kLoadedAndIdling) &&
@@ -180,48 +222,93 @@
 
   // Otherwise do normal state transitions.
   switch (data->load_idle_state()) {
-    case LoadIdleState::kLoadingNotStarted: {
-      if (!data->loading_received_response_)
+    case LoadIdleState::kLoadingWaitingForResponse: {
+      if (now - data->loading_started_ >= kWaitingForResponseTimeout) {
+        data->SetLoadIdleState(
+            page_node, LoadIdleState::kLoadingWaitingForResponseTimedOut);
+      }
+
+      FALLTHROUGH;
+    }
+
+    case LoadIdleState::kLoadingWaitingForResponseTimedOut: {
+      if (data->received_response_) {
+        data->SetLoadIdleState(page_node,
+                               LoadIdleState::kLoadingDidReceiveResponse);
         return;
-      data->SetLoadIdleState(page_node, LoadIdleState::kLoading);
+      }
+
+      if (!data->is_loading_) {
+        // Transition to kLoadedAndIdle when load stops without receiving a
+        // response.
+        TransitionToLoadedAndIdle(page_node);
+        return;
+      }
+
+      // Schedule a state update to transition to
+      // |kLoadingWaitingForResponseTimedOut| when the page has been waiting for
+      // a response for too long.
+      if (data->load_idle_state() ==
+          LoadIdleState::kLoadingWaitingForResponse) {
+        ScheduleDelayedUpdateLoadIdleStatePage(
+            page_node, now,
+            data->loading_started_ + kWaitingForResponseTimeout);
+      }
+
       return;
     }
 
-    case LoadIdleState::kLoading: {
-      if (data->loading_received_response_)
+    case LoadIdleState::kLoadingDidReceiveResponse: {
+      if (data->is_loading_) {
+        // DidStopLoading() was not invoked yet.
         return;
+      }
+      // DidStartLoading() -> DidReceiveResponse() -> DidStopLoading() were all
+      // invoked. Wait for the page to become idle.
       data->SetLoadIdleState(page_node, LoadIdleState::kLoadedNotIdling);
       data->loading_stopped_ = now;
       // Let the kLoadedNotIdling state transition evaluate, allowing an
-      // effective transition directly from kLoading to kLoadedAndIdling.
+      // immediate transition to kLoadedAndIdling if the page is already idling.
       FALLTHROUGH;
     }
 
     case LoadIdleState::kLoadedNotIdling: {
-      if (IsIdling(page_node)) {
-        data->SetLoadIdleState(page_node, LoadIdleState::kLoadedAndIdling);
-        data->idling_started_ = now;
+      if (!IsIdling(page_node)) {
+        // Schedule a state update to transition to |kLoadedAndIdle| when the
+        // page has been loaded but not idling for too long.
+        ScheduleDelayedUpdateLoadIdleStatePage(
+            page_node, now, data->loading_stopped_ + kWaitingForIdleTimeout);
+        return;
       }
-      // Break out of the switch statement and set a timer to check for the
-      // next state transition.
-      break;
+
+      data->SetLoadIdleState(page_node, LoadIdleState::kLoadedAndIdling);
+      data->idling_started_ = now;
+      FALLTHROUGH;
     }
 
     case LoadIdleState::kLoadedAndIdling: {
-      // If the page is not still idling then transition back a state.
       if (!IsIdling(page_node)) {
+        // If the page is not still idling then transition back a state.
         data->SetLoadIdleState(page_node, LoadIdleState::kLoadedNotIdling);
-      } else {
+        // Schedule a state update to transition to |kLoadedAndIdle| when the
+        // page has been loaded but not idling for too long.
+        ScheduleDelayedUpdateLoadIdleStatePage(
+            page_node, now, data->loading_stopped_ + kWaitingForIdleTimeout);
+        return;
+      }
+
+      if (now - data->idling_started_ >= kLoadedAndIdlingTimeout) {
         // Idling has been happening long enough so make the last state
         // transition.
-        if (now - data->idling_started_ >= kLoadedAndIdlingTimeout) {
-          TransitionToLoadedAndIdle(page_node);
-          return;
-        }
+        TransitionToLoadedAndIdle(page_node);
+        return;
       }
-      // Break out of the switch statement and set a timer to check for the
-      // next state transition.
-      break;
+
+      // Schedule a state update to transition to |kLoadedAndIdle| when the page
+      // has been idling long enough to be considered "loaded and idle".
+      ScheduleDelayedUpdateLoadIdleStatePage(
+          page_node, now, data->idling_started_ + kLoadedAndIdlingTimeout);
+      return;
     }
 
     // This should never occur.
@@ -229,23 +316,26 @@
       NOTREACHED();
   }
 
-  // Getting here means a new timer needs to be set. Use the nearer of the two
-  // applicable timeouts.
-  base::TimeDelta timeout =
-      (data->loading_stopped_ + kWaitingForIdleTimeout) - now;
-  if (data->load_idle_state() == LoadIdleState::kLoadedAndIdling) {
-    timeout = std::min(timeout,
-                       (data->idling_started_ + kLoadedAndIdlingTimeout) - now);
-  }
+  // All paths of the switch statement return.
+  NOTREACHED();
+}
 
-  // It's safe to use base::Unretained here because the graph owns the timer via
-  // PageNodeImpl, and all nodes are destroyed *before* this observer during
-  // tear down. By the time the observer is destroyed, the timer will have
-  // already been destroyed and the associated posted task canceled.
-  data->idling_timer_.Start(
-      FROM_HERE, timeout,
+// static
+void PageLoadTrackerDecorator::ScheduleDelayedUpdateLoadIdleStatePage(
+    PageNodeImpl* page_node,
+    base::TimeTicks now,
+    base::TimeTicks delayed_run_time) {
+  auto* data = DataImpl::Get(page_node);
+  DCHECK(data);
+  DCHECK_GE(delayed_run_time, now);
+
+  // |timer| is owned by |page_node| indirectly through |data|. Because of that,
+  // the |timer| will be canceled if |page_node| is deleted, making the use of
+  // Unretained() safe.
+  data->timer_.Start(
+      FROM_HERE, delayed_run_time - now,
       base::BindRepeating(&PageLoadTrackerDecorator::UpdateLoadIdleStatePage,
-                          page_node));
+                          base::Unretained(page_node)));
 }
 
 void PageLoadTrackerDecorator::UpdateLoadIdleStateProcess(
@@ -258,8 +348,8 @@
 void PageLoadTrackerDecorator::TransitionToLoadedAndIdle(
     PageNodeImpl* page_node) {
   auto* data = DataImpl::Get(page_node);
+  DCHECK(data);
   data->SetLoadIdleState(page_node, LoadIdleState::kLoadedAndIdle);
-
   // Destroy the metadata as there are no more transitions possible. The
   // machinery will start up again if a navigation occurs.
   DataImpl::Destroy(page_node);
@@ -311,15 +401,24 @@
   load_idle_state_ = load_idle_state;
 
   switch (load_idle_state_) {
-    case LoadIdleState::kLoadingNotStarted:
-    case LoadIdleState::kLoadedAndIdle:
-      page_node->SetIsLoading(false);
+    case LoadIdleState::kLoadingWaitingForResponse:
+    case LoadIdleState::kLoadingDidReceiveResponse: {
+      page_node->SetLoadingState(PageNode::LoadingState::kLoading);
       break;
-    case LoadIdleState::kLoading:
+    }
+    case LoadIdleState::kLoadingWaitingForResponseTimedOut: {
+      page_node->SetLoadingState(PageNode::LoadingState::kLoadingTimedOut);
+      break;
+    }
     case LoadIdleState::kLoadedNotIdling:
-    case LoadIdleState::kLoadedAndIdling:
-      page_node->SetIsLoading(true);
+    case LoadIdleState::kLoadedAndIdling: {
+      page_node->SetLoadingState(PageNode::LoadingState::kLoadedBusy);
       break;
+    }
+    case LoadIdleState::kLoadedAndIdle: {
+      page_node->SetLoadingState(PageNode::LoadingState::kLoadedIdle);
+      break;
+    }
   }
 }
 
diff --git a/components/performance_manager/decorators/page_load_tracker_decorator.h b/components/performance_manager/decorators/page_load_tracker_decorator.h
index e924a2a..b0eae5bf2 100644
--- a/components/performance_manager/decorators/page_load_tracker_decorator.h
+++ b/components/performance_manager/decorators/page_load_tracker_decorator.h
@@ -50,12 +50,19 @@
   // Invoked by PageLoadTrackerDecoratorHelper when corresponding
   // WebContentsObserver methods are invoked, and the WebContents is loading to
   // a different document.
+  static void DidStartLoading(PageNodeImpl* page_node);
   static void DidReceiveResponse(PageNodeImpl* page_node);
   static void DidStopLoading(PageNodeImpl* page_node);
 
  protected:
   friend class PageLoadTrackerDecoratorTest;
 
+  // The amount of time after which a page transitions from
+  // kLoadingWaitingForResponse to kLoadingWaitingForResponseTimedOut if it
+  // hasn't received a response.
+  static constexpr base::TimeDelta kWaitingForResponseTimeout =
+      base::TimeDelta::FromSeconds(5);
+
   // The amount of time a page has to be idle post-loading in order for it to be
   // considered loaded and idle. This is used in UpdateLoadIdleState
   // transitions.
@@ -88,6 +95,13 @@
   void UpdateLoadIdleStateProcess(ProcessNodeImpl* process_node);
   static void UpdateLoadIdleStatePage(PageNodeImpl* page_node);
 
+  // Schedules a call to UpdateLoadIdleStatePage() for |page_node| after
+  // |delayed_run_time| - |now| has elapsed.
+  static void ScheduleDelayedUpdateLoadIdleStatePage(
+      PageNodeImpl* page_node,
+      base::TimeTicks now,
+      base::TimeTicks delayed_run_time);
+
   // Helper function for transitioning to the final state.
   static void TransitionToLoadedAndIdle(PageNodeImpl* page_node);
 
@@ -99,25 +113,32 @@
 
 class PageLoadTrackerDecorator::Data {
  public:
-  // The state transitions associated with a load. In general a page transitions
-  // through these states from top to bottom.
+  // The state transitions associated with a load. This is more granular than
+  // the publicly exposed PageNode::LoadingState, to provide the required
+  // details to implement state transitions.
   enum class LoadIdleState {
-    // The initial state. Can only transition to kLoading from here.
-    kLoadingNotStarted,
+    // Loading started, but no data arrived yet. Can transition to
+    // kLoadingDidReceiveResponse, kLoadingWaitingForResponseTimedOut or
+    // kLoadedAndIdle from here.
+    kLoadingWaitingForResponse,
+    // Loading started and a timeout has elapsed, but no data arrived yet. Can
+    // transition to kLoadingDidReceiveResponse or kLoadedAndIdle from here.
+    kLoadingWaitingForResponseTimedOut,
     // Incoming data has started to arrive for a load. Almost idle signals are
     // ignored in this state. Can transition to kLoadedNotIdling and
     // kLoadedAndIdling from here.
-    kLoading,
+    kLoadingDidReceiveResponse,
     // Loading has completed, but the page has not started idling. Can only
     // transition to kLoadedAndIdling from here.
     kLoadedNotIdling,
     // Loading has completed, and the page is idling. Can transition to
     // kLoadedNotIdling or kLoadedAndIdle from here.
     kLoadedAndIdling,
-    // Loading has completed and the page has been idling for sufficiently long.
-    // This is the final state. Once this state has been reached a signal will
-    // be emitted and no further state transitions will be tracked. Committing a
-    // new non-same document navigation can start the cycle over again.
+    // Loading has completed and the page has been idling for sufficiently long
+    // or encountered an error. This is the final state. Once this state has
+    // been reached a signal will be emitted and no further state transitions
+    // will be tracked. Committing a new non-same document navigation can start
+    // the cycle over again.
     kLoadedAndIdle
   };
 
@@ -132,9 +153,19 @@
   // Returns the LoadIdleState for the page.
   LoadIdleState load_idle_state() const { return load_idle_state_; }
 
+  // Whether there is an ongoing different-document load, i.e. DidStartLoading()
+  // was invoked but not DidStopLoading().
+  bool is_loading_ = false;
+
   // Whether there is an ongoing different-document load for which data started
-  // arriving.
-  bool loading_received_response_ = false;
+  // arriving, i.e. both DidStartLoading() and DidReceiveResponse() were
+  // invoked but not DidStopLoading().
+  bool received_response_ = false;
+
+  // Marks the point in time when the state transitioned to
+  // kLoadingWaitingForResponse. This is used as the basis for the
+  // kWaitingForResponseTimeout.
+  base::TimeTicks loading_started_;
 
   // Marks the point in time when the DidStopLoading signal was received,
   // transitioning to kLoadedAndNotIdling or kLoadedAndIdling. This is used as
@@ -142,18 +173,16 @@
   base::TimeTicks loading_stopped_;
 
   // Marks the point in time when the last transition to kLoadedAndIdling
-  // occurred. Used for gating the transition to kLoadedAndIdle.
+  // occurred. This is used as the basis for the kLoadedAndIdlingTimeout.
   base::TimeTicks idling_started_;
 
-  // A one-shot timer used for transitioning between kLoadedAndIdling and
-  // kLoadedAndIdle.
-  base::OneShotTimer idling_timer_;
+  // A one-shot timer used to transition state after a timeout.
+  base::OneShotTimer timer_;
 
  private:
-  // Initially at kLoadingNotStarted. Transitions through the states via calls
-  // to UpdateLoadIdleState. Is reset to kLoadingNotStarted when a non-same
-  // document navigation is committed.
-  LoadIdleState load_idle_state_ = LoadIdleState::kLoadingNotStarted;
+  // Initially at kLoadingWaitingForResponse when a load starts. Transitions
+  // through the states via calls to UpdateLoadIdleState.
+  LoadIdleState load_idle_state_ = LoadIdleState::kLoadingWaitingForResponse;
 };
 
 }  // namespace performance_manager
diff --git a/components/performance_manager/decorators/page_load_tracker_decorator_helper.cc b/components/performance_manager/decorators/page_load_tracker_decorator_helper.cc
index a590b1b8..f2bccee1 100644
--- a/components/performance_manager/decorators/page_load_tracker_decorator_helper.cc
+++ b/components/performance_manager/decorators/page_load_tracker_decorator_helper.cc
@@ -55,11 +55,9 @@
     }
     outer_->first_web_contents_observer_ = this;
 
-    if (web_contents->IsLoadingToDifferentDocument() &&
-        !web_contents->IsWaitingForResponse()) {
-      // Simulate receiving the missed DidReceiveResponse() notification.
-      DidReceiveResponse();
-    }
+    // |web_contents| must not be loading when it starts being tracked by this
+    // observer. Otherwise, loading state wouldn't be tracked correctly.
+    DCHECK(!web_contents->IsLoadingToDifferentDocument());
   }
 
   WebContentsObserver(const WebContentsObserver&) = delete;
@@ -70,6 +68,20 @@
   }
 
   // content::WebContentsObserver:
+  void DidStartLoading() override {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    DCHECK(web_contents()->IsLoading());
+    DCHECK_EQ(loading_state_, LoadingState::kNotLoading);
+
+    // Only observe top-level navigation to a different document.
+    if (!web_contents()->IsLoadingToDifferentDocument())
+      return;
+
+    loading_state_ = LoadingState::kLoadingWaitingForResponse;
+    NotifyPageLoadTrackerDecoratorOnPMSequence(
+        web_contents(), &PageLoadTrackerDecorator::DidStartLoading);
+  }
+
   void DidReceiveResponse() override {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
@@ -78,20 +90,22 @@
       return;
 
     DCHECK(web_contents()->IsLoading());
-
-#if DCHECK_IS_ON()
-    DCHECK(!did_receive_response_);
-    did_receive_response_ = true;
-#endif
+    DCHECK_EQ(loading_state_, LoadingState::kLoadingWaitingForResponse);
+    loading_state_ = LoadingState::kLoadingDidReceiveResponse;
     NotifyPageLoadTrackerDecoratorOnPMSequence(
         web_contents(), &PageLoadTrackerDecorator::DidReceiveResponse);
   }
 
   void DidStopLoading() override {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-#if DCHECK_IS_ON()
-    did_receive_response_ = false;
-#endif
+
+    // The state can be |kNotLoading| if this isn't a top-level navigation to a
+    // different document.
+    if (loading_state_ == LoadingState::kNotLoading)
+      return;
+
+    loading_state_ = LoadingState::kNotLoading;
+
     NotifyPageLoadTrackerDecoratorOnPMSequence(
         web_contents(), &PageLoadTrackerDecorator::DidStopLoading);
   }
@@ -126,11 +140,23 @@
   WebContentsObserver* prev_;
   WebContentsObserver* next_;
 
-#if DCHECK_IS_ON()
-  // Used to verify the invariant that DidReceiveResponse() cannot be called
-  // twice in a row without a DidStopLoading() in between.
-  bool did_receive_response_ = false;
-#endif
+  enum class LoadingState {
+    // Initial state.
+    // DidStartLoading():     Transition to kLoadingWaitingForResponse.
+    // DidReceiveResponse():  Invalid from this state.
+    // DidStopLoading():      Invalid from this state.
+    kNotLoading,
+    // DidStartLoading():     Invalid from this state.
+    // DidReceiveResponse():  Transition to kLoadingDidReceiveResponse.
+    // DidStopLoading():      Transition to kNotLoading.
+    kLoadingWaitingForResponse,
+    // DidStartLoading():     Invalid from this state.
+    // DidReceiveResponse():  Invalid from this state.
+    // DidStopLoading():      Transition to kNotLoading.
+    kLoadingDidReceiveResponse,
+  };
+
+  LoadingState loading_state_ = LoadingState::kNotLoading;
 
   SEQUENCE_CHECKER(sequence_checker_);
 };
diff --git a/components/performance_manager/decorators/page_load_tracker_decorator_unittest.cc b/components/performance_manager/decorators/page_load_tracker_decorator_unittest.cc
index 11784420..77742e0 100644
--- a/components/performance_manager/decorators/page_load_tracker_decorator_unittest.cc
+++ b/components/performance_manager/decorators/page_load_tracker_decorator_unittest.cc
@@ -23,6 +23,7 @@
 // Aliasing these here makes this unittest much more legible.
 using Data = PageLoadTrackerDecorator::Data;
 using LIS = Data::LoadIdleState;
+using LS = PageNode::LoadingState;
 
 class PageLoadTrackerDecoratorTest : public GraphTestHarness {
  protected:
@@ -34,19 +35,26 @@
     graph()->PassToGraph(base::WrapUnique(pltd_));
   }
 
-  void TestPageAlmostIdleTransitions(bool timeout);
+  void TestPageAlmostIdleTransitions(bool timeout_waiting_for_response,
+                                     bool timeout_waiting_for_idle);
 
   bool IsIdling(const PageNodeImpl* page_node) const {
     return PageLoadTrackerDecorator::IsIdling(page_node);
   }
 
+  static constexpr base::TimeDelta GetWaitingForIdleTimeout() {
+    return PageLoadTrackerDecorator::kWaitingForIdleTimeout;
+  }
+
   PageLoadTrackerDecorator* pltd_ = nullptr;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PageLoadTrackerDecoratorTest);
 };
 
-void PageLoadTrackerDecoratorTest::TestPageAlmostIdleTransitions(bool timeout) {
+void PageLoadTrackerDecoratorTest::TestPageAlmostIdleTransitions(
+    bool timeout_waiting_for_response,
+    bool timeout_waiting_for_idle) {
   static const base::TimeDelta kLoadedAndIdlingTimeout =
       PageLoadTrackerDecorator::kLoadedAndIdlingTimeout;
   static const base::TimeDelta kWaitingForIdleTimeout =
@@ -56,81 +64,101 @@
   auto* frame_node = mock_graph.frame.get();
   auto* page_node = mock_graph.page.get();
   auto* proc_node = mock_graph.process.get();
-  auto* page_data = Data::GetOrCreateForTesting(page_node);
 
   // Initially the page should be in a loading not started state.
-  EXPECT_EQ(LIS::kLoadingNotStarted, page_data->load_idle_state());
-  EXPECT_FALSE(page_node->is_loading());
-  EXPECT_FALSE(page_data->idling_timer_.IsRunning());
+  EXPECT_FALSE(Data::GetForTesting(page_node));
+  EXPECT_EQ(LS::kLoadingNotStarted, page_node->loading_state());
 
-  // The state should transition to loading when DidReceiveResponse() is called
-  // to indicate that loading starts.
+  // The state should transition to loading when DidStartLoading() is called to
+  // indicate that loading starts.
+  PageLoadTrackerDecorator::DidStartLoading(page_node);
+  auto* page_data = Data::GetForTesting(page_node);
+  ASSERT_TRUE(page_data);
+  EXPECT_EQ(LIS::kLoadingWaitingForResponse, page_data->load_idle_state());
+  EXPECT_EQ(LS::kLoading, page_node->loading_state());
+  EXPECT_TRUE(page_data->timer_.IsRunning());
+  EXPECT_EQ(page_data->timer_.GetCurrentDelay(),
+            PageLoadTrackerDecorator::kWaitingForResponseTimeout);
+
+  if (timeout_waiting_for_response) {
+    // Let the timeout run down. The page should transition to loading timed
+    // out.
+    task_env().FastForwardBy(
+        PageLoadTrackerDecorator::kWaitingForResponseTimeout);
+    EXPECT_EQ(LIS::kLoadingWaitingForResponseTimedOut,
+              page_data->load_idle_state());
+    EXPECT_EQ(LS::kLoadingTimedOut, page_node->loading_state());
+    EXPECT_FALSE(page_data->timer_.IsRunning());
+  }
+
+  // Indicate that a response was received. The state should transition to
+  // kLoadingDidReceiveResponse (no matter whether the
+  // kWaitingForResponseTimeout expired since load started).
   PageLoadTrackerDecorator::DidReceiveResponse(page_node);
-  EXPECT_EQ(LIS::kLoading, page_data->load_idle_state());
-  EXPECT_TRUE(page_node->is_loading());
-  EXPECT_FALSE(page_data->idling_timer_.IsRunning());
+  EXPECT_EQ(LIS::kLoadingDidReceiveResponse, page_data->load_idle_state());
+  EXPECT_EQ(LS::kLoading, page_node->loading_state());
+  EXPECT_FALSE(page_data->timer_.IsRunning());
 
-  // Mark the page as idling. It should transition from kLoading directly
-  // to kLoadedAndIdling after this.
+  // Mark the page as idling. It should transition from
+  // kLoadingDidReceiveResponse directly to kLoadedAndIdling after this.
   frame_node->SetNetworkAlmostIdle();
   proc_node->SetMainThreadTaskLoadIsLow(true);
   PageLoadTrackerDecorator::DidStopLoading(page_node);
   EXPECT_EQ(LIS::kLoadedAndIdling, page_data->load_idle_state());
-  EXPECT_TRUE(page_node->is_loading());
-  EXPECT_TRUE(page_data->idling_timer_.IsRunning());
-
-  // Indicate that a response was received again. This should be ignored.
-  PageLoadTrackerDecorator::DidReceiveResponse(page_node);
-  EXPECT_EQ(LIS::kLoadedAndIdling, page_data->load_idle_state());
-  EXPECT_TRUE(page_node->is_loading());
-  EXPECT_TRUE(page_data->idling_timer_.IsRunning());
-  PageLoadTrackerDecorator::DidStopLoading(page_node);
-  EXPECT_EQ(LIS::kLoadedAndIdling, page_data->load_idle_state());
-  EXPECT_TRUE(page_node->is_loading());
-  EXPECT_TRUE(page_data->idling_timer_.IsRunning());
+  EXPECT_EQ(LS::kLoadedBusy, page_node->loading_state());
+  EXPECT_TRUE(page_data->timer_.IsRunning());
 
   // Go back to not idling. We should transition back to kLoadedNotIdling, and
   // a timer should still be running.
   frame_node->OnNavigationCommitted(GURL(), false);
   EXPECT_FALSE(frame_node->network_almost_idle());
   EXPECT_EQ(LIS::kLoadedNotIdling, page_data->load_idle_state());
-  EXPECT_TRUE(page_data->idling_timer_.IsRunning());
+  EXPECT_TRUE(page_data->timer_.IsRunning());
 
-  if (timeout) {
+  if (timeout_waiting_for_idle) {
     // Let the timeout run down. The final state transition should occur.
     task_env().FastForwardBy(kWaitingForIdleTimeout);
     EXPECT_FALSE(Data::GetForTesting(page_node));
-    EXPECT_FALSE(page_node->is_loading());
+    EXPECT_EQ(LS::kLoadedIdle, page_node->loading_state());
   } else {
     // Go back to idling.
     frame_node->SetNetworkAlmostIdle();
     EXPECT_TRUE(frame_node->network_almost_idle());
     EXPECT_EQ(LIS::kLoadedAndIdling, page_data->load_idle_state());
-    EXPECT_TRUE(page_node->is_loading());
-    EXPECT_TRUE(page_data->idling_timer_.IsRunning());
+    EXPECT_EQ(LS::kLoadedBusy, page_node->loading_state());
+    EXPECT_TRUE(page_data->timer_.IsRunning());
 
     // Let the idle timer evaluate. The final state transition should occur.
     task_env().FastForwardBy(kLoadedAndIdlingTimeout);
     EXPECT_FALSE(Data::GetForTesting(page_node));
-    EXPECT_FALSE(page_node->is_loading());
+    EXPECT_EQ(LS::kLoadedIdle, page_node->loading_state());
   }
 
   // Firing other signals should not change the state at all.
   proc_node->SetMainThreadTaskLoadIsLow(false);
   EXPECT_FALSE(Data::GetForTesting(page_node));
-  EXPECT_FALSE(page_node->is_loading());
+  EXPECT_EQ(LS::kLoadedIdle, page_node->loading_state());
   frame_node->OnNavigationCommitted(GURL(), false);
   EXPECT_FALSE(frame_node->network_almost_idle());
   EXPECT_FALSE(Data::GetForTesting(page_node));
-  EXPECT_FALSE(page_node->is_loading());
+  EXPECT_EQ(LS::kLoadedIdle, page_node->loading_state());
 }
 
 TEST_F(PageLoadTrackerDecoratorTest, TestTransitionsNoTimeout) {
-  TestPageAlmostIdleTransitions(false);
+  TestPageAlmostIdleTransitions(false, false);
 }
 
-TEST_F(PageLoadTrackerDecoratorTest, TestTransitionsWithTimeout) {
-  TestPageAlmostIdleTransitions(true);
+TEST_F(PageLoadTrackerDecoratorTest, TestTransitionsTimeoutWaitingForResponse) {
+  TestPageAlmostIdleTransitions(true, false);
+}
+
+TEST_F(PageLoadTrackerDecoratorTest, TestTransitionsTimeoutWaitingForIdle) {
+  TestPageAlmostIdleTransitions(false, true);
+}
+
+TEST_F(PageLoadTrackerDecoratorTest,
+       TestTransitionsTimeoutWaitingForResponseAndWaitingForIdle) {
+  TestPageAlmostIdleTransitions(true, true);
 }
 
 TEST_F(PageLoadTrackerDecoratorTest, TestTransitionsNotIdlingOnDidStopLoading) {
@@ -138,19 +166,20 @@
   auto* frame_node = mock_graph.frame.get();
   auto* page_node = mock_graph.page.get();
   auto* proc_node = mock_graph.process.get();
-  auto* page_data = Data::GetOrCreateForTesting(page_node);
 
   // Initially the page should be in a loading not started state.
-  EXPECT_EQ(LIS::kLoadingNotStarted, page_data->load_idle_state());
-  EXPECT_FALSE(page_node->is_loading());
-  EXPECT_FALSE(page_data->idling_timer_.IsRunning());
+  EXPECT_FALSE(Data::GetForTesting(page_node));
+  EXPECT_EQ(LS::kLoadingNotStarted, page_node->loading_state());
 
   // The state should transition to loading when DidReceiveResponse() is called
   // to indicate that loading starts.
+  PageLoadTrackerDecorator::DidStartLoading(page_node);
   PageLoadTrackerDecorator::DidReceiveResponse(page_node);
-  EXPECT_EQ(LIS::kLoading, page_data->load_idle_state());
-  EXPECT_TRUE(page_node->is_loading());
-  EXPECT_FALSE(page_data->idling_timer_.IsRunning());
+  auto* page_data = Data::GetForTesting(page_node);
+  ASSERT_TRUE(page_data);
+  EXPECT_EQ(LIS::kLoadingDidReceiveResponse, page_data->load_idle_state());
+  EXPECT_EQ(LS::kLoading, page_node->loading_state());
+  EXPECT_FALSE(page_data->timer_.IsRunning());
 
   // Mark the page as not idling.
   frame_node->OnNavigationCommitted(GURL(), false);
@@ -160,8 +189,58 @@
   // DidStopLoading() should cause a transition to kLoadedNotIdling.
   PageLoadTrackerDecorator::DidStopLoading(page_node);
   EXPECT_EQ(LIS::kLoadedNotIdling, page_data->load_idle_state());
-  EXPECT_TRUE(page_node->is_loading());
-  EXPECT_TRUE(page_data->idling_timer_.IsRunning());
+  EXPECT_EQ(LS::kLoadedBusy, page_node->loading_state());
+  EXPECT_TRUE(page_data->timer_.IsRunning());
+}
+
+TEST_F(PageLoadTrackerDecoratorTest, TestStartLoadingAgainBeforeIdle) {
+  MockSinglePageInSingleProcessGraph mock_graph(graph());
+  auto* frame_node = mock_graph.frame.get();
+  auto* page_node = mock_graph.page.get();
+  auto* proc_node = mock_graph.process.get();
+
+  // Initially the page should be in a loading not started state.
+  EXPECT_FALSE(Data::GetForTesting(page_node));
+  EXPECT_EQ(LS::kLoadingNotStarted, page_node->loading_state());
+
+  // The state should transition to loading when DidReceiveResponse() is called
+  // to indicate that loading starts.
+  PageLoadTrackerDecorator::DidStartLoading(page_node);
+  PageLoadTrackerDecorator::DidReceiveResponse(page_node);
+  auto* page_data = Data::GetForTesting(page_node);
+  ASSERT_TRUE(page_data);
+  EXPECT_EQ(LIS::kLoadingDidReceiveResponse, page_data->load_idle_state());
+  EXPECT_EQ(LS::kLoading, page_node->loading_state());
+
+  // Mark the page as not idling.
+  frame_node->OnNavigationCommitted(GURL(), false);
+  proc_node->SetMainThreadTaskLoadIsLow(false);
+  EXPECT_FALSE(IsIdling(page_node));
+
+  // DidStopLoading() should cause a transition to kLoadedNotIdling.
+  PageLoadTrackerDecorator::DidStopLoading(page_node);
+  EXPECT_EQ(LIS::kLoadedNotIdling, page_data->load_idle_state());
+  EXPECT_EQ(LS::kLoadedBusy, page_node->loading_state());
+
+  // The state should transition to loading if DidStartLoading() is invoked
+  // again, before the page reaches an idle state.
+  PageLoadTrackerDecorator::DidStartLoading(page_node);
+  EXPECT_EQ(LIS::kLoadingWaitingForResponse, page_data->load_idle_state());
+  EXPECT_EQ(LS::kLoading, page_node->loading_state());
+
+  // Test transitions until the page is loaded and idle.
+  PageLoadTrackerDecorator::DidReceiveResponse(page_node);
+  EXPECT_EQ(LIS::kLoadingDidReceiveResponse, page_data->load_idle_state());
+  EXPECT_EQ(LS::kLoading, page_node->loading_state());
+
+  PageLoadTrackerDecorator::DidStopLoading(page_node);
+  EXPECT_EQ(LIS::kLoadedNotIdling, page_data->load_idle_state());
+  EXPECT_EQ(LS::kLoadedBusy, page_node->loading_state());
+
+  task_env().FastForwardBy(GetWaitingForIdleTimeout());
+
+  EXPECT_FALSE(Data::GetForTesting(page_node));
+  EXPECT_EQ(LS::kLoadedIdle, page_node->loading_state());
 }
 
 TEST_F(PageLoadTrackerDecoratorTest, IsIdling) {
diff --git a/components/performance_manager/decorators/site_data_recorder.cc b/components/performance_manager/decorators/site_data_recorder.cc
index 693e397..97eb943 100644
--- a/components/performance_manager/decorators/site_data_recorder.cc
+++ b/components/performance_manager/decorators/site_data_recorder.cc
@@ -38,6 +38,18 @@
 
 namespace {
 
+bool IsLoadedIdle(PageNode::LoadingState loading_state) {
+  switch (loading_state) {
+    case PageNode::LoadingState::kLoadingNotStarted:
+    case PageNode::LoadingState::kLoadedBusy:
+    case PageNode::LoadingState::kLoading:
+    case PageNode::LoadingState::kLoadingTimedOut:
+      return false;
+    case PageNode::LoadingState::kLoadedIdle:
+      return true;
+  }
+}
+
 // NodeAttachedData used to adorn every page node with a SiteDataWriter.
 class SiteDataNodeData : public NodeAttachedDataImpl<SiteDataNodeData>,
                          public SiteDataRecorder::Data {
@@ -62,7 +74,7 @@
 
   // Functions called whenever one of the tracked properties changes.
   void OnMainFrameUrlChanged(const GURL& url, bool page_is_visible);
-  void OnIsLoadingChanged(bool is_loading);
+  void OnIsLoadedIdleChanged(bool is_loaded_idle);
   void OnIsVisibleChanged(bool is_visible);
   void OnIsAudibleChanged(bool audible);
   void OnTitleUpdated();
@@ -111,9 +123,9 @@
   // The PageNode that owns this object.
   const PageNodeImpl* page_node_ = nullptr;
 
-  // The time at which this tab switched to the loaded state, null if this tab
-  // is not currently loaded.
-  base::TimeTicks loaded_time_;
+  // The time at which this tab switched to LoadingState::kLoadedIdle, null if
+  // this tab is not currently in that state.
+  base::TimeTicks loaded_idle_time_;
 
   std::unique_ptr<SiteDataWriter> writer_;
   std::unique_ptr<SiteDataReader> reader_;
@@ -140,22 +152,26 @@
   writer_ = data_cache_->GetWriterForOrigin(origin);
   reader_ = data_cache_->GetReaderForOrigin(origin);
 
-  // The writer is assumed to be in an unloaded state by default, set the proper
-  // loading state if necessary.
-  if (!page_node_->is_loading())
-    OnIsLoadingChanged(false);
+  // The writer is assumed not to be LoadingState::kLoadedIdle at this point.
+  // Make adjustments if it is LoadingState::kLoadedIdle.
+  if (IsLoadedIdle(page_node_->loading_state()))
+    OnIsLoadedIdleChanged(true);
+
+  DCHECK_EQ(IsLoadedIdle(page_node_->loading_state()),
+            !loaded_idle_time_.is_null());
 }
 
-void SiteDataNodeData::OnIsLoadingChanged(bool is_loading) {
+void SiteDataNodeData::OnIsLoadedIdleChanged(bool is_loaded_idle) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!writer_)
     return;
-  if (is_loading && !loaded_time_.is_null()) {
+
+  if (!is_loaded_idle && !loaded_idle_time_.is_null()) {
     writer_->NotifySiteUnloaded(GetPageNodeVisibility());
-    loaded_time_ = base::TimeTicks();
-  } else if (!is_loading) {
+    loaded_idle_time_ = base::TimeTicks();
+  } else if (is_loaded_idle) {
     writer_->NotifySiteLoaded(GetPageNodeVisibility());
-    loaded_time_ = base::TimeTicks::Now();
+    loaded_idle_time_ = base::TimeTicks::Now();
   }
 }
 
@@ -164,9 +180,9 @@
   if (!writer_)
     return;
   if (is_visible) {
-    writer_->NotifySiteForegrounded(!page_node_->is_loading());
+    writer_->NotifySiteForegrounded(IsLoadedIdle(page_node_->loading_state()));
   } else {
-    writer_->NotifySiteBackgrounded(!page_node_->is_loading());
+    writer_->NotifySiteBackgrounded(IsLoadedIdle(page_node_->loading_state()));
   }
 }
 
@@ -196,9 +212,10 @@
 
 void SiteDataNodeData::Reset() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (writer_ && !loaded_time_.is_null() && !page_node_->is_loading()) {
+  if (writer_ && !loaded_idle_time_.is_null() &&
+      IsLoadedIdle(page_node_->loading_state())) {
     writer_->NotifySiteUnloaded(GetPageNodeVisibility());
-    loaded_time_ = base::TimeTicks();
+    loaded_idle_time_ = base::TimeTicks();
   }
   writer_.reset();
   reader_.reset();
@@ -211,7 +228,7 @@
     return true;
 
   // Ignore all features happening before the website gets fully loaded.
-  if (page_node_->is_loading())
+  if (!IsLoadedIdle(page_node_->loading_state()))
     return true;
 
   // Ignore events if the tab is not in background.
@@ -220,8 +237,8 @@
 
   if (feature_type == FeatureType::kTitleChange ||
       feature_type == FeatureType::kFaviconChange) {
-    DCHECK(!loaded_time_.is_null());
-    if (base::TimeTicks::Now() - loaded_time_ <
+    DCHECK(!loaded_idle_time_.is_null());
+    if (base::TimeTicks::Now() - loaded_idle_time_ <
         kTitleOrFaviconChangePostLoadGracePeriod) {
       return true;
     }
@@ -292,10 +309,10 @@
                               page_node->IsVisible());
 }
 
-void SiteDataRecorder::OnIsLoadingChanged(const PageNode* page_node) {
+void SiteDataRecorder::OnLoadingStateChanged(const PageNode* page_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   auto* data = GetSiteDataNodeDataFromPageNode(page_node);
-  data->OnIsLoadingChanged(page_node->IsLoading());
+  data->OnIsLoadedIdleChanged(IsLoadedIdle(page_node->GetLoadingState()));
 }
 
 void SiteDataRecorder::OnIsVisibleChanged(const PageNode* page_node) {
diff --git a/components/performance_manager/decorators/site_data_recorder_unittest.cc b/components/performance_manager/decorators/site_data_recorder_unittest.cc
index 854d875..61440d2 100644
--- a/components/performance_manager/decorators/site_data_recorder_unittest.cc
+++ b/components/performance_manager/decorators/site_data_recorder_unittest.cc
@@ -157,7 +157,7 @@
       auto* page_node_impl = PageNodeImpl::FromNode(page_node.get());
       page_node_impl->SetIsAudible(false);
       page_node_impl->SetIsVisible(false);
-      page_node_impl->SetIsLoading(true);
+      page_node_impl->SetLoadingState(PageNode::LoadingState::kLoading);
     }));
   }
 
@@ -242,7 +242,7 @@
 
     node_impl = PageNodeImpl::FromNode(page_node.get());
     EXPECT_CALL(*mock_writer, NotifySiteLoaded(TabVisibility::kBackground));
-    node_impl->SetIsLoading(false);
+    node_impl->SetLoadingState(PageNode::LoadingState::kLoadedIdle);
     ::testing::Mock::VerifyAndClear(mock_writer);
 
     EXPECT_CALL(*mock_writer, NotifySiteForegrounded(true));
@@ -373,11 +373,11 @@
     // Test that the load/unload events get forwarded to the writer.
 
     EXPECT_CALL(*mock_writer, NotifySiteLoaded(TabVisibility::kBackground));
-    node_impl->SetIsLoading(false);
+    node_impl->SetLoadingState(PageNode::LoadingState::kLoadedIdle);
     ::testing::Mock::VerifyAndClear(mock_writer);
 
     EXPECT_CALL(*mock_writer, NotifySiteUnloaded(TabVisibility::kBackground));
-    node_impl->SetIsLoading(true);
+    node_impl->SetLoadingState(PageNode::LoadingState::kLoading);
     ::testing::Mock::VerifyAndClear(mock_writer);
   }));
 }
diff --git a/components/performance_manager/graph/page_node.cc b/components/performance_manager/graph/page_node.cc
index b1a40079..1ae4e7f 100644
--- a/components/performance_manager/graph/page_node.cc
+++ b/components/performance_manager/graph/page_node.cc
@@ -23,6 +23,23 @@
   NOTREACHED();
 }
 
+// static
+const char* PageNode::ToString(PageNode::LoadingState loading_state) {
+  switch (loading_state) {
+    case LoadingState::kLoadingNotStarted:
+      return "kLoadingNotStated";
+    case LoadingState::kLoading:
+      return "kLoading";
+    case LoadingState::kLoadingTimedOut:
+      return "kLoadingTimedOut";
+    case LoadingState::kLoadedBusy:
+      return "kLoadedBusy";
+    case LoadingState::kLoadedIdle:
+      return "kLoadedIdle";
+  }
+  NOTREACHED();
+}
+
 PageNode::PageNode() = default;
 PageNode::~PageNode() = default;
 
diff --git a/components/performance_manager/graph/page_node_impl.cc b/components/performance_manager/graph/page_node_impl.cc
index e8352a8..e2923509 100644
--- a/components/performance_manager/graph/page_node_impl.cc
+++ b/components/performance_manager/graph/page_node_impl.cc
@@ -68,8 +68,8 @@
   }
 }
 
-void PageNodeImpl::SetIsLoading(bool is_loading) {
-  is_loading_.SetAndMaybeNotify(this, is_loading);
+void PageNodeImpl::SetLoadingState(LoadingState loading_state) {
+  loading_state_.SetAndMaybeNotify(this, loading_state);
 }
 
 void PageNodeImpl::SetIsVisible(bool is_visible) {
@@ -176,9 +176,9 @@
   return is_audible_.value();
 }
 
-bool PageNodeImpl::is_loading() const {
+PageNode::LoadingState PageNodeImpl::loading_state() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return is_loading_.value();
+  return loading_state_.value();
 }
 
 ukm::SourceId PageNodeImpl::ukm_source_id() const {
@@ -358,9 +358,9 @@
   return is_audible();
 }
 
-bool PageNodeImpl::IsLoading() const {
+PageNode::LoadingState PageNodeImpl::GetLoadingState() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return is_loading();
+  return loading_state();
 }
 
 ukm::SourceId PageNodeImpl::GetUkmSourceID() const {
diff --git a/components/performance_manager/graph/page_node_impl.h b/components/performance_manager/graph/page_node_impl.h
index 7242e1ae..c83e517 100644
--- a/components/performance_manager/graph/page_node_impl.h
+++ b/components/performance_manager/graph/page_node_impl.h
@@ -57,7 +57,7 @@
 
   void SetIsVisible(bool is_visible);
   void SetIsAudible(bool is_audible);
-  void SetIsLoading(bool is_loading);
+  void SetLoadingState(LoadingState loading_state);
   void SetUkmSourceId(ukm::SourceId ukm_source_id);
   void OnFaviconUpdated();
   void OnTitleUpdated();
@@ -87,7 +87,7 @@
   OpenedType opened_type() const;
   bool is_visible() const;
   bool is_audible() const;
-  bool is_loading() const;
+  LoadingState loading_state() const;
   ukm::SourceId ukm_source_id() const;
   LifecycleState lifecycle_state() const;
   bool is_holding_weblock() const;
@@ -180,7 +180,7 @@
   bool IsVisible() const override;
   base::TimeDelta GetTimeSinceLastVisibilityChange() const override;
   bool IsAudible() const override;
-  bool IsLoading() const override;
+  LoadingState GetLoadingState() const override;
   ukm::SourceId GetUkmSourceID() const override;
   LifecycleState GetLifecycleState() const override;
   bool IsHoldingWebLock() const override;
@@ -272,9 +272,10 @@
       is_audible_{false};
   // The loading state. This is driven by instrumentation in the browser
   // process.
-  ObservedProperty::NotifiesOnlyOnChanges<bool,
-                                          &PageNodeObserver::OnIsLoadingChanged>
-      is_loading_{false};
+  ObservedProperty::NotifiesOnlyOnChanges<
+      LoadingState,
+      &PageNodeObserver::OnLoadingStateChanged>
+      loading_state_{LoadingState::kLoadingNotStarted};
   // The UKM source ID associated with the URL of the main frame of this page.
   ObservedProperty::NotifiesOnlyOnChanges<
       ukm::SourceId,
diff --git a/components/performance_manager/graph/page_node_impl_describer.cc b/components/performance_manager/graph/page_node_impl_describer.cc
index c0a3e2fe..6fb1f812 100644
--- a/components/performance_manager/graph/page_node_impl_describer.cc
+++ b/components/performance_manager/graph/page_node_impl_describer.cc
@@ -60,7 +60,9 @@
                       page_node_impl->browser_context_id_);
   result.SetBoolKey("is_visible", page_node_impl->is_visible_.value());
   result.SetBoolKey("is_audible", page_node_impl->is_audible_.value());
-  result.SetBoolKey("is_loading", page_node_impl->is_loading_.value());
+  result.SetStringKey(
+      "loading_state",
+      PageNode::ToString(page_node_impl->loading_state_.value()));
   result.SetStringKey(
       "ukm_source_id",
       base::NumberToString(page_node_impl->ukm_source_id_.value()));
diff --git a/components/performance_manager/graph/page_node_impl_unittest.cc b/components/performance_manager/graph/page_node_impl_unittest.cc
index 050c4c2..92fe008 100644
--- a/components/performance_manager/graph/page_node_impl_unittest.cc
+++ b/components/performance_manager/graph/page_node_impl_unittest.cc
@@ -164,24 +164,26 @@
   EXPECT_EQ(public_page_node->GetBrowserContextID(), kTestBrowserContextId);
 }
 
-TEST_F(PageNodeImplTest, IsLoading) {
+TEST_F(PageNodeImplTest, LoadingState) {
   MockSinglePageInSingleProcessGraph mock_graph(graph());
   auto* page_node = mock_graph.page.get();
 
-  // This should be initialized to false.
-  EXPECT_FALSE(page_node->is_loading());
+  // This should start at kLoadingNotStarted.
+  EXPECT_EQ(PageNode::LoadingState::kLoadingNotStarted,
+            page_node->loading_state());
 
-  // Set to false and the property should stay false.
-  page_node->SetIsLoading(false);
-  EXPECT_FALSE(page_node->is_loading());
+  // Set to kLoadingNotStarted and the property should stay kLoadingNotStarted.
+  page_node->SetLoadingState(PageNode::LoadingState::kLoadingNotStarted);
+  EXPECT_EQ(PageNode::LoadingState::kLoadingNotStarted,
+            page_node->loading_state());
 
-  // Set to true and the property should read true.
-  page_node->SetIsLoading(true);
-  EXPECT_TRUE(page_node->is_loading());
+  // Set to kLoading and the property should switch to kLoading.
+  page_node->SetLoadingState(PageNode::LoadingState::kLoading);
+  EXPECT_EQ(PageNode::LoadingState::kLoading, page_node->loading_state());
 
-  // Set to false and the property should read false again.
-  page_node->SetIsLoading(false);
-  EXPECT_FALSE(page_node->is_loading());
+  // Set to kLoading again and the property should stay kLoading.
+  page_node->SetLoadingState(PageNode::LoadingState::kLoading);
+  EXPECT_EQ(PageNode::LoadingState::kLoading, page_node->loading_state());
 }
 
 TEST_F(PageNodeImplTest, HadFormInteractions) {
@@ -228,7 +230,7 @@
                void(const PageNode*, const FrameNode*, OpenedType));
   MOCK_METHOD1(OnIsVisibleChanged, void(const PageNode*));
   MOCK_METHOD1(OnIsAudibleChanged, void(const PageNode*));
-  MOCK_METHOD1(OnIsLoadingChanged, void(const PageNode*));
+  MOCK_METHOD1(OnLoadingStateChanged, void(const PageNode*));
   MOCK_METHOD1(OnUkmSourceIdChanged, void(const PageNode*));
   MOCK_METHOD1(OnPageLifecycleStateChanged, void(const PageNode*));
   MOCK_METHOD1(OnPageIsHoldingWebLockChanged, void(const PageNode*));
@@ -284,9 +286,9 @@
   page_node->SetIsAudible(true);
   EXPECT_EQ(raw_page_node, obs.TakeNotifiedPageNode());
 
-  EXPECT_CALL(obs, OnIsLoadingChanged(_))
+  EXPECT_CALL(obs, OnLoadingStateChanged(_))
       .WillOnce(Invoke(&obs, &MockObserver::SetNotifiedPageNode));
-  page_node->SetIsLoading(true);
+  page_node->SetLoadingState(PageNode::LoadingState::kLoading);
   EXPECT_EQ(raw_page_node, obs.TakeNotifiedPageNode());
 
   EXPECT_CALL(obs, OnUkmSourceIdChanged(_))
@@ -349,7 +351,7 @@
             public_page_node->GetBrowserContextID());
   EXPECT_EQ(page_node->is_visible(), public_page_node->IsVisible());
   EXPECT_EQ(page_node->is_audible(), public_page_node->IsAudible());
-  EXPECT_EQ(page_node->is_loading(), public_page_node->IsLoading());
+  EXPECT_EQ(page_node->loading_state(), public_page_node->GetLoadingState());
   EXPECT_EQ(page_node->ukm_source_id(), public_page_node->GetUkmSourceID());
   EXPECT_EQ(page_node->lifecycle_state(),
             public_page_node->GetLifecycleState());
diff --git a/components/performance_manager/public/decorators/site_data_recorder.h b/components/performance_manager/public/decorators/site_data_recorder.h
index 5abf5d26..270dc99 100644
--- a/components/performance_manager/public/decorators/site_data_recorder.h
+++ b/components/performance_manager/public/decorators/site_data_recorder.h
@@ -37,7 +37,7 @@
   void OnPageNodeAdded(const PageNode* page_node) override;
   void OnBeforePageNodeRemoved(const PageNode* page_node) override;
   void OnMainFrameUrlChanged(const PageNode* page_node) override;
-  void OnIsLoadingChanged(const PageNode* page_node) override;
+  void OnLoadingStateChanged(const PageNode* page_node) override;
   void OnIsVisibleChanged(const PageNode* page_node) override;
   void OnIsAudibleChanged(const PageNode* page_node) override;
   void OnTitleUpdated(const PageNode* page_node) override;
diff --git a/components/performance_manager/public/graph/page_node.h b/components/performance_manager/public/graph/page_node.h
index 4ceace3..e8edbb9 100644
--- a/components/performance_manager/public/graph/page_node.h
+++ b/components/performance_manager/public/graph/page_node.h
@@ -51,6 +51,30 @@
   // Returns a string for a PageNode::OpenedType enumeration.
   static const char* ToString(PageNode::OpenedType opened_type);
 
+  // Loading state of a page.
+  enum class LoadingState {
+    // No top-level document has started loading yet.
+    kLoadingNotStarted,
+    // A different top-level document is loading. The load started less than 5
+    // seconds ago or the initial response was received.
+    kLoading,
+    // A different top-level document is loading. The load started more than 5
+    // seconds ago and no response was received yet. Note: The state will
+    // transition back to |kLoading| if a response is received.
+    kLoadingTimedOut,
+    // A different top-level document finished loading, but the page did not
+    // reach CPU and network quiescence since then. Note: A page is considered
+    // to have reached CPU and network quiescence after 1 minute, even if the
+    // CPU and network are still busy - see page_load_tracker_decorator.h.
+    kLoadedBusy,
+    // The page reached CPU and network quiescence after loading the current
+    // top-level document, or the load failed.
+    kLoadedIdle,
+  };
+
+  // Returns a string for a PageNode::LoadingState enumeration.
+  static const char* ToString(PageNode::LoadingState loading_state);
+
   PageNode();
   ~PageNode() override;
 
@@ -77,13 +101,8 @@
   // See PageNodeObserver::OnIsAudibleChanged.
   virtual bool IsAudible() const = 0;
 
-  // Returns true if this page is currently loading, false otherwise. The page
-  // starts loading when incoming data starts arriving for a top-level load to a
-  // different document. It stops loading when it reaches an "almost idle"
-  // state, based on CPU and network quiescence, or after an absolute timeout.
-  // Note: This is different from WebContents::IsLoading(). See
-  // PageNodeObserver::OnIsLoadingChanged.
-  virtual bool IsLoading() const = 0;
+  // Returns the page's loading state.
+  virtual LoadingState GetLoadingState() const = 0;
 
   // Returns the UKM source ID associated with the URL of the main frame of
   // this page.
@@ -194,8 +213,8 @@
   // Invoked when the IsAudible property changes.
   virtual void OnIsAudibleChanged(const PageNode* page_node) = 0;
 
-  // Invoked when the IsLoading property changes.
-  virtual void OnIsLoadingChanged(const PageNode* page_node) = 0;
+  // Invoked when the GetLoadingState property changes.
+  virtual void OnLoadingStateChanged(const PageNode* page_node) = 0;
 
   // Invoked when the UkmSourceId property changes.
   virtual void OnUkmSourceIdChanged(const PageNode* page_node) = 0;
@@ -254,7 +273,7 @@
                                 OpenedType previous_opened_type) override {}
   void OnIsVisibleChanged(const PageNode* page_node) override {}
   void OnIsAudibleChanged(const PageNode* page_node) override {}
-  void OnIsLoadingChanged(const PageNode* page_node) override {}
+  void OnLoadingStateChanged(const PageNode* page_node) override {}
   void OnUkmSourceIdChanged(const PageNode* page_node) override {}
   void OnPageLifecycleStateChanged(const PageNode* page_node) override {}
   void OnPageIsHoldingWebLockChanged(const PageNode* page_node) override {}
diff --git a/components/permissions/permission_manager.cc b/components/permissions/permission_manager.cc
index 6ff3c23..f5f6887e 100644
--- a/components/permissions/permission_manager.cc
+++ b/components/permissions/permission_manager.cc
@@ -95,8 +95,6 @@
       return ContentSettingsType::MEDIASTREAM_CAMERA;
     case PermissionType::BACKGROUND_SYNC:
       return ContentSettingsType::BACKGROUND_SYNC;
-    case PermissionType::FLASH:
-      return ContentSettingsType::PLUGINS;
     case PermissionType::SENSORS:
       return ContentSettingsType::SENSORS;
     case PermissionType::ACCESSIBILITY_EVENTS:
diff --git a/components/permissions/permission_request_enums.h b/components/permissions/permission_request_enums.h
index fb554c9f..8bc2092 100644
--- a/components/permissions/permission_request_enums.h
+++ b/components/permissions/permission_request_enums.h
@@ -31,7 +31,7 @@
   PERMISSION_NOTIFICATIONS = 9,
   PERMISSION_PROTECTED_MEDIA_IDENTIFIER = 10,
   // PERMISSION_PUSH_MESSAGING = 11,
-  PERMISSION_FLASH = 12,
+  // PERMISSION_FLASH = 12,
   PERMISSION_MEDIASTREAM_MIC = 13,
   PERMISSION_MEDIASTREAM_CAMERA = 14,
   PERMISSION_ACCESSIBILITY_EVENTS = 15,
diff --git a/components/permissions/permission_uma_util.cc b/components/permissions/permission_uma_util.cc
index 393dca1..08f8e33 100644
--- a/components/permissions/permission_uma_util.cc
+++ b/components/permissions/permission_uma_util.cc
@@ -68,8 +68,6 @@
       return "Notifications";
     case PermissionRequestType::PERMISSION_PROTECTED_MEDIA_IDENTIFIER:
       return "ProtectedMedia";
-    case PermissionRequestType::PERMISSION_FLASH:
-      return "Flash";
     case PermissionRequestType::PERMISSION_MEDIASTREAM_MIC:
       return "AudioCapture";
     case PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA:
diff --git a/components/permissions/permission_util.cc b/components/permissions/permission_util.cc
index 9567d4bc..eaf2fbe4 100644
--- a/components/permissions/permission_util.cc
+++ b/components/permissions/permission_util.cc
@@ -89,8 +89,6 @@
       return PermissionRequestType::PERMISSION_MIDI_SYSEX;
     case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
       return PermissionRequestType::PERMISSION_PROTECTED_MEDIA_IDENTIFIER;
-    case ContentSettingsType::PLUGINS:
-      return PermissionRequestType::PERMISSION_FLASH;
     case ContentSettingsType::MEDIASTREAM_MIC:
       return PermissionRequestType::PERMISSION_MEDIASTREAM_MIC;
     case ContentSettingsType::MEDIASTREAM_CAMERA:
@@ -146,8 +144,6 @@
     *out = PermissionType::AUDIO_CAPTURE;
   } else if (type == ContentSettingsType::BACKGROUND_SYNC) {
     *out = PermissionType::BACKGROUND_SYNC;
-  } else if (type == ContentSettingsType::PLUGINS) {
-    *out = PermissionType::FLASH;
 #if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
   } else if (type == ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER) {
     *out = PermissionType::PROTECTED_MEDIA_IDENTIFIER;
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc
index b33850e..3104189 100644
--- a/components/plugins/renderer/webview_plugin.cc
+++ b/components/plugins/renderer/webview_plugin.cc
@@ -330,7 +330,7 @@
   plugin_->current_cursor_ = cursor;
 }
 
-void WebViewPlugin::WebViewHelper::ScheduleAnimation() {
+void WebViewPlugin::WebViewHelper::ScheduleNonCompositedAnimation() {
   // Resizes must be self-contained: any lifecycle updating must
   // be triggerd from within the WebView or this WebViewPlugin.
   // This is because this WebViewPlugin is contained in another
diff --git a/components/plugins/renderer/webview_plugin.h b/components/plugins/renderer/webview_plugin.h
index 29369f92..8abe5dc0 100644
--- a/components/plugins/renderer/webview_plugin.h
+++ b/components/plugins/renderer/webview_plugin.h
@@ -183,7 +183,7 @@
                                 const SkBitmap&,
                                 const gfx::Point&) override;
     void DidChangeCursor(const ui::Cursor& cursor) override;
-    void ScheduleAnimation() override;
+    void ScheduleNonCompositedAnimation() override;
 
     // WebLocalFrameClient methods:
     void BindToFrame(blink::WebNavigationControl* frame) override;
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc
index 0c323c0..baf2d09 100644
--- a/components/policy/core/common/cloud/cloud_policy_client.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -280,6 +280,9 @@
   request->set_machine_name(GetMachineName());
   request->set_os_platform(GetOSPlatform());
   request->set_os_version(GetOSVersion());
+#if defined(OS_IOS)
+  request->set_device_model(GetDeviceModel());
+#endif  // defined(OS_IOS)
 
   policy_fetch_request_job_ = service_->CreateJob(std::move(config));
 }
diff --git a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
index a81ac7c..56ffe544 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
@@ -232,6 +232,9 @@
     enrollment_request->set_machine_name(policy::GetMachineName());
     enrollment_request->set_os_platform(policy::GetOSPlatform());
     enrollment_request->set_os_version(policy::GetOSVersion());
+#if defined(OS_IOS)
+    enrollment_request->set_device_model(policy::GetDeviceModel());
+#endif
 #endif
 
     unregistration_request_.mutable_unregister_request();
diff --git a/components/policy/core/common/cloud/cloud_policy_util.cc b/components/policy/core/common/cloud/cloud_policy_util.cc
index c7902703..fc8ab24 100644
--- a/components/policy/core/common/cloud/cloud_policy_util.cc
+++ b/components/policy/core/common/cloud/cloud_policy_util.cc
@@ -75,10 +75,23 @@
 #include "base/system/sys_info.h"
 #endif
 
+#if defined(OS_IOS)
+#include "base/ios/device_util.h"
+#endif
+
 namespace policy {
 
 namespace em = enterprise_management;
 
+std::string GetDeviceModel() {
+#if defined(OS_IOS)
+  // Obtains the Apple internal device name (e.g. "iPad6,11").
+  return base::SysInfo::HardwareModelName();
+#else
+  return std::string();
+#endif
+}
+
 std::string GetMachineName() {
 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
 // of lacros-chrome is complete.
@@ -87,17 +100,10 @@
   if (gethostname(hostname, HOST_NAME_MAX) == 0)  // Success.
     return hostname;
   return std::string();
+#elif defined(OS_IOS)
+  // Use the Vendor ID as the machine name.
+  return ios::device_util::GetVendorId();
 #elif defined(OS_APPLE)
-
-#if defined(OS_IOS)
-  // The user-entered device name (e.g. "Foo's iPhone") should not be used, as
-  // there are privacy considerations (crbug.com/1123949). The Apple internal
-  // device name (e.g. "iPad6,11") is used instead.
-  std::string ios_model_name = base::SysInfo::HardwareModelName();
-  if (!ios_model_name.empty()) {
-    return ios_model_name;
-  }
-#else
   // Do not use NSHost currentHost, as it's very slow. http://crbug.com/138570
   SCDynamicStoreContext context = {0, NULL, NULL, NULL};
   base::ScopedCFTypeRef<SCDynamicStoreRef> store(SCDynamicStoreCreate(
@@ -112,7 +118,6 @@
       SCDynamicStoreCopyComputerName(store.get(), NULL));
   if (computer_name.get())
     return base::SysCFStringRefToUTF8(computer_name.get());
-#endif  // defined(OS_IOS)
 
   // If all else fails, return to using a slightly nicer version of the
   // hardware model.
diff --git a/components/policy/core/common/cloud/cloud_policy_util.h b/components/policy/core/common/cloud/cloud_policy_util.h
index 538dda3..332f24f 100644
--- a/components/policy/core/common/cloud/cloud_policy_util.h
+++ b/components/policy/core/common/cloud/cloud_policy_util.h
@@ -14,6 +14,9 @@
 
 namespace policy {
 
+// Returns the model of the device. This function is platform specific.
+POLICY_EXPORT std::string GetDeviceModel();
+
 // Returns the name of the machine. This function is platform specific.
 POLICY_EXPORT std::string GetMachineName();
 
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index f329463c..3bd323e 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -1924,6 +1924,8 @@
   repeated PartialReportType partial_report_types = 10;
   // Public key that can be used for attesting the machine.
   optional string machine_attestation_key = 11;
+  // A string that represents the device model.
+  optional string device_model = 12;
 }
 
 // Report user level status on Chrome OS platform. Chrome OS equivalent of
@@ -2717,6 +2719,8 @@
   // Device identifier for helping identify non-Chrome OS devices.
   // TODO(crbug.com/1105938): This will also replace the machine_name field.
   optional BrowserDeviceIdentifier browser_device_identifier = 4;
+  // The device model, e.g., iPad6,11
+  optional string device_model = 5;
 }
 
 // Gets an enrollment token to a managed Google Play account for using it with
diff --git a/components/policy/resources/policy_templates_es-419.xtb b/components/policy/resources/policy_templates_es-419.xtb
index fc2676b..535ec03 100644
--- a/components/policy/resources/policy_templates_es-419.xtb
+++ b/components/policy/resources/policy_templates_es-419.xtb
@@ -42,7 +42,7 @@
 <translation id="1040446814317236570">Habilitar la eliminación de URL de PAC (para https://)</translation>
 <translation id="1041719059374171202">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen los sitios que no pueden ejecutar JavaScript.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_JAVA_SCRIPT_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_JAVA_SCRIPT_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Para obtener información detallada sobre los patrones de <ph name="URL_LABEL" /> válidos, consulta https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns. <ph name="WILDCARD_VALUE" /> no es un valor aceptado para esta política.</translation>
 <translation id="1046484220783400299">Habilitar funciones de Web Platform, que dejaron de estar disponibles, durante un período limitado</translation>
@@ -88,9 +88,9 @@
       Permite determinar el tiempo que debe transcurrir antes de que se muestre el protector de pantalla en la página de inicio de sesión para dispositivos que se encuentren en el modo de venta.
 
       El valor de la política debe especificarse en milisegundos.</translation>
-<translation id="1144540226829648811">Especifica el canal de publicaciones al que debe conectarse este dispositivo.
+<translation id="1144540226829648811">Especifica el canal de versiones al que debe asociarse de forma exclusiva este dispositivo.
 
-      <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> solo tiene un efecto si estableces <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> como falso.</translation>
+      <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> solo tiene efecto si estableces <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> como falsa.</translation>
 <translation id="1151353063931113432">Permitir imágenes en estos sitios</translation>
 <translation id="1160479894929412407">Permitir el protocolo QUIC</translation>
 <translation id="1160939557934457296">Inhabilita continuar desde la página de advertencia de Navegación segura.</translation>
@@ -136,7 +136,7 @@
 <translation id="1204263402976895730">Impresoras empresariales habilitadas</translation>
 <translation id="1209065772997672966">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen los sitios que pueden abrir ventanas emergentes.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_POPUPS_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_POPUPS_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Para obtener información detallada sobre los patrones de <ph name="URL_LABEL" /> válidos, consulta https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns.  <ph name="WILDCARD_VALUE" /> no es un valor aceptado para esta política.</translation>
 <translation id="120937472976628837">Envía información de los ventiladores</translation>
@@ -198,9 +198,9 @@
       restricciones en los orígenes no seguros</translation>
 <translation id="1308526987406924874">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que no pueden pedir permiso a los usuarios para acceder a un puerto en serie.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
-      Para los patrones de URL que no coinciden con la política <ph name="SERIAL_ASK_FOR_URLS_POLICY_NAME" /> (si hay una coincidencia), tendrá prioridad <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> (si se establece) o la configuración personal de los usuarios, en ese orden.
+      En el caso de patrones de URL que no coincidan con la política <ph name="SERIAL_ASK_FOR_URLS_POLICY_NAME" /> (si hay alguna coincidencia), tendrá prioridad <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> (si se establece) o la configuración personal de los usuarios, en ese orden.
 
       Los patrones de URL no pueden entrar en conflicto con <ph name="SERIAL_ASK_FOR_URLS_POLICY_NAME" />. Si una URL se ajusta a ambas políticas, no prevalece ninguna de las dos.
 
@@ -251,7 +251,7 @@
 <translation id="1434300053894025056">Inhabilitar el corrector ortográfico</translation>
 <translation id="1434743866147056474">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen los sitios que no pueden mostrar imágenes.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_IMAGE_SETTING_ENABLED_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_IMAGE_SETTING_ENABLED_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
        Para obtener información detallada sobre los patrones de <ph name="URL_LABEL" /> válidos, consulta https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns. <ph name="WILDCARD_VALUE" /> no es un valor aceptado para esta política.
 
@@ -535,9 +535,9 @@
 <translation id="1736269219679256369">Permitir continuar desde la página de advertencia de SSL</translation>
 <translation id="174765717426930019">Permitir que se abran todas ventanas emergentes destinadas a <ph name="BLANK_PAGE_NAME" /> para interactuar con la página que abrió la ventana emergente, a menos que esta página inhabilite esta interacción de forma explícita </translation>
 <translation id="1750315445671978749">Bloquear todas las descargas</translation>
-<translation id="1751429117283165017">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que no pueden pedirle a los usuarios acceso de escritura a archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host.
+<translation id="1751429117283165017">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que no pueden pedir a los usuarios acceso de escritura a los archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_WRITE_GUARD_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_WRITE_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Los patrones de URL no pueden entrar en conflicto con <ph name="FILE_SYSTEM_WRITE_ASK_FOR_URLS_POLICY_NAME" />. Si una URL se ajusta a ambas políticas, no prevalece ninguna de las dos.
 
@@ -731,9 +731,9 @@
 
       Si la inhabilitas, los dispositivos inscritos no informarán sobre las estadísticas de hardware.</translation>
 <translation id="2040479044912658454">Modo de rasterización de impresiones</translation>
-<translation id="2042513383871755994">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que no pueden pedirle a los usuarios, mediante la API de File System, acceso de lectura a los archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host.
+<translation id="2042513383871755994">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que no pueden pedir a los usuarios acceso de lectura a los archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host mediante la API de File System.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Los patrones de URL no pueden entrar en conflicto con <ph name="FILE_SYSTEM_READ_ASK_FOR_URLS_POLICY_NAME" />. Si una URL se ajusta a ambas políticas, no prevalece ninguna de las dos.
 
@@ -1448,9 +1448,9 @@
           Esta política solo se respeta si la política "DefaultSearchProviderEnabled" está habilitada.</translation>
 <translation id="3049115011983576556">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que pueden pedir permiso a los usuarios para acceder a un puerto en serie.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
-      Para los patrones de URL que no coinciden con la política <ph name="SERIAL_BLOCKED_FOR_URLS_POLICY_NAME" /> (si hay una coincidencia), tendrá prioridad <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> (si se establece) o la configuración personal de los usuarios, en ese orden.
+      En el caso de patrones de URL que no coincidan con la política <ph name="SERIAL_BLOCKED_FOR_URLS_POLICY_NAME" /> (si hay alguna coincidencia), tendrá prioridad <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> (si se establece) o la configuración personal de los usuarios, en ese orden.
 
       Los patrones de URL no deben entrar en conflicto con <ph name="SERIAL_BLOCKED_FOR_URLS_POLICY_NAME" />. Si una URL se ajusta a ambas políticas, no prevalece ninguna de las dos.
 
@@ -1488,7 +1488,7 @@
 <translation id="316778957754360075">Esta opción se eliminó a partir de la versión 29 de <ph name="PRODUCT_NAME" />. La forma recomendada de configurar colecciones de aplicaciones o extensiones alojadas por una organización es incluir el sitio que aloja los paquetes CRX en la política ExtensionInstallSources y colocar vínculos de descarga directa a los paquetes en una página web. Se puede crear un selector para esa página web con la política ExtensionInstallForcelist.</translation>
 <translation id="3168303368727724798">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen qué sitios pueden pedir a los usuarios permiso para acceder a un dispositivo USB.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_WEB_USB_GUARD_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_WEB_USB_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Los patrones de URL no deben entrar en conflicto con <ph name="WEB_USB_ASK_FOR_URLS_POLICY_NAME" />. Si una URL se ajusta a ambas políticas, no prevalece ninguna de las dos.
 
@@ -1525,7 +1525,7 @@
 <translation id="3205825995289802549">Maximizar la primera ventana del navegador en la primera ejecución</translation>
 <translation id="3206959584699016689">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que pueden acceder a sensores, como los de movimiento o luz.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_SENSORS_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_SENSORS_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Si el mismo patrón de URL aparece en esta política y en la política <ph name="SENSORS_BLOCKED_FOR_URLS_POLICY_NAME" />, prevalecerá esta última y no se podrá acceder a los sensores de movimiento o luz.
 
@@ -1889,11 +1889,11 @@
 <translation id="3727675072430693164">Si habilitas la política, los dispositivos inscritos informarán sobre las estadísticas de hardware de los componentes de SoC.
 
       Si la inhabilitas o no la estableces, los dispositivos inscritos no informarán sobre estas estadísticas.</translation>
-<translation id="3731968520685217674">Si estableces la política, podrás especificar el comportamiento del sistema al iniciar el navegador. Si desactivas esta configuración, equivale a no establecerla, dado que debe especificarse el comportamiento de <ph name="PRODUCT_NAME" /> al iniciarse.
+<translation id="3731968520685217674">Si estableces la política, podrás especificar el comportamiento del sistema al iniciar el navegador. Desactivar esta configuración equivale a no establecerla, dado que no es posible dejar sin especificar el comportamiento de <ph name="PRODUCT_NAME" /> al iniciarse.
 
       Si estableces esta política, los usuarios no podrán cambiarla en <ph name="PRODUCT_NAME" />. Si no la estableces, los usuarios podrán cambiarla.
 
-      Si estableces esta política como <ph name="POLICY_ENUM_RESTOREONSTARTUP_RESTOREONSTARTUPISLASTSESSION" />, se desactivarán algunas opciones de configuración específicas de las sesiones o que realizan acciones al salir del navegador, como borrar cookies específicas de la sesión o datos de navegación al salir del navegador.
+      Si estableces esta política como <ph name="POLICY_ENUM_RESTOREONSTARTUP_RESTOREONSTARTUPISLASTSESSION" />, se desactivarán algunas opciones de configuración asociadas a las sesiones o que realizan acciones al salir del navegador, como borrar cookies específicas de la sesión o los datos de navegación al salir del navegador.
 
       En <ph name="MS_WIN_NAME" />, esta funcionalidad solo estará disponible en instancias que están vinculadas a un dominio de <ph name="MS_AD_NAME" />, están inscritas en <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" /> o se ejecutan en Windows 10 Pro. En <ph name="MAC_OS_NAME" />, esta funcionalidad solo está disponible en instancias administradas mediante MDM o vinculadas a un dominio a través de MCX.</translation>
 <translation id="3736879847913515635">Habilitar la opción para agregar una persona en el Administrador de usuarios</translation>
@@ -2137,11 +2137,11 @@
 <translation id="4025500273782820766">Permitir que los usuarios seleccionen "Permitir siempre" cuando se muestra un diálogo de protocolo externo para omitir futuros mensajes de confirmación</translation>
 <translation id="402759845255257575">No permitir que los sitios ejecuten JavaScript.</translation>
 <translation id="4027608872760987929">Habilitar el proveedor de búsqueda predeterminado</translation>
-<translation id="4041577849977347218">Si habilitas la política o no la estableces, se enviarán los archivos descargados para que la Navegación segura los analice, incluso cuando provienen de una fuente de confianza.
+<translation id="4041577849977347218">Si habilitas la política o no la estableces, se enviarán los archivos descargados para que la Navegación segura los analice, incluso cuando provengan de una fuente de confianza.
 
-      Si inhabilitas la política, no se enviarán los archivos descargados para que la Navegación segura los analice cuando provienen de una fuente de confianza.
+      Si inhabilitas la política, no se enviarán los archivos descargados para que la Navegación segura los analice cuando provengan de una fuente de confianza.
 
-      Se aplican estas restricciones a las descargas que se inician desde el contenido de páginas web o mediante la opción "Descargar vínculo" del menú. No se aplican estas restricciones a la acción de descargar o guardar la página que se muestra actualmente ni a la opción para guardar como PDF desde las opciones de impresión.
+      Estas restricciones se aplican a las descargas que se inician desde el contenido de páginas web o mediante la opción de descarga de vínculo del menú. No se aplican a las acciones de descargar o guardar la página que se muestra actualmente ni a la de guardar como PDF desde las opciones de impresión.
 
       En <ph name="MS_WIN_NAME" />, esta funcionalidad solo estará disponible en instancias que están vinculadas a un dominio de <ph name="MS_AD_NAME" />, están inscritas en <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" /> o se ejecutan en Windows 10 Pro. En <ph name="MAC_OS_NAME" />, esta funcionalidad solo está disponible en instancias administradas mediante MDM o vinculadas a un dominio a través de MCX.</translation>
 <translation id="4056910949759281379">Inhabilitar el protocolo SPDY</translation>
@@ -2184,7 +2184,7 @@
 
       Esta política solo afecta a los usuarios que realizan la autenticación con SAML.</translation>
 <translation id="4105989332710272578">Inhabilitar la aplicación del Certificado de transparencia para una lista de URL</translation>
-<translation id="4114059938441379876">Si estableces la política, se establecerá la URL para que los usuarios cambien sus contraseñas en el caso de que vean una advertencia en el navegador. El servicio de protección de contraseñas envía a los usuarios a la URL (solo protocolos HTTP y HTTPS) que designes a través de esta política. Para que <ph name="PRODUCT_NAME" /> capture correctamente el hash con sal de la nueva contraseña en esta página de cambio de contraseña, asegúrate de que la página cumpla con estos lineamientos ( https://www.chromium.org/developers/design-documents/create-amazing-password-forms ).
+<translation id="4114059938441379876">Si estableces la política, se configurará la URL para que los usuarios cambien su contraseña cuando vean una advertencia en el navegador. El servicio de protección de contraseñas envíará a los usuarios a la URL (solo protocolos HTTP y HTTPS) que designes a través de esta política. Para que <ph name="PRODUCT_NAME" /> capture correctamente el hash con sal de la nueva contraseña en esta página de cambio de contraseña, asegúrate de que la página cumpla con estos lineamientos ( https://www.chromium.org/developers/design-documents/create-amazing-password-forms ).
 
       Si desactivas la política o no la estableces, el servicio enviará a los usuarios a https://myaccount.google.com para que cambien su contraseña.
 
@@ -2204,7 +2204,7 @@
 
       Esta política no definirá las páginas que se abren al iniciar el navegador. Esa tarea está controlada por las políticas <ph name="RESTORE_ON_STARTUP_POLICY_NAME" />. Esta política afecta tanto a la página principal como a la página de inicio (si respectivamente están configuradas para abrir la página Nueva pestaña).
 
-      Se recomienda proporcionar una URL totalmente canónica. Caso contrario, <ph name="PRODUCT_NAME" /> se establecerá como https:// de forma predeterminada.
+      Se recomienda proporcionar una URL totalmente canónica. De lo contrario, <ph name="PRODUCT_NAME" /> se establecerá como https:// de forma predeterminada.
 
       Si no estableces la política o la dejas vacía, se utilizará la página Nueva pestaña predeterminada.
 
@@ -2223,7 +2223,7 @@
           Si estableces esta política, los usuarios no podrán cambiar ni anular la configuración.
 
           Si no la estableces, los comentarios por voz estarán inicialmente inhabilitados en la pantalla de acceso, pero el usuario podrá habilitarlos en cualquier momento.</translation>
-<translation id="4175667688338118889">Si habilitas la política, la Navegación segura confiará en los dominios que designes. No comprobará si tienen recursos peligrosos, como software malicioso, no deseado o de suplantación de identidad (phishing). El servicio de protección de descargas de la Navegación segura no comprobará las descargas alojadas en estos dominios. Su servicio de protección de contraseñas no comprobará si se está reutilizando la contraseña.
+<translation id="4175667688338118889">Si habilitas la política, la Navegación segura confiará en los dominios que designes. No comprobará si incluyen recursos peligrosos, como software malicioso, no deseado o de suplantación de identidad (phishing). El servicio de protección de descargas de la Navegación segura no comprobará las descargas alojadas en estos dominios. Su servicio de protección de contraseñas no comprobará que no se reutilicen contraseñas.
 
       Si inhabilitas la política o no la estableces, se aplicará la protección predeterminada de la Navegación segura en todos los recursos.
 
@@ -2326,7 +2326,7 @@
 <translation id="4382413175336720282">Inhabilita la verificación de URL en tiempo real</translation>
 <translation id="4387922553629365459">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen los sitios que no pueden abrir ventanas emergentes.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_POPUPS_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_POPUPS_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Para obtener información detallada sobre los patrones de <ph name="URL_LABEL" /> válidos, consulta https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns. <ph name="WILDCARD_VALUE" /> no es un valor aceptado para esta política.</translation>
 <translation id="4389073105055031853">Permitir que los usuarios administren todos los certificados</translation>
@@ -2381,9 +2381,9 @@
 <translation id="4467952432486360968">Bloquear cookies de terceros</translation>
 <translation id="4474167089968829729">Habilitar el guardado de contraseñas en el administrador de contraseñas</translation>
 <translation id="4476769083125004742">Si esta política se establece como <ph name="BLOCK_GEOLOCATION_SETTING" />, las apps de Android no podrán acceder a la información de la ubicación. Si estableces esta política en cualquier valor o no la estableces, se le pedirá al usuario que autorice la app de Android que quiera acceder a la información de ubicación.</translation>
-<translation id="4479671363221255277">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que pueden pedirle a los usuarios, mediante la API de File System, acceso de lectura a los archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host.
+<translation id="4479671363221255277">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que pueden pedir a los usuarios acceso de lectura a los archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host mediante la API de File System.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Los patrones de URL no deben entrar en conflicto con <ph name="FILE_SYSTEM_READ_BLOCKED_FOR_URLS_POLICY_NAME" />. Si una URL se ajusta a ambas políticas, no prevalece ninguna de las dos.
 
@@ -2579,11 +2579,11 @@
 <translation id="4834526953114077364">Elimina los usuarios que más tiempo hace que no se utilizan y que no accedieron en los últimos tres meses hasta que se libere suficiente espacio.</translation>
 <translation id="483544442646753291">Controla la experiencia del usuario de las funciones inhabilitadas que se mencionan en <ph name="SYSTEM_FEATURES_DISABLE_LIST" />.
 
-      Si estableces esta política como "blocked", las funciones inhabilitadas estarán inutilizables, pero los usuarios aún podrán verlas.
+      Si estableces esta política como bloqueada, las funciones inhabilitadas estarán inutilizables, pero los usuarios aún podrán verlas.
 
-      Si la estableces como "hidden", las funciones inhabilitadas estarán utilizables, pero los usuarios no podrán verlas.
+      Si la estableces como oculta, las funciones inhabilitadas estarán inutilizables y los usuarios no podrán verlas.
 
-      Si no la estableces o esta tiene un valor no válido, el modo de inhabilitación de las funciones del sistema estará bloqueado.</translation>
+      Si no la estableces o tiene un valor no válido, el modo de inhabilitación de las funciones del sistema estará bloqueado.</translation>
 <translation id="4835470005923546373">Inhabilitar el modo de impresión de los gráficos de fondo de forma predeterminada</translation>
 <translation id="4835622243021053389">Habilitar la autenticación NTLMv2</translation>
 <translation id="4855636880814771207">Si habilitas la política o no la estableces, los usuarios podrán activar y desactivar la conexión Bluetooth.
@@ -2603,11 +2603,11 @@
 
       Si la inhabilitas o no la estableces, la inscripción en <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" /> será opcional y no se bloqueará el proceso de ejecución de <ph name="PRODUCT_NAME" /> si esta falla.
 
-      Esta política se usa en máquinas de escritorio con inscripción a las políticas de nube. Para obtener más información, consulta https://support.google.com/chrome/a/answer/9301891?ref_topic=9301744.</translation>
+      Esta política se usa en máquinas de escritorio con inscripción en las políticas de nube. Para obtener más información, consulta https://support.google.com/chrome/a/answer/9301891?ref_topic=9301744.</translation>
 <translation id="4887274746092315609">Habilita una página para cambiar la contraseña dentro de la sesión para usuarios de SAML</translation>
-<translation id="4890453377345554695">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que pueden pedirle a los usuarios acceso de escritura a archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host.
+<translation id="4890453377345554695">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que pueden pedir a los usuarios acceso de escritura a los archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_WRITE_GUARD_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_WRITE_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Los patrones de URL no deben entrar en conflicto con <ph name="FILE_SYSTEM_WRITE_BLOCKED_FOR_URLS_POLICY_NAME" />. Si una URL se ajusta a ambas políticas, no prevalece ninguna de las dos.
 
@@ -2748,7 +2748,7 @@
 <translation id="5085647276663819155">Inhabilitar vista previa de impresión</translation>
 <translation id="5087424855041813182">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen los sitios que pueden mostrar notificaciones.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_JAVA_SCRIPT_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_JAVA_SCRIPT_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Para obtener información detallada sobre los patrones de <ph name="URL_LABEL" /> válidos, consulta https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns. <ph name="WILDCARD_VALUE" /> no es un valor aceptado para esta política.</translation>
 <translation id="5090209345759901501">Extender la configuración del contenido Flash a todo el contenido</translation>
@@ -3016,9 +3016,9 @@
           Si no la estableces, la función de portapapeles compartido estará habilitada de forma predeterminada.
 
           Los administradores son los que deben establecer las políticas en todas las plataformas que quieran. Te recomendamos que establezcas un valor para esta política en todas las plataformas.</translation>
-<translation id="5389798680516458665">Si estableces la política, podrás establecer una lista de patrones de URL que especifiquen los sitios que pueden mostrar imágenes.
+<translation id="5389798680516458665">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen los sitios que pueden mostrar imágenes.
 
-      Si no la estableces, se aplicará <ph name="DEFAULT_IMAGES_SETTING_ENABLED_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_IMAGES_SETTING_ENABLED_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Para obtener información detallada sobre los patrones de <ph name="URL_LABEL" /> válidos, consulta https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns. <ph name="WILDCARD_VALUE" /> no es un valor aceptado para esta política.
 
@@ -3167,9 +3167,9 @@
           Si inhabilitas esta configuración, el administrador de contraseñas no permitirá mostrar contraseñas guardadas en texto claro en la ventana del administrador de contraseñas.
 
           Si habilitas o no estableces esta política, los usuarios podrán ver las contraseñas en texto claro en el administrador de contraseñas.</translation>
-<translation id="5619498195290770056">Si estableces la política, podrás crear una lista de patrones de URL que especifiquen los sitios que no pueden establecer cookies.
+<translation id="5619498195290770056">Si estableces la política, podrás crear una lista de patrones de URL que especifiquen los sitios que no pueden configurar cookies.
 
-      Si no la estableces, se aplicará la política <ph name="DEFAULT_COOKIES_SETTINGS_POLICY_NAME" /> (si está establecida) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_COOKIES_SETTINGS_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Si bien no prevalece ninguna política específica, consulta <ph name="COOKIES_ALLOWED_FOR_URLS_POLICY_NAME" /> y <ph name="COOKIES_SESSION_ONLY_FOR_URLS_POLICY_NAME" />. Los patrones de URL entre estas 3 políticas no deben entrar en conflicto.
 
@@ -3251,7 +3251,7 @@
       Nota: El factor de escala debe ser 100% o más.</translation>
 <translation id="5738892881453299672">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que no pueden acceder a sensores, como los de movimiento o luz.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_SENSORS_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_SENSORS_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Si el mismo patrón de URL aparece en esta política y en la política <ph name="SENSORS_ALLOWED_FOR_URLS_POLICY_NAME" />, prevalecerá esta última y no se podrá acceder a los sensores de movimiento o luz.
 
@@ -3591,9 +3591,9 @@
 <translation id="6282524907402492171">Muestra las advertencias de baja de <ph name="CLOUD_PRINT_NAME" /></translation>
 <translation id="6282799760374509080">Permitir o rechazar la captura de audio</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
-<translation id="6300871921951390976">Si estableces esta política como verdadera, los usuarios solo podrán cambiar el canal de versiones del dispositivo. Si la estableces como falsa o no la estableces, los usuarios no podrán cambiar el canal.
+<translation id="6300871921951390976">Los usuarios solo podrán cambiar el canal de versiones del dispositivo si estableces esta política como verdadera. Si la estableces como falsa o no la estableces, los usuarios no podrán cambiar el canal.
 
-      <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> solo tiene un efecto si estableces <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> como falso.</translation>
+      <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> solo tiene efecto si estableces <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> como falsa.</translation>
 <translation id="6310223829319187614">Habilitar la opción de autocompletar el nombre de dominio durante el accceso del usuario</translation>
 <translation id="631081324835911099">Fuerza el cierre de sesión del usuario cuando el token de autenticación de la cuenta principal deja de ser válido.
         Esta política puede proteger al usuario del acceso a contenido restringido en propiedades web de Google.
@@ -4117,9 +4117,9 @@
       Si no estableces la política, los usuarios podrán cambiar esta configuración.
 
       Nota: Se mejorará la compatibilidad del aislamiento de sitios en Android, pero actualmente es posible que haya problemas de rendimiento. Esta política solo se aplica a Chrome cuando se ejecuta en dispositivos con Android que tengan exclusivamente más de 1 GB de RAM. Para aplicar la política en plataformas que no tengan Android, utiliza <ph name="ISOLATE_ORIGINS_POLICY_NAME" />.</translation>
-<translation id="6978404102280820831">A menos que establezcas la política <ph name="RESTORE_ON_STARTUP_POLICY_NAME" /> para restablecer las URL de sesiones anteriores de forma definitiva, la configuración <ph name="COOKIES_SESSION_ONLY_FOR_URLS_POLICY_NAME" /> te permitirá crear una lista de patrones de URL donde se especifiquen los sitios que pueden y no pueden establecer cookies para una sesión determinada.
+<translation id="6978404102280820831">A menos que establezcas la política <ph name="RESTORE_ON_STARTUP_POLICY_NAME" /> para restablecer las URL de sesiones anteriores de forma definitiva, la configuración de <ph name="COOKIES_SESSION_ONLY_FOR_URLS_POLICY_NAME" /> te permitirá crear una lista de patrones de URL donde se especifiquen los sitios que pueden y no pueden configurar cookies para una sesión determinada.
 
-      Si no estableces la política, se aplicará la política <ph name="DEFAULT_COOKIES_SETTINGS_POLICY_NAME" /> (si está establecida) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario. Para las URL que no estén contempladas en los patrones especificados, también se utilizará la configuración predeterminada.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_COOKIES_SETTINGS_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario. En el caso de URL que no estén contempladas en los patrones especificados, también se utilizará la configuración predeterminada.
 
       Si <ph name="PRODUCT_NAME" /> se ejecuta en segundo plano, es posible que la sesión permanezca activa hasta que el usuario cierre por completo el navegador (y no solo cierre la última ventana). Para obtener información sobre cómo configurar este comportamiento, consulta <ph name="BACKGROUND_MODE_ENABLED_POLICY_NAME" />.
 
@@ -4135,7 +4135,7 @@
 <translation id="6986172482189158664">Configuración de la duración de los datos de navegación</translation>
 <translation id="6986838929449128437">Esta política dejó de estar disponible; usa <ph name="SAFE_BROWSING_ALLOWLIST_DOMAINS_POLICY_NAME" /> en su lugar.
 
-      Si habilitas la política, la Navegación segura confiará en los dominios que designes. No comprobará si tienen recursos peligrosos, como software malicioso, no deseado o de suplantación de identidad (phishing). El servicio de protección de descargas de la Navegación segura no comprobará las descargas alojadas en estos dominios. Su servicio de protección de contraseñas no comprobará si se está reutilizando la contraseña.
+      Si habilitas la política, la Navegación segura confiará en los dominios que designes. No comprobará si incluyen recursos peligrosos, como software malicioso, no deseado o de suplantación de identidad (phishing). El servicio de protección de descargas de la Navegación segura no comprobará las descargas alojadas en estos dominios. Su servicio de protección de contraseñas no comprobará que no se reutilicen contraseñas.
 
       Si inhabilitas la política o no la estableces, se aplicará la protección predeterminada de la Navegación segura en todos los recursos.
 
@@ -4209,7 +4209,7 @@
 <translation id="7086720321892395256">Controla las políticas de dispositivo y usuario para la función de la pantalla de privacidad.</translation>
 <translation id="7090668780328470271">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen qué sitios no pueden pedir a los usuarios permiso para acceder a un dispositivo USB.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_WEB_USB_GUARD_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_WEB_USB_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Los patrones de URL no pueden entrar en conflicto con <ph name="WEB_USB_ASK_FOR_URLS_POLICY_NAME" />. Si una URL se ajusta a ambas políticas, no prevalece ninguna de las dos.
 
@@ -4237,7 +4237,7 @@
 <translation id="7127892035367404455">Reversión a la versión objetivo</translation>
 <translation id="7129052644387688634">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen los sitios que no pueden mostrar notificaciones.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_JAVA_SCRIPT_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_JAVA_SCRIPT_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Para obtener información detallada sobre los patrones de <ph name="URL_LABEL" /> válidos, consulta https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns.  <ph name="WILDCARD_VALUE" /> no es un valor aceptado para esta política.</translation>
 <translation id="712963038874313213">Proporciona un playbook de Ansible que debe ejecutarse en el contenedor predeterminado de Crostini.
@@ -4456,9 +4456,9 @@
       Si estableces la política, los usuarios no podrán cambiarla. Si no la estableces, se activará la predicción de red, pero el usuario podrá cambiarla.</translation>
 <translation id="7415655595380180976">Esta política dejó de estar disponible. Usa la política "<ph name="URL_ALLOWLIST_POLICY_NAME" />" en su lugar.
 
-      Si estableces la política, permitirás el acceso a las URL de la lista, como excepciones a la lista de URL bloqueadas. Consulta la descripción de esa política para conocer el formato de las entradas de esta lista. Por ejemplo, si estableces "*" en la política <ph name="URL_BLOCKLIST_POLICY_NAME" />, se bloquearán todas las solicitudes. Además, esta política puede permitir el acceso a una lista limitada de URL y excepciones para determinados esquemas, subdominios de otros dominios, puertos o rutas específicas, mediante el formato que se especifica en la siguiente dirección ( https://www.chromium.org/administrators/url-blacklist-filter-format ). El filtro más específico determina si una URL está bloqueada o habilitada. La lista de elementos permitidos tiene prioridad sobre la de elementos bloqueados, y se limitará a 1,000 entradas.
+      Si estableces la política, permitirás el acceso a las URL de la lista, como excepciones a la lista de URL bloqueadas. Consulta la descripción de esa política para conocer el formato de las entradas de esta lista. Por ejemplo, si estableces "*" en la política <ph name="URL_BLOCKLIST_POLICY_NAME" />, se bloquearán todas las solicitudes. Además, con esta política puedes permitir el acceso a una lista limitada de URL. Úsala a fin de abrir excepciones para determinados esquemas, subdominios de otros dominios, puertos o rutas específicas, mediante el formato que se indica en la siguiente dirección ( https://www.chromium.org/administrators/url-blacklist-filter-format ). El filtro más específico determina si una URL está bloqueada o habilitada. La lista de elementos permitidos tiene prioridad sobre la de elementos bloqueados. Esta política se limitará a 1,000 entradas
 
-      Esta política también puede permitir que el navegador invoque de forma automática aplicaciones externas registradas como controladores de los protocolos que se encuentran en la lista de elementos permitidos, p. ej., "tel:" o "ssh:".
+      y puede permitir que el navegador invoque de forma automática aplicaciones externas registradas como controladores de los protocolos que se encuentran en la lista correspondiente, p. ej., "tel:" o "ssh:".
 
       Si no estableces la política, no se permitirán excepciones.
 
@@ -5352,7 +5352,7 @@
 <translation id="8656110680728938054">Habilita Seleccionar para pronunciar</translation>
 <translation id="8661297125441579970">No permitir la migración de datos y ARC</translation>
 <translation id="8665314828727504286">Nivel de protección de la Navegación segura</translation>
-<translation id="8669313549017524373">Si estableces <ph name="RESTORE_ON_STARTUP_POLICY_NAME" /> como RestoreOnStartupIsURLs, se abrirán las URL de la lista que se determinen en <ph name="RESTORE_ON_STARTUP_URLS_POLICY_NAME" />.
+<translation id="8669313549017524373">Si estableces <ph name="RESTORE_ON_STARTUP_POLICY_NAME" /> como RestoreOnStartupIsURLs, configurar <ph name="RESTORE_ON_STARTUP_URLS_POLICY_NAME" /> con una lista de URL determinará qué URL se abrirán.
 
       Si no la estableces, se abrirá la página Nueva pestaña al iniciar el navegador.
 
@@ -5479,7 +5479,7 @@
        Nota: Esta política no se aplica al modo Incógnito. Obtén más información sobre el alojamiento de extensiones en https://developer.chrome.com/extensions/hosting.</translation>
 <translation id="8831911834413504983">Si estableces la política, podrás especificar una lista de patrones de URL que indiquen los sitios que pueden ejecutar JavaScript.
 
-      Si no estableces la política, se aplicará <ph name="DEFAULT_JAVA_SCRIPT_SETTING_POLICY_NAME" /> (si se establece) para todos los sitios. De lo contrario, se aplicará la configuración personal del usuario.
+      Si no estableces la política, se aplicará <ph name="DEFAULT_JAVA_SCRIPT_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
 
       Para obtener información detallada sobre los patrones de <ph name="URL_LABEL" /> válidos, consulta https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns. <ph name="WILDCARD_VALUE" /> no es un valor aceptado para esta política.</translation>
 <translation id="8832829916385857156">La página Nueva pestaña mostrará tarjetas si hay contenido disponible</translation>
@@ -5575,9 +5575,9 @@
       Para obtener más información sobre contextos seguros, consulta
       https://www.w3.org/TR/secure-contexts/
       </translation>
-<translation id="8940519618730206658">Si estableces la política, permitirás el acceso a las URL de la lista, como excepciones a la lista de la política <ph name="URL_BLOCKLIST_POLICY_NAME" />. Consulta la descripción de esa política para conocer el formato de las entradas de esta lista. Por ejemplo, si estableces "*" en la política <ph name="URL_BLOCKLIST_POLICY_NAME" />, se bloquearán todas las solicitudes. Además, esta política puede permitir el acceso a una lista limitada de URL y excepciones para determinados esquemas, subdominios de otros dominios, puertos o rutas específicas, mediante el formato que se especifica en la siguiente dirección ( https://www.chromium.org/administrators/url-blacklist-filter-format ). El filtro más específico determina si una URL está bloqueada o habilitada. La política <ph name="URL_ALLOWLIST_POLICY_NAME" /> tiene prioridad sobre la política <ph name="URL_BLOCKLIST_POLICY_NAME" />, y se limitará a 1,000 entradas.
+<translation id="8940519618730206658">Si estableces la política, permitirás el acceso a las URL de la lista, como excepciones a la lista de la política <ph name="URL_BLOCKLIST_POLICY_NAME" />. Consulta la descripción de esa política para conocer el formato de las entradas de esta lista. Por ejemplo, si estableces "*" en la política <ph name="URL_BLOCKLIST_POLICY_NAME" />, se bloquearán todas las solicitudes. Además, con esta política puedes permitir el acceso a una lista limitada de URL. Úsala a fin de abrir excepciones para determinados esquemas, subdominios de otros dominios, puertos o rutas específicas, mediante el formato que se indica en la siguiente dirección ( https://www.chromium.org/administrators/url-blacklist-filter-format ). El filtro más específico determina si una URL está bloqueada o habilitada. La política <ph name="URL_ALLOWLIST_POLICY_NAME" /> tiene prioridad sobre la política <ph name="URL_BLOCKLIST_POLICY_NAME" />, y se limitará a 1,000 entradas.
 
-      Esta política también puede permitir que el navegador invoque de forma automática aplicaciones externas registradas como controladores de los protocolos que se encuentran en la lista de elementos permitidos, p. ej., "tel:" o "ssh:".
+      Esta política también puede permitir que el navegador invoque de forma automática aplicaciones externas registradas como controladores de los protocolos que se encuentran en la lista correspondiente, p. ej., "tel:" o "ssh:".
 
       Si no estableces la política, no se permitirán excepciones a la política <ph name="URL_BLOCKLIST_POLICY_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_fr.xtb b/components/policy/resources/policy_templates_fr.xtb
index 1903e4d..ee6dbdb5 100644
--- a/components/policy/resources/policy_templates_fr.xtb
+++ b/components/policy/resources/policy_templates_fr.xtb
@@ -576,9 +576,9 @@
       Cette règle étant obsolète, veuillez utiliser la règle <ph name="DEVICE_USER_ALLOWLIST_POLICY_NAME" /> à la place.
       </translation>
 <translation id="1827523283178827583">Utiliser des serveurs proxy déterminés</translation>
-<translation id="1829839214911753838">Si cette règle est activée, l'hôte d'assistance à distance est exécuté dans un processus avec des autorisations <ph name="UIACCESS_PERMISSION_NAME" />. Les utilisateurs distants peuvent ainsi interagir avec des fenêtres élevées sur le bureau de l'utilisateur local.
+<translation id="1829839214911753838">Si cette règle est activée, l'hôte d'assistance à distance est exécuté dans un processus avec des autorisations <ph name="UIACCESS_PERMISSION_NAME" />. Les utilisateurs distants peuvent ainsi interagir avec des fenêtres de niveau administrateur sur le bureau de l'utilisateur local.
 
-      Si cette règle est désactivée ou qu'elle n'est pas configurée, l'hôte d'assistance à distance est exécuté dans le contexte de l'utilisateur, et les utilisateurs distants ne peuvent pas interagir avec des fenêtres élevées sur le bureau.</translation>
+      Si cette règle est désactivée ou qu'elle n'est pas configurée, l'hôte d'assistance à distance est exécuté dans le contexte de l'utilisateur, et les utilisateurs distants ne peuvent pas interagir avec des fenêtres de niveau administrateur sur le bureau.</translation>
 <translation id="1839278886947586809">
       Cette règle a été retirée de la version M80, car elle n'est plus nécessaire
       depuis que WebDriver est compatible avec toutes les règles existantes.
@@ -2050,7 +2050,7 @@
 
       Pour que les destinations <ph name="CLOUD_PRINT_NAME" /> restent visibles, cette règle doit être définie sur "True", et le type "<ph name="POLICY_ENUM_PRINTERTYPEDENYLIST_CLOUD" />" ne doit pas être ajouté à la règle "<ph name="POLICY_PRINTERTYPEDENYLIST" />".</translation>
 <translation id="3915395663995367577">URL d'un fichier .pac de proxy</translation>
-<translation id="3915587396318773837">Si cette règle est configurée, l'hôte d'accès à distance exigent des clients qui s'authentifient qu'ils obtiennent un jeton d'authentification à partir de cette URL pour se connecter.
+<translation id="3915587396318773837">Si cette règle est configurée, l'hôte d'accès à distance exige des clients qui s'authentifient qu'ils obtiennent un jeton d'authentification à partir de cette URL pour se connecter.
 
       Si cette règle est définie sur une chaîne vide ou qu'elle n'est pas configurée, elle est désactivée.
 
diff --git a/components/policy/resources/policy_templates_id.xtb b/components/policy/resources/policy_templates_id.xtb
index 0ad95220..8156dd8c 100644
--- a/components/policy/resources/policy_templates_id.xtb
+++ b/components/policy/resources/policy_templates_id.xtb
@@ -129,7 +129,7 @@
 <translation id="1198183996903759302">Jika kebijakan disetel ke Benar (True) (atau <ph name="HARDWARE_ACCELERATION_MODE_ENABLED_POLICY_NAME" /> disetel ke Salah (False)), halaman web tidak akan dapat mengakses WebGL API, dan plugin tidak dapat menggunakan Pepper 3D API.
 
       Jika kebijakan disetel ke Salah (False) atau tidak disetel, halaman web akan menggunakan WebGL API dan plugin akan menggunakan Pepper 3D API, tetapi setelan browser default mungkin masih memerlukan argumen command line untuk menggunakan API ini.</translation>
-<translation id="1199366379198964260">Jika kebijakan disetel ke Aktif, PIN yang lemah akan diizinkan. Beberapa karakteristik PIN yang lemah: hanya satu digit (1111), digit ditambah 1 secara berurutan (1234), digit dikurangi 1 secara berurutan (4321), dan PIN umum. Jika kebijakan disetel ke Nonaktif, pengguna tidak akan dapat menyetel PIN yang lemah dan mudah ditebak.
+<translation id="1199366379198964260">Jika kebijakan disetel ke Aktif, PIN yang lemah akan diizinkan. Beberapa karakteristik PIN yang lemah: hanya satu digit (1111), digit ditambah 1 secara berurutan (1234), digit dikurangi 1 secara berurutan (4321), dan PIN yang umum dipakai. Jika kebijakan disetel ke Nonaktif, pengguna tidak akan dapat menyetel PIN yang lemah dan mudah ditebak.
 
       Secara default, pengguna akan mendapatkan peringatan tentang PIN yang lemah, dan bukan mengalami error.</translation>
 <translation id="1202216683470826356">Tampilkan kartu di Halaman Tab Baru</translation>
@@ -410,9 +410,9 @@
 
       * Layar akan dinonaktifkan jika pengguna tidak ada aktivitas selama kurun waktu yang telah ditentukan oleh <ph name="SCREEN_OFF_FIELD_NAME" />.
 
-      * Dialog peringatan akan muncul jika pengguna tetap tidak ada aktivitas selama kurun waktu yang telah ditentukan oleh <ph name="IDLE_WARNING_FIELD_NAME" />. Dialog tersebut memperingatkan pengguna bahwa tindakan tidak ada aktivitas akan diambil dan hanya muncul jika tindakan tidak ada aktivitas adalah untuk logout atau mematikan perangkat.
+      * Dialog peringatan akan muncul jika pengguna tetap tidak ada aktivitas selama kurun waktu yang telah ditentukan oleh <ph name="IDLE_WARNING_FIELD_NAME" />. Dialog tersebut memperingatkan pengguna bahwa tindakan tidak ada aktivitas akan diberlakukan dan hanya muncul jika tindakannya adalah untuk logout atau mematikan perangkat.
 
-      * Tindakan yang ditentukan oleh <ph name="IDLE_ACTION_FIELD_NAME" /> akan diambil jika pengguna tidak ada aktivitas selama kurun waktu yang telah ditentukan oleh <ph name="IDLE_FIELD_NAME" />.
+      * Tindakan yang ditentukan oleh <ph name="IDLE_ACTION_FIELD_NAME" /> akan diberlakukan jika pengguna tidak ada aktivitas selama kurun waktu yang telah ditentukan oleh <ph name="IDLE_FIELD_NAME" />.
 
       Untuk setiap tindakan di atas, penundaan harus ditentukan dalam milidetik dan disetel ke nilai yang lebih besar dari nol untuk memicu tindakan terkait. Jika penundaan disetel ke nol, <ph name="PRODUCT_OS_NAME" /> tidak akan melakukan tindakan terkait.
 
@@ -511,7 +511,7 @@
 <translation id="1690383938831887552">Cegah pemuatan Signed HTTP Exchange</translation>
 <translation id="1700811900332333712">Izinkan perangkat untuk meminta powerwash</translation>
 <translation id="1708496595873025510">Setel batasan pada pengambilan bibit Varietas</translation>
-<translation id="1713829924716792485">Jika kebijakan disetel ke Aktif atau tidak disetel, pengguna akan diizinkan terhubung ke host akses jarak jauh untuk mentransfer file antara klien dan host. Ini tidak berlaku untuk koneksi bantuan jarak jauh, yang tidak mendukung transfer file.
+<translation id="1713829924716792485">Jika kebijakan disetel ke Aktif atau tidak disetel, pengguna yang terhubung ke host akses jarak jauh akan diizinkan untuk mentransfer file antara klien dan host. Ini tidak berlaku untuk koneksi bantuan jarak jauh, yang tidak mendukung transfer file.
 
       Jika kebijakan disetel ke Nonaktif, transfer file tidak akan diizinkan.</translation>
 <translation id="171511968762040550">Jika kebijakan ditetapkan ke Benar (True) atau tidak ditetapkan, pengguna akan dapat menambahkan, menghapus, atau mengubah bookmark.
@@ -574,9 +574,9 @@
       Kebijakan ini tidak digunakan lagi. Sebagai gantinya, gunakan <ph name="DEVICE_USER_ALLOWLIST_POLICY_NAME" />.
       </translation>
 <translation id="1827523283178827583">Gunakan server proxy tetap</translation>
-<translation id="1829839214911753838">Jika kebijakan disetel ke Aktif, host bantuan jarak jauh akan berjalan dalam proses dengan izin <ph name="UIACCESS_PERMISSION_NAME" />. Ini memungkinkan pengguna jarak jauh berinteraksi dengan jendela timbul di desktop pengguna lokal.
+<translation id="1829839214911753838">Jika kebijakan disetel ke Aktif, host bantuan jarak jauh akan berjalan dalam proses dengan izin <ph name="UIACCESS_PERMISSION_NAME" />. Ini memungkinkan pengguna jarak jauh berinteraksi dengan jendela administrator di desktop pengguna lokal.
 
-      Jika kebijakan disetel ke Nonaktif atau tidak disetel, host bantuan jarak jauh akan berjalan dalam konteks pengguna, dan pengguna jarak jauh tidak dapat berinteraksi dengan jendela timbul di desktop.</translation>
+      Jika kebijakan disetel ke Nonaktif atau tidak disetel, host bantuan jarak jauh akan berjalan dalam konteks pengguna, dan pengguna jarak jauh tidak dapat berinteraksi dengan jendela administrator di desktop.</translation>
 <translation id="1839278886947586809">
       Kebijakan ini telah dihapus di M80, karena tidak diperlukan lagi karena
       WebDriver saat ini kompatibel dengan semua kebijakan yang sudah ada.
@@ -1184,7 +1184,7 @@
 <translation id="2702023190395322609">Mengaktifkan Rekomendasi Media</translation>
 <translation id="2706708761587205154">Hanya izinkan pencetakan dengan PIN</translation>
 <translation id="2707873794476722903">Safe Browsing aktif dalam mode standar.</translation>
-<translation id="2714359695399346815">Jika kebijakan disetel ke Aktif atau tidak disetel, penggunaan server STUN akan diizinkan dan klien jarak jauh dapat ditemukan serta dihubungkan ke perangkat ini, meskipun dipisahkan dengan firewall.
+<translation id="2714359695399346815">Jika kebijakan disetel ke Aktif atau tidak disetel, penggunaan server STUN akan diizinkan sehingga klien jarak jauh dapat menemukan serta terhubung ke perangkat ini, meskipun dipisahkan oleh firewall.
 
       Jika kebijakan disetel ke Nonaktif saat koneksi UDP keluar difilter oleh firewall, perangkat hanya akan mengizinkan koneksi dari perangkat klien dalam jaringan lokal.</translation>
 <translation id="2716623398185506073">Jika kebijakan disetel ke Aktif, perangkat yang terdaftar akan melaporkan statistik dan ID hardware yang terkait daya.
@@ -1227,7 +1227,7 @@
 <translation id="2759224876420453487">Mengontrol perilaku pengguna pada sesi multiprofil</translation>
 <translation id="2761483219396643566">Menunda peringatan waktu menganggur saat menggunakan daya baterai</translation>
 <translation id="2769952903507981510">Mengonfigurasi nama domain yang dibutuhkan untuk hosting akses jarak jauh</translation>
-<translation id="2772955711376920612">Menyetel kebijakan ke Aktif serta menyetel <ph name="DEVICE_POWER_PEAK_SHIFT_BATTERY_THRESHOLD_POLICY_NAME" /> dan <ph name="DEVICE_POWER_PEAK_SHIFT_DAY_CONFIG_POLICY_NAME" /> akan terus memicu pengaktifan daya baterai, jika didukung di perangkat. Kebijakan manajemen pengaktifan daya baterai adalah kebijakan penghematan daya yang meminimalkan penggunaan arus listrik AC selama waktu penggunaan puncak. Untuk setiap hari kerja, Anda dapat menyetel waktu mulai dan waktu akhir untuk menjalankan sistem dalam mode pengaktifan daya baterai. Selama baterai tetap berada di atas nilai minimum yang ditentukan, perangkat akan berjalan menggunakan daya baterai (meski arus listrik AC terhubung) selama waktu tersebut. Setelah waktu akhir yang ditentukan, perangkat akan berjalan menggunakan arus listrik AC (jika terhubung), tetapi tidak akan mengisi daya baterai. Perangkat akan berfungsi kembali secara normal menggunakan arus listrik AC dan mengisi ulang daya baterai setelah waktu mulai pengisian daya yang ditentukan.
+<translation id="2772955711376920612">Menyetel kebijakan ke Aktif serta menyetel <ph name="DEVICE_POWER_PEAK_SHIFT_BATTERY_THRESHOLD_POLICY_NAME" /> dan <ph name="DEVICE_POWER_PEAK_SHIFT_DAY_CONFIG_POLICY_NAME" /> akan terus memicu pengaktifan daya baterai, jika didukung di perangkat. Kebijakan manajemen pengaktifan daya baterai adalah kebijakan penghematan daya yang meminimalkan penggunaan arus listrik AC selama waktu penggunaan puncak. Untuk setiap hari kerja, Anda dapat menyetel waktu mulai dan waktu akhir untuk menjalankan sistem dalam mode pengaktifan daya baterai. Selama baterai tetap berada di atas nilai minimum yang ditentukan, perangkat akan berjalan menggunakan daya baterai (meski arus listrik AC terhubung) selama waktu tersebut. Setelah waktu akhir yang ditentukan, perangkat akan berjalan menggunakan arus listrik AC (jika terhubung), tetapi tidak akan mengisi daya baterai. Perangkat akan berfungsi normal kembali menggunakan arus listrik AC dan mengisi ulang daya baterai setelah waktu mulai pengisian daya yang ditentukan.
 
       Jika kebijakan disetel ke Nonaktif, pengaktifan daya baterai akan tetap nonaktif.
 
@@ -2935,9 +2935,9 @@
 
       Jika kebijakan tidak ditetapkan, pengguna tidak dapat memainkan game di <ph name="PRODUCT_OS_NAME" /> yang terdaftar, tetapi dapat memainkannya dalam kondisi lain.</translation>
 <translation id="529457411593078576">Menampilkan Persyaratan Layanan (ToS) saat CCT pertama kali dijalankan</translation>
-<translation id="5303080953475303561">Menyetel kebijakan akan mengontrol frekuensi layar kunci meminta sandi untuk mode buka kunci cepat. Jika entri sandi terakhir terjadi sebelum waktu jendela yang ditentukan oleh nilai terpilih, mode buka kunci cepat tidak akan tersedia setiap kali layar kunci muncul. Jika pengguna tetap berada di layar kunci melebihi jangka waktu ini, sandi akan diminta saat pengguna memasukkan lagi kode yang salah atau masuk kembali ke layar kunci, mana saja yang terjadi lebih dahulu.
+<translation id="5303080953475303561">Menyetel kebijakan akan mengontrol frekuensi layar kunci meminta sandi untuk mode buka kunci cepat. Setiap kali layar kunci ditampilkan, jika entri sandi terakhir terjadi sebelum jangka waktu yang ditentukan oleh nilai yang dipilih, mode buka kunci cepat tidak akan tersedia. Jika pengguna tetap berada di layar kunci setelah jangka waktu ini, sandi akan diminta saat pengguna salah memasukkan kode lagi atau masuk kembali ke layar kunci, mana saja yang terjadi lebih dahulu.
 
-      Jika kebijakan tidak disetel, pengguna yang menggunakan mode buka kunci cepat akan memasukkan sandinya di layar kunci setiap hari.</translation>
+      Jika kebijakan tidak disetel, pengguna yang menggunakan mode buka kunci cepat hanya perlu memasukkan sandi di layar kunci satu kali dalam sehari.</translation>
 <translation id="5306186200045823863">Mengaktifkan kepercayaan pada Infrastruktur IKP Lama milik Symantec Corporation</translation>
 <translation id="5307432759655324440">Ketersediaan mode samaran</translation>
 <translation id="5311275381462687162">Setelan default perilaku cookie <ph name="ATTRIBUTE_SAMESITE_NAME" /> lama</translation>
@@ -3769,7 +3769,7 @@
 <translation id="6536600139108165863">Booting ulang otomatis saat mematikan perangkat</translation>
 <translation id="6539246272469751178">Kebijakan ini tidak memengaruhi aplikasi Android. Aplikasi Android selalu menggunakan direktori download default dan tidak dapat mengakses file apa pun yang didownload oleh <ph name="PRODUCT_OS_NAME" /> ke direktori download non-default.</translation>
 <translation id="654303922206238013">Strategi migrasi untuk ecryptfs</translation>
-<translation id="654546276700640113">Jika kebijakan disetel, panjang PIN maksimum yang dikonfigurasi akan diterapkan. Nilai 0 atau yang lebih kecil berarti pengguna dapat menyetel panjang PIN sesuai keinginan. Jika nilainya lebih kecil dari <ph name="PIN_UNLOCK_MINIMUM_LENGTH_POLICY_NAME" /> tetapi lebih besar dari 0, panjang maksimum akan disetel ke panjang minimum.
+<translation id="654546276700640113">Jika kebijakan disetel, panjang PIN maksimum yang dikonfigurasi akan diterapkan. Nilai 0 atau lebih kecil berarti pengguna dapat menyetel panjang PIN sesuai keinginan. Jika nilainya lebih kecil dari <ph name="PIN_UNLOCK_MINIMUM_LENGTH_POLICY_NAME" /> tetapi lebih besar dari 0, panjang maksimum akan disetel ke panjang minimum.
 
       Jika kebijakan tidak disetel, tidak akan ada panjang maksimum yang diterapkan.</translation>
 <translation id="6553143066970470539">Persentase kecerahan layar</translation>
@@ -4228,7 +4228,7 @@
       Untuk informasi selengkapnya tentang pola <ph name="URL_LABEL" /> yang valid, lihat https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns. <ph name="WILDCARD_VALUE" /> bukanlah nilai yang diterima untuk kebijakan ini.</translation>
 <translation id="7091220433954923921">Menyetel kebijakan akan membatasi rentang port UDP yang digunakan oleh host akses jarak jauh di perangkat ini.
 
-      Jika kebijakan tidak disetel atau disetel ke string kosong, host akses jarak jauh akan dapat menggunakan semua port yang tersedia.
+      Jika kebijakan tidak disetel atau disetel ke string kosong, host akses jarak jauh akan dapat menggunakan port mana pun yang tersedia.
 
       Catatan: Jika <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME" /> Dinonaktifkan, host akses jarak jauh akan menggunakan port UDP dalam rentang 12400-12409.</translation>
 <translation id="7091842872805965910">Mengaktifkan fitur kirim otomatis PIN di layar kunci dan login.</translation>
@@ -4851,7 +4851,7 @@
       Jika tidak ditetapkan, kebijakan ini akan diaktifkan tetapi pengguna dapat mengubahnya.</translation>
 <translation id="7955263399078148032">Jika <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME" /> disetel ke Aktif, menyetel <ph name="REMOTE_ACCESS_HOST_ALLOW_RELAYED_CONNECTION_POLICY_NAME" /> ke Aktif atau tidak menyetelnya akan mengizinkan klien jarak jauh untuk menggunakan server relai agar terhubung ke perangkat ini saat koneksi langsung tidak tersedia, misalnya karena batasan firewall.
 
-      Jika kebijakan disetel ke Nonaktif, akses jarak jauh tidak akan dinonaktifkan, tetapi hanya mengizinkan koneksi dari jaringan yang sama (bukan NAT traversal atau relai).</translation>
+      Jika kebijakan disetel ke Nonaktif, akses jarak jauh tidak akan dinonaktifkan, tetapi koneksi hanya akan diizinkan dari jaringan yang sama (bukan NAT traversal atau relai).</translation>
 <translation id="7956210013490975468">Mengonfigurasi layanan System-proxy untuk <ph name="PRODUCT_OS_NAME" />.</translation>
 <translation id="7958537754689366707">Sandi harus dimasukkan setiap dua belas jam</translation>
 <translation id="7961779417826583251">Nonaktifkan penerapan Transparansi Sertifikat untuk daftar Otoritas Sertifikat Lama</translation>
@@ -5246,7 +5246,7 @@
       Jika kebijakan ini tidak disetel, HTTP/0.9 akan dinonaktifkan di port non-default.</translation>
 <translation id="8504243661032323176">Menyetel kebijakan akan menerapkan panjang PIN minimum yang dipilih. (Nilai di bawah 1 akan dibulatkan ke atas ke minimum 1).
 
-      Tidak menyetel kebijakan akan membatalkan penerapan panjang PIN minimum 6 digit, nilai minimum yang direkomendasikan.</translation>
+      Tidak menyetel kebijakan akan membatalkan penerapan panjang PIN minimum 6 digit, yakni nilai minimum yang direkomendasikan.</translation>
 <translation id="8504725006737796967">Menentukan printer yang dapat digunakan pengguna.
 
       Kebijakan ini hanya digunakan jika <ph name="PRINTERS_WHITELIST" /> dipilih untuk <ph name="BULK_PRINTERS_ACCESS_MODE_POLICY_NAME" />.
diff --git a/components/policy/resources/policy_templates_it.xtb b/components/policy/resources/policy_templates_it.xtb
index f1a46fd..7da47b5 100644
--- a/components/policy/resources/policy_templates_it.xtb
+++ b/components/policy/resources/policy_templates_it.xtb
@@ -129,9 +129,9 @@
 <translation id="1198183996903759302">Se il criterio è impostato su true (o se <ph name="HARDWARE_ACCELERATION_MODE_ENABLED_POLICY_NAME" /> è impostato su false), le pagine web non possono accedere all'API WebGL e i plug-in non possono usare l'API Pepper 3D.
 
       Se il criterio è impostato su false o non viene configurato, le pagine web possono usare l'API WebGL e i plug-in possono usare l'API Pepper 3D, ma le impostazioni predefinite del browser potrebbero comunque richiedere argomenti della riga di comando per usare queste API.</translation>
-<translation id="1199366379198964260">Se il criterio viene impostato su Attivato, vengono consentiti PIN inefficaci. Ecco alcune caratteristiche dei PIN inefficaci: una sola cifra ripetuta (1111), cifre con incrementi di 1 (1234), cifre con decrementi di 1 (4321) e PIN comuni. Se il criterio viene impostato su Disattivato, gli utenti non possono impostare PIN inefficaci facili da indovinare.
+<translation id="1199366379198964260">Se il criterio viene impostato su Attivato, vengono consentiti PIN non sicuri. Ecco alcune caratteristiche dei PIN non sicuri: una sola cifra ripetuta (1111), cifre con incrementi di 1 (1234), cifre con decrementi di 1 (4321) e PIN comuni. Se il criterio viene impostato su Disattivato, gli utenti non possono impostare PIN non sicuri facili da indovinare.
 
-      Per impostazione predefinita, gli utenti ricevono un avviso, non un messaggio di errore, se usano un PIN inefficace.</translation>
+      Per impostazione predefinita, gli utenti ricevono un avviso, non un messaggio di errore, se usano un PIN non sicuro.</translation>
 <translation id="1202216683470826356">Mostra schede nella pagina Nuova scheda</translation>
 <translation id="1204263402976895730">Stampanti aziendali attive</translation>
 <translation id="1209065772997672966">Se il criterio viene configurato, puoi impostare un elenco di pattern URL che specificano i siti che possono aprire popup.
@@ -400,7 +400,7 @@
 
       * Lo schermo viene spento se l'utente rimane inattivo per il tempo specificato nel campo <ph name="SCREEN_OFF_FIELD_NAME" />.
 
-      * Se l'utente rimane inattivo per il tempo specificato nel campo <ph name="IDLE_WARNING_FIELD_NAME" />, viene visualizzata una finestra di dialogo di avviso per indicare all'utente che verrà compiuta l'azione per inattività e tale finestra viene visualizzata soltanto se l'azione per inattività è l'uscita dall'account o l'arresto del sistema.
+      * Se l'utente rimane inattivo per il tempo specificato nel campo <ph name="IDLE_WARNING_FIELD_NAME" />, viene visualizzata una finestra di dialogo di avviso per indicare all'utente che verrà compiuta l'azione per inattività. Tale finestra viene visualizzata soltanto se l'azione per inattività è l'uscita dall'account o l'arresto del sistema.
 
       * Se l'utente rimane inattivo per il tempo specificato nel campo <ph name="IDLE_FIELD_NAME" />, viene compiuta l'azione specificata nel campo <ph name="IDLE_ACTION_FIELD_NAME" />.
 
@@ -706,7 +706,7 @@
 
       * PIN e impronta, usa ["PIN", "FINGERPRINT"].
 
-      Se il criterio non viene configurato o se viene impostato un elenco vuoto, non saranno disponibili modalità di sblocco rapido per i dispositivi gestiti.
+      Se il criterio non viene configurato o se viene impostato su un elenco vuoto, non saranno disponibili modalità di sblocco rapido per i dispositivi gestiti.
 
       Questo criterio è deprecato. Usa il criterio <ph name="QUICK_UNLOCK_MODE_ALLOW_LIST_POLICY_NAME" />.</translation>
 <translation id="2036522553891755455">Se il criterio viene impostato su Attivato, il rilevamento delle condivisioni (la funzionalità Condivisione file di rete di <ph name="PRODUCT_NAME" />) utilizza il protocollo <ph name="NETBIOS_PROTOCOL" /> per rilevare le condivisioni sulla rete. Se viene impostato su Disattivato, il rilevamento delle condivisioni non utilizza il protocollo per rilevare le condivisioni.
@@ -4545,7 +4545,7 @@
 
       * PIN e impronta, usa ["PIN", "FINGERPRINT"].
 
-      Se il criterio non viene configurato o se viene impostato un elenco vuoto, non saranno disponibili modalità di sblocco rapido per i dispositivi gestiti.</translation>
+      Se il criterio non viene configurato o se viene impostato su un elenco vuoto, non saranno disponibili modalità di sblocco rapido per i dispositivi gestiti.</translation>
 <translation id="7547549430720182663">Unisci</translation>
 <translation id="7553535237300701827">Se viene impostata questa norma, il flusso di autenticazione dell'accesso sarà uno dei seguenti, a seconda del valore dell'impostazione:
 
diff --git a/components/policy/resources/policy_templates_ko.xtb b/components/policy/resources/policy_templates_ko.xtb
index f2ba2b5..c7dda36 100644
--- a/components/policy/resources/policy_templates_ko.xtb
+++ b/components/policy/resources/policy_templates_ko.xtb
@@ -2931,7 +2931,7 @@
 
       정책을 설정하지 않으면 사용자가 등록한 <ph name="PRODUCT_OS_NAME" />에서 게임을 플레이할 수 없지만 다른 상황에서는 플레이할 수 있습니다.</translation>
 <translation id="529457411593078576">첫 실행 중 CCT에 서비스 약관 사용 설정</translation>
-<translation id="5303080953475303561">정책을 설정하면 빠른 잠금 해제를 위해 잠금 화면에서 비밀번호를 요청하는 빈도를 제어할 수 있습니다. 잠금 화면이 표시되었을 때 선택한 값을 통해 지정된 기간 이전에 마지막 비밀번호 입력이 이루어진 경우 빠른 잠금 해제를 사용할 수 없습니다. 사용자가 이 시간이 지날 때까지 잠금 화면에 머무르면 다음번에 잘못된 코드를 입력하거나 잠금 화면으로 다시 이동했을 때(둘 중 먼저 발생한 상황에 적용됨) 비밀번호를 입력해야 합니다.
+<translation id="5303080953475303561">정책을 설정하면 빠른 잠금 해제를 위해 잠금 화면에서 비밀번호를 요청하는 빈도를 제어할 수 있습니다. 선택한 값을 통해 지정된 기간 이전에 마지막 비밀번호 입력이 이루어진 경우 잠금 화면이 표시되었을 때 빠른 잠금 해제를 사용할 수 없습니다. 사용자가 이 시간이 지날 때까지 잠금 화면에 머무르면 다음번에 잘못된 코드를 입력하거나 잠금 화면으로 다시 이동했을 때(둘 중 먼저 발생한 상황에 적용됨) 비밀번호를 입력해야 합니다.
 
       정책을 설정하지 않으면 빠른 잠금 해제를 이용하는 사용자가 잠금 화면에서 매일 비밀번호를 입력해야 합니다.</translation>
 <translation id="5306186200045823863">Symantec Corporation의 Legacy PKI 인프라에서 트러스트를 사용 설정합니다.</translation>
diff --git a/components/policy/resources/policy_templates_pt-BR.xtb b/components/policy/resources/policy_templates_pt-BR.xtb
index 7aa5f022..168b0512 100644
--- a/components/policy/resources/policy_templates_pt-BR.xtb
+++ b/components/policy/resources/policy_templates_pt-BR.xtb
@@ -2091,7 +2091,7 @@
 <translation id="3997519162482760140">URLs que terão acesso a dispositivos de captura de vídeo em páginas de login SAML</translation>
 <translation id="4007646377576030214"> Esta política foi suspensa na versão M87 e foi removida na M89. Use a <ph name="MANAGED_GUEST_SESSION_PRIVACY_WARNINGS_POLICY_NAME" /> para configurar alertas de privacidade de sessões de visitante gerenciadas.
 
-      Controlar notificações de lançamento automático da sessão de visitante gerenciada no <ph name="PRODUCT_OS_NAME" />.
+      Controle as notificações de lançamento automático da sessão de visitante gerenciada no <ph name="PRODUCT_OS_NAME" />.
 
       Se esta política for definida como verdadeira, a notificação de aviso de privacidade será fechada após alguns segundos.
 
@@ -2567,7 +2567,7 @@
 
       Se ela for definida como "oculta", os recursos desativados não poderão ser utilizados e ficarão invisíveis para os usuários.
 
-      Se a política for deixada sem definição tiver um valor inválido, o modo de desativação de recursos do sistema será "bloqueado".</translation>
+      Se a política for deixada sem definição ou tiver um valor inválido, o modo de desativação de recursos do sistema será "bloqueado".</translation>
 <translation id="4835470005923546373">Desativar modo de impressão de gráficos de segundo plano por padrão</translation>
 <translation id="4835622243021053389">Ativar autenticação NTLMv2.</translation>
 <translation id="4855636880814771207">Se esta política for definida como ativada ou não for definida, o usuário poderá ativar ou desativar o Bluetooth.
@@ -4312,7 +4312,7 @@
 <translation id="7252681704926980614">Envia o nome de usuário e de arquivo para o servidor de impressoras nativas com cada trabalho de impressão. O padrão é não enviar.
 
       Se esta política for definida como verdadeira, ela também desativará impressoras que usam protocolos diferentes de IPPS, USB ou IPP-over-USB, uma vez que o nome de usuário e o nome de arquivo não podem ser enviados pela rede abertamente.</translation>
-<translation id="7257092058788772055">Se a política for definida, o URL de página inicial padrão será definido no <ph name="PRODUCT_NAME" />. Use o botão "Início" para abrir a página inicial. No computador, as políticas <ph name="RESTORE_ON_STARTUP_POLICY_NAME" /> controlam as páginas que são abertas na inicialização.
+<translation id="7257092058788772055">Se a política for definida, o URL de página inicial padrão será definido no <ph name="PRODUCT_NAME" />. O botão "Início" abrirá a página inicial. No computador, as políticas <ph name="RESTORE_ON_STARTUP_POLICY_NAME" /> controlam as páginas que são abertas na inicialização.
 
       Se a página inicial for definida como a página Nova guia, seja pelo usuário ou por <ph name="HOMEPAGE_IS_NEW_TAB_PAGE_POLICY_NAME" />, esta política não terá efeito.
 
diff --git a/components/policy/resources/policy_templates_th.xtb b/components/policy/resources/policy_templates_th.xtb
index 935f136..06fe997 100644
--- a/components/policy/resources/policy_templates_th.xtb
+++ b/components/policy/resources/policy_templates_th.xtb
@@ -88,7 +88,7 @@
       กำหนดระยะเวลาการไม่ใช้งานก่อนที่โปรแกรมรักษาหน้าจอจะแสดงขึ้นบนหน้าจอลงชื่อเข้าใช้สำหรับอุปกรณ์ในโหมดปลีก
 
       ควรระบุค่าของนโยบายเป็นมิลลิวินาที</translation>
-<translation id="1144540226829648811">ระบุเวอร์ชันการเผยแพร่ที่ควรจะล็อกเข้ากับอุปกรณ์นี้
+<translation id="1144540226829648811">ระบุเวอร์ชันการเผยแพร่ที่อุปกรณ์นี้ควรจะใช้ได้
 
       การตั้งค่า <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> จะมีผลเฉพาะในกรณีที่ตั้งค่า <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> เป็น "เท็จ"</translation>
 <translation id="1151353063931113432">อนุญาตให้แสดงภาพบนไซต์เหล่านี้</translation>
@@ -196,7 +196,7 @@
       การตั้งค่านโยบายเป็น "ปิดใช้" หรือไม่ได้ตั้งค่าจะทำให้ใช้การโรมมิ่งข้อมูลไม่ได้</translation>
 <translation id="1307454923744766368">ต้นทางหรือรูปแบบชื่อโฮสต์ที่ไม่ควรใช้ข้อจำกัด
       เกี่ยวกับต้นทางที่ไม่ปลอดภัย</translation>
-<translation id="1308526987406924874">การตั้งค่านโยบายจะให้คุณสร้างรายการรูปแบบ URL ซึ่งระบุเว็บไซต์ที่ขอให้ผู้ใช้ให้สิทธิ์เข้าถึงพอร์ตอนุกรมไม่ได้
+<translation id="1308526987406924874">การตั้งค่านโยบายจะให้คุณสร้างรายการรูปแบบ URL ซึ่งระบุเว็บไซต์ที่ไม่สามารถขอให้ผู้ใช้ให้สิทธิ์เข้าถึงพอร์ตอนุกรมได้
 
       การไม่ตั้งค่านโยบายหมายความว่า <ph name="DEFAULT_SERIAL_GUARD_SETTING_POLICY_NAME" /> จะมีผลกับทุกเว็บไซต์ (หากตั้งค่าไว้) แต่หากไม่ได้ตั้งค่าไว้ การตั้งค่าส่วนตัวของผู้ใช้จะมีผล
 
@@ -524,7 +524,7 @@
 <translation id="1736269219679256369">อนุญาตให้ดำเนินการจากหน้าคำเตือน SSL</translation>
 <translation id="174765717426930019">อนุญาตให้เปิดป๊อปอัปทั้งหมดโดยมีการกำหนดเป้าหมายให้ <ph name="BLANK_PAGE_NAME" /> โต้ตอบกับหน้าที่ขอเปิดป๊อปอัป เว้นแต่หน้าที่เปิดเลือกไม่ใช้การโต้ตอบดังกล่าวอย่างชัดแจ้ง </translation>
 <translation id="1750315445671978749">บล็อกการดาวน์โหลดทั้งหมด</translation>
-<translation id="1751429117283165017">การตั้งค่านโยบายจะให้คุณสร้างรายการรูปแบบ URL ซึ่งระบุเว็บไซต์ที่จะขอให้ผู้ใช้ให้สิทธิ์การเข้าถึงในการเขียนไฟล์หรือไดเรกทอรีในระบบไฟล์ของระบบปฏิบัติการของโฮสต์ไม่ได้
+<translation id="1751429117283165017">การตั้งค่านโยบายจะให้คุณสร้างรายการรูปแบบ URL ซึ่งระบุเว็บไซต์ที่ไม่สามารถขอให้ผู้ใช้ให้สิทธิ์การเข้าถึงในการอ่านไฟล์หรือไดเรกทอรีในระบบไฟล์ของระบบปฏิบัติการของโฮสต์ผ่าน File System API ได้
 
       การไม่ตั้งค่านโยบายหมายความว่า <ph name="DEFAULT_FILE_SYSTEM_WRITE_GUARD_SETTING_POLICY_NAME" /> จะมีผลกับทุกเว็บไซต์ (หากตั้งค่าไว้) แต่หากไม่ได้ตั้งค่าไว้ การตั้งค่าส่วนตัวของผู้ใช้จะมีผล
 
@@ -711,7 +711,7 @@
 
       การตั้งค่านโยบายเป็น "ปิดใช้" จะทำให้อุปกรณ์ที่ลงทะเบียนไว้ไม่รายงานสถิติด้านฮาร์ดแวร์</translation>
 <translation id="2040479044912658454">โหมดการแรสเตอร์งานพิมพ์</translation>
-<translation id="2042513383871755994">การตั้งค่านโยบายจะให้คุณสร้างรายการรูปแบบ URL ซึ่งระบุเว็บไซต์ที่จะขอให้ผู้ใช้ให้สิทธิ์การเข้าถึงในการอ่านไฟล์หรือไดเรกทอรีในระบบไฟล์ของระบบปฏิบัติการของโฮสต์ผ่าน File System API ไม่ได้
+<translation id="2042513383871755994">การตั้งค่านโยบายจะให้คุณสร้างรายการรูปแบบ URL ซึ่งระบุเว็บไซต์ที่ไม่สามารถขอให้ผู้ใช้ให้สิทธิ์การเข้าถึงในการอ่านไฟล์หรือไดเรกทอรีในระบบไฟล์ของระบบปฏิบัติการของโฮสต์ผ่าน File System API ได้
 
       การไม่ตั้งค่านโยบายหมายความว่า <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> จะมีผลกับทุกเว็บไซต์ (หากตั้งค่าไว้) แต่หากไม่ได้ตั้งค่าไว้ การตั้งค่าส่วนตัวของผู้ใช้จะมีผล
 
@@ -3554,7 +3554,7 @@
 <translation id="6282524907402492171">แสดงคำเตือนการเลิกใช้งาน <ph name="CLOUD_PRINT_NAME" /></translation>
 <translation id="6282799760374509080">อนุญาตหรือปฏิเสธการจับเสียง</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
-<translation id="6300871921951390976">ผู้ใช้ได้รับอนุญาตให้เปลี่ยนเวอร์ชันการเผยแพร่ของอุปกรณ์หากตั้งค่านโยบายนี้เป็น "จริง" เท่านั้น หากนโยบายนี้เป็น "เท็จ" หรือไม่ได้ตั้งค่า ผู้ใช้จะไม่ได้รับอนุญาตให้เปลี่ยนเวอร์ชันการเผยแพร่
+<translation id="6300871921951390976">ผู้ใช้ได้รับอนุญาตให้เปลี่ยนเวอร์ชันการเผยแพร่ของอุปกรณ์หากตั้งค่านโยบายนี้เป็น "จริง" เท่านั้น หากนโยบายนี้เป็น "เท็จ" หรือไม่ได้ตั้งค่า ผู้ใช้จะไม่ได้รับอนุญาตให้เปลี่ยนเวอร์ชัน
 
       การตั้งค่า <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> จะมีผลเฉพาะในกรณีที่ตั้งค่า <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> เป็น "เท็จ"</translation>
 <translation id="6310223829319187614">เปิดใช้การเติมชื่อโดเมนอัตโนมัติระหว่างการลงชื่อเข้าใช้ของผู้ใช้</translation>
@@ -4169,7 +4169,7 @@
 
       การตั้งค่านโยบายเป็น "ปิดใช้" ทำให้ระบบสามารถระบุว่าผู้ใช้ไม่มีความเคลื่อนไหวแม้จะมีกิจกรรมวิดีโอ</translation>
 <translation id="7086720321892395256">ควบคุมนโยบายด้านผู้ใช้และอุปกรณ์สำหรับฟีเจอร์หน้าจอส่วนตัว</translation>
-<translation id="7090668780328470271">การตั้งค่านโยบายจะให้คุณสร้างรายการรูปแบบ URL ซึ่งระบุเว็บไซต์ที่ขอให้ผู้ใช้ให้สิทธิ์เข้าถึงอุปกรณ์ USB ไม่ได้
+<translation id="7090668780328470271">การตั้งค่านโยบายจะให้คุณสร้างรายการรูปแบบ URL ซึ่งระบุเว็บไซต์ที่ไม่สามารถขอให้ผู้ใช้ให้สิทธิ์เข้าถึงอุปกรณ์ USB ได้
 
       การไม่ตั้งค่านโยบายหมายความว่า <ph name="DEFAULT_WEB_USB_GUARD_SETTING_POLICY_NAME" /> จะมีผลกับทุกเว็บไซต์ (หากตั้งค่าไว้) แต่หากไม่ได้ตั้งค่าไว้ การตั้งค่าส่วนตัวของผู้ใช้จะมีผล
 
diff --git a/components/policy/resources/policy_templates_uk.xtb b/components/policy/resources/policy_templates_uk.xtb
index fe8c567f..663599bf 100644
--- a/components/policy/resources/policy_templates_uk.xtb
+++ b/components/policy/resources/policy_templates_uk.xtb
@@ -659,7 +659,7 @@
 <translation id="1971991630422430420">Якщо це правило ввімкнено, а безпровідна точка доступу підтримує швидкий перехід, то ця функція використовуватиметься. Це правило стосується всіх користувачів та інтерфейсів на пристрої.
 
       Якщо це правило вимкнено або не налаштовано, швидкий перехід не використовуватиметься.</translation>
-<translation id="1977581177449752640">Якщо налаштувати це правило, для автентифікації за URL-адресою, визначеною правилом <ph name="REMOTE_ACCESS_HOST_TOKEN_VALIDATION_URL_POLICY_NAME" />, хост віддаленого доступу використовуватиме сертифікат клієнта з указаним загальним іменем видавця. Щоб використовувався будь-який наявний сертифікат клієнта, задайте значення "<ph name="WILDCARD_VALUE" />". Якщо це правило не налаштовано або задано пустий рядок, відповідна функція вимикається.</translation>
+<translation id="1977581177449752640">Якщо налаштувати це правило, хост віддаленого доступу використовуватиме тільки сертифікати клієнта з указаним загальним іменем видавця для авторизації в <ph name="REMOTE_ACCESS_HOST_TOKEN_VALIDATION_URL_POLICY_NAME" />. Щоб використовувався будь-який наявний сертифікат клієнта, задайте значення "<ph name="WILDCARD_VALUE" />". Якщо це правило не налаштовано або задано пустий рядок, відповідна функція вимикається.</translation>
 <translation id="1988345404999458987">Указує налаштування доступних серверів друку.
 
       Це правило дає змогу налаштувати зовнішні сервери друку для пристроїв <ph name="PRODUCT_OS_NAME" /> як файл JSON.
diff --git a/components/policy/resources/policy_templates_zh-CN.xtb b/components/policy/resources/policy_templates_zh-CN.xtb
index 45c3b9bb..14fa93d 100644
--- a/components/policy/resources/policy_templates_zh-CN.xtb
+++ b/components/policy/resources/policy_templates_zh-CN.xtb
@@ -128,6 +128,9 @@
 <translation id="1197437816436565375">您无法强制 Android 应用使用代理。一小部分代理设置已可供 Android 应用使用,此类应用可能会主动选择使用这些设置。有关详情,请参阅 <ph name="PROXY_MODE_POLICY_NAME" /> 政策。</translation>
 <translation id="1198183996903759302">如果此政策设为 True(或者 <ph name="HARDWARE_ACCELERATION_MODE_ENABLED_POLICY_NAME" /> 设为 False),网页会无法访问 WebGL API,而且插件会无法使用 Pepper 3D API。
       如果此政策设为 False 或未设置,网页可以使用 WebGL API,而且插件可以使用 Pepper 3D API,但浏览器的默认设置可能仍然要求在使用这些 API 前先传递命令行参数。</translation>
+<translation id="1199366379198964260">如果此政策已启用,系统会允许使用安全系数低的 PIN 码。安全系数低的 PIN 码的一些特征:由同一个数字构成 (1111)、数字以 1 为单位递增 (1234)、数字以 1 为单位递减 (4321),以及常用的 PIN 码。如果此政策已停用,用户将无法设置安全系数低且易被猜中的 PIN 码。
+
+      默认情况下,如果系统认为 PIN 码的安全系数偏低,就会向用户显示警告(而非错误消息)。</translation>
 <translation id="1202216683470826356">在“新标签页”页面上显示卡片</translation>
 <translation id="1204263402976895730">已启用企业打印机</translation>
 <translation id="1209065772997672966">通过设置此政策,您可以创建一个网址格式列表,从而指定哪些网站可以打开弹出式窗口。
@@ -387,6 +390,37 @@
 <translation id="1600340610556453828">如果此政策已停用,<ph name="PRODUCT_OS_NAME" />会关闭 Wi-Fi,而且用户无法更改相关设置。
 
       如果此政策已启用或未设置,系统会允许用户开启或关闭 Wi-Fi。</translation>
+<translation id="1601848091543601739">通过设置此政策,您可以控制设备闲置时的电源管理策略。
+
+      系统可执行以下四种闲置操作:
+
+      * 当设备闲置时长达到 <ph name="SCREEN_DIM_FIELD_NAME" /> 指定的值后,屏幕将变暗。
+
+      * 当设备闲置时长达到 <ph name="SCREEN_OFF_FIELD_NAME" /> 指定的值后,屏幕将关闭。
+
+      * 当设备闲置时长达到 <ph name="IDLE_WARNING_FIELD_NAME" /> 指定的值后,屏幕上将显示一个警告对话框。该警告消息旨在让用户知道系统将执行闲置操作,仅会在闲置操作是退出登录或关机时显示。
+
+      * 当设备闲置时长达到 <ph name="IDLE_FIELD_NAME" /> 指定的值后,系统将执行 <ph name="IDLE_ACTION_FIELD_NAME" /> 指定的操作。
+
+      对于上述各项操作,延迟时间均应以毫秒为单位指定,并且必须设为大于 0 的值才能触发相应操作。如果延迟时间设为 0,<ph name="PRODUCT_OS_NAME" />将不会执行相应操作。
+
+      对于上述各个延迟时间,如果您未设置时间值,系统会使用默认值。
+
+      <ph name="SCREEN_DIM_FIELD_NAME" /> 的值不得大于 <ph name="SCREEN_OFF_FIELD_NAME" /> 的值,否则会被强制修改。<ph name="SCREEN_OFF_FIELD_NAME" /> 和 <ph name="IDLE_WARNING_FIELD_NAME" /> 的值不得大于 <ph name="IDLE_FIELD_NAME" /> 的值,否则会被强制修改。
+
+      <ph name="IDLE_ACTION_FIELD_NAME" /> 可以是下列四种操作之一:
+
+      * <ph name="IDLE_ACTION_ENUM_SUSPEND" />
+
+      * <ph name="IDLE_ACTION_ENUM_LOGOUT" />
+
+      * <ph name="IDLE_ACTION_ENUM_SHUTDOWN" />
+
+      * <ph name="IDLE_ACTION_ENUM_DO_NOTHING" />
+
+      如果 <ph name="IDLE_ACTION_FIELD_NAME" /> 未设置,系统将执行 <ph name="IDLE_ACTION_ENUM_SUSPEND" />。
+
+      注意:交流电源和电池各有对应的设置。</translation>
 <translation id="1606917441621112087">如果此政策设为 True,系统会在 <ph name="PRODUCT_NAME" /> 中停用内部 PDF 查看器,将 PDF 文件视为下载项,并允许用户使用默认应用打开 PDF 文件。
 
       如果此政策设为 False 或未设置,系统将会使用 PDF 插件打开 PDF 文件,除非用户停用了该插件。</translation>
@@ -651,6 +685,19 @@
           </translation>
 <translation id="2030905906517501646">默认搜索服务提供商关键字</translation>
 <translation id="203096360153626918">此政策对 Android 应用没有任何影响。即使此政策设为 <ph name="FALSE" />,这些应用也将能够进入全屏模式。</translation>
+<translation id="2032848225007871645">通过设置此政策,您可以控制哪些快速解锁模式可为锁定屏幕解锁。
+
+      若要:
+
+      * 允许使用所有快速解锁模式(包括日后会添加的模式),请使用 ["all"]。
+
+      * 仅允许使用 PIN 码解锁,请使用 ["PIN"]。
+
+      * 允许使用 PIN 码和指纹解锁,请使用 ["PIN", "FINGERPRINT"]。
+
+      如果此政策未设置或设为一个空列表,用户将无法在受管理的设备上使用任何快速解锁模式。
+
+      此政策已被弃用,请改用 <ph name="QUICK_UNLOCK_MODE_ALLOW_LIST_POLICY_NAME" /></translation>
 <translation id="2036522553891755455">如果此政策已启用,共享文件发现功能(<ph name="PRODUCT_NAME" />的网络文件共享功能)会使用 <ph name="NETBIOS_PROTOCOL" />来搜寻网络上的共享文件。如果此政策已停用,共享文件发现功能将不会使用此协议来搜寻共享文件。
 
       如果您未设置此政策,系统的默认行为就会是:为受管用户停用此政策,并为其他用户启用此政策。</translation>
@@ -1145,6 +1192,11 @@
 <translation id="2759224876420453487">控制多用户配置会话中的用户行为</translation>
 <translation id="2761483219396643566">使用电池供电时的闲置警告延迟时间</translation>
 <translation id="2769952903507981510">为远程访问主机配置所需的域名</translation>
+<translation id="2772955711376920612">如果此政策已启用,且 <ph name="DEVICE_POWER_PEAK_SHIFT_BATTERY_THRESHOLD_POLICY_NAME" /> 和 <ph name="DEVICE_POWER_PEAK_SHIFT_DAY_CONFIG_POLICY_NAME" /> 均已设置,“用电高峰期切换电源”功能会保持开启状态(如果相应设备支持的话)。“用电高峰期切换电源”电源管理政策是一种节电政策,可在用电高峰期间尽可能少用交流电。您可分别为每个工作日设置“用电高峰期切换电源”模式的运行开始时间和结束时间。在您所设定的时段内,只要电池电量高于指定阈值,即使连接了交流电,设备也会仅使用电池来维持运行。待指定的结束时间过后,设备会使用交流电(如果已连接)来维持运行,但不会为电池充电。待指定的充电开始时间过后,设备会再次使用交流电来维持正常运行,并会为电池充电。
+
+      如果此政策已停用,“用电高峰期切换电源”功能会保持关闭状态。
+
+      如果此政策未设置,“用电高峰期切换电源”功能最初会处于关闭状态。用户无法更改相关设置。</translation>
 <translation id="2787173078141616821">报告有关 Android 状态的信息</translation>
 <translation id="2787774054174244402">如果此政策设为 True,用户将无法向外部存储设备写入内容。
 
@@ -2449,6 +2501,11 @@
 <translation id="4700190441681139987">不允许任何网站使用传感器</translation>
 <translation id="4703402283970867140">启用智能调暗模式,以最大限度地推迟屏幕变暗时间</translation>
 <translation id="4722122254122249791">为指定的来源启用网站隔离功能</translation>
+<translation id="4723122879352880315">此设置允许用户使用 <ph name="PRODUCT_OS_NAME" />登录凭据向通过 NTLM 身份验证机制提供安全保护的受管理代理验证身份。
+
+      如果此政策设为 False 或未设置,<ph name="PRODUCT_OS_NAME" />登录凭据将不会被用于网络身份验证。
+
+      如果此政策设为 True,<ph name="PRODUCT_OS_NAME" />登录凭据将会被用于向受管理的代理进行网络身份验证。如果采用 <ph name="PRODUCT_OS_NAME" />登录凭据的身份验证失败,系统会提示用户提供凭据。</translation>
 <translation id="4723829699367336876">支持通过远程访问客户端穿越防火墙</translation>
 <translation id="4725528134735324213">启用 Android Backup Service</translation>
 <translation id="4725801978265372736">要求本地用户的名称和远程访问主机所有者的名称必须一致</translation>
@@ -2597,6 +2654,7 @@
 <translation id="4983201894483989687">允许运行过期的插件</translation>
 <translation id="4986560318567565414">控制用于从替代浏览器切换至 Chrome 的路径。</translation>
 <translation id="4988291787868618635">闲置延迟时间已过时执行的操作</translation>
+<translation id="4996068111491152684"><ph name="PRODUCT_OS_NAME" />登录凭据不会被用于网络身份验证。</translation>
 <translation id="4996086761250834365">允许进行 <ph name="PLUGIN_VM_NAME" /> 产品分析</translation>
 <translation id="500149597848135831">启用所有变体</translation>
 <translation id="5017369989680827157">如果此政策设为 True 或未设置,用户可以控制是否在界面中自动填充地址。
@@ -2830,6 +2888,9 @@
 
       如果此政策未设置,用户无法在已注册的 <ph name="PRODUCT_OS_NAME" />上玩恐龙游戏,但可在其他环境下玩这款游戏。</translation>
 <translation id="529457411593078576">在 CCT 首次运行期间启用《服务条款》</translation>
+<translation id="5303080953475303561">通过设置此政策,您可以控制锁定屏幕将会按照什么样的频率要求用户输入密码以实现快速解锁。每当系统显示锁定屏幕时,如果与上次密码输入时间之间的间隔超过了所选值指定的时间段,便无法快速解锁。如果用户在锁定屏幕上的停留时长超过了此时间段,那么当用户下次输错代码或重新进入锁定屏幕时(以先发生者为准),系统就会要求输入密码。
+
+      如果您未设置此政策,使用快速解锁功能的用户每天都需在锁定屏幕上输入其密码。</translation>
 <translation id="5306186200045823863">信任 Symantec Corporation 的旧版 PKI 基础架构</translation>
 <translation id="5307432759655324440">隐身模式的可用性</translation>
 <translation id="5311275381462687162">默认旧版 <ph name="ATTRIBUTE_SAMESITE_NAME" /> Cookie 行为设置</translation>
@@ -3655,6 +3716,9 @@
 <translation id="6536600139108165863">设备关机后自动重新启动</translation>
 <translation id="6539246272469751178">此政策对 Android 应用没有任何影响。Android 应用始终都会使用默认下载目录,并且无法访问由 <ph name="PRODUCT_OS_NAME" />下载到非默认下载目录中的任何文件。</translation>
 <translation id="654303922206238013">ecryptfs 迁移策略</translation>
+<translation id="654546276700640113">如果您设置了此政策,系统会强制实施所配置的 PIN 码长度上限。如果值小于或等于 0,即表示用户可以设置任意长度的 PIN 码。如果值小于 <ph name="PIN_UNLOCK_MINIMUM_LENGTH_POLICY_NAME" /> 但大于 0,则表示长度上限与下限相同。
+
+      如果您未设置此政策,系统将不会强制实施任何长度上限。</translation>
 <translation id="6553143066970470539">屏幕亮度百分比</translation>
 <translation id="6558362593755624474">通过设置此政策,您可为该设备指定 <ph name="PLUGIN_VM_NAME" /> 许可密钥。</translation>
 <translation id="6559057113164934677">不允许任何网站使用摄像头和麦克风</translation>
@@ -4339,6 +4403,7 @@
           如果您未设置此政策,那么,倘若“DefaultKeygenSetting”政策已设置,系统便会将它的全局默认值应用于所有网站,否则就会应用用户个人配置中的全局默认值。
 
           如需详细了解有效网址格式,请访问 https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns。<ph name="WILDCARD_VALUE" /> 不是此政策可接受的值。</translation>
+<translation id="739556497251174388">允许将 <ph name="PRODUCT_OS_NAME" />登录凭据重用于网络身份验证</translation>
 <translation id="7400971609879083218">如果此政策已启用,系统会允许网页上的第三方图片显示身份验证提示。
 
        如果此政策已停用或未设置,第三方图片将无法显示身份验证提示。
@@ -4436,6 +4501,17 @@
 <translation id="7534199150025803530">此政策对 Android 版“Google 云端硬盘”应用没有任何影响。如果您想阻止通过移动网络连接使用 Google 云端硬盘,则应禁止安装 Android 版“Google 云端硬盘”应用。</translation>
 <translation id="7540622499178214923">允许使用 Wilco 诊断和遥测控制器</translation>
 <translation id="7540826630642174841">如果您设置了此政策,那么在指定的时间间隔内,指定的设备政策会被忽略(使用这些政策的默认设置)。当政策时段开始或结束时,<ph name="PRODUCT_NAME" /> 会重新应用设备政策。当此时段有变且设备政策设置有变时(例如,当用户使用禁用的帐号登录时),系统会通知用户并强制用户退出。</translation>
+<translation id="7540945123920084379">通过设置此政策,您可以控制哪些快速解锁模式可为锁定屏幕解锁。
+
+      若要:
+
+      * 允许使用所有快速解锁模式(包括日后会添加的模式),请使用 ["all"]。
+
+      * 仅允许使用 PIN 码解锁,请使用 ["PIN"]。
+
+      * 允许使用 PIN 码和指纹解锁,请使用 ["PIN", "FINGERPRINT"]。
+
+      如果此政策未设置或设为一个空列表,用户将无法在受管理的设备上使用任何快速解锁模式。</translation>
 <translation id="7547549430720182663">合并</translation>
 <translation id="7553535237300701827">设置此政策后,登录身份验证流程将采用以下其中一种方式,具体取决于设置的值:
 
@@ -4796,6 +4872,7 @@
 <translation id="8050080920415773384">本机打印</translation>
 <translation id="8053580360728293758">替换默认打印颜色模式。如果这种模式不适用,则忽略此政策。</translation>
 <translation id="8056237304861875584">允许启用 Phone Hub 任务延续功能。</translation>
+<translation id="8056273037819805106"><ph name="PRODUCT_OS_NAME" />登录凭据会被用于向受管理的代理进行网络身份验证。</translation>
 <translation id="8059164285174960932">远程访问客户端获取身份验证令牌的网址</translation>
 <translation id="8062485064082966327">使用匿名 Google 服务为无标签图片提供自动说明</translation>
 <translation id="8076521374016204899">如果此政策已启用或未设置,使用密码验证身份的用户便可以锁定屏幕。
@@ -4940,6 +5017,7 @@
 <translation id="8266778278542911985">如果此政策设为 3,系统会允许网站请求访问串行端口。如果此政策设为 2,系统会禁止访问串行端口。
 
       如果此政策未设置,系统会允许网站请求访问,但用户可以更改此设置。</translation>
+<translation id="827054846390793641">允许主机桌面在处于连接状态时显示与连接相关的界面</translation>
 <translation id="8274603902181597201">清空用户的 ecryptfs 主目录,并改用全新的 ext4 加密主目录。</translation>
 <translation id="8284296539558710573">跨域 HTTP 身份验证提示</translation>
 <translation id="8284527236880877730">如果 <ph name="POWER_SMART_DIM_ENABLED_POLICY_NAME" /> 已停用,您可以通过设置 <ph name="PRESENTATION_SCREEN_DIM_DELAY_SCALE_POLICY_NAME" /> 来指定:当设备处于演示模式时,系统应该对屏幕变暗延迟时间采取的调整幅度(百分比)。调整屏幕变暗延迟时间时,系统会随之调整屏幕关闭延迟时间、屏幕锁定延迟时间和闲置延迟时间,以使它们保持在原有设置下与屏幕变暗延迟时间的间隔。
@@ -5111,6 +5189,9 @@
       此政策旨在让企业能够使现有服务器迁移到 HTTP/0.9 以外的协议版本,日后会被移除。
 
       如果未设置此政策,非默认端口上将会停用 HTTP/0.9。</translation>
+<translation id="8504243661032323176">通过设置此政策,您可以强制实施所选的 PIN 码长度下限。(小于 1 的值会被向上舍入到下限值 1。)
+
+      如果您未设置此政策,系统会强制要求 PIN 码的长度下限为 6 位数(这是建议的长度下限)。</translation>
 <translation id="8504725006737796967">此政策旨在指定用户可以使用的打印机。
 
       仅当为 <ph name="BULK_PRINTERS_ACCESS_MODE_POLICY_NAME" /> 选择了 <ph name="PRINTERS_WHITELIST" /> 时,才会用到此政策。
@@ -5189,6 +5270,7 @@
       如果此政策设为 false,系统将不会冻结任何标签页。</translation>
 <translation id="8631434304112909927">到版本 <ph name="UNTIL_VERSION" /> 为止</translation>
 <translation id="8631437968147930597">可在 <ph name="PRODUCT_OS_NAME" />锁定屏幕中显示的笔记应用的列表。</translation>
+<translation id="8643838501942693770">允许使用第三方 Cookie,但用户可以更改相关设置</translation>
 <translation id="8649763579836720255">Chrome 操作系统设备可使用远程凭证(经验证的访问凭证)来获取由 Chrome OS CA 颁发的证书,以证明该设备符合播放受保护内容的条件。此过程涉及向 Chrome OS CA 发送用于唯一标识设备的硬件背书信息。
 
           如果该设置为 False,设备将不使用远程凭证来保护内容,并且设备可能无法播放受保护内容。
diff --git a/components/policy/resources/policy_templates_zh-TW.xtb b/components/policy/resources/policy_templates_zh-TW.xtb
index d45f394c..0345551f 100644
--- a/components/policy/resources/policy_templates_zh-TW.xtb
+++ b/components/policy/resources/policy_templates_zh-TW.xtb
@@ -455,9 +455,9 @@
 <translation id="1634989431648355062">允許在這些網站上執行 <ph name="FLASH_PLUGIN_NAME" /> 外掛程式</translation>
 <translation id="1641394008743444477">這項政策可讓你設定要停用的 <ph name="PRODUCT_OS_NAME" />功能清單。
 
-      停用清單上的任何一項功能後,使用者將無法在使用者介面上存取這項功能,且畫面上會顯示為「已由管理員停用」。已停用功能的使用者體驗由 <ph name="SYSTEM_FEATURES_DISABLE_MODE" /> 決定
+      任何功能一經停用,使用者就無法在使用者介面上存取該功能,且畫面上會顯示為「已由管理員停用」。已停用功能的使用者體驗由 <ph name="SYSTEM_FEATURES_DISABLE_MODE" /> 決定
 
-      如果不設定這項政策,預設狀態下會啟用所有 <ph name="PRODUCT_OS_NAME" /> 的功能,且使用者皆可存取。
+      如果不設定這項政策,預設狀態下會啟用所有 <ph name="PRODUCT_OS_NAME" />的功能,且使用者皆可存取。
 
       注意:掃描功能目前已透過功能標記預設為停用。如果使用者透過功能標記啟用該功能,這項政策仍然可以將其停用。</translation>
 <translation id="1645793986494086629">架構:</translation>
@@ -515,7 +515,7 @@
 <translation id="1736269219679256369">允許忽略 SSL 警告網頁,繼續前往原本指定的頁面</translation>
 <translation id="174765717426930019">除非要求開啟彈出式視窗的網頁明確拒絕與該彈出式視窗互動,否則一律允許透過 <ph name="BLANK_PAGE_NAME" /> 連結目標開啟的彈出式視窗進行這類互動 </translation>
 <translation id="1750315445671978749">封鎖所有下載作業</translation>
-<translation id="1751429117283165017">你可以透過這項政策建立網址模式清單,指定哪些網站可以要求使用者授予寫入權限,以寫入主機作業系統中檔案系統的檔案或目錄。
+<translation id="1751429117283165017">你可以透過這項政策建立網址模式清單,指定哪些網站無法要求使用者授予寫入權限,以寫入主機作業系統中檔案系統的檔案或目錄。
 
       如果未設定這項政策,系統會針對所有網站套用 <ph name="DEFAULT_FILE_SYSTEM_WRITE_GUARD_SETTING_POLICY_NAME" /> 政策 (如果已設定)。否則系統會套用使用者的個人設定。
       網址模式不得與 <ph name="FILE_SYSTEM_WRITE_ASK_FOR_URLS_POLICY_NAME" /> 政策衝突。如果網址同時符合兩項政策,系統不會優先採用任何一項政策。
@@ -1343,7 +1343,7 @@
 
           如果不設定這項政策,系統會根據 <ph name="DEFAULT_COOKIES_SETTINGS_POLICY_NAME" /> 政策 (如有設定) 或使用者的個人設定,將全域預設值套用至所有網站。
 
-          另請參閲 <ph name="COOKIES_BLOCKED_FOR_URLS_POLICY_NAME" /> 政策和 <ph name="COOKIES_SESSIONS_ONLY_FOR_URLS" />。請注意,這三項政策的網址模式不可發生衝突,否則系統將無法判斷應優先採用哪項政策。
+          另請參閲 <ph name="COOKIES_BLOCKED_FOR_URLS_POLICY_NAME" /> 和 <ph name="COOKIES_SESSIONS_ONLY_FOR_URLS" /> 政策。請注意,這三項政策的網址模式不可發生衝突,否則系統將無法判斷應優先採用哪項政策。
 
           想進一步瞭解有效的網址模式,請參閱 https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns。<ph name="WILDCARD_VALUE" /> 不是這項政策許可的值。</translation>
 <translation id="3001285126226650303">允許 <ph name="PRODUCT_NAME" /> 載入實驗性政策。
@@ -1477,9 +1477,9 @@
           如果不設定這項政策,系統會使用預設時間長度。
 
           指定政策值時需以毫秒為單位。</translation>
-<translation id="3205649498518960697">你可以設定網址模式清單,指定哪些網站能夠顯示可封鎖 (即使用中) 複合型內容 (亦即 HTTPS 網站上的 HTTP 內容),並指定要停用哪些選用的可封鎖複合型內容升級功能。
+<translation id="3205649498518960697">你可以設定網址模式清單,指定哪些網站能夠顯示可封鎖的 (即主動) 複合型內容 (亦即 HTTPS 網站上的 HTTP 內容),並停用可選擇性封鎖的複合型內容的升級功能。
 
-         如果不設定這項政策,系統會封鎖可封鎖的複合型內容,並升級選用的可封鎖複合型內容。此外,使用者可以設定例外網站,允許特定網站顯示可封鎖的複合型內容。
+         如果不設定這項政策,可封鎖的複合型內容將遭到封鎖,且系統會升級可選擇性封鎖的複合型內容。此外,使用者可以設定例外網站,允許特定網站顯示複合型內容。
 
           想進一步瞭解有效的網址模式,請參閱 https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns。<ph name="WILDCARD_VALUE" /> 不是這項政策許可的值。</translation>
 <translation id="3205825995289802549">首次執行時將第一個瀏覽器視窗最大化</translation>
@@ -2088,9 +2088,9 @@
 <translation id="4025500273782820766">如有外部通訊協定對話方塊詢問使用者是否要略過日後的確認提示,允許使用者選取 [一律允許]</translation>
 <translation id="402759845255257575">不允許任何網站執行 JavaScript</translation>
 <translation id="4027608872760987929">啟用預設搜尋引擎</translation>
-<translation id="4041577849977347218">如果將這項政策設為啟用或不設定,即使下載的檔案來自可信任的來源,安全瀏覽功能仍會將下載內容送交分析。
+<translation id="4041577849977347218">如果將這項政策設為啟用或不設定,即使下載的檔案來自可信任的來源,安全瀏覽功能仍會將其送交分析。
 
-      如果將這項政策設為停用,只要下載的檔案來自可信任的來源,安全瀏覽功能就不會將下載內容送交分析。
+      如果將這項政策設為停用,只要下載的檔案來自可信任的來源,安全瀏覽功能就不會將其送交分析。
 
       這些限制適用於網頁內容和 [下載連結] 選單選項所觸發的下載作業,但不適用於目前顯示網頁的儲存或下載作業,或透過列印選項另存為 PDF 檔的作業。
 
@@ -2137,7 +2137,7 @@
 <translation id="4105989332710272578">不針對列出的網址強制執行憑證透明化政策</translation>
 <translation id="4114059938441379876">你可以透過設定這項政策,指定使用者在瀏覽器中看到警告後,前往變更密碼的網址。密碼保護服務會將使用者導向你透過這項政策設定的網址 (僅限 HTTP 和 HTTPS 通訊協定)。為了讓 <ph name="PRODUCT_NAME" /> 能在這個變更密碼頁面中正確擷取新密碼的加鹽雜湊值,請確保變更密碼頁面符合以下網址所述的規範:https://www.chromium.org/developers/design-documents/create-amazing-password-forms。
 
-      如果關閉這項政策或不設定,密碼保護服務會將使用者導向至 https://myaccount.google.com 以變更密碼。
+      如果停用這項政策或不設定,密碼保護服務會將使用者導向至 https://myaccount.google.com 以變更密碼。
 
       在 <ph name="MS_WIN_NAME" /> 上,這項功能僅適用於已加入 <ph name="MS_AD_NAME" /> 網域的執行個體、在 Windows 10 專業版上執行的執行個體,或是已註冊 <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />服務的執行個體。在 <ph name="MAC_OS_NAME" /> 上,這項功能僅適用於透過行動裝置管理 (MDM) 軟體進行管理或透過 MCX 加入網域的執行個體。</translation>
 <translation id="4121350739760194865">阻止應用程式宣傳資訊在新分頁上顯示</translation>
@@ -2629,9 +2629,9 @@
 
       如果將這項政策設為 False,<ph name="PRODUCT_NAME" /> 就無法讓使用者從使用者管理工具建立新設定檔。</translation>
 <translation id="4970855112942626932">禁止登入瀏覽器</translation>
-<translation id="4977702914571821981">你可以設定網址模式清單,指定哪些網站不能顯示可封鎖 (即使用中) 複合型內容 (亦即 HTTPS 網站上的 HTTP 內容),並指定要升級哪些選用的可封鎖 (即非使用中) 複合型內容。
+<translation id="4977702914571821981">你可以設定網址模式清單,指定哪些網站不能顯示可封鎖的 (即主動) 複合型內容 (亦即 HTTPS 網站上的 HTTP 內容),並讓那些網站升級可選擇性封鎖的 (即被動) 複合型內容。
 
-         如果不設定這項政策,可封鎖的複合型內容將遭到封鎖,且系統會升級選用的可封鎖複合型內容。但使用者可以設定例外網站,允許特定網站顯示可封鎖的複合型內容。
+         如果不設定這項政策,可封鎖的複合型內容將遭到封鎖,且系統會升級可選擇性封鎖的複合型內容。但使用者可以設定例外網站,允許特定網站顯示複合型內容。
 
           想進一步瞭解有效的網址模式,請參閱 https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns。<ph name="WILDCARD_VALUE" /> 不是這項政策許可的值。</translation>
 <translation id="4978533099939732984">一律顯示磁碟空間不足的警告</translation>
@@ -3532,7 +3532,7 @@
 <translation id="6282524907402492171">顯示 <ph name="CLOUD_PRINT_NAME" />淘汰警告訊息</translation>
 <translation id="6282799760374509080">允許或拒絕擷取音訊</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
-<translation id="6300871921951390976">如果將這項政策設為 True,使用者只可變更裝置的發布版本。如果將這項政策設為 False 或不設定,使用者就不可變更版本。
+<translation id="6300871921951390976">必須將這項政策設為 True,使用者才可變更裝置的發布版本。如果將這項政策設為 False 或不設定,使用者就不可變更版本。
 
       只有將 <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> 設為 False,<ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> 設定才會生效。</translation>
 <translation id="6310223829319187614">允許在使用者登入過程中以自動完成功能填入網域名稱</translation>
@@ -4061,7 +4061,7 @@
       注意:Android 的網站隔離支援日後將會改善,但目前可能會導致效能問題。執行 Chrome 的 Android 系統必須運行於 RAM 實際超過 1 GB 的裝置上,才能套用這項政策。如要在非 Android 平台上套用這項政策,請使用 <ph name="ISOLATE_ORIGINS_POLICY_NAME" />。</translation>
 <translation id="6978404102280820831">除非將 <ph name="RESTORE_ON_STARTUP_POLICY_NAME" /> 政策設為一律還原先前工作階段的網址,否則你可以透過 <ph name="COOKIES_SESSION_ONLY_FOR_URLS_POLICY_NAME" /> 政策建立網址模式清單,用來指定網站是否可為單一工作階段設定 Cookie。
 
-      如果未設定這項政策,系統會針對所有網站使用 <ph name="DEFAULT_COOKIES_SETTINGS_POLICY_NAME" /> (如果已設定);否則系統會套用使用者的個人設定。如果指定的模式中不包含使用者設定的網址,系統也會使用預設值。
+      如果未設定這項政策,系統會針對所有網站使用 <ph name="DEFAULT_COOKIES_SETTINGS_POLICY_NAME" /> (如果已設定);否則系統會套用使用者的個人設定。如果網址不符合指定的模式,系統也會使用預設值。
 
       如果 <ph name="PRODUCT_NAME" /> 在背景模式下執行,工作階段可能會持續運作到使用者關閉瀏覽器為止,而非只持續到關閉最後一個視窗。請參閱 <ph name="BACKGROUND_MODE_ENABLED_POLICY_NAME" />,進一步瞭解如何設定這項行為。
 
@@ -4203,10 +4203,9 @@
           如果不設定這項政策,系統會將滑鼠左鍵預設為主要按鈕,但使用者隨時可以切換。</translation>
 <translation id="7137460825181247519">這項政策已在 <ph name="PRODUCT_NAME" /> 83 版遭到淘汰,請改用 <ph name="SAFE_BROWSING_PROTECTION_LEVEL_POLICY_NAME" />。
 
-      如果將這項政策設為啟用,Chrome 的安全瀏覽功能會保持開啟。如果將這項政策設為停用,安全瀏覽
-功能會保持關閉。
+      如果將這項政策設為啟用,Chrome 的安全瀏覽功能會保持開啟。如果將這項政策設為停用,安全瀏覽功能會保持關閉。
 
-      如果你設定這項政策,使用者無法變更這項設定,也無法覆寫 Chrome 的「啟用網路詐騙和惡意軟體防護功能」設定。如果未設定,系統會將「阻擋釣魚網站及惡意程式」設定設為 True,但使用者可變更這項設定。
+      如果設定這項政策,使用者將無法變更這項設定,也無法覆寫 Chrome 的「阻擋釣魚網站及惡意程式」設定。如果未設定,系統會將「阻擋釣魚網站及惡意程式」設定設為 True,但使用者可變更這項設定。
 
       如要進一步瞭解安全瀏覽功能,請前往 https://developers.google.com/safe-browsing。
 
@@ -4399,7 +4398,7 @@
       如果設定這項政策,使用者將無法變更。如果未設定這項政策,系統會關閉網路預測功能,但使用者可以變更這項設定。</translation>
 <translation id="7415655595380180976">這項政策已遭淘汰,請改用「<ph name="URL_ALLOWLIST_POLICY_NAME" />」政策。
 
-      如果設定這項政策,使用者可以存取許可清單中的網址,這些網址是網址封鎖清單的例外項目。請參閱該項政策的說明,瞭解這份清單所含項目的格式。舉例來說,如果將 <ph name="URL_BLOCKLIST_POLICY_NAME" /> 設為「*」,系統會封鎖所有要求。你可以透過這項政策允許使用者存取一些特定的網址。請使用 https://www.chromium.org/administrators/url-blacklist-filter-format 網頁中所指定的格式,透過這項政策將特定的網路協定、其他網域的子網域、通訊埠或特定路徑設為例外。需要判定是否封鎖某一個網址時,則會以條件最精確的篩選器做為判定依據。許可清單的優先順序高於封鎖清單。這項政策最多只能輸入 1000 個項目。
+      如果設定這項政策,使用者可以存取許可清單中的網址,這些網址是網址封鎖清單的例外項目。請參閱該項政策的說明,瞭解這份清單所含項目的格式。舉例來說,如果將 <ph name="URL_BLOCKLIST_POLICY_NAME" /> 設為「*」,系統會封鎖所有要求。你可以透過這項政策允許使用者存取一些特定的網址。請使用 https://www.chromium.org/administrators/url-blacklist-filter-format 網頁中所指定的格式,透過這項政策將特定的網路通訊協定、其他網域的子網域、通訊埠或特定路徑設為例外。系統需要判定是否封鎖某一個網址時,會以最精確的篩選條件為依據。許可清單的優先順序高於封鎖清單。這項政策最多只能輸入 1,000 個項目。
 
       這項政策還可以讓瀏覽器自動叫用已註冊為通訊協定處理常式的外部應用程式,用於處理許可清單中的「tel:」或「ssh:」等通訊協定。
 
@@ -5471,7 +5470,7 @@
 
 如要進一步瞭解安全內容,請參閱 https://www.w3.org/TR/secure-contexts/
       </translation>
-<translation id="8940519618730206658">如果設定這項政策,使用者可以存取許可清單中的網址,這些網址是 <ph name="URL_BLOCKLIST_POLICY_NAME" /> 的例外項目。請參閱該項政策的說明,瞭解這份清單所含項目的格式。舉例來說,如果將 <ph name="URL_BLOCKLIST_POLICY_NAME" /> 設為「*」,系統會封鎖所有要求。你可以透過這項政策允許使用者存取一些特定的網址。請使用 https://www.chromium.org/administrators/url-blacklist-filter-format 網頁中所指定的格式,透過這項政策將特定的網路協定、其他網域的子網域、通訊埠或特定路徑設為例外。需要判定是否封鎖某一個網址時,則會以條件最精確的篩選器做為判定依據。<ph name="URL_ALLOWLIST_POLICY_NAME" /> 政策的優先順序高於 <ph name="URL_BLOCKLIST_POLICY_NAME" />。這項政策最多只能輸入 1000 個項目。
+<translation id="8940519618730206658">如果設定這項政策,使用者可以存取許可清單中的網址,這些網址是 <ph name="URL_BLOCKLIST_POLICY_NAME" /> 的例外項目。請參閱該項政策的說明,瞭解這份清單所含項目的格式。舉例來說,如果將 <ph name="URL_BLOCKLIST_POLICY_NAME" /> 設為「*」,系統會封鎖所有要求。你可以透過這項政策允許使用者存取一些特定的網址。請使用 https://www.chromium.org/administrators/url-blacklist-filter-format 網頁中所指定的格式,透過這項政策將特定的網路通訊協定、其他網域的子網域、通訊埠或特定路徑設為例外。系統需要判定是否封鎖某一個網址時,會以最精確的篩選條件為依據。<ph name="URL_ALLOWLIST_POLICY_NAME" /> 政策的優先順序高於 <ph name="URL_BLOCKLIST_POLICY_NAME" />。這項政策最多只能輸入 1,000 個項目。
 
       這項政策還可以讓瀏覽器自動叫用已註冊為通訊協定處理常式的外部應用程式,用於處理許可清單中的「tel:」或「ssh:」等通訊協定。
 
diff --git a/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc b/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc
index 92db7fa0..a251be27e 100644
--- a/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc
+++ b/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc
@@ -76,7 +76,7 @@
         discardable_memory::mojom::DiscardableSharedMemoryManager> manager) {
   mojo::PendingRemote<discardable_memory::mojom::DiscardableSharedMemoryManager>
       manager_remote(std::move(manager));
-  discardable_shared_memory_manager_ = std::make_unique<
+  discardable_shared_memory_manager_ = base::MakeRefCounted<
       discardable_memory::ClientDiscardableSharedMemoryManager>(
       std::move(manager_remote), io_task_runner_);
   base::DiscardableMemoryAllocator::SetInstance(
diff --git a/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h b/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h
index f3560255..d90bbb0 100644
--- a/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h
+++ b/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h
@@ -67,7 +67,7 @@
   mojo::Receiver<mojom::PaintPreviewCompositorCollection> receiver_{this};
 
   const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-  std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+  scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
       discardable_shared_memory_manager_;
 
   base::flat_map<base::UnguessableToken,
diff --git a/components/services/print_compositor/print_compositor_impl.cc b/components/services/print_compositor/print_compositor_impl.cc
index 81db9af..f8f81cc9 100644
--- a/components/services/print_compositor/print_compositor_impl.cc
+++ b/components/services/print_compositor/print_compositor_impl.cc
@@ -112,7 +112,7 @@
   // Set up discardable memory manager.
   mojo::PendingRemote<discardable_memory::mojom::DiscardableSharedMemoryManager>
       manager_remote(std::move(manager));
-  discardable_shared_memory_manager_ = std::make_unique<
+  discardable_shared_memory_manager_ = base::MakeRefCounted<
       discardable_memory::ClientDiscardableSharedMemoryManager>(
       std::move(manager_remote), io_task_runner_);
   base::DiscardableMemoryAllocator::SetInstance(
diff --git a/components/services/print_compositor/print_compositor_impl.h b/components/services/print_compositor/print_compositor_impl.h
index 44a3d291..6a97b270 100644
--- a/components/services/print_compositor/print_compositor_impl.h
+++ b/components/services/print_compositor/print_compositor_impl.h
@@ -230,7 +230,7 @@
   mojo::Receiver<mojom::PrintCompositor> receiver_{this};
 
   const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-  std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+  scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
       discardable_shared_memory_manager_;
 
   // The creator of this service.
diff --git a/components/session_manager/DIR_METADATA b/components/session_manager/DIR_METADATA
new file mode 100644
index 0000000..d08126ac
--- /dev/null
+++ b/components/session_manager/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Shell"
+}
diff --git a/components/session_manager/OWNERS b/components/session_manager/OWNERS
index 22db12b..b280edc9 100644
--- a/components/session_manager/OWNERS
+++ b/components/session_manager/OWNERS
@@ -1,4 +1,3 @@
 achuith@chromium.org
 alemate@chromium.org
 xiyuan@chromium.org
-# COMPONENT: UI>Shell
diff --git a/components/session_manager/core/DIR_METADATA b/components/session_manager/core/DIR_METADATA
new file mode 100644
index 0000000..d08126ac
--- /dev/null
+++ b/components/session_manager/core/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Shell"
+}
diff --git a/components/session_manager/core/OWNERS b/components/session_manager/core/OWNERS
index 036a36bd..e69de29 100644
--- a/components/session_manager/core/OWNERS
+++ b/components/session_manager/core/OWNERS
@@ -1 +0,0 @@
-# COMPONENT: UI>Shell
diff --git a/components/sessions/DIR_METADATA b/components/sessions/DIR_METADATA
new file mode 100644
index 0000000..1a6d7ee6
--- /dev/null
+++ b/components/sessions/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Services>Sync"
+}
diff --git a/components/sessions/OWNERS b/components/sessions/OWNERS
index 8ba5325..0ba9926 100644
--- a/components/sessions/OWNERS
+++ b/components/sessions/OWNERS
@@ -1,4 +1,2 @@
 sky@chromium.org
 skuhne@chromium.org
-
-# COMPONENT: Services>Sync
diff --git a/components/sessions/content/DIR_METADATA b/components/sessions/content/DIR_METADATA
new file mode 100644
index 0000000..b48e6bf
--- /dev/null
+++ b/components/sessions/content/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>Sessions"
+}
diff --git a/components/sessions/content/OWNERS b/components/sessions/content/OWNERS
index dd4c58a..e69de29 100644
--- a/components/sessions/content/OWNERS
+++ b/components/sessions/content/OWNERS
@@ -1 +0,0 @@
-# COMPONENT: UI>Browser>Sessions
diff --git a/components/sessions/ios/DIR_METADATA b/components/sessions/ios/DIR_METADATA
new file mode 100644
index 0000000..14b5edb5
--- /dev/null
+++ b/components/sessions/ios/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals"
+}
diff --git a/components/sessions/ios/OWNERS b/components/sessions/ios/OWNERS
index f136fc1..e69de29 100644
--- a/components/sessions/ios/OWNERS
+++ b/components/sessions/ios/OWNERS
@@ -1 +0,0 @@
-# COMPONENT: Internals
diff --git a/components/shared_highlighting/core/common/shared_highlighting_metrics.cc b/components/shared_highlighting/core/common/shared_highlighting_metrics.cc
index 1a866f69..8f414652 100644
--- a/components/shared_highlighting/core/common/shared_highlighting_metrics.cc
+++ b/components/shared_highlighting/core/common/shared_highlighting_metrics.cc
@@ -75,29 +75,50 @@
 void LogLinkOpenedUkmEvent(ukm::SourceId source_id,
                            const GURL& referrer,
                            bool success) {
+  LogLinkOpenedUkmEvent(ukm::UkmRecorder::Get(), source_id, referrer, success);
+}
+
+void LogLinkOpenedUkmEvent(ukm::UkmRecorder* recorder,
+                           ukm::SourceId source_id,
+                           const GURL& referrer,
+                           bool success) {
+  DCHECK(recorder);
   if (source_id != ukm::kInvalidSourceId) {
     ukm::builders::SharedHighlights_LinkOpened(source_id)
         .SetSuccess(success)
         .SetSource(static_cast<int64_t>(GetLinkSource(referrer)))
-        .Record(ukm::UkmRecorder::Get());
+        .Record(recorder);
   }
 }
 
 void LogLinkGeneratedSuccessUkmEvent(ukm::SourceId source_id) {
+  LogLinkGeneratedSuccessUkmEvent(ukm::UkmRecorder::Get(), source_id);
+}
+
+void LogLinkGeneratedSuccessUkmEvent(ukm::UkmRecorder* recorder,
+                                     ukm::SourceId source_id) {
+  DCHECK(recorder);
   if (source_id != ukm::kInvalidSourceId) {
     ukm::builders::SharedHighlights_LinkGenerated(source_id)
         .SetSuccess(true)
-        .Record(ukm::UkmRecorder::Get());
+        .Record(recorder);
   }
 }
 
 void LogLinkGeneratedErrorUkmEvent(ukm::SourceId source_id,
                                    LinkGenerationError reason) {
+  LogLinkGeneratedErrorUkmEvent(ukm::UkmRecorder::Get(), source_id, reason);
+}
+
+void LogLinkGeneratedErrorUkmEvent(ukm::UkmRecorder* recorder,
+                                   ukm::SourceId source_id,
+                                   LinkGenerationError reason) {
+  DCHECK(recorder);
   if (source_id != ukm::kInvalidSourceId) {
     ukm::builders::SharedHighlights_LinkGenerated(source_id)
         .SetSuccess(false)
         .SetError(static_cast<int64_t>(reason))
-        .Record(ukm::UkmRecorder::Get());
+        .Record(recorder);
   }
 }
 
diff --git a/components/shared_highlighting/core/common/shared_highlighting_metrics.h b/components/shared_highlighting/core/common/shared_highlighting_metrics.h
index 0d7f9da..71bc8ea 100644
--- a/components/shared_highlighting/core/common/shared_highlighting_metrics.h
+++ b/components/shared_highlighting/core/common/shared_highlighting_metrics.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_SHARED_HIGHLIGHTING_METRICS_H_
 #define COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_SHARED_HIGHLIGHTING_METRICS_H_
 
+#include "services/metrics/public/cpp/ukm_recorder.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "url/gurl.h"
 
@@ -84,21 +85,54 @@
 // Records a UKM event for opening a link with text fragments. |source_id|
 // refers to the navigation action's ID, |referrer| will be used to record the
 // source and |success| should be true only if fragments highlighting was a
-// complete success. This event can only be recorded once per navigation.
+// complete success. This event can only be recorded once per navigation, and
+// this function will record using the static Recorder instance. This API can
+// only be used when calling from the browser process, otherwise no event will
+// be recorded.
 void LogLinkOpenedUkmEvent(ukm::SourceId source_id,
                            const GURL& referrer,
                            bool success);
 
+// Records a UKM event for opening a link with text fragments. |source_id|
+// refers to the navigation action's ID, |referrer| will be used to record the
+// source and |success| should be true only if fragments highlighting was a
+// complete success. This event can only be recorded once per navigation, and
+// will record using the given custom |recorder|. Prefer this API when calling
+// from a process other than the browser process.
+void LogLinkOpenedUkmEvent(ukm::UkmRecorder* recorder,
+                           ukm::SourceId source_id,
+                           const GURL& referrer,
+                           bool success);
+
 // Records a UKM event for successfully generating a link with text fragments.
-// |source_id| refers to the current frame.
+// |source_id| refers to the current frame, and this function will record using
+// the static Recorder. This API can only be used when calling from the browser
+// process, otherwise no event will be recorded.
 void LogLinkGeneratedSuccessUkmEvent(ukm::SourceId source_id);
 
+// Records a UKM event for successfully generating a link with text fragments.
+// |source_id| refers to the current frame. This function will record using the
+// given custom |recorder|. Prefer this API when calling from a process other
+// than the browser process.
+void LogLinkGeneratedSuccessUkmEvent(ukm::UkmRecorder* recorder,
+                                     ukm::SourceId source_id);
+
 // Records a UKM event for failing to generate a link with text fragments.
 // |source_id| refers to the current frame and |reason| highlights the cause of
-// the failure.
+// the failure. This function will record using the static Recorder. This API
+// can only be used when calling from the browser process, otherwise no event
+// will be recorded.
 void LogLinkGeneratedErrorUkmEvent(ukm::SourceId source_id,
                                    LinkGenerationError reason);
 
+// Records a UKM event for failing to generate a link with text fragments.
+// |source_id| refers to the current frame and |reason| highlights the cause of
+// the failure. This function will record using the given custom |recorder|.
+// Prefer this API when calling from a process other than the browser process.
+void LogLinkGeneratedErrorUkmEvent(ukm::UkmRecorder* recorder,
+                                   ukm::SourceId source_id,
+                                   LinkGenerationError reason);
+
 }  // namespace shared_highlighting
 
 #endif  // COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_SHARED_HIGHLIGHTING_METRICS_H_
diff --git a/components/shared_highlighting/core/common/shared_highlighting_metrics_unittest.cc b/components/shared_highlighting/core/common/shared_highlighting_metrics_unittest.cc
index d048cf02..b30a7c5b 100644
--- a/components/shared_highlighting/core/common/shared_highlighting_metrics_unittest.cc
+++ b/components/shared_highlighting/core/common/shared_highlighting_metrics_unittest.cc
@@ -200,6 +200,25 @@
   EXPECT_EQ(0u, entries.size());
 }
 
+// Tests that using the endpoints with a custom recorder won't use the static
+// UKM recorder.
+TEST_F(SharedHighlightingMetricsTest, LinkOpenedUkm_CustomRecorder) {
+  ukm::TestAutoSetUkmRecorder static_ukm_recorder;
+  ukm::TestUkmRecorder custom_ukm_recorder;
+  ukm::SourceId source_id = 1;
+
+  LogLinkOpenedUkmEvent(&custom_ukm_recorder, source_id, GURL(),
+                        /*success=*/true);
+
+  auto static_entries = static_ukm_recorder.GetEntriesByName(
+      ukm::builders::SharedHighlights_LinkOpened::kEntryName);
+  EXPECT_EQ(0U, static_entries.size());
+
+  auto custom_entries = custom_ukm_recorder.GetEntriesByName(
+      ukm::builders::SharedHighlights_LinkOpened::kEntryName);
+  EXPECT_EQ(1U, custom_entries.size());
+}
+
 TEST_F(SharedHighlightingMetricsTest, LinkGeneratedUkm_Success) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
   ukm::SourceId source_id = 1;
@@ -243,6 +262,26 @@
   EXPECT_EQ(0u, entries.size());
 }
 
+// Tests that using the endpoints with a custom recorder won't use the static
+// UKM recorder.
+TEST_F(SharedHighlightingMetricsTest, LinkGeneratedUkm_CustomRecorder) {
+  ukm::TestAutoSetUkmRecorder static_ukm_recorder;
+  ukm::TestUkmRecorder custom_ukm_recorder;
+  ukm::SourceId source_id = 1;
+
+  LogLinkGeneratedSuccessUkmEvent(&custom_ukm_recorder, source_id);
+  LogLinkGeneratedErrorUkmEvent(&custom_ukm_recorder, source_id,
+                                LinkGenerationError::kEmptySelection);
+
+  auto static_entries = static_ukm_recorder.GetEntriesByName(
+      ukm::builders::SharedHighlights_LinkGenerated::kEntryName);
+  EXPECT_EQ(0U, static_entries.size());
+
+  auto custom_entries = custom_ukm_recorder.GetEntriesByName(
+      ukm::builders::SharedHighlights_LinkGenerated::kEntryName);
+  EXPECT_EQ(2U, custom_entries.size());
+}
+
 }  // namespace
 
 }  // namespace shared_highlighting
diff --git a/components/strings/components_strings_am.xtb b/components/strings/components_strings_am.xtb
index 646e86b..b157b9b 100644
--- a/components/strings/components_strings_am.xtb
+++ b/components/strings/components_strings_am.xtb
@@ -902,7 +902,7 @@
 <translation id="455113658016510503">A9</translation>
 <translation id="4558551763791394412">ቅጥያዎችዎን አሰናክለው ይሞክሩ።</translation>
 <translation id="4559332380232738994">10x11</translation>
-<translation id="457875822857220463">መላኪያ</translation>
+<translation id="457875822857220463">ማድረስ</translation>
 <translation id="4579056131138995126">የግል (የደብዳቤ ፖስታ)</translation>
 <translation id="4582204425268416675">ካርድ አስወግድ</translation>
 <translation id="4587425331216688090">አድራሻ ከChrome ይወገድ?</translation>
diff --git a/components/strings/components_strings_gu.xtb b/components/strings/components_strings_gu.xtb
index e04eb0c..51d24da 100644
--- a/components/strings/components_strings_gu.xtb
+++ b/components/strings/components_strings_gu.xtb
@@ -912,7 +912,7 @@
 <translation id="455113658016510503">A9</translation>
 <translation id="4558551763791394412">તમારા એક્સ્ટેન્શન્સને અક્ષમ કરવાનો પ્રયાસ કરો.</translation>
 <translation id="4559332380232738994">10x11</translation>
-<translation id="457875822857220463">વિતરણ</translation>
+<translation id="457875822857220463">ડિલિવરી</translation>
 <translation id="4579056131138995126">વ્યક્તિગત (એન્વલપ)</translation>
 <translation id="4582204425268416675">કાર્ડ કાઢી નાખો</translation>
 <translation id="4587425331216688090">Chrome માંથી સરનામું દૂર કરીએ?</translation>
diff --git a/components/strings/components_strings_nl.xtb b/components/strings/components_strings_nl.xtb
index db6c927..064b46e 100644
--- a/components/strings/components_strings_nl.xtb
+++ b/components/strings/components_strings_nl.xtb
@@ -819,7 +819,7 @@
     &lt;p&gt;Deze foutmelding wordt weergegeven wanneer je antivirussoftware gebruikt met HTTPS-bescherming of HTTPS-scannen. Deze software verhindert dat Chrome beveiliging biedt.&lt;/p&gt;
     &lt;p&gt;Schakel je antivirussoftware uit om het probleem op te lossen. Als de pagina werkt nadat je de software hebt uitgeschakeld, kun je de software uitschakelen wanneer je beveiligde sites bezoekt.&lt;/p&gt;
     &lt;p&gt;Vergeet niet je antivirussoftware weer in te schakelen zodra je klaar bent.&lt;/p&gt;
-    &lt;h4&gt;Stap 5: Vraag extra ondersteuning&lt;/h4&gt;
+    &lt;h4&gt;Stap 5: Vraag extra support&lt;/h4&gt;
     &lt;p&gt;Als de fout nog steeds wordt weergegeven, neem je contact op met de eigenaar van de website.&lt;/p&gt;</translation>
 <translation id="4226937834893929579"><ph name="BEGIN_LINK" />Voer Netwerkcontrole uit<ph name="END_LINK" />.</translation>
 <translation id="4234495348042597185"><ph name="BEGIN_LINK" />Doorgaan naar <ph name="SITE" /><ph name="END_LINK" /></translation>
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index 935c083..1b5fda88 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -4,22 +4,17 @@
 
 #include "components/sync/driver/data_type_manager_impl.h"
 
-#include <algorithm>
-#include <functional>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/containers/queue.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/sequenced_task_runner.h"
-#include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
 #include "components/sync/driver/configure_context.h"
 #include "components/sync/driver/data_type_encryption_handler.h"
 #include "components/sync/driver/data_type_manager_observer.h"
@@ -253,18 +248,18 @@
   // 3. Flip |types_being_configured| to CONFIGURE_ACTIVE.
   // 4. Set non-enabled user types as DISABLED.
   // 5. Set the fatal, crypto, and unready types to their respective states.
-  ModelTypeSet fatal_types = data_type_status_table_.GetFatalErrorTypes();
-  ModelTypeSet crypto_types = data_type_status_table_.GetCryptoErrorTypes();
-  ModelTypeSet unready_types = data_type_status_table_.GetUnreadyErrorTypes();
-
+  const ModelTypeSet fatal_types = data_type_status_table_.GetFatalErrorTypes();
+  const ModelTypeSet crypto_types =
+      data_type_status_table_.GetCryptoErrorTypes();
   // Types with unready errors do not count as unready if they've been disabled.
-  unready_types.RetainAll(last_requested_types_);
+  const ModelTypeSet unready_types = Intersection(
+      data_type_status_table_.GetUnreadyErrorTypes(), last_requested_types_);
 
-  ModelTypeSet enabled_types = GetEnabledTypes();
+  const ModelTypeSet enabled_types = GetEnabledTypes();
 
-  ModelTypeSet disabled_types =
+  const ModelTypeSet disabled_types =
       Difference(Union(UserTypes(), ControlTypes()), enabled_types);
-  ModelTypeSet to_configure =
+  const ModelTypeSet to_configure =
       Intersection(enabled_types, types_being_configured);
   DVLOG(1) << "Enabling: " << ModelTypeSetToString(enabled_types);
   DVLOG(1) << "Configuring: " << ModelTypeSetToString(to_configure);
@@ -336,6 +331,8 @@
 }
 
 void DataTypeManagerImpl::OnAllDataTypesReadyForConfigure() {
+  // TODO(crbug.com/1102837): Handle |needs_reconfigure_| here, then we don't
+  // need to handle it in StartNextAssociation.
   DCHECK(!download_started_);
   download_started_ = true;
   // TODO(pavely): By now some of datatypes in |download_types_queue_| could
@@ -461,8 +458,11 @@
 
 void DataTypeManagerImpl::DownloadCompleted(
     ModelTypeSet downloaded_types,
-    ModelTypeSet first_sync_types,
+    ModelTypeSet succeeded_configuration_types,
     ModelTypeSet failed_configuration_types) {
+  // Note: |downloaded_types| are the types we requested to download, but some
+  // of them might have been downloaded already. |succeeded_configuration_types|
+  // are the ones that were actually downloaded just now.
   DCHECK_EQ(CONFIGURING, state_);
 
   if (!failed_configuration_types.Empty()) {
@@ -485,6 +485,7 @@
   }
 
   DCHECK(!download_types_queue_.empty());
+  DCHECK(download_types_queue_.front() == downloaded_types);
   download_types_queue_.pop();
 
   // Those types that were already downloaded (non first sync/error types)
@@ -492,9 +493,9 @@
   if (association_types_info_) {
     // A non-empty |association_types_info_| means there were actually types
     // downloading. Finalize those.
-    association_types_info_->first_sync_types = first_sync_types;
+    association_types_info_->first_sync_types = succeeded_configuration_types;
     association_types_info_->download_ready_time = base::Time::Now();
-    StartNextAssociation(UNREADY_AT_CONFIG);
+    StartNextAssociation(association_types_info_->types);
   } else if (download_types_queue_.empty()) {
     // There's nothing more to download or associate (implying either there were
     // no types to associate or they associated as part of |ready_types|).
@@ -536,8 +537,8 @@
   association_types_info_->high_priority_types_before =
       high_priority_types_before;
 
-  // Start associating those types that are already downloaded.
-  StartNextAssociation(READY_AT_CONFIG);
+  // Finalize the types that are already downloaded.
+  StartNextAssociation(ready_types);
 }
 
 ModelTypeSet DataTypeManagerImpl::PrepareConfigureParams(
@@ -561,7 +562,7 @@
   const ModelTypeSet inactive_types =
       GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
 
-  ModelTypeSet enabled_types = active_types;
+  const ModelTypeSet enabled_types = active_types;
   ModelTypeSet disabled_types = GetDataTypesInState(DISABLED, config_state_map);
   disabled_types.PutAll(fatal_types);
   disabled_types.PutAll(crypto_types);
@@ -618,6 +619,7 @@
     types_to_purge.RemoveAll(inactive_types);
     types_to_purge.RemoveAll(unready_types);
   }
+  DCHECK(Intersection(active_types, types_to_purge).Empty());
 
   DCHECK(Intersection(downloaded_types_, crypto_types).Empty());
   // |downloaded_types_| was already updated to include all enabled types.
@@ -636,27 +638,13 @@
   params->is_sync_feature_enabled =
       last_requested_context_.sync_mode == SyncMode::kFull;
 
-  DCHECK(Intersection(active_types, types_to_purge).Empty());
-  DCHECK(Intersection(active_types, fatal_types).Empty());
-  DCHECK(Intersection(active_types, inactive_types).Empty());
   return Difference(active_types, types_to_download);
 }
 
-void DataTypeManagerImpl::StartNextAssociation(AssociationGroup group) {
+void DataTypeManagerImpl::StartNextAssociation(
+    ModelTypeSet types_to_associate) {
   DCHECK(association_types_info_);
-  DCHECK(state_ == STOPPING || state_ == CONFIGURING);
-
-  ModelTypeSet types_to_associate;
-  if (group == READY_AT_CONFIG) {
-    types_to_associate = association_types_info_->ready_types;
-  } else {
-    DCHECK_EQ(UNREADY_AT_CONFIG, group);
-    DCHECK(!association_types_info_->download_ready_time.is_null());
-    // 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.
-    types_to_associate = association_types_info_->types;
-  }
+  DCHECK(state_ == CONFIGURING);
 
   for (ModelType type : types_to_associate) {
     if (ProtocolTypes().Has(type)) {
@@ -664,28 +652,25 @@
     }
   }
 
-  if (state_ == STOPPING)
-    return;
-
   if (needs_reconfigure_) {
     ProcessReconfigure();
     return;
   }
 
-  // If this model association was for the full set of types, then this priority
-  // set is done. Otherwise it was just the ready types and the unready types
-  // still need to be associated.
-  if (types_to_associate == association_types_info_->types) {
-    association_types_info_.reset();
-    if (download_types_queue_.empty()) {
-      state_ = CONFIGURED;
-      NotifyDone(ConfigureResult(OK, types_to_associate));
-    }
-  } else {
+  // If any pending types weren't covered here, then we're not done yet.
+  if (types_to_associate != association_types_info_->types) {
     DCHECK_EQ(association_types_info_->ready_types, types_to_associate);
     // The remaining types are still downloading; this method will get called
     // again (with UNREADY_AT_CONFIG) once the download finishes.
     DCHECK(association_types_info_->download_ready_time.is_null());
+    return;
+  }
+
+  association_types_info_.reset();
+  // If there's nothing more to download either, then we're done configuring.
+  if (download_types_queue_.empty()) {
+    state_ = CONFIGURED;
+    NotifyDone(ConfigureResult(OK, types_to_associate));
   }
 }
 
diff --git a/components/sync/driver/data_type_manager_impl.h b/components/sync/driver/data_type_manager_impl.h
index a72089e..b6c81ad1 100644
--- a/components/sync/driver/data_type_manager_impl.h
+++ b/components/sync/driver/data_type_manager_impl.h
@@ -8,10 +8,7 @@
 #include "components/sync/driver/data_type_manager.h"
 
 #include <map>
-#include <vector>
 
-#include "base/callback_forward.h"
-#include "base/compiler_specific.h"
 #include "base/containers/queue.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -83,20 +80,6 @@
   };
   using DataTypeConfigStateMap = std::map<ModelType, DataTypeConfigState>;
 
-  // Helper enum for identifying which types within a priority group to
-  // associate.
-  enum AssociationGroup {
-    // Those types that were already downloaded and didn't have an error at
-    // configuration time. Corresponds with AssociationTypesInfo's
-    // |ready_types|. These types can start associating as soon as the
-    // ModelLoadManager is not busy.
-    READY_AT_CONFIG,
-    // All other types, including first time sync types and those that have
-    // encountered an error. These types must wait until the syncer has done
-    // any db changes and/or downloads before associating.
-    UNREADY_AT_CONFIG,
-  };
-
   void RecordConfigurationStats(ModelType type);
 
   // Return model types in |state_map| that match |state|.
@@ -139,7 +122,7 @@
   void Restart();
 
   void DownloadCompleted(ModelTypeSet downloaded_types,
-                         ModelTypeSet first_sync_types,
+                         ModelTypeSet succeeded_configuration_types,
                          ModelTypeSet failed_configuration_types);
 
   void NotifyStart();
@@ -159,13 +142,11 @@
   // Will kick off configuration of any new ready types.
   void StartNextDownload(ModelTypeSet high_priority_types_before);
 
-  // Start association of next batch of data types after association of
-  // previous batch finishes. |group| controls which set of types within
-  // an AssociationTypesInfo to associate.
+  // Finalize a set of data types that have finished downloading.
   // TODO(crbug.com/1102837): Simplify and rename this. "Association" doesn't
   // exist anymore; all this does is record configuration stats and eventually
   // update |state_|.
-  void StartNextAssociation(AssociationGroup group);
+  void StartNextAssociation(ModelTypeSet types_to_associate);
 
   void StopImpl(ShutdownReason reason);
 
@@ -187,8 +168,7 @@
   // set.
   ConfigureContext last_requested_context_;
 
-  // A set of types that were enabled at the time initialization with the
-  // |model_load_manager_| was last attempted.
+  // A set of types that were enabled at the time of Restart().
   ModelTypeSet last_enabled_types_;
 
   // A set of types that should be redownloaded even if initial sync is
@@ -223,17 +203,17 @@
   // Types waiting to be downloaded.
   base::queue<ModelTypeSet> download_types_queue_;
 
-  // Types waiting for association and related time tracking info.
+  // Pending types and related time tracking info.
   struct AssociationTypesInfo {
     AssociationTypesInfo();
     AssociationTypesInfo(const AssociationTypesInfo& other);
     ~AssociationTypesInfo();
 
-    // Types to associate.
+    // Pending types. This is generally the same as
+    // |download_types_queue_.front()|.
     ModelTypeSet types;
-    // Types that have just been downloaded and are being associated for the
-    // first time. This includes types that had previously encountered an error
-    // and had to be purged/unapplied from the sync db.
+    // Types that have just been downloaded. This includes types that had
+    // previously encountered an error and had to be purged.
     // This is a subset of |types|.
     ModelTypeSet first_sync_types;
     // Types that were already already downloaded at configuration time.
@@ -245,7 +225,8 @@
     // The set of types that are higher priority, and were therefore blocking
     // the download of |types|.
     ModelTypeSet high_priority_types_before;
-    // The subset of |types| that were successfully configured.
+    // The subset of |types| that were successfully configured. Populated
+    // one-by-one as types finish configuring.
     ModelTypeSet configured_types;
   };
   base::Optional<AssociationTypesInfo> association_types_info_;
diff --git a/components/translate/content/browser/content_translate_driver.cc b/components/translate/content/browser/content_translate_driver.cc
index 7b95620..bfed44b 100644
--- a/components/translate/content/browser/content_translate_driver.cc
+++ b/components/translate/content/browser/content_translate_driver.cc
@@ -325,8 +325,9 @@
     TranslateErrors::Type error_type) {
   if (cancelled) {
     // Informs the |TranslateMetricsLogger| that the translation was cancelled.
+    DCHECK(error_type != TranslateErrors::NONE);
     translate_manager_->GetActiveTranslateMetricsLogger()
-        ->LogTranslationFinished(false);
+        ->LogTranslationFinished(error_type);
     return;
   }
 
diff --git a/components/translate/core/browser/mock_translate_metrics_logger.h b/components/translate/core/browser/mock_translate_metrics_logger.h
index 67e0fc7..3874582 100644
--- a/components/translate/core/browser/mock_translate_metrics_logger.h
+++ b/components/translate/core/browser/mock_translate_metrics_logger.h
@@ -35,7 +35,7 @@
   MOCK_METHOD0(LogAutofillAssistantDeferredTriggerDecision, void());
   MOCK_METHOD0(LogInitialState, void());
   MOCK_METHOD0(LogTranslationStarted, void());
-  MOCK_METHOD1(LogTranslationFinished, void(bool));
+  MOCK_METHOD1(LogTranslationFinished, void(TranslateErrors::Type));
   MOCK_METHOD0(LogReversion, void());
   MOCK_METHOD1(LogUIChange, void(bool));
   MOCK_METHOD1(LogOmniboxIconChange, void(bool));
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index 05a69e8bc..6265465d 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -522,8 +522,7 @@
                                      false);
   NotifyTranslateError(error_type);
 
-  GetActiveTranslateMetricsLogger()->LogTranslationFinished(
-      error_type == TranslateErrors::NONE);
+  GetActiveTranslateMetricsLogger()->LogTranslationFinished(error_type);
 }
 
 void TranslateManager::OnTranslateScriptFetchComplete(
@@ -545,7 +544,8 @@
         translate::TRANSLATE_STEP_TRANSLATE_ERROR, source_lang, target_lang,
         TranslateErrors::NETWORK, false);
     NotifyTranslateError(TranslateErrors::NETWORK);
-    GetActiveTranslateMetricsLogger()->LogTranslationFinished(false);
+    GetActiveTranslateMetricsLogger()->LogTranslationFinished(
+        TranslateErrors::NETWORK);
   }
 }
 
diff --git a/components/translate/core/browser/translate_metrics_logger.h b/components/translate/core/browser/translate_metrics_logger.h
index 99235f25..0ad61f2 100644
--- a/components/translate/core/browser/translate_metrics_logger.h
+++ b/components/translate/core/browser/translate_metrics_logger.h
@@ -8,6 +8,8 @@
 #include <stdint.h>
 #include <string>
 
+#include "components/translate/core/common/translate_errors.h"
+
 namespace translate {
 
 // These values are persisted to logs. Entries should not be renumbered and
@@ -85,7 +87,7 @@
   // Tracks the state of Translate over the course of the page load.
   virtual void LogInitialState() = 0;
   virtual void LogTranslationStarted() = 0;
-  virtual void LogTranslationFinished(bool was_successful) = 0;
+  virtual void LogTranslationFinished(TranslateErrors::Type error_type) = 0;
   virtual void LogReversion() = 0;
   virtual void LogUIChange(bool is_ui_shown) = 0;
   virtual void LogOmniboxIconChange(bool is_omnibox_icon_show) = 0;
diff --git a/components/translate/core/browser/translate_metrics_logger_impl.cc b/components/translate/core/browser/translate_metrics_logger_impl.cc
index da8edfe..58f13bc 100644
--- a/components/translate/core/browser/translate_metrics_logger_impl.cc
+++ b/components/translate/core/browser/translate_metrics_logger_impl.cc
@@ -161,8 +161,10 @@
   is_translation_in_progress_ = true;
 }
 
-void TranslateMetricsLoggerImpl::LogTranslationFinished(bool was_sucessful) {
-  if (was_sucessful) {
+void TranslateMetricsLoggerImpl::LogTranslationFinished(
+    TranslateErrors::Type error_type) {
+  // The translation succeeded if and only if there were no translation errors.
+  if (error_type == TranslateErrors::NONE) {
     UpdateTimeTranslated(previous_state_is_translated_, is_foreground_);
     num_translations_++;
   } else {
@@ -172,6 +174,12 @@
     // Update the initial state if it was dependent on this translation..
     if (is_initial_state_dependent_on_in_progress_translation_)
       initial_state_is_translated_ = previous_state_is_translated_;
+
+    // Check if this was the first error, and then increment the number of
+    // errors for this page load.
+    if (first_translate_error_type_ == TranslateErrors::NONE)
+      first_translate_error_type_ = error_type;
+    num_translate_errors_++;
   }
 
   is_translation_in_progress_ = false;
diff --git a/components/translate/core/browser/translate_metrics_logger_impl.h b/components/translate/core/browser/translate_metrics_logger_impl.h
index 2f666a4..5d92292 100644
--- a/components/translate/core/browser/translate_metrics_logger_impl.h
+++ b/components/translate/core/browser/translate_metrics_logger_impl.h
@@ -45,7 +45,7 @@
   void LogAutofillAssistantDeferredTriggerDecision() override {}
   void LogInitialState() override {}
   void LogTranslationStarted() override {}
-  void LogTranslationFinished(bool was_sucessful) override {}
+  void LogTranslationFinished(TranslateErrors::Type error_type) override {}
   void LogReversion() override {}
   void LogUIChange(bool is_ui_shown) override {}
   void LogOmniboxIconChange(bool is_omnibox_icon_shown) override {}
@@ -85,7 +85,7 @@
   void LogAutofillAssistantDeferredTriggerDecision() override;
   void LogInitialState() override;
   void LogTranslationStarted() override;
-  void LogTranslationFinished(bool was_sucessful) override;
+  void LogTranslationFinished(TranslateErrors::Type error_type) override;
   void LogReversion() override;
   void LogUIChange(bool is_ui_shown) override;
   void LogOmniboxIconChange(bool is_omnibox_icon_shown) override;
@@ -167,6 +167,10 @@
   std::string current_target_language_;
   int num_target_language_changes_ = 0;
 
+  // Tracks any translation errors that occur over the course of the page load.
+  TranslateErrors::Type first_translate_error_type_ = TranslateErrors::NONE;
+  int num_translate_errors_ = 0;
+
   base::WeakPtrFactory<TranslateMetricsLoggerImpl> weak_method_factory_{this};
 };
 
diff --git a/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc b/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc
index b254723..10a5764e 100644
--- a/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc
+++ b/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc
@@ -46,6 +46,14 @@
                                            expected_num_reversions, 1);
   }
 
+  void CheckTranslateErrors(TranslateErrors::Type first_translate_error_type,
+                            int num_translate_errors) {
+    EXPECT_EQ(translate_metrics_logger_->first_translate_error_type_,
+              first_translate_error_type);
+    EXPECT_EQ(translate_metrics_logger_->num_translate_errors_,
+              num_translate_errors);
+  }
+
   void CheckTotalTimeTranslated(base::TimeDelta total_time_translated,
                                 base::TimeDelta total_time_not_translated) {
     EXPECT_EQ(translate_metrics_logger_->total_time_translated_,
@@ -76,7 +84,7 @@
   translate_metrics_logger()->LogInitialState();
   translate_metrics_logger()->LogUIChange(true);
   translate_metrics_logger()->LogTranslationStarted();
-  translate_metrics_logger()->LogTranslationFinished(true);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
   translate_metrics_logger()->LogReversion();
 
   // Simulate |RecordMetrics| being called multiple times.
@@ -152,24 +160,26 @@
   translate_metrics_logger()->LogInitialState();
 
   translate_metrics_logger()->LogTranslationStarted();
-  translate_metrics_logger()->LogTranslationFinished(true);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
 
   translate_metrics_logger()->RecordMetrics(true);
 
   CheckTranslateStateHistograms(TranslateState::kNotTranslatedNoUI,
                                 TranslateState::kTranslatedNoUI, 1, 0);
+  CheckTranslateErrors(TranslateErrors::NONE, 0);
 
   // Simulate a failed translation.
   ResetTest();
   translate_metrics_logger()->LogInitialState();
 
   translate_metrics_logger()->LogTranslationStarted();
-  translate_metrics_logger()->LogTranslationFinished(false);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NETWORK);
 
   translate_metrics_logger()->RecordMetrics(true);
 
   CheckTranslateStateHistograms(TranslateState::kNotTranslatedNoUI,
                                 TranslateState::kNotTranslatedNoUI, 0, 0);
+  CheckTranslateErrors(TranslateErrors::NETWORK, 1);
 
   // Simulate a translation that does not finish.
   ResetTest();
@@ -181,6 +191,7 @@
 
   CheckTranslateStateHistograms(TranslateState::kNotTranslatedNoUI,
                                 TranslateState::kNotTranslatedNoUI, 0, 0);
+  CheckTranslateErrors(TranslateErrors::NONE, 0);
 
   // Simulate translating an already translated page, but the second translation
   // fails.
@@ -188,14 +199,15 @@
   translate_metrics_logger()->LogInitialState();
 
   translate_metrics_logger()->LogTranslationStarted();
-  translate_metrics_logger()->LogTranslationFinished(true);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
   translate_metrics_logger()->LogTranslationStarted();
-  translate_metrics_logger()->LogTranslationFinished(false);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NETWORK);
 
   translate_metrics_logger()->RecordMetrics(true);
 
   CheckTranslateStateHistograms(TranslateState::kNotTranslatedNoUI,
                                 TranslateState::kTranslatedNoUI, 1, 0);
+  CheckTranslateErrors(TranslateErrors::NETWORK, 1);
 
   // Simulate the page being auto translated. Note that in this case the
   // translation will be queued before we mark the initial state, but in general
@@ -204,23 +216,25 @@
   ResetTest();
   translate_metrics_logger()->LogTranslationStarted();
   translate_metrics_logger()->LogInitialState();
-  translate_metrics_logger()->LogTranslationFinished(true);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
 
   translate_metrics_logger()->RecordMetrics(true);
 
   CheckTranslateStateHistograms(TranslateState::kTranslatedNoUI,
                                 TranslateState::kTranslatedNoUI, 1, 0);
+  CheckTranslateErrors(TranslateErrors::NONE, 0);
 
   // Simulate an auto translation where the translation fails.
   ResetTest();
   translate_metrics_logger()->LogTranslationStarted();
   translate_metrics_logger()->LogInitialState();
-  translate_metrics_logger()->LogTranslationFinished(false);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NETWORK);
 
   translate_metrics_logger()->RecordMetrics(true);
 
   CheckTranslateStateHistograms(TranslateState::kNotTranslatedNoUI,
                                 TranslateState::kNotTranslatedNoUI, 0, 0);
+  CheckTranslateErrors(TranslateErrors::NETWORK, 1);
 
   // Simulate an auto translation where the translation does not finish.
   ResetTest();
@@ -231,6 +245,7 @@
 
   CheckTranslateStateHistograms(TranslateState::kNotTranslatedNoUI,
                                 TranslateState::kNotTranslatedNoUI, 0, 0);
+  CheckTranslateErrors(TranslateErrors::NONE, 0);
 
   // Simualte a page that is repeatedly translated and then reverted.
   ResetTest();
@@ -241,7 +256,7 @@
 
   for (int i = 0; i < num_translations_and_reversions; i++) {
     translate_metrics_logger()->LogTranslationStarted();
-    translate_metrics_logger()->LogTranslationFinished(true);
+    translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
     translate_metrics_logger()->LogReversion();
   }
 
@@ -250,6 +265,39 @@
   CheckTranslateStateHistograms(
       TranslateState::kNotTranslatedNoUI, TranslateState::kNotTranslatedNoUI,
       num_translations_and_reversions, num_translations_and_reversions);
+  CheckTranslateErrors(TranslateErrors::NONE, 0);
+}
+
+TEST_F(TranslateMetricsLoggerImplTest, LogTranslateErrors) {
+  // Sets the sequences of errors to supply.
+  const TranslateErrors::Type kTranslateErrorTypes[] = {
+      TranslateErrors::NONE,
+      TranslateErrors::NETWORK,
+      TranslateErrors::INITIALIZATION_ERROR,
+      TranslateErrors::NONE,
+      TranslateErrors::UNSUPPORTED_LANGUAGE,
+      TranslateErrors::TRANSLATION_ERROR,
+      TranslateErrors::NONE,
+      TranslateErrors::TRANSLATION_TIMEOUT,
+      TranslateErrors::SCRIPT_LOAD_ERROR,
+      TranslateErrors::NONE};
+
+  // Simulates the translations with the predefined errors.
+  for (auto translate_error_type : kTranslateErrorTypes) {
+    translate_metrics_logger()->LogTranslationStarted();
+    translate_metrics_logger()->LogTranslationFinished(translate_error_type);
+  }
+
+  translate_metrics_logger()->RecordMetrics(true);
+
+  // We expect to capture the first non-NONE value, and the total number of
+  // non-NONE errors.
+  CheckTranslateErrors(TranslateErrors::NETWORK, 6);
+
+  // The number of successful translations is equal to the number of NONE
+  // errors.
+  histogram_tester()->ExpectUniqueSample(kTranslatePageLoadNumTranslations, 4,
+                                         1);
 }
 
 TEST_F(TranslateMetricsLoggerImplTest, LogTranslateState) {
@@ -261,7 +309,7 @@
   translate_metrics_logger()->LogInitialState();
 
   translate_metrics_logger()->LogTranslationStarted();
-  translate_metrics_logger()->LogTranslationFinished(true);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
   translate_metrics_logger()->LogUIChange(true);
   translate_metrics_logger()->LogOmniboxIconChange(true);
 
@@ -278,7 +326,7 @@
   translate_metrics_logger()->LogUIChange(true);
   translate_metrics_logger()->LogOmniboxIconChange(true);
   translate_metrics_logger()->LogInitialState();
-  translate_metrics_logger()->LogTranslationFinished(true);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
 
   translate_metrics_logger()->LogReversion();
   translate_metrics_logger()->LogUIChange(false);
@@ -313,7 +361,7 @@
 
   // Translate the page (while still in the background).
   translate_metrics_logger()->LogTranslationStarted();
-  translate_metrics_logger()->LogTranslationFinished(true);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
 
   test_clock.Advance(delay3);
 
@@ -352,7 +400,7 @@
   test_clock.Advance(delay2);
 
   // Translation finally finishes.
-  translate_metrics_logger()->LogTranslationFinished(true);
+  translate_metrics_logger()->LogTranslationFinished(TranslateErrors::NONE);
 
   test_clock.Advance(delay3);
 
diff --git a/components/viz/service/display/surface_aggregator_perftest.cc b/components/viz/service/display/surface_aggregator_perftest.cc
index fd3e9a3..f30a0171 100644
--- a/components/viz/service/display/surface_aggregator_perftest.cc
+++ b/components/viz/service/display/surface_aggregator_perftest.cc
@@ -23,9 +23,6 @@
 namespace viz {
 namespace {
 
-constexpr bool kIsRoot = true;
-constexpr bool kIsChildRoot = false;
-
 constexpr char kMetricPrefixSurfaceAggregator[] = "SurfaceAggregator.";
 constexpr char kMetricSpeedRunsPerS[] = "speed";
 
@@ -36,6 +33,26 @@
   return reporter;
 }
 
+class ExpectedOutput {
+ public:
+  ExpectedOutput(size_t expected_render_passes, size_t expected_quads)
+      : expected_render_passes_(expected_render_passes),
+        expected_quads_(expected_quads) {}
+
+  void VerifyAggregatedFrame(const AggregatedFrame& frame) {
+    EXPECT_EQ(expected_render_passes_, frame.render_pass_list.size());
+    size_t count_quads = 0;
+    for (auto& render_pass : frame.render_pass_list) {
+      count_quads += render_pass->quad_list.size();
+    }
+    EXPECT_EQ(expected_quads_, count_quads);
+  }
+
+ private:
+  size_t expected_render_passes_;
+  size_t expected_quads_;
+};
+
 class SurfaceAggregatorPerfTest : public testing::Test {
  public:
   SurfaceAggregatorPerfTest() : manager_(&shared_bitmap_manager_) {
@@ -43,7 +60,7 @@
     context_provider_->BindToCurrentThread();
 
     resource_provider_ = std::make_unique<DisplayResourceProvider>(
-        DisplayResourceProvider::kGpu, context_provider_.get(),
+        DisplayResourceProvider::kSoftware, context_provider_.get(),
         &shared_bitmap_manager_);
   }
 
@@ -52,13 +69,14 @@
                float opacity,
                bool optimize_damage,
                bool full_damage,
-               const std::string& story) {
+               const std::string& story,
+               ExpectedOutput expected_output) {
     std::vector<std::unique_ptr<CompositorFrameSinkSupport>> child_supports(
         num_surfaces);
     std::vector<base::UnguessableToken> child_tokens(num_surfaces);
     for (int i = 0; i < num_surfaces; i++) {
       child_supports[i] = std::make_unique<CompositorFrameSinkSupport>(
-          nullptr, &manager_, FrameSinkId(1, i + 1), kIsChildRoot);
+          nullptr, &manager_, FrameSinkId(1, i + 1), /*is_root=*/false);
       child_tokens[i] = base::UnguessableToken::Create();
     }
     aggregator_ = std::make_unique<SurfaceAggregator>(
@@ -74,13 +92,14 @@
 
       auto* sqs = pass->CreateAndAppendSharedQuadState();
       for (int j = 0; j < num_textures; j++) {
-        TransferableResource resource;
+        const gfx::Size size(1, 2);
+        TransferableResource resource = TransferableResource::MakeSoftware(
+            SharedBitmap::GenerateId(), size, ResourceFormat::RGBA_8888);
         resource.id = j;
-        resource.is_software = true;
         frame_builder.AddTransferableResource(resource);
 
         auto* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
-        const gfx::Rect rect(0, 0, 1, 2);
+        const gfx::Rect rect(size);
         // Half of rects should be visible with partial damage.
         gfx::Rect visible_rect =
             j % 2 == 0 ? gfx::Rect(0, 0, 1, 2) : gfx::Rect(0, 1, 1, 1);
@@ -117,10 +136,12 @@
     }
 
     auto root_support = std::make_unique<CompositorFrameSinkSupport>(
-        nullptr, &manager_, FrameSinkId(1, num_surfaces + 1), kIsRoot);
+        nullptr, &manager_, FrameSinkId(1, num_surfaces + 1), /*is_root=*/true);
     auto root_token = base::UnguessableToken::Create();
     base::TimeTicks next_fake_display_time =
         base::TimeTicks() + base::TimeDelta::FromSeconds(1);
+
+    bool first_lap = true;
     timer_.Reset();
     do {
       auto pass = CompositorRenderPass::Create();
@@ -155,6 +176,18 @@
                     LocalSurfaceId(num_surfaces + 1, root_token)),
           next_fake_display_time, gfx::OVERLAY_TRANSFORM_NONE);
       next_fake_display_time += BeginFrameArgs::DefaultInterval();
+
+      if (!timer_.IsWarmedUp()) {
+        // Verify the expected number of RenderPasses and DrawQuads are
+        // produced for all warmup laps except the first. The first frame will
+        // have full damage regardless of what |full_damage| specifies which
+        // can impact how many quads are aggregated.
+        if (first_lap) {
+          first_lap = false;
+        } else {
+          expected_output.VerifyAggregatedFrame(aggregated);
+        }
+      }
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
@@ -172,47 +205,57 @@
 };
 
 TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaque) {
-  RunTest(20, 100, 1.f, false, true, "many_surfaces_opaque");
+  RunTest(20, 100, 1.f, false, true, "many_surfaces_opaque",
+          ExpectedOutput(1, 2000));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaque_100) {
-  RunTest(100, 1, 1.f, true, false, "100_surfaces_1_quad_each");
+  RunTest(100, 1, 1.f, true, false, "100_surfaces_1_quad_each",
+          ExpectedOutput(1, 100));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaque_300) {
-  RunTest(300, 1, 1.f, true, false, "300_surfaces_1_quad_each");
+  RunTest(300, 1, 1.f, true, false, "300_surfaces_1_quad_each",
+          ExpectedOutput(1, 300));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, ManySurfacesManyQuadsOpaque_100) {
-  RunTest(100, 100, 1.f, true, false, "100_surfaces_100_quads_each");
+  RunTest(100, 100, 1.f, true, false, "100_surfaces_100_quads_each",
+          ExpectedOutput(1, 5000));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, ManySurfacesManyQuadsOpaque_300) {
-  RunTest(300, 100, 1.f, true, false, "300_surfaces_100_quads_each");
+  RunTest(300, 100, 1.f, true, false, "300_surfaces_100_quads_each",
+          ExpectedOutput(1, 15000));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, ManySurfacesTransparent) {
-  RunTest(20, 100, .5f, false, true, "many_surfaces_transparent");
+  RunTest(20, 100, .5f, false, true, "many_surfaces_transparent",
+          ExpectedOutput(20, 2019));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, FewSurfaces) {
-  RunTest(3, 1000, 1.f, false, true, "few_surfaces");
+  RunTest(3, 20, 1.f, false, true, "few_surfaces", ExpectedOutput(1, 60));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaqueDamageCalc) {
-  RunTest(20, 100, 1.f, true, true, "many_surfaces_opaque_damage_calc");
+  RunTest(20, 100, 1.f, true, true, "many_surfaces_opaque_damage_calc",
+          ExpectedOutput(1, 2000));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, ManySurfacesTransparentDamageCalc) {
-  RunTest(20, 100, .5f, true, true, "many_surfaces_transparent_damage_calc");
+  RunTest(20, 100, .5f, true, true, "many_surfaces_transparent_damage_calc",
+          ExpectedOutput(20, 2019));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, FewSurfacesDamageCalc) {
-  RunTest(3, 1000, 1.f, true, true, "few_surfaces_damage_calc");
+  RunTest(3, 1000, 1.f, true, true, "few_surfaces_damage_calc",
+          ExpectedOutput(1, 3000));
 }
 
 TEST_F(SurfaceAggregatorPerfTest, FewSurfacesAggregateDamaged) {
-  RunTest(3, 1000, 1.f, true, false, "few_surfaces_aggregate_damaged");
+  RunTest(3, 1000, 1.f, true, false, "few_surfaces_aggregate_damaged",
+          ExpectedOutput(1, 1500));
 }
 
 }  // namespace
diff --git a/components/viz/service/display_embedder/image_context_impl.cc b/components/viz/service/display_embedder/image_context_impl.cc
index 2173d66..03def30 100644
--- a/components/viz/service/display_embedder/image_context_impl.cc
+++ b/components/viz/service/display_embedder/image_context_impl.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "build/build_config.h"
 #include "components/viz/common/resources/resource_format_utils.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
@@ -102,11 +103,20 @@
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores) {
   // Prepare for accessing shared image.
-  if (mailbox_holder().mailbox.IsSharedImage() &&
-      BeginAccessIfNecessaryForSharedImage(context_state,
-                                           representation_factory,
-                                           begin_semaphores, end_semaphores)) {
-    return;
+  if (mailbox_holder().mailbox.IsSharedImage()) {
+    constexpr bool allow_legacy_mailbox_fallback =
+#if defined(OS_ANDROID)
+        false;
+#else
+        true;
+#endif
+    bool result = BeginAccessIfNecessaryForSharedImage(
+        context_state, representation_factory, begin_semaphores,
+        end_semaphores);
+    if (!result && !allow_legacy_mailbox_fallback) {
+      CreateFallbackImage(context_state);
+      return;
+    }
   }
 
   // Prepare for accessing legacy mailbox.
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 42ef422..433da4cb 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -750,10 +750,10 @@
 
   // For downscaling, use the GOOD quality setting (appropriate for
   // thumbnailing); and, for upscaling, use the BEST quality.
-  bool is_downscale_in_both_dimensions =
-      request->scale_to().x() < request->scale_from().x() &&
-      request->scale_to().y() < request->scale_from().y();
-  SkFilterQuality filter_quality = is_downscale_in_both_dimensions
+  bool is_downscale_or_identity_in_both_dimensions =
+      request->scale_to().x() <= request->scale_from().x() &&
+      request->scale_to().y() <= request->scale_from().y();
+  SkFilterQuality filter_quality = is_downscale_or_identity_in_both_dimensions
                                        ? kMedium_SkFilterQuality
                                        : kHigh_SkFilterQuality;
 
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc
index c14240c3..ab67d65 100644
--- a/components/viz/service/main/viz_main_impl.cc
+++ b/components/viz/service/main/viz_main_impl.cc
@@ -159,7 +159,7 @@
   if (!gpu_init_->gpu_info().in_process_gpu) {
     // If the GPU is running in the browser process, discardable memory manager
     // has already been initialized.
-    discardable_shared_memory_manager_ = std::make_unique<
+    discardable_shared_memory_manager_ = base::MakeRefCounted<
         discardable_memory::ClientDiscardableSharedMemoryManager>(
         std::move(discardable_memory_manager), io_task_runner());
     base::DiscardableMemoryAllocator::SetInstance(
diff --git a/components/viz/service/main/viz_main_impl.h b/components/viz/service/main/viz_main_impl.h
index a0ab831..429ce85 100644
--- a/components/viz/service/main/viz_main_impl.h
+++ b/components/viz/service/main/viz_main_impl.h
@@ -190,7 +190,7 @@
 
   mojo::AssociatedReceiver<mojom::VizMain> receiver_{this};
 
-  std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+  scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
       discardable_shared_memory_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(VizMainImpl);
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index cc7fbcf..02831758 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1247,6 +1247,8 @@
     "renderer_host/back_forward_cache_impl.h",
     "renderer_host/back_forward_cache_metrics.cc",
     "renderer_host/back_forward_cache_metrics.h",
+    "renderer_host/back_forward_cache_throttle.cc",
+    "renderer_host/back_forward_cache_throttle.h",
     "renderer_host/blocked_scheme_navigation_throttle.cc",
     "renderer_host/blocked_scheme_navigation_throttle.h",
     "renderer_host/clipboard_host_impl.cc",
diff --git a/content/browser/accessibility/accessibility_tree_formatter_android.cc b/content/browser/accessibility/accessibility_tree_formatter_android.cc
index 6cdde118..ac442804 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -15,6 +15,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
 #include "content/browser/accessibility/browser_accessibility_android.h"
 
 using base::StringPrintf;
@@ -109,17 +110,21 @@
 // static
 std::unique_ptr<ui::AXTreeFormatter>
 AXInspectFactory::CreatePlatformFormatter() {
-  return std::make_unique<AccessibilityTreeFormatterAndroid>();
+  return AXInspectFactory::CreateFormatter(kAndroid);
 }
 
 // static
-std::vector<AccessibilityTreeFormatter::TestPass>
-AccessibilityTreeFormatter::GetTestPasses() {
-  // Note: Android doesn't do a "blink" pass; the blink tree is different on
-  // Android because we exclude inline text boxes, for performance.
-  return {
-      {"android", &AXInspectFactory::CreatePlatformFormatter},
-  };
+std::unique_ptr<ui::AXTreeFormatter> AXInspectFactory::CreateFormatter(
+    AXInspectFactory::Type type) {
+  switch (type) {
+    case kAndroid:
+      return std::make_unique<AccessibilityTreeFormatterAndroid>();
+    case kBlink:
+      return std::make_unique<AccessibilityTreeFormatterBlink>();
+    default:
+      NOTREACHED() << "Unsupported formatter type " << type;
+  }
+  return nullptr;
 }
 
 AccessibilityTreeFormatterAndroid::AccessibilityTreeFormatterAndroid() {}
diff --git a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index d9fc8f08..dc95c6e 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -72,16 +72,21 @@
 // static
 std::unique_ptr<ui::AXTreeFormatter>
 AXInspectFactory::CreatePlatformFormatter() {
-  return std::make_unique<AccessibilityTreeFormatterAuraLinux>();
+  return AXInspectFactory::CreateFormatter(kLinux);
 }
 
 // static
-std::vector<AccessibilityTreeFormatter::TestPass>
-AccessibilityTreeFormatter::GetTestPasses() {
-  return {
-      {"blink", &AXInspectFactory::CreateBlinkFormatter},
-      {"linux", &AXInspectFactory::CreatePlatformFormatter},
-  };
+std::unique_ptr<ui::AXTreeFormatter> AXInspectFactory::CreateFormatter(
+    AXInspectFactory::Type type) {
+  switch (type) {
+    case kBlink:
+      return std::make_unique<AccessibilityTreeFormatterBlink>();
+    case kLinux:
+      return std::make_unique<AccessibilityTreeFormatterAuraLinux>();
+    default:
+      NOTREACHED() << "Unsupported formatter type " << type;
+  }
+  return nullptr;
 }
 
 AccessibilityTreeFormatterAuraLinux::AccessibilityTreeFormatterAuraLinux() {}
diff --git a/content/browser/accessibility/accessibility_tree_formatter_base.cc b/content/browser/accessibility/accessibility_tree_formatter_base.cc
index b7abcad..71aedc01 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_base.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_base.cc
@@ -35,22 +35,6 @@
 
 }  // namespace
 
-// static
-std::string AccessibilityTreeFormatterBase::DumpAccessibilityTreeFromManager(
-    BrowserAccessibilityManager* ax_mgr,
-    bool internal,
-    std::vector<AXPropertyFilter> property_filters) {
-  std::unique_ptr<ui::AXTreeFormatter> formatter =
-      internal ? AXInspectFactory::CreateBlinkFormatter()
-               : AXInspectFactory::CreatePlatformFormatter();
-
-  formatter->SetPropertyFilters(property_filters);
-  base::Value dict =
-      static_cast<AccessibilityTreeFormatterBase*>(formatter.get())
-          ->BuildTree(ax_mgr->GetRoot());
-  return formatter->FormatTree(dict);
-}
-
 AccessibilityTreeFormatterBase::AccessibilityTreeFormatterBase() = default;
 
 AccessibilityTreeFormatterBase::~AccessibilityTreeFormatterBase() = default;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_base.h b/content/browser/accessibility/accessibility_tree_formatter_base.h
index bd650dc..d1516ae7 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_base.h
+++ b/content/browser/accessibility/accessibility_tree_formatter_base.h
@@ -36,16 +36,11 @@
 // This is extended by a subclass for each platform where accessibility is
 // implemented.
 class CONTENT_EXPORT AccessibilityTreeFormatterBase
-    : public AccessibilityTreeFormatter {
+    : public ui::AXTreeFormatter {
  public:
   AccessibilityTreeFormatterBase();
   ~AccessibilityTreeFormatterBase() override;
 
-  static std::string DumpAccessibilityTreeFromManager(
-      BrowserAccessibilityManager* ax_mgr,
-      bool internal,
-      std::vector<AXPropertyFilter> property_filters);
-
   std::string Format(ui::AXPlatformNodeDelegate* root) const override;
 
   // Populates the given DictionaryValue with the accessibility tree.
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 6ff525c..bd73a07 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -114,16 +114,21 @@
 // static
 std::unique_ptr<ui::AXTreeFormatter>
 AXInspectFactory::CreatePlatformFormatter() {
-  return std::make_unique<AccessibilityTreeFormatterMac>();
+  return AXInspectFactory::CreateFormatter(kMac);
 }
 
 // static
-std::vector<AccessibilityTreeFormatter::TestPass>
-AccessibilityTreeFormatter::GetTestPasses() {
-  return {
-      {"blink", &AXInspectFactory::CreateBlinkFormatter},
-      {"mac", &AXInspectFactory::CreatePlatformFormatter},
-  };
+std::unique_ptr<ui::AXTreeFormatter> AXInspectFactory::CreateFormatter(
+    AXInspectFactory::Type type) {
+  switch (type) {
+    case kBlink:
+      return std::make_unique<AccessibilityTreeFormatterBlink>();
+    case kMac:
+      return std::make_unique<AccessibilityTreeFormatterMac>();
+    default:
+      NOTREACHED() << "Unsupported formatter type " << type;
+  }
+  return nullptr;
 }
 
 AccessibilityTreeFormatterMac::AccessibilityTreeFormatterMac() {}
diff --git a/content/browser/accessibility/accessibility_tree_formatter_stub.cc b/content/browser/accessibility/accessibility_tree_formatter_stub.cc
index 0ce0509..37ca8d2 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_stub.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_stub.cc
@@ -9,19 +9,25 @@
 namespace content {
 
 #if !BUILDFLAG(HAS_PLATFORM_ACCESSIBILITY_SUPPORT)
+
 // static
 std::unique_ptr<ui::AXTreeFormatter>
 AXInspectFactory::CreatePlatformFormatter() {
-  return AXInspectFactory::CreateBlinkFormatter();
+  return AXInspectFactory::CreateFormatter(kBlink);
 }
 
 // static
-std::vector<AccessibilityTreeFormatter::TestPass>
-AccessibilityTreeFormatter::GetTestPasses() {
-  return {
-      {"blink", &AXInspectFactory::CreateBlinkFormatter},
-  };
+std::unique_ptr<ui::AXTreeFormatter> AXInspectFactory::CreateFormatter(
+    AXInspectFactory::Type type) {
+  switch (type) {
+    case kBlink:
+      return std::make_unique<AccessibilityTreeFormatterBlink>();
+    default:
+      NOTREACHED() << "Unsupported formatter type " << type;
+  }
+  return nullptr;
 }
+
 #endif
 
 }  // namespace content
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
index d033e0d..c479839 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
@@ -255,12 +255,6 @@
     UIA_TableRowOrColumnMajorPropertyId,              // 30083
     UIA_ToggleToggleStatePropertyId,                  // 30086
 };
-// static
-std::unique_ptr<ui::AXTreeFormatter>
-AccessibilityTreeFormatterUia::CreateUia() {
-  base::win::AssertComInitialized();
-  return std::make_unique<AccessibilityTreeFormatterUia>();
-}
 
 AccessibilityTreeFormatterUia::AccessibilityTreeFormatterUia() {
   // Create an instance of the CUIAutomation class.
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.h b/content/browser/accessibility/accessibility_tree_formatter_uia_win.h
index be0c6b0..3b4073bd 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.h
+++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.h
@@ -24,8 +24,6 @@
   AccessibilityTreeFormatterUia();
   ~AccessibilityTreeFormatterUia() override;
 
-  static std::unique_ptr<ui::AXTreeFormatter> CreateUia();
-
   // AccessibilityTreeFormatterBase:
   void AddDefaultFilters(
       std::vector<AXPropertyFilter>* property_filters) override;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_win.cc b/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 2ff240b..96b84c0 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -89,20 +89,25 @@
 // static
 std::unique_ptr<ui::AXTreeFormatter>
 AXInspectFactory::CreatePlatformFormatter() {
-  base::win::AssertComInitialized();
-  return std::make_unique<AccessibilityTreeFormatterWin>();
+  return CreateFormatter(kWinIA2);
 }
 
 // static
-std::vector<AccessibilityTreeFormatter::TestPass>
-AccessibilityTreeFormatter::GetTestPasses() {
-  // In addition to the 'Blink' pass, Windows includes two accessibility APIs
-  // that need to be tested independently (MSAA & UIA).
-  return {
-      {"blink", &AXInspectFactory::CreateBlinkFormatter},
-      {"win", &AXInspectFactory::CreatePlatformFormatter},
-      {"uia", &AccessibilityTreeFormatterUia::CreateUia},
-  };
+std::unique_ptr<ui::AXTreeFormatter> AXInspectFactory::CreateFormatter(
+    AXInspectFactory::Type type) {
+  switch (type) {
+    case kBlink:
+      return std::make_unique<AccessibilityTreeFormatterBlink>();
+    case kWinIA2:
+      base::win::AssertComInitialized();
+      return std::make_unique<AccessibilityTreeFormatterWin>();
+    case kWinUIA:
+      base::win::AssertComInitialized();
+      return std::make_unique<AccessibilityTreeFormatterUia>();
+    default:
+      NOTREACHED() << "Unsupported formatter type " << type;
+  }
+  return nullptr;
 }
 
 void AccessibilityTreeFormatterWin::AddDefaultFilters(
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index 1416864..add5eb58 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -1854,9 +1854,9 @@
   EXPECT_LT(1, prev_height);
 
   // Delete the character in the input field.
-  AccessibilityNotificationWaiter waiter(
-      shell()->web_contents(), ui::kAXModeComplete,
-      ax::mojom::Event::kTextSelectionChanged);
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kValueChanged);
   ExecuteScript(std::wstring(L"document.querySelector('input').value='';"));
   waiter.WaitForNotification();
 
@@ -1913,9 +1913,9 @@
   }
 
   // Delete the character in the input field.
-  AccessibilityNotificationWaiter waiter(
-      shell()->web_contents(), ui::kAXModeComplete,
-      ax::mojom::Event::kTextSelectionChanged);
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kValueChanged);
   ExecuteScript(std::wstring(L"document.querySelector('input').value='';"));
   waiter.WaitForNotification();
 
@@ -2120,9 +2120,9 @@
   }
 
   // Delete the character in the input field.
-  AccessibilityNotificationWaiter waiter(
-      shell()->web_contents(), ui::kAXModeComplete,
-      ax::mojom::Event::kTextSelectionChanged);
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kValueChanged);
   ExecuteScript(
       std::wstring(L"document.querySelector('textarea').innerText='';"));
   waiter.WaitForNotification();
@@ -2180,9 +2180,9 @@
   }
 
   // Delete the character in the input field.
-  AccessibilityNotificationWaiter waiter(
-      shell()->web_contents(), ui::kAXModeComplete,
-      ax::mojom::Event::kTextSelectionChanged);
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kValueChanged);
   ExecuteScript(
       std::wstring(L"const input = document.querySelector('input');"
                    "input.value='';"));
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 38908bea..eed5aa8 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -194,6 +194,19 @@
           GetRole() == ax::mojom::Role::kTreeItem);
 }
 
+bool BrowserAccessibilityAndroid::IsCombobox() const {
+  return (GetRole() == ax::mojom::Role::kComboBoxGrouping ||
+          GetRole() == ax::mojom::Role::kTextFieldWithComboBox ||
+          GetRole() == ax::mojom::Role::kComboBoxMenuButton);
+}
+
+bool BrowserAccessibilityAndroid::IsComboboxControl() const {
+  return (GetRole() == ax::mojom::Role::kTree ||
+          GetRole() == ax::mojom::Role::kGrid ||
+          GetRole() == ax::mojom::Role::kDialog ||
+          GetRole() == ax::mojom::Role::kListBox);
+}
+
 bool BrowserAccessibilityAndroid::IsContentInvalid() const {
   return HasIntAttribute(ax::mojom::IntAttribute::kInvalidState) &&
          GetData().GetInvalidState() != ax::mojom::InvalidState::kFalse;
@@ -768,6 +781,109 @@
   return content_client->GetLocalizedString(message_id);
 }
 
+base::string16 BrowserAccessibilityAndroid::GetComboboxExpandedText() const {
+  content::ContentClient* content_client = content::GetContentClient();
+
+  // We consider comboboxes of the form:
+  //
+  // <div role="combobox">
+  //   <input type="text" aria-controls="options">
+  //   <ul role="listbox" id="options">...</ul> (Can be outside <div>)
+  // </div>
+  //
+  // Find child input node:
+  const BrowserAccessibilityAndroid* input_node = nullptr;
+  for (PlatformChildIterator it = PlatformChildrenBegin();
+       it != PlatformChildrenEnd(); ++it) {
+    const BrowserAccessibilityAndroid* child_node =
+        static_cast<BrowserAccessibilityAndroid*>(it.get());
+    if (child_node->IsTextField()) {
+      input_node = child_node;
+      break;
+    }
+  }
+
+  // If we have not found a child input element, consider aria 1.0 spec:
+  //
+  // <input type="text" role="combobox" aria-owns="options">
+  // <ul role="listbox" id="options">...</ul>
+  //
+  // Check if |this| is the input, otherwise try our fallbacks.
+  if (!input_node) {
+    if (IsTextField()) {
+      input_node = this;
+    } else {
+      return GetComboboxExpandedTextFallback();
+    }
+  }
+
+  // Get the aria-controls nodes of |input_node|.
+  std::vector<BrowserAccessibility*> controls =
+      manager()->GetAriaControls(input_node);
+
+  // |input_node| should control only one element, if it doesn't, try fallbacks.
+  if (controls.size() != 1)
+    return GetComboboxExpandedTextFallback();
+
+  // |controlled_node| needs to be a combobox control, if not, try fallbacks.
+  BrowserAccessibilityAndroid* controlled_node =
+      static_cast<BrowserAccessibilityAndroid*>(controls[0]);
+  if (!controlled_node->IsComboboxControl())
+    return GetComboboxExpandedTextFallback();
+
+  // For dialogs, return special case string.
+  if (controlled_node->GetRole() == ax::mojom::Role::kDialog)
+    return content_client->GetLocalizedString(IDS_AX_COMBOBOX_EXPANDED_DIALOG);
+
+  // Find |controlled_node| set size, or return default string.
+  if (!controlled_node->GetSetSize())
+    return content_client->GetLocalizedString(
+        IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_DEFAULT);
+
+  // Replace placeholder with count and return string.
+  return base::ReplaceStringPlaceholders(
+      content_client->GetLocalizedString(
+          IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_X_OPTIONS_AVAILABLE),
+      base::NumberToString16(*controlled_node->GetSetSize()), nullptr);
+}
+
+base::string16 BrowserAccessibilityAndroid::GetComboboxExpandedTextFallback()
+    const {
+  content::ContentClient* content_client = content::GetContentClient();
+
+  // If a combobox was of an indeterminate form, attempt any special cases here,
+  // or return "expanded" as a final option.
+
+  // Check for child nodes that are collections.
+  int child_collection_count = 0;
+  BrowserAccessibilityAndroid* collection_node = nullptr;
+  for (PlatformChildIterator it = PlatformChildrenBegin();
+       it != PlatformChildrenEnd(); ++it) {
+    BrowserAccessibilityAndroid* child =
+        static_cast<BrowserAccessibilityAndroid*>(it.get());
+    if (child->IsCollection()) {
+      child_collection_count++;
+      collection_node = child;
+    }
+  }
+
+  // If we find none, or more than one, we will not be able to determine the
+  // correct utterance, so return a default string instead.
+  if (child_collection_count != 1)
+    return content_client->GetLocalizedString(IDS_AX_COMBOBOX_EXPANDED);
+
+  // Find |collection_node| set size, or return defaul string.
+  if (!collection_node->GetSetSize())
+    return content_client->GetLocalizedString(
+        IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_DEFAULT);
+
+  // Replace placeholder with count and return string.
+  return base::ReplaceStringPlaceholders(
+      content_client->GetLocalizedString(
+          IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_X_OPTIONS_AVAILABLE),
+      base::NumberToString16(*collection_node->GetSetSize()), nullptr);
+}
+
 std::string BrowserAccessibilityAndroid::GetRoleString() const {
   return ui::ToString(GetRole());
 }
diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h
index 0d2c403..9885f96 100644
--- a/content/browser/accessibility/browser_accessibility_android.h
+++ b/content/browser/accessibility/browser_accessibility_android.h
@@ -35,6 +35,8 @@
   bool IsCollapsed() const;
   bool IsCollection() const;
   bool IsCollectionItem() const;
+  bool IsCombobox() const;
+  bool IsComboboxControl() const;
   bool IsContentInvalid() const;
   bool IsDismissable() const;
   bool IsEnabled() const;
@@ -101,6 +103,9 @@
   base::string16 GetListBoxItemStateDescription() const;
   base::string16 GetAriaCurrentStateDescription() const;
 
+  base::string16 GetComboboxExpandedText() const;
+  base::string16 GetComboboxExpandedTextFallback() const;
+
   base::string16 GetRoleDescription() const;
 
   int GetItemIndex() const;
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index 6ac3d1e..6cb38df 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -671,6 +671,21 @@
   return node;
 }
 
+std::vector<BrowserAccessibility*> BrowserAccessibilityManager::GetAriaControls(
+    const BrowserAccessibility* focus) const {
+  if (!focus)
+    return {};
+
+  std::vector<BrowserAccessibility*> aria_control_nodes;
+  for (const auto& id :
+       focus->GetIntListAttribute(ax::mojom::IntListAttribute::kControlsIds)) {
+    if (focus->manager()->GetFromID(id))
+      aria_control_nodes.push_back(focus->manager()->GetFromID(id));
+  }
+
+  return aria_control_nodes;
+}
+
 bool BrowserAccessibilityManager::NativeViewHasFocus() {
   BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
   return delegate && delegate->AccessibilityViewHasFocus();
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index dbce722..d0969c9df 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -373,6 +373,11 @@
   // focused.
   BrowserAccessibility* GetActiveDescendant(BrowserAccessibility* node) const;
 
+  // Given a focused node |focus|, returns a list of nodes that the focused
+  // node controls.
+  std::vector<BrowserAccessibility*> GetAriaControls(
+      const BrowserAccessibility* focus) const;
+
   // Returns true if native focus is anywhere in this WebContents or not.
   bool NativeViewHasFocus();
 
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index c5e2399..53c5cfc 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -249,6 +249,13 @@
       }
       break;
     }
+    case ui::AXEventGenerator::Event::EXPANDED: {
+      if (android_node->IsCombobox() &&
+          GetFocus()->IsDescendantOf(android_node)) {
+        wcax->AnnounceLiveRegionText(android_node->GetComboboxExpandedText());
+      }
+      break;
+    }
     case ui::AXEventGenerator::Event::LOAD_COMPLETE:
       if (node->manager() == GetRootManager()) {
         auto* android_focused =
@@ -295,7 +302,6 @@
     case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
     case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
     case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
-    case ui::AXEventGenerator::Event::EXPANDED:
     case ui::AXEventGenerator::Event::EDITABLE_TEXT_CHANGED:
     case ui::AXEventGenerator::Event::ENABLED_CHANGED:
     case ui::AXEventGenerator::Event::FOCUS_CHANGED:
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 408e76b..5b040f2 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -82,11 +82,9 @@
 
 // DumpAccessibilityTestBase
 DumpAccessibilityTestBase::DumpAccessibilityTestBase()
-    : formatter_factory_(nullptr),
-      event_recorder_factory_(nullptr),
+    : event_recorder_factory_(nullptr),
       enable_accessibility_after_navigating_(false),
-      test_helper_(
-          AccessibilityTreeFormatter::GetTestPasses()[GetParam()].name) {}
+      test_helper_(DumpAccessibilityTestHelper::TestPasses()[GetParam()]) {}
 
 DumpAccessibilityTestBase::~DumpAccessibilityTestBase() {}
 
@@ -145,7 +143,7 @@
 
 std::string
 DumpAccessibilityTestBase::DumpUnfilteredAccessibilityTreeAsString() {
-  std::unique_ptr<AXTreeFormatter> formatter(formatter_factory_());
+  std::unique_ptr<AXTreeFormatter> formatter(CreateFormatter());
   std::vector<AXPropertyFilter> property_filters;
   property_filters.emplace_back("*", AXPropertyFilter::ALLOW);
   formatter->SetPropertyFilters(property_filters);
@@ -193,29 +191,26 @@
 void DumpAccessibilityTestBase::RunTest(const base::FilePath file_path,
                                         const char* file_dir) {
   // Get all the tree formatters; the test is run independently on each one.
-  auto formatters = AccessibilityTreeFormatter::GetTestPasses();
+  auto test_passes = DumpAccessibilityTestHelper::TestPasses();
   auto event_recorders = AccessibilityEventRecorder::GetTestPasses();
-  CHECK(event_recorders.size() == formatters.size());
+  CHECK(event_recorders.size() == test_passes.size());
 
   // The current test number is supplied as a test parameter.
   size_t current_pass = GetParam();
-  CHECK_LT(current_pass, formatters.size());
-  CHECK_EQ(std::string(formatters[current_pass].name),
-           std::string(event_recorders[current_pass].name));
+  CHECK_LT(current_pass, test_passes.size());
+  CHECK_EQ(test_passes.size(), event_recorders.size());
 
-  formatter_factory_ = formatters[current_pass].create_formatter;
   event_recorder_factory_ = event_recorders[current_pass].create_recorder;
 
   RunTestForPlatform(file_path, file_dir);
 
-  formatter_factory_ = nullptr;
   event_recorder_factory_ = nullptr;
 }
 
 void DumpAccessibilityTestBase::RunTestForPlatform(
     const base::FilePath file_path,
     const char* file_dir) {
-  formatter_ = formatter_factory_();
+  formatter_ = CreateFormatter();
 
   // Disable the "hot tracked" state (set when the mouse is hovering over
   // an object) because it makes test output change based on the mouse position.
@@ -483,6 +478,12 @@
   return web_contents->GetRootBrowserAccessibilityManager();
 }
 
+std::unique_ptr<AXTreeFormatter> DumpAccessibilityTestBase::CreateFormatter()
+    const {
+  return AXInspectFactory::CreateFormatter(
+      DumpAccessibilityTestHelper::TestPasses()[GetParam()]);
+}
+
 BrowserAccessibility* DumpAccessibilityTestBase::FindNodeInSubtree(
     BrowserAccessibility& node,
     const std::string& name) {
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.h b/content/browser/accessibility/dump_accessibility_browsertest_base.h
index b0a0e4f..f9d8054c 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.h
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.h
@@ -117,6 +117,8 @@
   // contents.
   BrowserAccessibilityManager* GetManager();
 
+  std::unique_ptr<ui::AXTreeFormatter> CreateFormatter() const;
+
   // The default property filters plus the property filters loaded from the test
   // file.
   std::vector<ui::AXPropertyFilter> property_filters_;
@@ -125,7 +127,6 @@
   std::vector<ui::AXNodeFilter> node_filters_;
 
   // The current tree-formatter and event-recorder factories.
-  AccessibilityTreeFormatter::FormatterFactory formatter_factory_;
   AccessibilityEventRecorder::EventRecorderFactory event_recorder_factory_;
 
   // The current AXTreeFormatter.
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 7c30121..7f4120b4 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -150,7 +150,7 @@
   }
 
   std::vector<std::string> Dump(std::vector<std::string>& unused) override {
-    std::unique_ptr<AXTreeFormatter> formatter(formatter_factory_());
+    std::unique_ptr<AXTreeFormatter> formatter(CreateFormatter());
     formatter->SetPropertyFilters(property_filters_);
     formatter->SetNodeFilters(node_filters_);
     std::string actual_contents =
@@ -247,9 +247,9 @@
 // Parameterize the tests so that each test-pass is run independently.
 struct DumpAccessibilityTreeTestPassToString {
   std::string operator()(const ::testing::TestParamInfo<size_t>& i) const {
-    auto passes = AccessibilityTreeFormatter::GetTestPasses();
+    auto passes = DumpAccessibilityTestHelper::TestPasses();
     CHECK_LT(i.param, passes.size());
-    return passes[i.param].name;
+    return std::string(passes[i.param]);
   }
 };
 
@@ -257,14 +257,14 @@
     All,
     DumpAccessibilityTreeTest,
     ::testing::Range(size_t{0},
-                     AccessibilityTreeFormatter::GetTestPasses().size()),
+                     DumpAccessibilityTestHelper::TestPasses().size()),
     DumpAccessibilityTreeTestPassToString());
 
 INSTANTIATE_TEST_SUITE_P(
     All,
     DumpAccessibilityTreeTestWithIgnoredNodes,
     ::testing::Range(size_t{0},
-                     AccessibilityTreeFormatter::GetTestPasses().size()),
+                     DumpAccessibilityTestHelper::TestPasses().size()),
     DumpAccessibilityTreeTestPassToString());
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSColor) {
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index fee3b57..17c9f28 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -678,10 +678,12 @@
   }
 
   ~PageLifecycleStateManagerTestDelegate() override {
-    manager_->SetDelegateForTesting(nullptr);
+    if (manager_)
+      manager_->SetDelegateForTesting(nullptr);
   }
 
   void WaitForInBackForwardCacheAck() {
+    DCHECK(manager_);
     if (manager_->last_acknowledged_state().is_in_back_forward_cache) {
       return;
     }
@@ -694,6 +696,10 @@
     store_in_back_forward_cache_sent_ = std::move(cb);
   }
 
+  void OnDisableJsEvictionSent(base::OnceClosure cb) {
+    disable_eviction_sent_ = std::move(cb);
+  }
+
   void OnRestoreFromBackForwardCacheSent(base::OnceClosure cb) {
     restore_from_back_forward_cache_sent_ = std::move(cb);
   }
@@ -714,16 +720,23 @@
       std::move(store_in_back_forward_cache_sent_).Run();
     }
 
+    if (disable_eviction_sent_ && new_state.eviction_enabled == false) {
+      std::move(disable_eviction_sent_).Run();
+    }
+
     if (restore_from_back_forward_cache_sent_ &&
         !new_state.is_in_back_forward_cache) {
       std::move(restore_from_back_forward_cache_sent_).Run();
     }
   }
 
-  PageLifecycleStateManager* const manager_;
+  void OnDeleted() override { manager_ = nullptr; }
+
+  PageLifecycleStateManager* manager_;
   base::OnceClosure store_in_back_forward_cache_sent_;
   base::OnceClosure store_in_back_forward_cache_ack_received_;
   base::OnceClosure restore_from_back_forward_cache_sent_;
+  base::OnceClosure disable_eviction_sent_;
 };
 
 class FakeIdleTimeProvider : public IdleManager::IdleTimeProvider {
@@ -3103,101 +3116,6 @@
       FROM_HERE);
 }
 
-// Similar to BackForwardCacheBrowserTest.EvictionOnJavaScriptExecution, but
-// cause the race condition of eviction and restoring.
-//
-// ┌───────┐                 ┌────────┐
-// │Browser│                 │Renderer│
-// └───┬───┘                 └───┬────┘
-// (Store to the bfcache)        │
-//     │         Freeze          │
-//     │────────────────────────>│
-//     │                         │
-// (Restore from the bfcache)    │
-//     │──┐                      │
-//     │  │                      │
-//     │EvictFromBackForwardCache│
-//     │<────────────────────────│
-//     │  │                      │
-//     │  │      Resume          │
-//     │  └─────────────────────>│
-// ┌───┴───┐                 ┌───┴────┐
-// │Browser│                 │Renderer│
-// └───────┘                 └────────┘
-IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
-                       EvictionOnJavaScriptExecutionRace) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
-
-  // 1) Navigate to A.
-  EXPECT_TRUE(NavigateToURL(shell(), url_a));
-  RenderFrameHostImpl* rfh_a = current_frame_host();
-  RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
-  EXPECT_TRUE(ExecJs(rfh_a, "window.foo = 'initial document'"));
-
-  // 2) Navigate to B.
-  EXPECT_TRUE(NavigateToURL(shell(), url_b));
-  RenderFrameHostImpl* rfh_b = current_frame_host();
-  RenderFrameDeletedObserver delete_observer_rfh_b(rfh_b);
-
-  EXPECT_FALSE(delete_observer_rfh_a.deleted());
-  EXPECT_FALSE(delete_observer_rfh_b.deleted());
-  EXPECT_TRUE(rfh_a->IsInBackForwardCache());
-  EXPECT_FALSE(rfh_b->IsInBackForwardCache());
-
-  // 3) Execute JavaScript on A when restoring A.
-  // Execute JavaScript after committing but before swapping happens on the
-  // renderer.
-  ReadyToCommitNavigationCallback host_changed_callback(
-      web_contents(),
-      base::BindOnce(
-          [](RenderFrameHostImpl* rfh_a,
-             RenderFrameDeletedObserver* delete_observer_rfh_a,
-             NavigationHandle* navigation_handle) {
-            ASSERT_FALSE(delete_observer_rfh_a->deleted());
-            EXPECT_EQ(rfh_a, navigation_handle->GetRenderFrameHost());
-            rfh_a->ExecuteJavaScriptForTests(
-                base::UTF8ToUTF16("console.log('hi');"), base::NullCallback());
-          },
-          rfh_a, &delete_observer_rfh_a));
-
-  // Wait for two navigations to finish. The first one is the BackForwardCache
-  // navigation, the other is the reload caused by the eviction.
-  //
-  //   1. BFcache navigation start.
-  //   2. BFcache navigation commit & finish.
-  //   3. Evict & reload start.
-  //   4. Reload commit.
-  //   5. Reload finish.
-  //
-  // Each item is a single task.
-  TestNavigationObserver observer(web_contents(),
-                                  2 /* number of navigations */);
-  observer.set_wait_event(
-      TestNavigationObserver::WaitEvent::kNavigationFinished);
-  web_contents()->GetController().GoBack();
-  observer.WaitForNavigationFinished();
-
-  // A is not destroyed. A is reloaded instead.
-  EXPECT_FALSE(delete_observer_rfh_a.deleted());
-  EXPECT_FALSE(delete_observer_rfh_b.deleted());
-  EXPECT_FALSE(rfh_a->IsInBackForwardCache());
-  EXPECT_TRUE(rfh_b->IsInBackForwardCache());
-  EXPECT_NE("initial document", EvalJs(rfh_a, "window.foo"));
-
-  ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kRestored,
-                FROM_HERE);
-  ExpectEvictedAfterCommitted(
-      {
-          BackForwardCacheMetrics::EvictedAfterDocumentRestoredReason::
-              kRestored,
-          BackForwardCacheMetrics::EvictedAfterDocumentRestoredReason::
-              kByJavaScript,
-      },
-      FROM_HERE);
-}
-
 // Tests the events are fired when going back from the cache.
 IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, Events) {
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -3565,7 +3483,8 @@
 }
 
 // Test the race condition where a document is evicted from the BackForwardCache
-// while it is in the middle of being restored.
+// while it is in the middle of being restored and before URL loader starts a
+// response.
 //
 // ┌───────┐                 ┌────────┐
 // │Browser│                 │Renderer│
@@ -3587,54 +3506,7 @@
 //
 // When the eviction occurs, the in flight NavigationRequest to the cached
 // document should be reissued (cancelled and replaced by a normal navigation).
-IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
-                       ReissuesNavigationIfEvictedDuringNavigation) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  GURL url_b(embedded_test_server()->GetURL("b.com", "/title2.html"));
-
-  // 1) Navigate to page A.
-  EXPECT_TRUE(NavigateToURL(shell(), url_a));
-  RenderFrameHostImpl* rfh_a = current_frame_host();
-  RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
-
-  // 2) Navigate to page B.
-  EXPECT_TRUE(NavigateToURL(shell(), url_b));
-  RenderFrameHostImpl* rfh_b = current_frame_host();
-  RenderFrameDeletedObserver delete_observer_rfh_b(rfh_b);
-  EXPECT_FALSE(delete_observer_rfh_a.deleted());
-  EXPECT_TRUE(rfh_a->IsInBackForwardCache());
-  EXPECT_NE(rfh_a, rfh_b);
-
-  // 3) Start navigation to page A, and cause the document to be evicted during
-  // the navigation.
-  TestNavigationManager navigation_manager(shell()->web_contents(), url_a);
-  web_contents()->GetController().GoBack();
-
-  EXPECT_TRUE(navigation_manager.WaitForRequestStart());
-  // Try to execute javascript, this will cause the document we are restoring to
-  // get evicted from the cache.
-  EvictByJavaScript(rfh_a);
-
-  // The navigation should get reissued, and ultimately finish.
-  navigation_manager.WaitForNavigationFinished();
-
-  // rfh_a should have been deleted, and page A navigated to normally.
-  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  delete_observer_rfh_a.WaitUntilDeleted();
-  RenderFrameHostImpl* rfh_a2 = current_frame_host();
-  EXPECT_NE(rfh_a2, rfh_b);
-  EXPECT_EQ(rfh_a2->GetLastCommittedURL(), url_a);
-
-  ExpectOutcome(BackForwardCacheMetrics::HistoryNavigationOutcome::kNotRestored,
-                FROM_HERE);
-  ExpectNotRestored(
-      {BackForwardCacheMetrics::NotRestoredReason::kJavaScriptExecution},
-      FROM_HERE);
-}
-
-// Same test as above, but with eviction happening before URL loader starts a
-// response.
+//
 // Flaky on most platforms (see crbug.com/1136683)
 IN_PROC_BROWSER_TEST_F(
     BackForwardCacheBrowserTest,
@@ -7171,6 +7043,10 @@
 }
 
 IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, PageshowMetrics) {
+  // TODO(https://crbug.com/1099395): Do not check for unexpected messages
+  // because the input task queue is not currently frozen, causing flakes in
+  // this test.
+  DoNotFailForUnexpectedMessagesWhileCached();
   ASSERT_TRUE(embedded_test_server()->Start());
 
   const char kHistogramName[] =
@@ -8576,6 +8452,45 @@
   };
 }
 
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
+                       NavigationCancelledAfterJsEvictionWasDisabled) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
+
+  // 1) Navigate to A.
+  EXPECT_TRUE(NavigateToURL(shell(), url_a));
+  RenderFrameHostImpl* rfh_a = current_frame_host();
+  RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
+
+  PageLifecycleStateManagerTestDelegate delegate(
+      rfh_a->render_view_host()->GetPageLifecycleStateManager());
+
+  // 2) Navigate to B.
+  EXPECT_TRUE(NavigateToURL(shell(), url_b));
+
+  RenderFrameHostImpl* rfh_b = current_frame_host();
+
+  delegate.OnDisableJsEvictionSent(
+      base::BindLambdaForTesting([&]() { web_contents()->Stop(); }));
+
+  // 3) Do not go back to A (navigation cancelled).
+  web_contents()->GetController().GoBack();
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+  EXPECT_EQ(rfh_b, current_frame_host());
+
+  delete_observer_rfh_a.WaitUntilDeleted();
+
+  // 4) Go back to A.
+  web_contents()->GetController().GoBack();
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+  ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
+                         kNavigationCancelledWhileRestoring},
+                    FROM_HERE);
+}
+
 class BackForwardCacheBrowserTestWithFileSystemAPISupported
     : public BackForwardCacheBrowserTest {
  protected:
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index 0dee92a..79b27f81 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -86,6 +86,7 @@
 #include "third_party/blink/public/mojom/content_index/content_index.mojom.h"
 #include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom.h"
 #include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.h"
+#include "third_party/blink/public/mojom/device/device.mojom.h"
 #include "third_party/blink/public/mojom/feature_observer/feature_observer.mojom.h"
 #include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom.h"
 #include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
@@ -614,6 +615,11 @@
   map->Add<blink::mojom::SpeechSynthesis>(base::BindRepeating(
       &RenderFrameHostImpl::GetSpeechSynthesis, base::Unretained(host)));
 
+#if !defined(OS_ANDROID)
+  map->Add<blink::mojom::DeviceAPIService>(base::BindRepeating(
+      &RenderFrameHostImpl::GetDeviceInfoService, base::Unretained(host)));
+#endif  // !defined(OS_ANDROID)
+
   map->Add<blink::mojom::ScreenEnumeration>(
       base::BindRepeating(&RenderFrameHostImpl::BindScreenEnumerationReceiver,
                           base::Unretained(host)));
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc
index 6ef2edef..6113591 100644
--- a/content/browser/cross_origin_opener_policy_browsertest.cc
+++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -2401,6 +2401,62 @@
                   .IsSameOriginWith(url::Origin::Create(isolated_page)));
 }
 
+// Reproducer test for https://crbug.com/1150938.
+IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest,
+                       MainFrameA_IframeB_Opens_WindowA) {
+  GURL isolated_page(
+      https_server()->GetURL("a.com",
+                             "/set-header?"
+                             "Cross-Origin-Opener-Policy: same-origin&"
+                             "Cross-Origin-Embedder-Policy: require-corp"));
+  GURL isolated_page_b(
+      https_server()->GetURL("cdn.a.com",
+                             "/set-header?"
+                             "Cross-Origin-Embedder-Policy: require-corp&"
+                             "Cross-Origin-Resource-Policy: cross-origin"));
+
+  // Initial cross-origin isolated page.
+  EXPECT_TRUE(NavigateToURL(shell(), isolated_page));
+  SiteInstanceImpl* main_si = current_frame_host()->GetSiteInstance();
+  EXPECT_TRUE(main_si->IsCoopCoepCrossOriginIsolated());
+
+  TestNavigationManager cross_origin_iframe_navigation(web_contents(),
+                                                       isolated_page_b);
+
+  EXPECT_TRUE(ExecJs(web_contents(),
+                     JsReplace("var iframe = document.createElement('iframe'); "
+                               "iframe.src = $1; "
+                               "document.body.appendChild(iframe);",
+                               isolated_page_b)));
+
+  cross_origin_iframe_navigation.WaitForNavigationFinished();
+  EXPECT_TRUE(cross_origin_iframe_navigation.was_successful());
+  RenderFrameHostImpl* iframe =
+      current_frame_host()->child_at(0)->current_frame_host();
+  SiteInstanceImpl* iframe_si = iframe->GetSiteInstance();
+  EXPECT_TRUE(iframe_si->IsCoopCoepCrossOriginIsolated());
+  EXPECT_TRUE(iframe_si->IsRelatedSiteInstance(main_si));
+  EXPECT_EQ(iframe_si->GetProcess(), main_si->GetProcess());
+
+  // Open an isolated popup, but cross-origin.
+  {
+    RenderFrameHostImpl* popup_frame =
+        static_cast<WebContentsImpl*>(
+            OpenPopup(iframe, isolated_page, "")->web_contents())
+            ->GetFrameTree()
+            ->root()
+            ->current_frame_host();
+
+    EXPECT_TRUE(
+        popup_frame->GetSiteInstance()->IsCoopCoepCrossOriginIsolated());
+    EXPECT_FALSE(popup_frame->GetSiteInstance()->IsRelatedSiteInstance(
+        current_frame_host()->GetSiteInstance()));
+    EXPECT_FALSE(popup_frame->frame_tree_node()->opener());
+    EXPECT_NE(popup_frame->GetSiteInstance()->GetProcess(),
+              current_frame_host()->GetSiteInstance()->GetProcess());
+  }
+}
+
 // TODO(https://crbug.com/1101339). Test inheritance of the virtual browsing
 // context group when using window.open from an iframe, same-origin and
 // cross-origin.
diff --git a/content/browser/devtools/protocol/browser_handler.cc b/content/browser/devtools/protocol/browser_handler.cc
index 73e30af..fb54e96 100644
--- a/content/browser/devtools/protocol/browser_handler.cc
+++ b/content/browser/devtools/protocol/browser_handler.cc
@@ -232,8 +232,6 @@
     *out_type = PermissionType::CAMERA_PAN_TILT_ZOOM;
   } else if (type == protocol::Browser::PermissionTypeEnum::BackgroundSync) {
     *out_type = PermissionType::BACKGROUND_SYNC;
-  } else if (type == protocol::Browser::PermissionTypeEnum::Flash) {
-    *out_type = PermissionType::FLASH;
   } else if (type == protocol::Browser::PermissionTypeEnum::Sensors) {
     *out_type = PermissionType::SENSORS;
   } else if (type ==
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc
index b3d7b76f..1e2bc1e 100644
--- a/content/browser/loader/prefetch_url_loader_service.cc
+++ b/content/browser/loader/prefetch_url_loader_service.cc
@@ -5,7 +5,6 @@
 #include "content/browser/loader/prefetch_url_loader_service.h"
 
 #include "base/bind.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/feature_list.h"
 #include "base/time/default_tick_clock.h"
 #include "content/browser/loader/prefetch_url_loader.h"
@@ -29,14 +28,6 @@
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
 
-namespace {
-void DumpWithoutCrashing(const network::ResourceRequest& request) {
-  DEBUG_ALIAS_FOR_GURL(prefetch_buf, request.url);
-  DEBUG_ALIAS_FOR_GURL(initiator_buf, request.request_initiator->GetURL());
-  base::debug::DumpWithoutCrashing();
-}
-}  // namespace
-
 namespace content {
 
 struct PrefetchURLLoaderService::BindContext {
@@ -171,18 +162,9 @@
 
   // Recursive prefetch from a cross-origin main resource prefetch.
   if (resource_request.recursive_prefetch_token) {
-    // A request's |recursive_prefetch_token| is only provided if the request is
-    // a recursive prefetch. This means it is expected that the current
-    // context's |cross_origin_factory| was already created.
+    // TODO(crbug.com/1132770): Figure out why we're seeing this condition hold
+    // true in the field.
     if (!current_context.cross_origin_factory) {
-      // This could happen due to a compromised renderer passing in a recursive
-      // prefetch token for a request that's not a recursive prefetch. Cancel
-      // the request.
-      DVLOG(1) << "Recursive prefetch token unexpectedly set.";
-      DumpWithoutCrashing(resource_request);
-      mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
-          ->OnComplete(
-              network::URLLoaderCompletionStatus(net::ERR_INVALID_ARGUMENT));
       return;
     }
 
@@ -196,8 +178,6 @@
     // a request in a special way. We'll cancel the request.
     if (isolation_info_iterator ==
         current_context.prefetch_isolation_infos.end()) {
-      DVLOG(1) << "Recursive prefetch request is missing prefetch isolation";
-      DumpWithoutCrashing(resource_request);
       mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
           ->OnComplete(
               network::URLLoaderCompletionStatus(net::ERR_INVALID_ARGUMENT));
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc
index 5581688..a558ad67 100644
--- a/content/browser/navigation_browsertest.cc
+++ b/content/browser/navigation_browsertest.cc
@@ -106,12 +106,6 @@
     return intercepted_messages_;
   }
 
-  std::vector<
-      mojo::PendingReceiver<::service_manager::mojom::InterfaceProvider>>&
-  intercepted_receivers() {
-    return intercepted_receivers_;
-  }
-
  protected:
   bool WillProcessDidCommitNavigation(
       RenderFrameHost* render_frame_host,
@@ -121,10 +115,6 @@
       override {
     intercepted_navigations_.push_back(navigation_request);
     intercepted_messages_.push_back(std::move(*params));
-    intercepted_receivers_.push_back(
-        *interface_params
-            ? std::move((*interface_params)->interface_provider_receiver)
-            : mojo::NullReceiver());
     if (loop_)
       loop_->Quit();
     // Do not send the message to the RenderFrameHostImpl.
@@ -135,9 +125,6 @@
   // indices in the RenderFrameHostImpl and not for themselves.
   std::vector<NavigationRequest*> intercepted_navigations_;
   std::vector<mojom::DidCommitProvisionalLoadParamsPtr> intercepted_messages_;
-  std::vector<
-      mojo::PendingReceiver<::service_manager::mojom::InterfaceProvider>>
-      intercepted_receivers_;
   std::unique_ptr<base::RunLoop> loop_;
 };
 
diff --git a/content/browser/permissions/permission_controller_impl.cc b/content/browser/permissions/permission_controller_impl.cc
index ddd6656..825296f2 100644
--- a/content/browser/permissions/permission_controller_impl.cc
+++ b/content/browser/permissions/permission_controller_impl.cc
@@ -51,7 +51,6 @@
           kRequestedStorageAccessGrant;
     case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
     case PermissionType::DURABLE_STORAGE:
-    case PermissionType::FLASH:
     case PermissionType::ACCESSIBILITY_EVENTS:
     case PermissionType::CLIPBOARD_READ_WRITE:
     case PermissionType::CLIPBOARD_SANITIZED_WRITE:
diff --git a/content/browser/portal/portal.cc b/content/browser/portal/portal.cc
index b741df68..06ccedf 100644
--- a/content/browser/portal/portal.cc
+++ b/content/browser/portal/portal.cc
@@ -127,17 +127,11 @@
     return nullptr;
   }
 
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      interface_provider;
-  auto interface_provider_receiver(
-      interface_provider.InitWithNewPipeAndPassReceiver());
-
   // Create a FrameTreeNode in the outer WebContents to host the portal, in
   // response to the creation of a portal in the renderer process.
   FrameTreeNode* outer_node = outer_contents_impl->GetFrameTree()->AddFrame(
       owner_render_frame_host_, owner_render_frame_host_->GetProcess()->GetID(),
       owner_render_frame_host_->GetProcess()->GetNextRoutingID(),
-      std::move(interface_provider_receiver),
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
           .InitWithNewPipeAndPassReceiver(),
       // Pass a null receiver for PolicyContainerHost. The PolicyContainerHost
diff --git a/content/browser/renderer_host/ancestor_throttle.cc b/content/browser/renderer_host/ancestor_throttle.cc
index 878d0287..cba465a 100644
--- a/content/browser/renderer_host/ancestor_throttle.cc
+++ b/content/browser/renderer_host/ancestor_throttle.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/renderer_host/ancestor_throttle.h"
 
+#include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/ranges/algorithm.h"
@@ -22,6 +23,7 @@
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
 #include "net/http/http_response_headers.h"
 #include "services/network/public/cpp/content_security_policy/csp_context.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
@@ -242,6 +244,9 @@
   if (EvaluateXFrameOptions(logging) == CheckResult::BLOCK)
     return NavigationThrottle::BLOCK_RESPONSE;
 
+  if (EvaluateEmbeddingOptIn(logging) == CheckResult::BLOCK)
+    return NavigationThrottle::BLOCK_RESPONSE;
+
   // CSPEE is checked only for the final response.
   if (is_response_check &&
       EvaluateCSPEmbeddedEnforcement() == CheckResult::BLOCK) {
@@ -258,15 +263,20 @@
 AncestorThrottle::AncestorThrottle(NavigationHandle* handle)
     : NavigationThrottle(handle) {}
 
-void AncestorThrottle::ParseXFrameOptionsError(const std::string& value,
-                                               HeaderDisposition disposition) {
-  DCHECK(disposition == HeaderDisposition::CONFLICT ||
-         disposition == HeaderDisposition::INVALID);
+void AncestorThrottle::ParseXFrameOptionsError(
+    const net::HttpResponseHeaders* headers,
+    network::mojom::XFrameOptionsValue disposition) {
+  DCHECK(disposition == network::mojom::XFrameOptionsValue::kConflict ||
+         disposition == network::mojom::XFrameOptionsValue::kInvalid);
+  DCHECK(headers);
   if (!navigation_handle()->GetRenderFrameHost())
     return;  // Some responses won't have a RFH (i.e. 204/205s or downloads).
 
+  std::string value;
+  headers->GetNormalizedHeader("X-Frame-Options", &value);
+
   std::string message;
-  if (disposition == HeaderDisposition::CONFLICT) {
+  if (disposition == network::mojom::XFrameOptionsValue::kConflict) {
     message = base::StringPrintf(
         "Refused to display '%s' in a frame because it set multiple "
         "'X-Frame-Options' headers with conflicting values "
@@ -295,10 +305,39 @@
       blink::mojom::ConsoleMessageLevel::kError, message);
 }
 
+void AncestorThrottle::ConsoleErrorEmbeddingRequiresOptIn() {
+  DCHECK(base::FeatureList::IsEnabled(features::kEmbeddingRequiresOptIn));
+
+  if (!navigation_handle()->GetRenderFrameHost())
+    return;  // Some responses won't have a RFH (i.e. 204/205s or downloads).
+
+  std::string message = base::StringPrintf(
+      "Refused to display '%s' in a frame: It did not opt-into cross-origin "
+      "embedding by setting either an 'X-Frame-Options' header, or a "
+      "'Content-Security-Policy' header containing a 'frame-ancestors' "
+      "directive.",
+      url::Origin::Create(navigation_handle()->GetURL())
+          .GetURL()
+          .spec()
+          .c_str());
+
+  // Log a console error in the parent of the current RenderFrameHost (as
+  // the current RenderFrameHost itself doesn't yet have a document).
+  //
+  // TODO(https://crbug.com/1146651): We should not leak any information at all
+  // to the parent frame. Send a message directly to Devtools instead (without
+  // passing through a renderer): that can also contain more information (like
+  // the full blocked url).
+  auto* frame = static_cast<RenderFrameHostImpl*>(
+      navigation_handle()->GetRenderFrameHost());
+  ParentOrOuterDelegate(frame)->AddMessageToConsole(
+      blink::mojom::ConsoleMessageLevel::kError, message);
+}
+
 void AncestorThrottle::ConsoleErrorXFrameOptions(
-    HeaderDisposition disposition) {
-  DCHECK(disposition == HeaderDisposition::DENY ||
-         disposition == HeaderDisposition::SAMEORIGIN);
+    network::mojom::XFrameOptionsValue disposition) {
+  DCHECK(disposition == network::mojom::XFrameOptionsValue::kDeny ||
+         disposition == network::mojom::XFrameOptionsValue::kSameOrigin);
   if (!navigation_handle()->GetRenderFrameHost())
     return;  // Some responses won't have a RFH (i.e. 204/205s or downloads).
 
@@ -309,7 +348,8 @@
           .GetURL()
           .spec()
           .c_str(),
-      disposition == HeaderDisposition::DENY ? "deny" : "sameorigin");
+      disposition == network::mojom::XFrameOptionsValue::kDeny ? "deny"
+                                                               : "sameorigin");
 
   // Log a console error in the parent of the current RenderFrameHost (as
   // the current RenderFrameHost itself doesn't yet have a document).
@@ -326,42 +366,43 @@
 
 AncestorThrottle::CheckResult AncestorThrottle::EvaluateXFrameOptions(
     LoggingDisposition logging) {
-  std::string header_value;
   NavigationRequest* request = NavigationRequest::From(navigation_handle());
-  HeaderDisposition disposition =
-      ParseXFrameOptionsHeader(request->GetResponseHeaders(), &header_value);
+  network::mojom::XFrameOptionsValue disposition =
+      request->response()->parsed_headers->xfo;
 
   // If 'X-Frame-Options' would potentially block the response, check whether
   // the 'frame-ancestors' CSP directive should take effect instead. See
   // https://www.w3.org/TR/CSP/#frame-ancestors-and-frame-options
-  if (disposition != HeaderDisposition::NONE &&
-      disposition != HeaderDisposition::ALLOWALL &&
+  if (disposition != network::mojom::XFrameOptionsValue::kNone &&
+      disposition != network::mojom::XFrameOptionsValue::kAllowAll &&
       HeadersContainFrameAncestorsCSP(request->response()->parsed_headers)) {
     RecordXFrameOptionsUsage(XFrameOptionsHistogram::BYPASS);
     return CheckResult::PROCEED;
   }
 
   switch (disposition) {
-    case HeaderDisposition::CONFLICT:
+    case network::mojom::XFrameOptionsValue::kConflict:
       if (logging == LoggingDisposition::LOG_TO_CONSOLE)
-        ParseXFrameOptionsError(header_value, disposition);
+        ParseXFrameOptionsError(request->GetResponseHeaders(), disposition);
       RecordXFrameOptionsUsage(XFrameOptionsHistogram::CONFLICT);
       return CheckResult::BLOCK;
 
-    case HeaderDisposition::INVALID:
+    case network::mojom::XFrameOptionsValue::kInvalid:
       if (logging == LoggingDisposition::LOG_TO_CONSOLE)
-        ParseXFrameOptionsError(header_value, disposition);
+        ParseXFrameOptionsError(request->GetResponseHeaders(), disposition);
       RecordXFrameOptionsUsage(XFrameOptionsHistogram::INVALID);
-      // TODO(mkwst): Consider failing here.
+      // TODO(mkwst): Consider failing here, especially if we end up shipping
+      // a new default behavior which requires embedees to explicitly opt-in
+      // to being embedded: https://crbug.com/1153274.
       return CheckResult::PROCEED;
 
-    case HeaderDisposition::DENY:
+    case network::mojom::XFrameOptionsValue::kDeny:
       if (logging == LoggingDisposition::LOG_TO_CONSOLE)
         ConsoleErrorXFrameOptions(disposition);
       RecordXFrameOptionsUsage(XFrameOptionsHistogram::DENY);
       return CheckResult::BLOCK;
 
-    case HeaderDisposition::SAMEORIGIN: {
+    case network::mojom::XFrameOptionsValue::kSameOrigin: {
       // Block the request when any ancestor is not same-origin.
       RenderFrameHostImpl* parent = ParentOrOuterDelegate(
           request->frame_tree_node()->current_frame_host());
@@ -392,15 +433,45 @@
       return CheckResult::PROCEED;
     }
 
-    case HeaderDisposition::NONE:
+    case network::mojom::XFrameOptionsValue::kNone:
       RecordXFrameOptionsUsage(XFrameOptionsHistogram::NONE);
       return CheckResult::PROCEED;
-    case HeaderDisposition::ALLOWALL:
+    case network::mojom::XFrameOptionsValue::kAllowAll:
       RecordXFrameOptionsUsage(XFrameOptionsHistogram::ALLOWALL);
       return CheckResult::PROCEED;
   }
 }
 
+AncestorThrottle::CheckResult AncestorThrottle::EvaluateEmbeddingOptIn(
+    LoggingDisposition logging) {
+  if (!base::FeatureList::IsEnabled(features::kEmbeddingRequiresOptIn))
+    return CheckResult::PROCEED;
+
+  NavigationRequest* request = NavigationRequest::From(navigation_handle());
+
+  // If embedding requires opt-in, then we check whether the response opted-into
+  // embedding via either an 'X-Frame-Options' header or a 'frame-ancestors'
+  // directive. If neither is present, the response will be blocked unless it is
+  // same-origin with its ancestor chain.
+  if (request->response()->parsed_headers->xfo ==
+          network::mojom::XFrameOptionsValue::kNone &&
+      !HeadersContainFrameAncestorsCSP(request->response()->parsed_headers)) {
+    RenderFrameHostImpl* parent =
+        ParentOrOuterDelegate(request->frame_tree_node()->current_frame_host());
+    url::Origin current_origin =
+        url::Origin::Create(navigation_handle()->GetURL());
+    while (parent) {
+      if (!parent->GetLastCommittedOrigin().IsSameOriginWith(current_origin)) {
+        if (logging == LoggingDisposition::LOG_TO_CONSOLE)
+          ConsoleErrorEmbeddingRequiresOptIn();
+        return CheckResult::BLOCK;
+      }
+      parent = ParentOrOuterDelegate(parent);
+    }
+  }
+  return CheckResult::PROCEED;
+}
+
 AncestorThrottle::CheckResult AncestorThrottle::EvaluateFrameAncestors(
     const std::vector<network::mojom::ContentSecurityPolicyPtr>&
         content_security_policy) {
@@ -531,46 +602,4 @@
   return false;
 }
 
-AncestorThrottle::HeaderDisposition AncestorThrottle::ParseXFrameOptionsHeader(
-    const net::HttpResponseHeaders* headers,
-    std::string* header_value) {
-  DCHECK(header_value);
-  if (!headers)
-    return HeaderDisposition::NONE;
-
-  // Process the 'X-Frame-Options header as per Section 2 of RFC7034:
-  // https://tools.ietf.org/html/rfc7034#section-2
-  //
-  // Note that we do not support the 'ALLOW-FROM' value, and we special-case
-  // the invalid "ALLOWALL" value due to its prevalance in the wild.
-  HeaderDisposition result = HeaderDisposition::NONE;
-  size_t iter = 0;
-  std::string value;
-  while (headers->EnumerateHeader(&iter, "x-frame-options", &value)) {
-    HeaderDisposition current = HeaderDisposition::INVALID;
-
-    base::StringPiece trimmed =
-        base::TrimWhitespaceASCII(value, base::TRIM_ALL);
-    if (!header_value->empty())
-      header_value->append(", ");
-    header_value->append(trimmed.as_string());
-
-    if (base::LowerCaseEqualsASCII(trimmed, "deny"))
-      current = HeaderDisposition::DENY;
-    else if (base::LowerCaseEqualsASCII(trimmed, "allowall"))
-      current = HeaderDisposition::ALLOWALL;
-    else if (base::LowerCaseEqualsASCII(trimmed, "sameorigin"))
-      current = HeaderDisposition::SAMEORIGIN;
-    else
-      current = HeaderDisposition::INVALID;
-
-    if (result == HeaderDisposition::NONE)
-      result = current;
-    else if (result != current)
-      result = HeaderDisposition::CONFLICT;
-  }
-
-  return result;
-}
-
 }  // namespace content
diff --git a/content/browser/renderer_host/ancestor_throttle.h b/content/browser/renderer_host/ancestor_throttle.h
index b14e2d6a..a5843ad1 100644
--- a/content/browser/renderer_host/ancestor_throttle.h
+++ b/content/browser/renderer_host/ancestor_throttle.h
@@ -13,6 +13,7 @@
 #include "content/public/browser/navigation_throttle.h"
 #include "services/network/public/mojom/content_security_policy.mojom-forward.h"
 #include "services/network/public/mojom/parsed_headers.mojom-forward.h"
+#include "services/network/public/mojom/x_frame_options.mojom-forward.h"
 
 class GURL;
 
@@ -31,15 +32,6 @@
 // rules, and blocking requests which violate them.
 class CONTENT_EXPORT AncestorThrottle : public NavigationThrottle {
  public:
-  enum class HeaderDisposition {
-    NONE = 0,
-    DENY,
-    SAMEORIGIN,
-    ALLOWALL,
-    INVALID,
-    CONFLICT
-  };
-
   static std::unique_ptr<NavigationThrottle> MaybeCreateThrottleFor(
       NavigationHandle* handle);
 
@@ -65,26 +57,22 @@
   NavigationThrottle::ThrottleCheckResult ProcessResponseImpl(
       LoggingDisposition logging,
       bool is_response_check);
-  void ParseXFrameOptionsError(const std::string& value,
-                               HeaderDisposition disposition);
-  void ConsoleErrorXFrameOptions(HeaderDisposition disposition);
+  void ParseXFrameOptionsError(const net::HttpResponseHeaders* headers,
+                               network::mojom::XFrameOptionsValue disposition);
+  void ConsoleErrorXFrameOptions(
+      network::mojom::XFrameOptionsValue disposition);
+  void ConsoleErrorEmbeddingRequiresOptIn();
   CheckResult EvaluateXFrameOptions(LoggingDisposition logging);
   CheckResult EvaluateFrameAncestors(
       const std::vector<network::mojom::ContentSecurityPolicyPtr>&
           content_security_policy);
+  CheckResult EvaluateEmbeddingOptIn(LoggingDisposition logging);
   CheckResult EvaluateCSPEmbeddedEnforcement();
   static bool AllowsBlanketEnforcementOfRequiredCSP(
       const url::Origin& request_origin,
       const GURL& response_url,
       const network::mojom::AllowCSPFromHeaderValuePtr& allow_csp_from);
 
-  // Parses an 'X-Frame-Options' header. If the result is either CONFLICT
-  // or INVALID, |header_value| will be populated with the value which caused
-  // the parse error.
-  HeaderDisposition ParseXFrameOptionsHeader(
-      const net::HttpResponseHeaders* headers,
-      std::string* header_value);
-
   DISALLOW_COPY_AND_ASSIGN(AncestorThrottle);
 };
 
diff --git a/content/browser/renderer_host/ancestor_throttle_unittest.cc b/content/browser/renderer_host/ancestor_throttle_unittest.cc
index 8baf9ab..f3f90dd 100644
--- a/content/browser/renderer_host/ancestor_throttle_unittest.cc
+++ b/content/browser/renderer_host/ancestor_throttle_unittest.cc
@@ -7,10 +7,12 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/memory/ref_counted.h"
+#include "base/test/scoped_feature_list.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/test/navigation_simulator_impl.h"
 #include "content/test/test_navigation_url_loader.h"
@@ -23,25 +25,6 @@
 
 namespace {
 
-using HeaderDisposition = AncestorThrottle::HeaderDisposition;
-
-net::HttpResponseHeaders* GetAncestorHeaders(const char* xfo, const char* csp) {
-  std::string header_string("HTTP/1.1 200 OK\nX-Frame-Options: ");
-  header_string += xfo;
-  if (csp != nullptr) {
-    header_string += "\nContent-Security-Policy: ";
-    header_string += csp;
-  }
-  header_string += "\n\n";
-  std::replace(header_string.begin(), header_string.end(), '\n', '\0');
-  net::HttpResponseHeaders* headers =
-      new net::HttpResponseHeaders(header_string);
-  EXPECT_TRUE(headers->HasHeader("X-Frame-Options"));
-  if (csp != nullptr)
-    EXPECT_TRUE(headers->HasHeader("Content-Security-Policy"));
-  return headers;
-}
-
 network::mojom::ContentSecurityPolicyPtr ParsePolicy(
     const std::string& policy) {
   scoped_refptr<net::HttpResponseHeaders> headers(
@@ -60,89 +43,6 @@
 
 class AncestorThrottleTest : public testing::Test {};
 
-TEST_F(AncestorThrottleTest, ParsingXFrameOptions) {
-  struct TestCase {
-    const char* header;
-    AncestorThrottle::HeaderDisposition expected;
-    const char* value;
-  } cases[] = {
-      // Basic keywords
-      {"DENY", HeaderDisposition::DENY, "DENY"},
-      {"SAMEORIGIN", HeaderDisposition::SAMEORIGIN, "SAMEORIGIN"},
-      {"ALLOWALL", HeaderDisposition::ALLOWALL, "ALLOWALL"},
-
-      // Repeated keywords
-      {"DENY,DENY", HeaderDisposition::DENY, "DENY, DENY"},
-      {"SAMEORIGIN,SAMEORIGIN", HeaderDisposition::SAMEORIGIN,
-       "SAMEORIGIN, SAMEORIGIN"},
-      {"ALLOWALL,ALLOWALL", HeaderDisposition::ALLOWALL, "ALLOWALL, ALLOWALL"},
-
-      // Case-insensitive
-      {"deNy", HeaderDisposition::DENY, "deNy"},
-      {"sAmEorIgIn", HeaderDisposition::SAMEORIGIN, "sAmEorIgIn"},
-      {"AlLOWaLL", HeaderDisposition::ALLOWALL, "AlLOWaLL"},
-
-      // Trim whitespace
-      {" DENY", HeaderDisposition::DENY, "DENY"},
-      {"SAMEORIGIN ", HeaderDisposition::SAMEORIGIN, "SAMEORIGIN"},
-      {" ALLOWALL ", HeaderDisposition::ALLOWALL, "ALLOWALL"},
-      {"   DENY", HeaderDisposition::DENY, "DENY"},
-      {"SAMEORIGIN   ", HeaderDisposition::SAMEORIGIN, "SAMEORIGIN"},
-      {"   ALLOWALL   ", HeaderDisposition::ALLOWALL, "ALLOWALL"},
-      {" DENY , DENY ", HeaderDisposition::DENY, "DENY, DENY"},
-      {"SAMEORIGIN,  SAMEORIGIN", HeaderDisposition::SAMEORIGIN,
-       "SAMEORIGIN, SAMEORIGIN"},
-      {"ALLOWALL  ,ALLOWALL", HeaderDisposition::ALLOWALL,
-       "ALLOWALL, ALLOWALL"},
-  };
-
-  AncestorThrottle throttle(nullptr);
-  for (const auto& test : cases) {
-    SCOPED_TRACE(test.header);
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        GetAncestorHeaders(test.header, nullptr);
-    std::string header_value;
-    EXPECT_EQ(test.expected,
-              throttle.ParseXFrameOptionsHeader(headers.get(), &header_value));
-    EXPECT_EQ(test.value, header_value);
-  }
-}
-
-TEST_F(AncestorThrottleTest, ErrorsParsingXFrameOptions) {
-  struct TestCase {
-    const char* header;
-    AncestorThrottle::HeaderDisposition expected;
-    const char* failure;
-  } cases[] = {
-      // Empty == Invalid.
-      {"", HeaderDisposition::INVALID, ""},
-
-      // Invalid
-      {"INVALID", HeaderDisposition::INVALID, "INVALID"},
-      {"INVALID DENY", HeaderDisposition::INVALID, "INVALID DENY"},
-      {"DENY DENY", HeaderDisposition::INVALID, "DENY DENY"},
-      {"DE NY", HeaderDisposition::INVALID, "DE NY"},
-
-      // Conflicts
-      {"INVALID,DENY", HeaderDisposition::CONFLICT, "INVALID, DENY"},
-      {"DENY,ALLOWALL", HeaderDisposition::CONFLICT, "DENY, ALLOWALL"},
-      {"SAMEORIGIN,DENY", HeaderDisposition::CONFLICT, "SAMEORIGIN, DENY"},
-      {"ALLOWALL,SAMEORIGIN", HeaderDisposition::CONFLICT,
-       "ALLOWALL, SAMEORIGIN"},
-      {"DENY,  SAMEORIGIN", HeaderDisposition::CONFLICT, "DENY, SAMEORIGIN"}};
-
-  AncestorThrottle throttle(nullptr);
-  for (const auto& test : cases) {
-    SCOPED_TRACE(test.header);
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        GetAncestorHeaders(test.header, nullptr);
-    std::string header_value;
-    EXPECT_EQ(test.expected,
-              throttle.ParseXFrameOptionsHeader(headers.get(), &header_value));
-    EXPECT_EQ(test.failure, header_value);
-  }
-}
-
 TEST_F(AncestorThrottleTest, AllowsBlanketEnforcementOfRequiredCSP) {
   struct TestCase {
     const char* name;
@@ -472,4 +372,119 @@
   }
 }
 
+TEST_F(AncestorThrottleNavigationTest, EmbeddingOptInRequirement) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kEmbeddingRequiresOptIn);
+
+  // Set up the main frame. We'll add nested frames to it in the tests below.
+  NavigateAndCommit(GURL("https://www.example.org"));
+  auto* main_frame = static_cast<TestRenderFrameHost*>(main_rfh());
+
+  struct TestCase {
+    const char* name;
+    const char* frame_url;
+    const char* xfo;
+    const char* csp;
+    NavigationThrottle::ThrottleAction expected_result;
+  } cases[] = {{
+                   "Same-origin, no XFO, no CSP",
+                   "https://www.example.org",
+                   nullptr,
+                   nullptr,
+                   NavigationThrottle::PROCEED,
+               },
+               {
+                   "Same-site, no XFO, no CSP",
+                   "https://not.example.org",
+                   nullptr,
+                   nullptr,
+                   NavigationThrottle::BLOCK_RESPONSE,
+               },
+               {
+                   "Same-site, XFO: ALLOWALL, no CSP",
+                   "https://not.example.org",
+                   "ALLOWALL",
+                   nullptr,
+                   NavigationThrottle::PROCEED,
+               },
+               {
+                   "Same-site, XFO: INVALID, no CSP",
+                   "https://not.example.org",
+                   "INVALID",
+                   nullptr,
+                   NavigationThrottle::PROCEED,
+               },
+               {
+                   "Same-site, no XFO, CSP: frame-ancestors *",
+                   "https://not.example.org",
+                   nullptr,
+                   "frame-ancestors *",
+                   NavigationThrottle::PROCEED,
+               },
+               {
+                   "Same-site, no XFO, CSP without frame-ancestors",
+                   "https://not.example.org",
+                   nullptr,
+                   "img-src 'self'",
+                   NavigationThrottle::BLOCK_RESPONSE,
+               },
+               {
+                   "Cross-origin, no XFO, no CSP",
+                   "https://www.not-example.org",
+                   nullptr,
+                   nullptr,
+                   NavigationThrottle::BLOCK_RESPONSE,
+               },
+               {
+                   "Cross-origin, XFO: ALLOWALL, no CSP",
+                   "https://www.not-example.org",
+                   "ALLOWALL",
+                   nullptr,
+                   NavigationThrottle::PROCEED,
+               },
+               {
+                   "Cross-origin, XFO: INVALID, no CSP",
+                   "https://www.not-example.org",
+                   "INVALID",
+                   nullptr,
+                   NavigationThrottle::PROCEED,
+               },
+               {
+                   "Cross-origin, no XFO, CSP: frame-ancestors *",
+                   "https://www.not-example.org",
+                   nullptr,
+                   "frame-ancestors *",
+                   NavigationThrottle::PROCEED,
+               },
+               {
+                   "Cross-origin, no XFO, CSP without frame-ancestors",
+                   "https://www.not-example.org",
+                   nullptr,
+                   "img-src 'self'",
+                   NavigationThrottle::BLOCK_RESPONSE,
+               }};
+
+  for (auto test : cases) {
+    SCOPED_TRACE(test.name);
+    auto* frame = static_cast<TestRenderFrameHost*>(
+        content::RenderFrameHostTester::For(main_frame)
+            ->AppendChild(test.name));
+    std::unique_ptr<NavigationSimulator> simulator =
+        content::NavigationSimulator::CreateRendererInitiated(
+            GURL(test.frame_url), frame);
+
+    auto response_headers =
+        base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
+    if (test.xfo)
+      response_headers->SetHeader("X-Frame-Options", test.xfo);
+    if (test.csp)
+      response_headers->SetHeader("Content-Security-Policy", test.csp);
+
+    simulator->SetResponseHeaders(response_headers);
+    simulator->ReadyToCommit();
+
+    EXPECT_EQ(test.expected_result, simulator->GetLastThrottleCheckResult());
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc b/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc
index 0700e61..6da52e8 100644
--- a/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc
+++ b/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc
@@ -131,6 +131,8 @@
       return "BackForwardCache is disabled through command line (may include "
              "cases where the embedder disabled it due to, e.g., enterprise "
              "policy)";
+    case Reason::kNavigationCancelledWhileRestoring:
+      return "Navigation request was cancelled after js eviction was disabled";
   }
 }
 
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.h b/content/browser/renderer_host/back_forward_cache_metrics.h
index 93cb081..307dc01 100644
--- a/content/browser/renderer_host/back_forward_cache_metrics.h
+++ b/content/browser/renderer_host/back_forward_cache_metrics.h
@@ -85,7 +85,8 @@
     // BackForwardCache is disabled due to command-line switch (may include
     // cases where the embedder disabled it due to, e.g., enterprise policy).
     kBackForwardCacheDisabledByCommandLine = 35,
-    kMaxValue = kBackForwardCacheDisabledByCommandLine,
+    kNavigationCancelledWhileRestoring = 36,
+    kMaxValue = kNavigationCancelledWhileRestoring,
   };
 
   using NotRestoredReasons =
diff --git a/content/browser/renderer_host/back_forward_cache_throttle.cc b/content/browser/renderer_host/back_forward_cache_throttle.cc
new file mode 100644
index 0000000..7cc3d2ad
--- /dev/null
+++ b/content/browser/renderer_host/back_forward_cache_throttle.cc
@@ -0,0 +1,87 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/back_forward_cache_throttle.h"
+
+#include "base/barrier_closure.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/time/time.h"
+#include "content/browser/renderer_host/navigation_controller_impl.h"
+#include "content/browser/renderer_host/navigation_request.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace content {
+
+// static
+std::unique_ptr<BackForwardCacheThrottle>
+BackForwardCacheThrottle::MaybeCreateThrottleFor(
+    NavigationRequest* navigation_request) {
+  if (navigation_request->IsServedFromBackForwardCache()) {
+    return base::WrapUnique(new BackForwardCacheThrottle(navigation_request));
+  }
+  return nullptr;
+}
+
+BackForwardCacheThrottle::BackForwardCacheThrottle(
+    NavigationRequest* navigation_request)
+    : NavigationThrottle(navigation_request) {
+  DCHECK(navigation_request->IsServedFromBackForwardCache());
+}
+
+BackForwardCacheThrottle::~BackForwardCacheThrottle() {
+  RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(main_rfh_id_);
+  // RFH could have been deleted. E.g. eviction timer fired
+  if (rfh && rfh->IsInBackForwardCache()) {
+    // rfh is still in the cache so the navigation must have failed. But we have
+    // already disabled eviction so the safest thing to do here to recover is to
+    // evict.
+    rfh->EvictFromBackForwardCacheWithReason(
+        BackForwardCacheMetrics::NotRestoredReason::
+            kNavigationCancelledWhileRestoring);
+  }
+}
+
+NavigationThrottle::ThrottleCheckResult
+BackForwardCacheThrottle::WillStartRequest() {
+  NavigationRequest* navigation_request =
+      NavigationRequest::From(navigation_handle());
+  BackForwardCacheImpl::Entry* bfcache_entry =
+      navigation_request->frame_tree_node()
+          ->navigator()
+          .controller()
+          ->GetBackForwardCache()
+          .GetEntry(navigation_request->nav_entry_id());
+
+  if (!bfcache_entry) {
+    // Go on for now. NavigationRequest will later restart the navigation
+    // without bfcache.
+    return PROCEED;
+  }
+
+  main_rfh_id_ = bfcache_entry->render_frame_host->GetGlobalFrameRoutingId();
+
+  auto cb = base::BarrierClosure(
+      bfcache_entry->render_view_hosts.size(),
+      base::BindOnce(&BackForwardCacheThrottle::OnAckReceived,
+                     weak_factory_.GetWeakPtr(), base::TimeTicks::Now()));
+  for (auto* rvh : bfcache_entry->render_view_hosts) {
+    rvh->PrepareToLeaveBackForwardCache(cb);
+  }
+  return DEFER;
+}
+
+const char* BackForwardCacheThrottle::GetNameForLogging() {
+  return "BackForwardCacheThrottle";
+}
+
+void BackForwardCacheThrottle::OnAckReceived(base::TimeTicks ipc_start_time) {
+  base::UmaHistogramTimes("BackForwardCache.Restore.DisableEvictionDelay",
+                          base::TimeTicks::Now() - ipc_start_time);
+  Resume();
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/back_forward_cache_throttle.h b/content/browser/renderer_host/back_forward_cache_throttle.h
new file mode 100644
index 0000000..9984ef78
--- /dev/null
+++ b/content/browser/renderer_host/back_forward_cache_throttle.h
@@ -0,0 +1,53 @@
+// 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 CONTENT_BROWSER_RENDERER_HOST_BACK_FORWARD_CACHE_THROTTLE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_BACK_FORWARD_CACHE_THROTTLE_H_
+
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/global_routing_id.h"
+#include "content/public/browser/navigation_throttle.h"
+
+namespace content {
+
+class NavigationRequest;
+
+// This throttle is used for back-forward-cache navigations. It unhooks the
+// Javascript eviction in every renderer process. The navigation is deferred
+// until a confirmation is received from each renderer. This ensures no renderer
+// will try to evict the document after the browser has activated it (due to
+// races in IPCs).
+//
+// If the back-forward cache entry isn't restored at the end of the navigation,
+// it becomes unsuitable for being restored later (as Javascript eviction is now
+// disabled) and is thus dropped.
+class BackForwardCacheThrottle : public NavigationThrottle {
+ public:
+  static std::unique_ptr<BackForwardCacheThrottle> MaybeCreateThrottleFor(
+      NavigationRequest* navigation_request);
+
+  ~BackForwardCacheThrottle() override;
+
+  ThrottleCheckResult WillStartRequest() override;
+  const char* GetNameForLogging() override;
+
+ private:
+  explicit BackForwardCacheThrottle(NavigationRequest* navigation_request);
+
+  void OnAckReceived(base::TimeTicks ipc_start_time);
+
+  // ID of the RenderFrameHost that is going to be restored from the
+  // back-forward cache. If the navigation finishes and this RenderFrameHost is
+  // still in the cache (navigation failed / canceled) we need to evict it, as
+  // we unhooked eviction and thus left it in an intermediate state.
+  GlobalFrameRoutingId main_rfh_id_;
+
+  base::WeakPtrFactory<BackForwardCacheThrottle> weak_factory_{this};
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_BACK_FORWARD_CACHE_THROTTLE_H_
diff --git a/content/browser/renderer_host/frame_tree.cc b/content/browser/renderer_host/frame_tree.cc
index 82d7b5b7..0e364b4 100644
--- a/content/browser/renderer_host/frame_tree.cc
+++ b/content/browser/renderer_host/frame_tree.cc
@@ -180,8 +180,6 @@
     RenderFrameHostImpl* parent,
     int process_id,
     int new_routing_id,
-    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-        interface_provider_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     mojo::PendingAssociatedReceiver<blink::mojom::PolicyContainerHost>
@@ -227,10 +225,6 @@
   FrameTreeNode* added_node = parent->AddChild(std::move(new_node), process_id,
                                                new_routing_id, frame_token);
 
-  DCHECK(interface_provider_receiver.is_valid());
-  added_node->current_frame_host()->BindInterfaceProviderReceiver(
-      std::move(interface_provider_receiver));
-
   DCHECK(browser_interface_broker_receiver.is_valid());
   added_node->current_frame_host()->BindBrowserInterfaceBrokerReceiver(
       std::move(browser_interface_broker_receiver));
diff --git a/content/browser/renderer_host/frame_tree.h b/content/browser/renderer_host/frame_tree.h
index f6c41071..bbf18355 100644
--- a/content/browser/renderer_host/frame_tree.h
+++ b/content/browser/renderer_host/frame_tree.h
@@ -161,8 +161,6 @@
       RenderFrameHostImpl* parent,
       int process_id,
       int new_routing_id,
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider_receiver,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker_receiver,
       mojo::PendingAssociatedReceiver<blink::mojom::PolicyContainerHost>
diff --git a/content/browser/renderer_host/frame_tree_node_blame_context_unittest.cc b/content/browser/renderer_host/frame_tree_node_blame_context_unittest.cc
index 2b0c893..ebee059 100644
--- a/content/browser/renderer_host/frame_tree_node_blame_context_unittest.cc
+++ b/content/browser/renderer_host/frame_tree_node_blame_context_unittest.cc
@@ -99,7 +99,6 @@
       int child_id = self_id * 10 + child_num;
       tree()->AddFrame(
           node->current_frame_host(), process_id(), child_id,
-          TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
           TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
           mojo::NullAssociatedReceiver(),
           blink::mojom::TreeScopeType::kDocument, std::string(),
diff --git a/content/browser/renderer_host/frame_tree_unittest.cc b/content/browser/renderer_host/frame_tree_unittest.cc
index fe61fc3..c0f56ed 100644
--- a/content/browser/renderer_host/frame_tree_unittest.cc
+++ b/content/browser/renderer_host/frame_tree_unittest.cc
@@ -53,11 +53,6 @@
   result->append("]");
 }
 
-mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-CreateStubInterfaceProviderReceiver() {
-  return TestRenderFrameHost::CreateStubInterfaceProviderReceiver();
-}
-
 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
 CreateStubBrowserInterfaceBrokerReceiver() {
   return TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver();
@@ -176,7 +171,6 @@
   constexpr auto kOwnerType = blink::mojom::FrameOwnerElementType::kIframe;
   // Simulate attaching a series of frames to build the frame tree.
   frame_tree->AddFrame(root->current_frame_host(), process_id, 14,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -184,7 +178,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(root->current_frame_host(), process_id, 15,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -192,7 +185,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(root->current_frame_host(), process_id, 16,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -200,7 +192,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(root->child_at(0)->current_frame_host(), process_id, 244,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -208,7 +199,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(root->child_at(1)->current_frame_host(), process_id, 255,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, no_children_node,
@@ -216,7 +206,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(root->child_at(0)->current_frame_host(), process_id, 245,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -232,7 +221,6 @@
 
   FrameTreeNode* child_16 = root->child_at(2);
   frame_tree->AddFrame(child_16->current_frame_host(), process_id, 264,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -240,7 +228,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(child_16->current_frame_host(), process_id, 265,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -248,7 +235,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(child_16->current_frame_host(), process_id, 266,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -256,7 +242,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(child_16->current_frame_host(), process_id, 267,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, deep_subtree,
@@ -264,7 +249,6 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(child_16->current_frame_host(), process_id, 268,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -274,7 +258,6 @@
 
   FrameTreeNode* child_267 = child_16->child_at(3);
   frame_tree->AddFrame(child_267->current_frame_host(), process_id, 365,
-                       CreateStubInterfaceProviderReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
@@ -282,8 +265,7 @@
                        base::UnguessableToken::Create(), blink::FramePolicy(),
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(child_267->child_at(0)->current_frame_host(), process_id,
-                       455, CreateStubInterfaceProviderReceiver(),
-                       CreateStubBrowserInterfaceBrokerReceiver(),
+                       455, CreateStubBrowserInterfaceBrokerReceiver(),
                        mojo::NullAssociatedReceiver(),
                        blink::mojom::TreeScopeType::kDocument, std::string(),
                        "uniqueName12", false, base::UnguessableToken::Create(),
@@ -291,16 +273,14 @@
                        blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       child_267->child_at(0)->child_at(0)->current_frame_host(), process_id,
-      555, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      555, CreateStubBrowserInterfaceBrokerReceiver(),
       mojo::NullAssociatedReceiver(), blink::mojom::TreeScopeType::kDocument,
       std::string(), "uniqueName13", false, base::UnguessableToken::Create(),
       base::UnguessableToken::Create(), blink::FramePolicy(),
       blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       child_267->child_at(0)->child_at(0)->child_at(0)->current_frame_host(),
-      process_id, 655, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      process_id, 655, CreateStubBrowserInterfaceBrokerReceiver(),
       mojo::NullAssociatedReceiver(), blink::mojom::TreeScopeType::kDocument,
       std::string(), "uniqueName14", false, base::UnguessableToken::Create(),
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -377,22 +357,19 @@
 
   constexpr auto kOwnerType = blink::mojom::FrameOwnerElementType::kIframe;
   main_test_rfh()->OnCreateChildFrame(
-      22, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      22, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "child0", "uniqueName0", false,
       base::UnguessableToken::Create(), base::UnguessableToken::Create(),
       blink::FramePolicy(), blink::mojom::FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
-      23, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      23, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "child1", "uniqueName1", false,
       base::UnguessableToken::Create(), base::UnguessableToken::Create(),
       blink::FramePolicy(), blink::mojom::FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
-      24, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      24, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName2",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -403,8 +380,7 @@
 
   // Add one grandchild frame.
   child1->current_frame_host()->OnCreateChildFrame(
-      33, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      33, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "grandchild", "uniqueName3",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -446,22 +422,19 @@
   FrameTree* frame_tree = contents()->GetFrameTree();
   FrameTreeNode* root = frame_tree->root();
   main_test_rfh()->OnCreateChildFrame(
-      22, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      22, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "child0", "uniqueName0", false,
       base::UnguessableToken::Create(), base::UnguessableToken::Create(),
       blink::FramePolicy(), blink::mojom::FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
-      23, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      23, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "child1", "uniqueName1", false,
       base::UnguessableToken::Create(), base::UnguessableToken::Create(),
       blink::FramePolicy(), blink::mojom::FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
-      24, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      24, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "child2", "uniqueName2", false,
       base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -472,8 +445,7 @@
 
   // Add one grandchild frame.
   child1->current_frame_host()->OnCreateChildFrame(
-      33, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      33, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "grandchild", "uniqueName3",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -508,8 +480,7 @@
   constexpr auto kOwnerType = blink::mojom::FrameOwnerElementType::kIframe;
   // Simulate attaching a series of frames to build the frame tree.
   main_test_rfh()->OnCreateChildFrame(
-      14, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      14, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName0",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -519,8 +490,7 @@
       "RenderFrameCreated(14) -> 1: [14: []]",
       activity.GetLog());
   main_test_rfh()->OnCreateChildFrame(
-      18, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      18, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName1",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -544,8 +514,7 @@
 
   constexpr auto kOwnerType = blink::mojom::FrameOwnerElementType::kIframe;
   main_test_rfh()->OnCreateChildFrame(
-      22, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      22, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName0",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -555,8 +524,7 @@
       "RenderFrameCreated(22) -> 1: [22: []]",
       activity.GetLog());
   main_test_rfh()->OnCreateChildFrame(
-      23, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      23, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName1",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -589,7 +557,6 @@
   // Simulate attaching a frame from mismatched process id.
   ASSERT_FALSE(frame_tree->AddFrame(
       root->current_frame_host(), process_id + 1, 1,
-      CreateStubInterfaceProviderReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       mojo::NullAssociatedReceiver(), blink::mojom::TreeScopeType::kDocument,
       std::string(), "uniqueName0", false, base::UnguessableToken::Create(),
@@ -609,15 +576,13 @@
 
   constexpr auto kOwnerType = blink::mojom::FrameOwnerElementType::kIframe;
   main_test_rfh()->OnCreateChildFrame(
-      22, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      22, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName0",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
       blink::FramePolicy(), blink::mojom::FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
-      23, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      23, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName1",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -626,8 +591,7 @@
   // Add one grandchild frame.
   RenderFrameHostImpl* child1_rfh = root->child_at(0)->current_frame_host();
   child1_rfh->OnCreateChildFrame(
-      33, CreateStubInterfaceProviderReceiver(),
-      CreateStubBrowserInterfaceBrokerReceiver(),
+      33, CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName2",
       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 7e76843..a55685e 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -2300,8 +2300,8 @@
 
   request->SetNavigationClient(std::move(*navigation_client));
 
-  render_frame_host->frame_tree_node()->navigator().Navigate(
-      std::move(request), ReloadType::NONE, RestoreType::NONE);
+  render_frame_host->frame_tree_node()->navigator().Navigate(std::move(request),
+                                                             ReloadType::NONE);
 
   return true;
 }
@@ -2321,8 +2321,7 @@
       false /* is_history_navigation_in_new_child */);
   if (!request)
     return false;
-  frame_tree_node->navigator().Navigate(std::move(request), reload_type,
-                                        RestoreType::NONE);
+  frame_tree_node->navigator().Navigate(std::move(request), reload_type);
   return true;
 }
 
@@ -2488,8 +2487,7 @@
   // remains of a cancelled browser initiated navigation to avoid URL spoofs.
   DiscardNonCommittedEntries();
 
-  node->navigator().Navigate(std::move(request), ReloadType::NONE,
-                             RestoreType::NONE);
+  node->navigator().Navigate(std::move(request), ReloadType::NONE);
 }
 
 void NavigationControllerImpl::SetSessionStorageNamespace(
@@ -2810,8 +2808,7 @@
         root, pending_entry_, pending_entry_->GetFrameEntry(root),
         ReloadType::NONE, false /* is_same_document_history_load */,
         false /* is_history_navigation_in_new_child */);
-    root->navigator().Navigate(std::move(navigation_request), ReloadType::NONE,
-                               RestoreType::NONE);
+    root->navigator().Navigate(std::move(navigation_request), ReloadType::NONE);
 
     return;
   }
@@ -2854,13 +2851,11 @@
   // Send all the same document frame loads before the different document loads.
   for (auto& item : same_document_loads) {
     FrameTreeNode* frame = item->frame_tree_node();
-    frame->navigator().Navigate(std::move(item), reload_type,
-                                pending_entry_->restore_type());
+    frame->navigator().Navigate(std::move(item), reload_type);
   }
   for (auto& item : different_document_loads) {
     FrameTreeNode* frame = item->frame_tree_node();
-    frame->navigator().Navigate(std::move(item), reload_type,
-                                pending_entry_->restore_type());
+    frame->navigator().Navigate(std::move(item), reload_type);
   }
 
   in_navigate_to_pending_entry_ = false;
@@ -3180,8 +3175,7 @@
   // function.
   std::unique_ptr<PendingEntryRef> pending_entry_ref = ReferencePendingEntry();
 
-  node->navigator().Navigate(std::move(request), reload_type,
-                             RestoreType::NONE);
+  node->navigator().Navigate(std::move(request), reload_type);
 
   in_navigate_to_pending_entry_ = false;
 }
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
index dd6e0af..b305e345 100644
--- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -8720,12 +8720,9 @@
   params->embedding_token = base::UnguessableToken::Create();
   RenderFrameHostImpl* rfh = contents()->GetMainFrame();
   RenderProcessHostBadIpcMessageWaiter kill_waiter(rfh->GetProcess());
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      isolated_interface_provider;
   static_cast<mojom::FrameHost*>(rfh)->DidCommitProvisionalLoad(
       std::move(params),
       mojom::DidCommitProvisionalLoadInterfaceParams::New(
-          isolated_interface_provider.InitWithNewPipeAndPassReceiver(),
           mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
               .InitWithNewPipeAndPassReceiver()));
 
diff --git a/content/browser/renderer_host/navigation_controller_impl_unittest.cc b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
index 30ce9df..37e8cfd 100644
--- a/content/browser/renderer_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
@@ -1944,7 +1944,6 @@
   std::string unique_name0("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), unique_name0,
@@ -1983,7 +1982,6 @@
   std::string unique_name1("uniqueName1");
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), unique_name1,
@@ -2022,7 +2020,6 @@
   std::string unique_name2("uniqueName2");
   subframe->OnCreateChildFrame(
       process()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), unique_name2,
@@ -2079,7 +2076,6 @@
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), unique_name, false,
@@ -3053,7 +3049,6 @@
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), unique_name, false,
@@ -3203,7 +3198,6 @@
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), unique_name, false,
@@ -4260,7 +4254,6 @@
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), unique_name, false,
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 7495862d..bcc2dada 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -2722,9 +2722,13 @@
 }
 
 void NavigationRequest::OnRequestStarted(base::TimeTicks timestamp) {
-  frame_tree_node_->navigator().LogResourceRequestTime(timestamp,
-                                                       common_params_->url);
+  // Nothing to be done in production code.
+  //
+  // TODO(lukasza): Consider refactoring tests that depend on
+  // TestNavigationURLLoaderDelegate::OnRequestStarted and remove the
+  // OnRequestStarted method from NavigationURLLoaderDelegate.
 }
+
 namespace {
 
 void OnServiceWorkerAccessedThreadSafeWrapper(
diff --git a/content/browser/renderer_host/navigation_throttle_runner.cc b/content/browser/renderer_host/navigation_throttle_runner.cc
index f21b7fb0..a41b169 100644
--- a/content/browser/renderer_host/navigation_throttle_runner.cc
+++ b/content/browser/renderer_host/navigation_throttle_runner.cc
@@ -7,6 +7,7 @@
 #include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/portal/portal_navigation_throttle.h"
 #include "content/browser/renderer_host/ancestor_throttle.h"
+#include "content/browser/renderer_host/back_forward_cache_throttle.h"
 #include "content/browser/renderer_host/blocked_scheme_navigation_throttle.h"
 #include "content/browser/renderer_host/form_submission_throttle.h"
 #include "content/browser/renderer_host/http_error_navigation_throttle.h"
@@ -132,6 +133,8 @@
   // throttles handling pages with 407 errors that require extra authentication.
   AddThrottle(HttpErrorNavigationThrottle::MaybeCreateThrottleFor(*request));
 
+  AddThrottle(BackForwardCacheThrottle::MaybeCreateThrottleFor(request));
+
   // Insert all testing NavigationThrottles last.
   throttles_.insert(throttles_.end(),
                     std::make_move_iterator(testing_throttles.begin()),
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index 6c59aec..e35ae43 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -60,23 +60,17 @@
   NavigationMetricsData(base::TimeTicks start_time,
                         GURL url,
                         ukm::SourceId ukm_source_id,
-                        bool is_browser_initiated_before_unload,
-                        RestoreType restore_type)
+                        bool is_browser_initiated_before_unload)
       : start_time_(start_time),
         url_(url),
         ukm_source_id_(ukm_source_id),
         is_browser_initiated_before_unload_(
-            is_browser_initiated_before_unload) {
-    is_restoring_from_last_session_ =
-        (restore_type == RestoreType::LAST_SESSION);
-  }
+            is_browser_initiated_before_unload) {}
 
   base::TimeTicks start_time_;
   GURL url_;
   ukm::SourceId ukm_source_id_;
   bool is_browser_initiated_before_unload_;
-  bool is_restoring_from_last_session_;
-  base::TimeTicks url_job_start_time_;
   base::TimeDelta before_unload_delay_;
 
   // Timestamps before_unload_(start|end)_ give the time it took to run
@@ -447,8 +441,7 @@
 }
 
 void Navigator::Navigate(std::unique_ptr<NavigationRequest> request,
-                         ReloadType reload_type,
-                         RestoreType restore_type) {
+                         ReloadType reload_type) {
   TRACE_EVENT0("browser,navigation", "Navigator::Navigate");
   TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(
       "navigation,rail", "NavigationTiming navigationStart",
@@ -463,7 +456,7 @@
   navigation_data_ = std::make_unique<NavigationMetricsData>(
       request->common_params().navigation_start, request->common_params().url,
       frame_tree_node->current_frame_host()->GetPageUkmSourceId(),
-      true /* is_browser_initiated_before_unload */, restore_type);
+      true /* is_browser_initiated_before_unload */);
 
   // Check if the BeforeUnload event needs to execute before assigning the
   // NavigationRequest to the FrameTreeNode. Assigning it to the FrameTreeNode
@@ -761,7 +754,7 @@
       navigation_request->common_params().navigation_start,
       navigation_request->common_params().url,
       frame_tree_node->current_frame_host()->GetPageUkmSourceId(),
-      false /* is_browser_initiated_before_unload */, RestoreType::NONE);
+      false /* is_browser_initiated_before_unload */);
 
   LogRendererInitiatedBeforeUnloadTime(
       navigation_request->begin_params()->before_unload_start,
@@ -818,16 +811,6 @@
     navigation_data_.reset();
 }
 
-void Navigator::LogResourceRequestTime(base::TimeTicks timestamp,
-                                       const GURL& url) {
-  if (navigation_data_ && navigation_data_->url_ == url) {
-    navigation_data_->url_job_start_time_ = timestamp;
-    UMA_HISTOGRAM_TIMES(
-        "Navigation.TimeToURLJobStart",
-        navigation_data_->url_job_start_time_ - navigation_data_->start_time_);
-  }
-}
-
 void Navigator::LogBeforeUnloadTime(
     base::TimeTicks renderer_before_unload_start_time,
     base::TimeTicks renderer_before_unload_end_time,
@@ -912,7 +895,6 @@
   DCHECK(site_instance->HasProcess());
 
   if (!details.is_main_frame || !navigation_data_ ||
-      navigation_data_->url_job_start_time_.is_null() ||
       navigation_data_->url_ != params.original_request_url) {
     return;
   }
@@ -920,43 +902,6 @@
   ukm::builders::Unload builder(navigation_data_->ukm_source_id_);
 
   if (navigation_data_->is_browser_initiated_before_unload_) {
-    base::TimeDelta time_to_commit =
-        base::TimeTicks::Now() - navigation_data_->start_time_;
-    UMA_HISTOGRAM_TIMES("Navigation.TimeToCommit", time_to_commit);
-
-    time_to_commit -= navigation_data_->before_unload_delay_;
-    base::TimeDelta time_to_network = navigation_data_->url_job_start_time_ -
-                                      navigation_data_->start_time_ -
-                                      navigation_data_->before_unload_delay_;
-    if (navigation_data_->is_restoring_from_last_session_) {
-      UMA_HISTOGRAM_TIMES(
-          "Navigation.TimeToCommit_SessionRestored_BeforeUnloadDiscounted",
-          time_to_commit);
-      UMA_HISTOGRAM_TIMES(
-          "Navigation.TimeToURLJobStart_SessionRestored_BeforeUnloadDiscounted",
-          time_to_network);
-      navigation_data_.reset();
-      return;
-    }
-    bool navigation_created_new_renderer_process =
-        site_instance->GetProcess()->GetInitTimeForNavigationMetrics() >
-        navigation_data_->start_time_;
-    if (navigation_created_new_renderer_process) {
-      UMA_HISTOGRAM_TIMES(
-          "Navigation.TimeToCommit_NewRenderer_BeforeUnloadDiscounted",
-          time_to_commit);
-      UMA_HISTOGRAM_TIMES(
-          "Navigation.TimeToURLJobStart_NewRenderer_BeforeUnloadDiscounted",
-          time_to_network);
-    } else {
-      UMA_HISTOGRAM_TIMES(
-          "Navigation.TimeToCommit_ExistingRenderer_BeforeUnloadDiscounted",
-          time_to_commit);
-      UMA_HISTOGRAM_TIMES(
-          "Navigation.TimeToURLJobStart_ExistingRenderer_"
-          "BeforeUnloadDiscounted",
-          time_to_network);
-    }
     if (navigation_data_->before_unload_start_ &&
         navigation_data_->before_unload_end_) {
       builder.SetBeforeUnloadDuration(
diff --git a/content/browser/renderer_host/navigator.h b/content/browser/renderer_host/navigator.h
index 60b8c49..f959d4f 100644
--- a/content/browser/renderer_host/navigator.h
+++ b/content/browser/renderer_host/navigator.h
@@ -115,8 +115,7 @@
   // RendererDidNavigate on success or DiscardPendingEntry on failure. The
   // callbacks should be called in a future iteration of the message loop.
   void Navigate(std::unique_ptr<NavigationRequest> request,
-                ReloadType reload_type,
-                RestoreType restore_type);
+                ReloadType reload_type);
 
   // The RenderFrameHostImpl has received a request to open a URL with the
   // specified |disposition|.
@@ -186,13 +185,6 @@
   // Cancel a NavigationRequest for |frame_tree_node|.
   void CancelNavigation(FrameTreeNode* frame_tree_node);
 
-  // Called when the network stack started handling the navigation request
-  // so that the |timestamp| when it happened can be recorded into an histogram.
-  // The |url| is used to verify we're tracking the correct navigation.
-  // TODO(carlosk): Remove the URL parameter and rename this method to better
-  // suit naming conventions.
-  void LogResourceRequestTime(base::TimeTicks timestamp, const GURL& url);
-
   // Called to record the time it took to execute the beforeunload hook for the
   // current navigation.
   void LogBeforeUnloadTime(base::TimeTicks renderer_before_unload_start_time,
diff --git a/content/browser/renderer_host/page_lifecycle_state_manager.cc b/content/browser/renderer_host/page_lifecycle_state_manager.cc
index dc86653..e285c464 100644
--- a/content/browser/renderer_host/page_lifecycle_state_manager.cc
+++ b/content/browser/renderer_host/page_lifecycle_state_manager.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/renderer_host/page_lifecycle_state_manager.h"
 
+#include "base/callback_helpers.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/public/browser/render_process_host.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
@@ -26,6 +28,8 @@
 void PageLifecycleStateManager::TestDelegate::OnUpdateSentToRenderer(
     const blink::mojom::PageLifecycleState& new_state) {}
 
+void PageLifecycleStateManager::TestDelegate::OnDeleted() {}
+
 PageLifecycleStateManager::PageLifecycleStateManager(
     RenderViewHostImpl* render_view_host_impl,
     blink::mojom::PageVisibilityState web_contents_visibility_state)
@@ -36,7 +40,8 @@
 }
 
 PageLifecycleStateManager::~PageLifecycleStateManager() {
-  DCHECK(!test_delegate_);
+  if (test_delegate_)
+    test_delegate_->OnDeleted();
 }
 
 void PageLifecycleStateManager::SetIsFrozen(bool frozen) {
@@ -44,7 +49,8 @@
     return;
   is_set_frozen_called_ = frozen;
 
-  SendUpdatesToRendererIfNeeded(/*page_restore_params=*/nullptr);
+  SendUpdatesToRendererIfNeeded(/*page_restore_params=*/nullptr,
+                                base::NullCallback());
 }
 
 void PageLifecycleStateManager::SetWebContentsVisibility(
@@ -53,7 +59,8 @@
     return;
 
   web_contents_visibility_ = visibility;
-  SendUpdatesToRendererIfNeeded(/*page_restore_params=*/nullptr);
+  SendUpdatesToRendererIfNeeded(/*page_restore_params=*/nullptr,
+                                base::NullCallback());
   // TODO(yuzus): When a page is frozen and made visible, the page should
   // automatically resume.
 }
@@ -63,7 +70,12 @@
     blink::mojom::PageRestoreParamsPtr page_restore_params) {
   if (is_in_back_forward_cache_ == is_in_back_forward_cache)
     return;
+  // Prevent races by waiting for confirmation that the renderer will no longer
+  // evict the page before allowing it to exit the back-forward cache
+  DCHECK(is_in_back_forward_cache ||
+         !last_acknowledged_state_->eviction_enabled);
   is_in_back_forward_cache_ = is_in_back_forward_cache;
+  eviction_enabled_ = is_in_back_forward_cache;
   if (is_in_back_forward_cache) {
     // When a page is put into BackForwardCache, the page can run a busy loop.
     // Set a timeout monitor to check that the transition finishes within the
@@ -83,7 +95,8 @@
     pagehide_dispatch_ = blink::mojom::PagehideDispatch::kNotDispatched;
   }
 
-  SendUpdatesToRendererIfNeeded(std::move(page_restore_params));
+  SendUpdatesToRendererIfNeeded(std::move(page_restore_params),
+                                base::NullCallback());
 }
 
 blink::mojom::PageLifecycleStatePtr
@@ -111,14 +124,34 @@
             blink::mojom::PageVisibilityState::kHidden);
   DCHECK_NE(acknowledged_state->pagehide_dispatch,
             blink::mojom::PagehideDispatch::kNotDispatched);
-  OnPageLifecycleChangedAck(std::move(acknowledged_state));
+  OnPageLifecycleChangedAck(std::move(acknowledged_state),
+                            base::NullCallback());
+}
+
+void PageLifecycleStateManager::SetIsLeavingBackForwardCache(
+    base::OnceClosure done_cb) {
+  DCHECK(is_in_back_forward_cache_);
+  eviction_enabled_ = false;
+  SendUpdatesToRendererIfNeeded(nullptr, std::move(done_cb));
+}
+
+bool PageLifecycleStateManager::RendererExpectedToSendChannelAssociatedIpcs()
+    const {
+  // eviction_enabled_ => is_in_back_forward_cache_
+  DCHECK(!eviction_enabled_ || is_in_back_forward_cache_);
+  return !eviction_enabled_ || !last_acknowledged_state_->eviction_enabled;
 }
 
 void PageLifecycleStateManager::SendUpdatesToRendererIfNeeded(
-    blink::mojom::PageRestoreParamsPtr page_restore_params) {
+    blink::mojom::PageRestoreParamsPtr page_restore_params,
+    base::OnceClosure done_cb) {
   if (!render_view_host_impl_->GetAssociatedPageBroadcast()) {
-    // For some tests, |render_view_host_impl_| does not have the associated
-    // page.
+    // TODO(https://crbug.com/1153155): For some tests, |render_view_host_impl_|
+    // does not have the associated page.
+    if (done_cb) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                    std::move(done_cb));
+    }
     return;
   }
 
@@ -140,7 +173,8 @@
   render_view_host_impl_->GetAssociatedPageBroadcast()->SetPageLifecycleState(
       std::move(state), std::move(page_restore_params),
       base::BindOnce(&PageLifecycleStateManager::OnPageLifecycleChangedAck,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(new_state)));
+                     weak_ptr_factory_.GetWeakPtr(), std::move(new_state),
+                     std::move(done_cb)));
 }
 
 blink::mojom::PageLifecycleStatePtr
@@ -157,11 +191,13 @@
        pagehide_dispatch_ != blink::mojom::PagehideDispatch::kNotDispatched)
           ? blink::mojom::PageVisibilityState::kHidden
           : web_contents_visibility_;
+  state->eviction_enabled = eviction_enabled_;
   return state;
 }
 
 void PageLifecycleStateManager::OnPageLifecycleChangedAck(
-    blink::mojom::PageLifecycleStatePtr acknowledged_state) {
+    blink::mojom::PageLifecycleStatePtr acknowledged_state,
+    base::OnceClosure done_cb) {
   blink::mojom::PageLifecycleStatePtr old_state =
       std::move(last_acknowledged_state_);
   last_acknowledged_state_ = std::move(acknowledged_state);
@@ -174,6 +210,8 @@
     test_delegate_->OnLastAcknowledgedStateChanged(*old_state,
                                                    *last_acknowledged_state_);
   }
+  if (done_cb)
+    std::move(done_cb).Run();
 }
 
 void PageLifecycleStateManager::OnBackForwardCacheTimeout() {
diff --git a/content/browser/renderer_host/page_lifecycle_state_manager.h b/content/browser/renderer_host/page_lifecycle_state_manager.h
index 0750054..b2f1174 100644
--- a/content/browser/renderer_host/page_lifecycle_state_manager.h
+++ b/content/browser/renderer_host/page_lifecycle_state_manager.h
@@ -5,8 +5,8 @@
 #ifndef CONTENT_BROWSER_RENDERER_HOST_PAGE_LIFECYCLE_STATE_MANAGER_H_
 #define CONTENT_BROWSER_RENDERER_HOST_PAGE_LIFECYCLE_STATE_MANAGER_H_
 
+#include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
 #include "content/browser/renderer_host/input/one_shot_timeout_monitor.h"
 #include "content/common/content_export.h"
 #include "content/public/common/page_visibility_state.h"
@@ -30,6 +30,7 @@
         const blink::mojom::PageLifecycleState& new_state);
     virtual void OnUpdateSentToRenderer(
         const blink::mojom::PageLifecycleState& new_state);
+    virtual void OnDeleted();
   };
 
   explicit PageLifecycleStateManager(
@@ -43,6 +44,7 @@
   void SetIsInBackForwardCache(
       bool is_in_back_forward_cache,
       blink::mojom::PageRestoreParamsPtr page_restore_params);
+  bool IsInBackForwardCache() const { return is_in_back_forward_cache_; }
 
   // Called when we're committing main-frame same-site navigations where we did
   // a proactive BrowsingInstance swap and we're reusing the old page's renderer
@@ -67,9 +69,12 @@
     return *last_acknowledged_state_;
   }
 
-  const blink::mojom::PageLifecycleState& last_state_sent_to_renderer() const {
-    return *last_state_sent_to_renderer_;
-  }
+  void SetIsLeavingBackForwardCache(base::OnceClosure done_cb);
+
+  // Whether the renderer is expected to send channel associated IPCs related to
+  // this page. E.g. while a page is in the back-forward cache the page should
+  // be performing no work and thus not sending any IPCs.
+  bool RendererExpectedToSendChannelAssociatedIpcs() const;
 
   void SetDelegateForTesting(TestDelegate* test_delegate_);
 
@@ -77,10 +82,12 @@
   // Send mojo message to renderer if the effective (page) lifecycle state has
   // changed.
   void SendUpdatesToRendererIfNeeded(
-      blink::mojom::PageRestoreParamsPtr page_restore_params);
+      blink::mojom::PageRestoreParamsPtr page_restore_params,
+      base::OnceClosure done_cb);
 
   void OnPageLifecycleChangedAck(
-      blink::mojom::PageLifecycleStatePtr acknowledged_state);
+      blink::mojom::PageLifecycleStatePtr acknowledged_state,
+      base::OnceClosure done_cb);
   void OnBackForwardCacheTimeout();
 
   // This represents the frozen state set by |SetIsFrozen|, which corresponds to
@@ -90,6 +97,7 @@
   bool is_set_frozen_called_ = false;
 
   bool is_in_back_forward_cache_ = false;
+  bool eviction_enabled_ = false;
 
   // This represents the visibility set by |SetVisibility|, which is web
   // contents visibility state. Effective visibility, i.e. per-page visibility
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 03895b3..95451c5a 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -211,7 +211,6 @@
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/network/public/mojom/url_loader.mojom-shared.h"
 #include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "storage/browser/blob/blob_storage_context.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
@@ -411,7 +410,10 @@
  private:
   // mojo::MessageFilter overrides.
   bool WillDispatch(mojo::Message* message) override {
-    if (!IsFrameInBackForwardCache() || ProcessHoldsNonCachedPages() ||
+    if (render_frame_host_->render_view_host()
+            ->GetPageLifecycleStateManager()
+            ->RendererExpectedToSendChannelAssociatedIpcs() ||
+        ProcessHoldsNonCachedPages() ||
         policy_ == BackForwardCacheImpl::kMessagePolicyNone) {
       return true;
     }
@@ -439,17 +441,6 @@
 
   void DidDispatchOrReject(mojo::Message* message, bool accepted) override {}
 
-  // Returns true if both the renderer and the browser think the frame is in the
-  // bfcache. That is the PageLifecycleState is in sync with regards to bfcache.
-  // In the intermediate states (no ACK received yet) messages must be allowed.
-  bool IsFrameInBackForwardCache() {
-    PageLifecycleStateManager* mgr =
-        render_frame_host_->render_view_host()->GetPageLifecycleStateManager();
-
-    return mgr->last_acknowledged_state().is_in_back_forward_cache &&
-           mgr->last_state_sent_to_renderer().is_in_back_forward_cache;
-  }
-
   // TODO(https://crbug.com/1125996): Remove once a well-behaved frozen
   // RenderFrame never send IPCs messages, even if there are active pages in the
   // process.
@@ -2057,7 +2048,6 @@
   // reset.
   SetRenderFrameCreated(false);
   InvalidateMojoConnection();
-  document_scoped_interface_provider_receiver_.reset();
   broker_receiver_.reset();
   SetLastCommittedUrl(GURL());
   web_bundle_handle_.reset();
@@ -2220,11 +2210,6 @@
 
   DCHECK(GetProcess()->IsInitializedAndNotDead());
 
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      interface_provider;
-  BindInterfaceProviderReceiver(
-      interface_provider.InitWithNewPipeAndPassReceiver());
-
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   BindBrowserInterfaceBrokerReceiver(
@@ -2232,7 +2217,7 @@
 
   mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
   params->interface_bundle = mojom::DocumentScopedInterfaceBundle::New(
-      std::move(interface_provider), std::move(browser_interface_broker));
+      std::move(browser_interface_broker));
 
   params->routing_id = routing_id_;
   params->previous_routing_id = previous_routing_id;
@@ -2543,8 +2528,6 @@
 
 void RenderFrameHostImpl::OnCreateChildFrame(
     int new_routing_id,
-    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-        new_interface_provider_provider_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     mojo::PendingAssociatedReceiver<blink::mojom::PolicyContainerHost>
@@ -2560,7 +2543,6 @@
     const blink::mojom::FrameOwnerElementType owner_type) {
   // TODO(lukasza): Call ReceivedBadMessage when |frame_unique_name| is empty.
   DCHECK(!frame_unique_name.empty());
-  DCHECK(new_interface_provider_provider_receiver.is_valid());
   DCHECK(browser_interface_broker_receiver.is_valid());
   DCHECK(policy_container_host_receiver.is_valid());
   if (owner_type == blink::mojom::FrameOwnerElementType::kNone) {
@@ -2581,12 +2563,10 @@
   if (IsInactiveAndDisallowReactivation() || !render_frame_created_)
     return;
 
-  // |new_routing_id|, |new_interface_provider_provider_receiver|,
-  // |browser_interface_broker_receiver| and |devtools_frame_token| were
-  // generated on the browser's IO thread and not taken from the renderer
-  // process.
+  // |new_routing_id|, |browser_interface_broker_receiver| and
+  // |devtools_frame_token| were generated on the browser's IO thread and not
+  // taken from the renderer process.
   frame_tree_->AddFrame(this, GetProcess()->GetID(), new_routing_id,
-                        std::move(new_interface_provider_provider_receiver),
                         std::move(browser_interface_broker_receiver),
                         std::move(policy_container_host_receiver), scope,
                         frame_name, frame_unique_name, is_created_by_script,
@@ -2596,8 +2576,6 @@
 
 void RenderFrameHostImpl::CreateChildFrame(
     int new_routing_id,
-    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-        new_interface_provider_provider_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     mojo::PendingAssociatedReceiver<blink::mojom::PolicyContainerHost>
@@ -2622,8 +2600,7 @@
   // TODO(crbug.com/1145708). The interface exposed to tests should
   // match the mojo interface.
   OnCreateChildFrame(
-      new_routing_id, std::move(new_interface_provider_provider_receiver),
-      std::move(browser_interface_broker_receiver),
+      new_routing_id, std::move(browser_interface_broker_receiver),
       std::move(policy_container_host_receiver), scope, frame_name,
       frame_unique_name, is_created_by_script, frame_token,
       devtools_frame_token, frame_policy, *frame_owner_properties, owner_type);
@@ -4493,7 +4470,10 @@
 
   if (!in_back_forward_cache) {
     TRACE_EVENT0("navigation", "BackForwardCache_EvictAfterDocumentRestored");
-
+    // TODO(carlscab): We should no longer get into this branch thanks to
+    // https://crrev.com/c/2352815. Lets keep this old code for now just in case
+    // and replace with a CHECK once we are confident that is the case.
+    base::debug::DumpWithoutCrashing();
     BackForwardCacheMetrics::RecordEvictedAfterDocumentRestored(
         BackForwardCacheMetrics::EvictedAfterDocumentRestoredReason::
             kByJavaScript);
@@ -4929,17 +4909,6 @@
   delegate()->CapturePaintPreviewOfCrossProcessSubframe(clip_rect, guid, this);
 }
 
-void RenderFrameHostImpl::BindInterfaceProviderReceiver(
-    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-        interface_provider_receiver) {
-  DCHECK(!document_scoped_interface_provider_receiver_.is_bound());
-  DCHECK(interface_provider_receiver.is_valid());
-  document_scoped_interface_provider_receiver_.Bind(
-      std::move(interface_provider_receiver));
-  document_scoped_interface_provider_receiver_.SetFilter(
-      std::make_unique<ActiveURLMessageFilter>(this));
-}
-
 void RenderFrameHostImpl::BindBrowserInterfaceBrokerReceiver(
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver) {
   DCHECK(receiver.is_valid());
@@ -5246,11 +5215,6 @@
     main_frame->frame_->BlockRequests();
   }
 
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      main_frame_interface_provider_info;
-  main_frame->BindInterfaceProviderReceiver(
-      main_frame_interface_provider_info.InitWithNewPipeAndPassReceiver());
-
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   main_frame->BindBrowserInterfaceBrokerReceiver(
@@ -5309,7 +5273,6 @@
       std::move(blink_frame_widget_receiver), std::move(blink_widget_host),
       std::move(blink_widget_receiver), std::move(page_broadcast_receiver),
       mojom::DocumentScopedInterfaceBundle::New(
-          std::move(main_frame_interface_provider_info),
           std::move(browser_interface_broker)),
       cloned_namespace->id(), main_frame->GetDevToolsFrameToken(),
       wait_for_debugger,
@@ -6796,6 +6759,7 @@
       remote_interfaces;
   frame_->GetInterfaceProvider(
       remote_interfaces.InitWithNewPipeAndPassReceiver());
+
   remote_interfaces_ = std::make_unique<service_manager::InterfaceProvider>(
       base::ThreadTaskRunnerHandle::Get());
   remote_interfaces_->Bind(std::move(remote_interfaces));
@@ -7925,18 +7889,6 @@
       std::move(receiver), ComputeTopFrameOrigin(GetLastCommittedOrigin()));
 }
 
-void RenderFrameHostImpl::GetInterface(
-    const std::string& interface_name,
-    mojo::ScopedMessagePipeHandle interface_pipe) {
-  // Requests are serviced on |document_scoped_interface_provider_receiver_|. It
-  // is therefore safe to assume that every incoming interface request is coming
-  // from the currently active document in the corresponding RenderFrame.
-  // NOTE: this way of acquiring interfaces has been replaced with
-  // BrowserInterfaceBroker (see https://crbug.com/718652). The code below is
-  // left to support the CastWebContentsImpl use case.
-  delegate_->OnInterfaceRequest(this, interface_name, &interface_pipe);
-}
-
 void RenderFrameHostImpl::CreateAppCacheBackend(
     mojo::PendingReceiver<blink::mojom::AppCacheBackend> receiver) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -7991,6 +7943,12 @@
   geolocation_service_->Bind(std::move(receiver));
 }
 
+void RenderFrameHostImpl::GetDeviceInfoService(
+    mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver) {
+  GetContentClient()->browser()->CreateDeviceInfoService(this,
+                                                         std::move(receiver));
+}
+
 void RenderFrameHostImpl::GetFontAccessManager(
     mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver) {
   static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition())
@@ -9023,23 +8981,7 @@
   if (IsPendingDeletion())
     return;
 
-  // Retroactive sanity check:
-  // - If this is the first real load committing in this frame, then by this
-  //   time the RenderFrameHost's InterfaceProvider implementation should have
-  //   already been bound to a message pipe whose client end is used to service
-  //   interface requests from the initial empty document.
-  // - Otherwise, the InterfaceProvider implementation should at this point be
-  //   bound to an interface connection servicing interface requests coming from
-  //   the document of the previously committed navigation.
-  DCHECK(document_scoped_interface_provider_receiver_.is_bound());
   if (interface_params) {
-    // As a general rule, expect the RenderFrame to have supplied the
-    // receiver end of a new InterfaceProvider connection that will be used by
-    // the new document to issue interface receivers to access RenderFrameHost
-    // services.
-    document_scoped_interface_provider_receiver_.reset();
-    BindInterfaceProviderReceiver(
-        std::move(interface_params->interface_provider_receiver));
     if (broker_receiver_.is_bound()) {
       auto broker_receiver_of_previous_document = broker_receiver_.Unbind();
       dropped_interface_request_logger_ =
@@ -9052,12 +8994,12 @@
     // If there had already been a real load committed in the frame, and this is
     // not a same-document navigation, then both the active document as well as
     // the global object was replaced in this browsing context. The RenderFrame
-    // should have rebound its InterfaceProvider to a new pipe, but failed to do
-    // so. Kill the renderer, and reset the old receiver to ensure that any
-    // pending interface requests originating from the previous document, hence
-    // possibly from a different security origin, will no longer be dispatched.
+    // should have rebound its BrowserInterfaceBroker to a new pipe, but failed
+    // to do so. Kill the renderer, and reset the old receiver to ensure that
+    // any pending interface requests originating from the previous document,
+    // hence possibly from a different security origin, will no longer be
+    // dispatched.
     if (frame_tree_node_->has_committed_real_load()) {
-      document_scoped_interface_provider_receiver_.reset();
       broker_receiver_.reset();
       bad_message::ReceivedBadMessage(
           process, bad_message::RFH_INTERFACE_PROVIDER_MISSING);
@@ -9065,9 +9007,9 @@
     }
 
     // Otherwise, it is the first real load committed, for which the RenderFrame
-    // is allowed to, and will re-use the existing InterfaceProvider connection
-    // if the new document is same-origin with the initial empty document, and
-    // therefore the global object is not replaced.
+    // is allowed to, and will re-use the existing BrowserInterfaceBroker
+    // connection if the new document is same-origin with the initial empty
+    // document, and therefore the global object is not replaced.
   }
 
   if (!DidCommitNavigationInternal(std::move(request), std::move(params),
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index f30df922..872af46 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -175,6 +175,7 @@
 
 namespace mojom {
 class CacheStorage;
+class DeviceAPIService;
 class GeolocationService;
 class WebUsbService;
 }  // namespace mojom
@@ -188,6 +189,10 @@
 class ResourceRequestBody;
 }  // namespace network
 
+namespace service_manager {
+class InterfaceProvider;
+}
+
 namespace ui {
 class ClipboardFormatType;
 }
@@ -248,7 +253,6 @@
       public BrowserAccessibilityDelegate,
       public RenderProcessHostObserver,
       public SiteInstanceImpl::Observer,
-      public service_manager::mojom::InterfaceProvider,
       public blink::mojom::BackForwardCacheControllerHost,
       public blink::mojom::LocalFrameHost,
       public network::CSPContext,
@@ -515,19 +519,13 @@
   // that was partially handled on the IO thread (to allocate |new_routing_id|,
   // |frame_token| and |devtools_frame_token|), and is forwarded here. The
   // renderer has already been told to create a RenderFrame with the specified
-  // ID values. |interface_provider_receiver| is the receiver end of the
-  // InterfaceProvider interface that the RenderFrameHost corresponding to the
-  // child frame should bind to expose services to the renderer process. The
-  // caller takes care of sending down the client end of the pipe to the child
-  // RenderFrame to use. |browser_interface_broker_receiver| is the receiver end
-  // of BrowserInterfaceBroker interface in the child frame. RenderFrameHost
-  // should bind this receiver to expose services to the renderer process. The
-  // caller takes care of sending down the client end of the pipe to the child
+  // ID values. |browser_interface_broker_receiver| is the receiver end of the
+  // BrowserInterfaceBroker interface in the child frame. RenderFrameHost should
+  // bind this receiver to expose services to the renderer process. The caller
+  // takes care of sending down the client end of the pipe to the child
   // RenderFrame to use.
   void OnCreateChildFrame(
       int new_routing_id,
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider_receiver,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker_receiver,
       mojo::PendingAssociatedReceiver<blink::mojom::PolicyContainerHost>
@@ -1070,14 +1068,6 @@
     return frame_token_;
   }
 
-  // Binds the receiver end of the InterfaceProvider interface through which
-  // services provided by this RenderFrameHost are exposed to the corresponding
-  // RenderFrame. The caller is responsible for plumbing the client end to the
-  // renderer process.
-  void BindInterfaceProviderReceiver(
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider_receiver);
-
   // Binds the receiver end of the BrowserInterfaceBroker interface through
   // which services provided by this RenderFrameHost are exposed to the
   // corresponding RenderFrame. The caller is responsible for plumbing the
@@ -1332,6 +1322,9 @@
   void GetGeolocationService(
       mojo::PendingReceiver<blink::mojom::GeolocationService> receiver);
 
+  void GetDeviceInfoService(
+      mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver);
+
   void GetFontAccessManager(
       mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver);
 
@@ -2056,8 +2049,6 @@
       override;
   void CreateChildFrame(
       int new_routing_id,
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider_receiver,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker_receiver,
       mojo::PendingAssociatedReceiver<blink::mojom::PolicyContainerHost>
@@ -2276,10 +2267,6 @@
       mojo::PendingReceiver<blink::mojom::Authenticator> receiver);
 #endif
 
-  // service_manager::mojom::InterfaceProvider:
-  void GetInterface(const std::string& interface_name,
-                    mojo::ScopedMessagePipeHandle interface_pipe) override;
-
   // Allows tests to disable the unload event timer to simulate bugs that
   // happen before it fires (to avoid flakiness).
   void DisableUnloadTimerForTesting();
@@ -2967,41 +2954,6 @@
   std::unique_ptr<JavaInterfaceProvider> java_interface_registry_;
 #endif
 
-  // Binding for the InterfaceProvider through which this RenderFrameHostImpl
-  // exposes frame-scoped Mojo services to the currently active document in the
-  // corresponding RenderFrame.
-  //
-  // GetInterface messages dispatched through this binding are guaranteed to
-  // originate from the document corresponding to the last committed navigation;
-  // or the initial empty document if no real navigation has ever been
-  // committed.
-  //
-  // The InterfaceProvider interface connection is established as follows:
-  //
-  // 1) For the initial empty document, the call site that creates this
-  //    RenderFrameHost is responsible for creating a message pipe, binding its
-  //    receiver end to this instance by calling
-  //    BindInterfaceProviderReceiver(), and plumbing the client end to the
-  //    renderer process, and ultimately supplying it to the RenderFrame
-  //    synchronously at construction time.
-  //
-  //    The only exception to this rule are out-of-process child frames, whose
-  //    RenderFrameHosts take care of this internally in CreateRenderFrame().
-  //
-  // 2) For subsequent documents, the RenderFrame creates a new message pipe
-  //    every time a cross-document navigation is committed, and pushes its
-  //    request end to the browser process as part of DidCommitProvisionalLoad.
-  //    The client end will be used by the new document corresponding to the
-  //    committed naviagation to access services exposed by the RenderFrameHost.
-  //
-  // This is required to prevent GetInterface messages racing with navigation
-  // commit from being serviced in the security context corresponding to the
-  // wrong document in the RenderFrame. The benefit of the approach taken is
-  // that it does not necessitate using channel-associated InterfaceProvider
-  // interfaces.
-  mojo::Receiver<service_manager::mojom::InterfaceProvider>
-      document_scoped_interface_provider_receiver_{this};
-
   // BrowserInterfaceBroker implementation through which this
   // RenderFrameHostImpl exposes document-scoped Mojo services to the currently
   // active document in the corresponding RenderFrame.
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 1772e14..f020be4 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -2160,7 +2160,10 @@
 
   // If we are asked to return a related SiteInstance but the BrowsingInstance
   // has a different cross_origin_isolated state, something went wrong.
-  CHECK(descriptor.relation != SiteInstanceRelation::RELATED ||
+  // This can be wrong for speculative frames, as the COOP mismatch mechanic has
+  // not yet been invoked.
+  CHECK(is_speculative ||
+        descriptor.relation != SiteInstanceRelation::RELATED ||
         current_instance->IsCoopCoepCrossOriginIsolated() ==
             descriptor.cross_origin_isolated_info.is_isolated());
 
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
index 9a2d6c0..aca47d7 100644
--- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -1810,7 +1810,6 @@
   contents()->NavigateAndCommit(kUrlA);
   contents()->GetMainFrame()->OnCreateChildFrame(
       contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "frame_name", "uniqueName1",
@@ -1818,7 +1817,6 @@
       blink::FramePolicy(), blink::mojom::FrameOwnerProperties(), kOwnerType);
   contents()->GetMainFrame()->OnCreateChildFrame(
       contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "frame_name", "uniqueName2",
@@ -1976,7 +1974,6 @@
   // |contents1| creates an out of process iframe.
   contents1->GetMainFrame()->OnCreateChildFrame(
       contents1->GetMainFrame()->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "frame_name", "uniqueName1",
@@ -2028,7 +2025,6 @@
   EXPECT_TRUE(main_rfh->IsRenderFrameLive());
   main_rfh->OnCreateChildFrame(
       main_rfh->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName1",
@@ -2238,7 +2234,6 @@
   constexpr auto kOwnerType = blink::mojom::FrameOwnerElementType::kIframe;
   tree1->AddFrame(
       root1->current_frame_host(), process_id, 12,
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       mojo::NullAssociatedReceiver(), blink::mojom::TreeScopeType::kDocument,
       std::string(), "uniqueName0", false, base::UnguessableToken::Create(),
@@ -2246,7 +2241,6 @@
       blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   tree1->AddFrame(
       root1->current_frame_host(), process_id, 13,
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       mojo::NullAssociatedReceiver(), blink::mojom::TreeScopeType::kDocument,
       std::string(), "uniqueName1", false, base::UnguessableToken::Create(),
@@ -2261,7 +2255,6 @@
   process_id = root2->current_frame_host()->GetProcess()->GetID();
   tree2->AddFrame(
       root2->current_frame_host(), process_id, 22,
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       mojo::NullAssociatedReceiver(), blink::mojom::TreeScopeType::kDocument,
       std::string(), "uniqueName2", false, base::UnguessableToken::Create(),
@@ -2269,7 +2262,6 @@
       blink::mojom::FrameOwnerProperties(), false, kOwnerType);
   tree2->AddFrame(
       root2->current_frame_host(), process_id, 23,
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       mojo::NullAssociatedReceiver(), blink::mojom::TreeScopeType::kDocument,
       std::string(), "uniqueName3", false, base::UnguessableToken::Create(),
@@ -2289,7 +2281,6 @@
   process_id = root4->current_frame_host()->GetProcess()->GetID();
   tree4->AddFrame(
       root4->current_frame_host(), process_id, 42,
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       mojo::NullAssociatedReceiver(), blink::mojom::TreeScopeType::kDocument,
       std::string(), "uniqueName4", false, base::UnguessableToken::Create(),
@@ -2358,7 +2349,6 @@
   contents()->NavigateAndCommit(kUrlA);
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "frame1", "uniqueName1", false,
@@ -2366,7 +2356,6 @@
       blink::FramePolicy(), blink::mojom::FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "frame2", "uniqueName2", false,
@@ -2374,7 +2363,6 @@
       blink::FramePolicy(), blink::mojom::FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "frame3", "uniqueName3", false,
@@ -2482,7 +2470,6 @@
   contents()->NavigateAndCommit(kUrlA);
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "frame1", "uniqueName1", false,
@@ -3034,7 +3021,6 @@
   // Create a child frame and navigate it cross-site.
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, "frame1", "uniqueName1", false,
diff --git a/content/browser/renderer_host/render_process_host_unittest.cc b/content/browser/renderer_host/render_process_host_unittest.cc
index 2919fa3f..50cd83d 100644
--- a/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/content/browser/renderer_host/render_process_host_unittest.cc
@@ -155,7 +155,6 @@
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
-      TestRenderFrameHost::CreateStubInterfaceProviderReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, std::string(), unique_name, false,
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index d50a4f5..53f1b8a 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -13,6 +13,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/command_line.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/feature_list.h"
@@ -437,9 +438,6 @@
         main_rfh->GetRenderWidgetHost()->GetRoutingID();
     params->main_frame_interface_bundle =
         mojom::DocumentScopedInterfaceBundle::New();
-    main_rfh->BindInterfaceProviderReceiver(
-        params->main_frame_interface_bundle->interface_provider
-            .InitWithNewPipeAndPassReceiver());
     main_rfh->BindBrowserInterfaceBrokerReceiver(
         params->main_frame_interface_bundle->browser_interface_broker
             .InitWithNewPipeAndPassReceiver());
@@ -537,6 +535,12 @@
       is_in_back_forward_cache_, /*page_restore_params=*/nullptr);
 }
 
+void RenderViewHostImpl::PrepareToLeaveBackForwardCache(
+    base::OnceClosure done_cb) {
+  page_lifecycle_state_manager_->SetIsLeavingBackForwardCache(
+      std::move(done_cb));
+}
+
 void RenderViewHostImpl::LeaveBackForwardCache(
     blink::mojom::PageRestoreParamsPtr page_restore_params) {
   TRACE_EVENT0("navigation", "RenderViewHostImpl::LeaveBackForwardCache");
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 98cc9b0a..5a95c4b3 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -307,6 +307,14 @@
   const mojo::AssociatedRemote<blink::mojom::PageBroadcast>&
   GetAssociatedPageBroadcast();
 
+  // Prepares the renderer page to leave the back-forward cache by disabling
+  // Javascript eviction. |done_cb| is called upon receipt of the
+  // acknowledgement from the renderer that this has actually happened.
+  //
+  // After |done_cb| is called you can be certain that this renderer will not
+  // trigger an eviction of this page.
+  void PrepareToLeaveBackForwardCache(base::OnceClosure done_cb);
+
   // NOTE: Do not add functions that just send an IPC message that are called in
   // one or two places. Have the caller send the IPC message directly (unless
   // the caller places are in different platforms, in which case it's better
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 328c8995..9dd9ce89 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -618,12 +618,9 @@
   params->origin = url::Origin::Create(GURL("about:blank"));
   params->embedding_token = base::UnguessableToken::Create();
   RenderProcessHostBadIpcMessageWaiter kill_waiter(rfh->GetProcess());
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      isolated_interface_provider;
   static_cast<mojom::FrameHost*>(rfh)->DidCommitProvisionalLoad(
       std::move(params),
       mojom::DidCommitProvisionalLoadInterfaceParams::New(
-          isolated_interface_provider.InitWithNewPipeAndPassReceiver(),
           mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
               .InitWithNewPipeAndPassReceiver()));
 
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index ed55bbd..79741f4 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -6325,8 +6325,6 @@
     mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
     params->routing_id = frame_routing_id;
     params->interface_bundle = mojom::DocumentScopedInterfaceBundle::New();
-    ignore_result(params->interface_bundle->interface_provider
-                      .InitWithNewPipeAndPassReceiver());
     ignore_result(params->interface_bundle->browser_interface_broker
                       .InitWithNewPipeAndPassReceiver());
     params->previous_routing_id = previous_routing_id;
@@ -6406,8 +6404,6 @@
     mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
     params->routing_id = frame_routing_id;
     params->interface_bundle = mojom::DocumentScopedInterfaceBundle::New();
-    ignore_result(params->interface_bundle->interface_provider
-                      .InitWithNewPipeAndPassReceiver());
     ignore_result(params->interface_bundle->browser_interface_broker
                       .InitWithNewPipeAndPassReceiver());
     params->previous_routing_id = IPC::mojom::kRoutingIdNone;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index bbf242f..6ed7d2e 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -50,7 +50,7 @@
 #include "components/rappor/public/rappor_utils.h"
 #include "components/url_formatter/url_formatter.h"
 #include "content/browser/accessibility/accessibility_event_recorder.h"
-#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
+#include "content/browser/accessibility/browser_accessibility.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
@@ -4018,8 +4018,13 @@
   OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::DumpAccessibilityTree");
   auto* ax_mgr = GetOrCreateRootBrowserAccessibilityManager();
   DCHECK(ax_mgr);
-  return AccessibilityTreeFormatterBase::DumpAccessibilityTreeFromManager(
-      ax_mgr, internal, property_filters);
+
+  std::unique_ptr<ui::AXTreeFormatter> formatter =
+      internal ? AXInspectFactory::CreateBlinkFormatter()
+               : AXInspectFactory::CreatePlatformFormatter();
+
+  formatter->SetPropertyFilters(property_filters);
+  return formatter->Format(ax_mgr->GetRoot());
 }
 
 void WebContentsImpl::RecordAccessibilityEvents(
diff --git a/content/common/cursors/webcursor_ozone.cc b/content/common/cursors/webcursor_ozone.cc
index e927bca..114a42c 100644
--- a/content/common/cursors/webcursor_ozone.cc
+++ b/content/common/cursors/webcursor_ozone.cc
@@ -32,10 +32,12 @@
       maximum_cursor_size_ == display.maximum_cursor_size())
     return;
   device_scale_factor_ = display.device_scale_factor();
+#if defined(OS_CHROMEOS)
   // The cursor should use the panel's physical rotation instead of
   // rotation. They can be different on ChromeOS but the same on
   // other platforms.
   rotation_ = display.panel_rotation();
+#endif
   maximum_cursor_size_ = display.maximum_cursor_size();
   // TODO(oshima): Identify if it's possible to remove this check here and move
   // the kDefaultMaxSize constants to a single place. crbug.com/603512
diff --git a/content/common/cursors/webcursor_unittest.cc b/content/common/cursors/webcursor_unittest.cc
index 5073af76..cc71373 100644
--- a/content/common/cursors/webcursor_unittest.cc
+++ b/content/common/cursors/webcursor_unittest.cc
@@ -62,15 +62,23 @@
 #if defined(USE_OZONE)
   // Test if the rotating custom cursor works correctly.
   display::Display display;
+#if defined(OS_CHROMEOS)
   display.set_panel_rotation(display::Display::ROTATE_90);
+#endif
   webcursor.SetDisplayInfo(display);
   EXPECT_FALSE(webcursor.has_custom_cursor_for_test());
   native_cursor = webcursor.GetNativeCursor();
   EXPECT_TRUE(webcursor.has_custom_cursor_for_test());
+#if defined(OS_CHROMEOS)
   // Hotspot should be scaled & rotated.  We're using the icon created for 2.0,
   // on the display with dsf=1.0, so the host spot should be
   // ((32 - 20) / 2, 10 / 2) = (6, 5).
   EXPECT_EQ(gfx::Point(6, 5), native_cursor.custom_hotspot());
+#else
+  // For non-CrOS platforms, the cursor mustn't be rotated as logical and
+  // physical location is the same.
+  EXPECT_EQ(gfx::Point(5, 10), native_cursor.custom_hotspot());
+#endif
 #endif
 #endif
 }
diff --git a/content/common/document_scoped_interface_bundle.mojom b/content/common/document_scoped_interface_bundle.mojom
index c7f12a9..b67d3e3d 100644
--- a/content/common/document_scoped_interface_bundle.mojom
+++ b/content/common/document_scoped_interface_bundle.mojom
@@ -4,14 +4,9 @@
 
 module content.mojom;
 
-import "services/service_manager/public/mojom/interface_provider.mojom";
 import "third_party/blink/public/mojom/browser_interface_broker.mojom";
 
 struct DocumentScopedInterfaceBundle {
-  // The InterfaceProvider through which the main RenderFrame can access
-  // services exposed by its RenderFrameHost.
-  pending_remote<service_manager.mojom.InterfaceProvider> interface_provider;
-
   // The BrowserInterfaceBroker through which the RenderFrame can access
   // interfaces exposed by its RenderFrameHost.
   // It will eventually replace interface_provider above and become the
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 88cbc26..5cb80e6 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -56,10 +56,6 @@
 [Native]
 struct PageState;
 
-// The name of the InterfaceProviderSpec in service manifests used by the
-// frame tree to expose frame-specific interfaces between renderer and browser.
-const string kNavigation_FrameSpec = "navigation:frame";
-
 // Provided with each call to Frame::GetSerializedHtmlWithLocalLinks() so that
 // the renderer can notify the browser process each time that a chunk of HTML
 // data gets serialized, as well as when the entire process is finished.
@@ -434,8 +430,6 @@
   // Each of these messages will have a corresponding mojom::FrameHost::Detach
   // API sent when the frame is detached from the DOM.
   CreateChildFrame(int32 child_routing_id,
-                   pending_receiver<service_manager.mojom.InterfaceProvider>
-                     new_interface_provider,
                    pending_receiver<blink.mojom.BrowserInterfaceBroker>
                      browser_interface_broker,
                    pending_associated_receiver<blink.mojom.PolicyContainerHost>
@@ -451,18 +445,18 @@
   // Sent by the renderer when a navigation commits in the frame.
 
   // If |interface_params| is non-empty, the FrameHost implementation
-  // must unbind the old InterfaceProvider and BrowserInterfaceBroker
-  // connections, and drop any interface requests pending on them.
-  // Then it should bind the appropriate requests and start servicing
-  // GetInterface messages coming in on these new connections
-  // in a security context that is appropriate for the committed navigation.
+  // must unbind the old BrowserInterfaceBroker connections, and drop any
+  // interface requests pending on them. Then it should bind the appropriate
+  // requests and start servicing GetInterface messages coming in on these new
+  // connections in a security context that is appropriate for the committed
+  // navigation.
   //
   // The FrameHost implementation must enforce that |interface_params|
   // is set for cross-document navigations. This prevents origin confusion by
   // ensuring that interface requests racing with navigation commit will be
   // either ignored, or serviced correctly in the security context of the
-  // document they originated from (based on which InterfaceProvider or
-  // BrowserInterfaceBroker connection the GetInterface messages arrive on).
+  // document they originated from (based on which BrowserInterfaceBroker
+  // connection the GetInterface messages arrive on).
   DidCommitProvisionalLoad(
       DidCommitProvisionalLoadParams params,
       DidCommitProvisionalLoadInterfaceParams? interface_params);
diff --git a/content/common/frame_messages.mojom b/content/common/frame_messages.mojom
index 0dcf5dc8..742f3da3 100644
--- a/content/common/frame_messages.mojom
+++ b/content/common/frame_messages.mojom
@@ -8,8 +8,6 @@
 import "third_party/blink/public/mojom/browser_interface_broker.mojom";
 
 struct DidCommitProvisionalLoadInterfaceParams {
-  pending_receiver<service_manager.mojom.InterfaceProvider>
-      interface_provider_receiver;
   pending_receiver<blink.mojom.BrowserInterfaceBroker>
       browser_interface_broker_receiver;
 };
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc
index f4f6a01..36a3437 100644
--- a/content/ppapi_plugin/ppapi_thread.cc
+++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -100,7 +100,7 @@
         manager_remote;
     ChildThread::Get()->BindHostReceiver(
         manager_remote.InitWithNewPipeAndPassReceiver());
-    discardable_shared_memory_manager_ = std::make_unique<
+    discardable_shared_memory_manager_ = base::MakeRefCounted<
         discardable_memory::ClientDiscardableSharedMemoryManager>(
         std::move(manager_remote), GetIOTaskRunner());
     base::DiscardableMemoryAllocator::SetInstance(
diff --git a/content/ppapi_plugin/ppapi_thread.h b/content/ppapi_plugin/ppapi_thread.h
index ae059e2..a631431 100644
--- a/content/ppapi_plugin/ppapi_thread.h
+++ b/content/ppapi_plugin/ppapi_thread.h
@@ -138,7 +138,7 @@
   // The BlinkPlatformImpl implementation.
   std::unique_ptr<PpapiBlinkPlatformImpl> blink_platform_impl_;
 
-  std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+  scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
       discardable_shared_memory_manager_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(PpapiThread);
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
index f466b36..025c76a 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -1355,7 +1355,12 @@
 
     @CalledByNative
     private void announceLiveRegionText(String text) {
-        mView.announceForAccessibility(text);
+        AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_ANNOUNCEMENT);
+        if (event == null || mView.getParent() == null) return;
+
+        event.getText().add(text);
+        event.setContentDescription(null);
+        mView.getParent().requestSendAccessibilityEvent(mView, event);
     }
 
     @CalledByNative
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
index 2bcbec3..604e2cc 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -49,6 +49,11 @@
  */
 @RunWith(BaseJUnit4ClassRunner.class)
 public class WebContentsAccessibilityTest {
+    // Test output error messages
+    private static final String TIMEOUT_ERROR =
+            "TYPE_ANNOUNCEMENT event not received before timeout.";
+    private static final String COMBOBOX_ERROR = "expanded combobox announcement was incorrect.";
+
     private interface AccessibilityNodeInfoMatcher {
         public boolean matches(AccessibilityNodeInfo node);
     }
@@ -61,6 +66,14 @@
         public int value;
     }
 
+    private static class MutableString {
+        public MutableString(String initialValue) {
+            value = initialValue;
+        }
+
+        public String value;
+    }
+
     // Constant from AccessibilityNodeInfo defined in the L SDK.
     private static final int ACTION_SET_TEXT = 0x200000;
 
@@ -74,6 +87,9 @@
     private MutableInt mSelectionFromIndex = new MutableInt(-1);
     private MutableInt mSelectionToIndex = new MutableInt(-1);
 
+    // Member variables used during unit tests involving comboboxes
+    private MutableString mComboboxText = new MutableString("");
+
     @Rule
     public ContentShellActivityTestRule mActivityTestRule = new ContentShellActivityTestRule();
 
@@ -278,6 +294,29 @@
     }
 
     /**
+     * Helper method to build a web page with a combobox and return virtualViewId
+     *
+     * @param fileLocation String           location of html file to open
+     * @return int                          virtualViewId of the combobox identified
+     */
+    private int buildWebPageWithComobobox(String fileLocation) {
+        // Load a simple page with a combobox
+        mActivityTestRule.launchContentShellWithUrl(UrlUtils.getIsolatedTestFileUrl(fileLocation));
+        mActivityTestRule.waitForActiveShellToBeDoneLoading();
+        mNodeProvider = enableAccessibilityAndWaitForNodeProvider();
+
+        // Find a node in the accessibility tree with input type TYPE_CLASS_TEXT.
+        int inputFieldVirtualViewId =
+                waitForNodeWithClassName(mNodeProvider, "android.widget.EditText");
+        mNodeInfo = mNodeProvider.createAccessibilityNodeInfo(inputFieldVirtualViewId);
+
+        // Assert we have got the correct node.
+        Assert.assertNotEquals(mNodeInfo, null);
+
+        return inputFieldVirtualViewId;
+    }
+
+    /**
      * Helper method to set up delegates on an edit text for testing. This is used in the tests
      * below that check our accessibility events are properly indexed. The editTextVirtualViewId
      * parameter should be the value returned from buildWebPageWithEditText
@@ -329,6 +368,47 @@
     }
 
     /**
+     * Helper method to set delegates on a combobox for testing. This is used in the tests below
+     * that check user actions trigger TYPE_ANNOUNCEMENT events. The comboboxVirtualViewId param
+     * should be the value returned from buildWebPageWithComobobox.
+     * @param comboboxVirtualViewId int     virtualViewId of the combobox to setup delegates on
+     * @throws Throwable Error
+     */
+    private void focusComboboxAndGetAnnouncement(int comboboxVirtualViewId) throws Throwable {
+        // Add an accessibility delegate to capture TYPE_ANNOUNCEMENT events and store their text.
+        // The delegate is set on the parent as WebContentsAccessibilityImpl sends events using the
+        // parent.
+        ((ViewGroup) mActivityTestRule.getContainerView().getParent())
+                .setAccessibilityDelegate(new View.AccessibilityDelegate() {
+                    @Override
+                    public boolean onRequestSendAccessibilityEvent(
+                            ViewGroup host, View child, AccessibilityEvent event) {
+                        if (event.getEventType() == AccessibilityEvent.TYPE_ANNOUNCEMENT) {
+                            mComboboxText.value = event.getText().get(0).toString();
+                        }
+                        // Return false so that an accessibility event is not actually sent.
+                        return false;
+                    }
+                });
+
+        // Focus our field
+        boolean result1 = performActionOnUiThread(
+                comboboxVirtualViewId, AccessibilityNodeInfo.ACTION_FOCUS, null);
+        boolean result2 = performActionOnUiThread(
+                comboboxVirtualViewId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+
+        // Assert all actions are performed successfully.
+        Assert.assertTrue(result1);
+        Assert.assertTrue(result2);
+
+        while (!mNodeInfo.isFocused() || !mNodeInfo.isAccessibilityFocused()) {
+            Thread.sleep(100);
+            mNodeInfo.recycle();
+            mNodeInfo = mNodeProvider.createAccessibilityNodeInfo(comboboxVirtualViewId);
+        }
+    }
+
+    /**
      * Helper method to refresh the |mNodeInfo| object by recycling, waiting 1 sec, then refresh.
      */
     private void refreshMNodeInfo(int virtualViewId) throws InterruptedException {
@@ -348,6 +428,81 @@
         mTraverseToIndex.value = -1;
         mSelectionFromIndex.value = -1;
         mSelectionToIndex.value = -1;
+
+        mComboboxText.value = "";
+    }
+
+    /**
+     * Helper method for executing a given JS method for the current web contents.
+     */
+    private void executeJS(String method) {
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> mActivityTestRule.getWebContents().evaluateJavaScriptForTests(method, null));
+    }
+
+    /**
+     * Ensure we send an announcement on combobox expansion.
+     */
+    @Test
+    @MediumTest
+    public void testEventText_Combobox() throws Throwable {
+        // Build a simple web page with a combobox, and focus the input field.
+        int comboboxVirtualViewId =
+                buildWebPageWithComobobox("content/test/data/android/input/input_combobox.html");
+        focusComboboxAndGetAnnouncement(comboboxVirtualViewId);
+
+        // Run JS code to expand the combobox
+        executeJS("expandCombobox()");
+
+        // We should receive a TYPE_ANNOUNCEMENT event, but it may take a moment.
+        CriteriaHelper.pollUiThread(() -> !mComboboxText.value.isEmpty(), TIMEOUT_ERROR);
+
+        // Check announcement text.
+        Assert.assertEquals(
+                COMBOBOX_ERROR, "expanded, 3 autocomplete options available.", mComboboxText.value);
+    }
+
+    /**
+     * Ensure we send an announcement on combobox expansion that opens a dialog.
+     */
+    @Test
+    @MediumTest
+    public void testEventText_Combobox_dialog() throws Throwable {
+        // Build a simple web page with a combobox, and focus the input field.
+        int comboboxVirtualViewId = buildWebPageWithComobobox(
+                "content/test/data/android/input/input_combobox_dialog.html");
+        focusComboboxAndGetAnnouncement(comboboxVirtualViewId);
+
+        // Run JS code to expand the combobox
+        executeJS("expandCombobox()");
+
+        // We should receive a TYPE_ANNOUNCEMENT event, but it may take a moment.
+        CriteriaHelper.pollUiThread(() -> !mComboboxText.value.isEmpty(), TIMEOUT_ERROR);
+
+        // Check announcement text.
+        Assert.assertEquals(COMBOBOX_ERROR, "expanded, dialog opened.", mComboboxText.value);
+    }
+
+    /**
+     * Ensure we send an announcement on combobox expansion with aria-1.0 spec.
+     */
+    @Test
+    @MediumTest
+    public void testEventText_Combobox_ariaOne() throws Throwable {
+        // Build a simple web page with a combobox, and focus the input field.
+        int comboboxVirtualViewId = buildWebPageWithComobobox(
+                "content/test/data/android/input/input_combobox_aria1.0.html");
+        focusComboboxAndGetAnnouncement(comboboxVirtualViewId);
+
+        // Run JS code to expand the combobox
+        executeJS("expandCombobox()");
+
+        // We should receive a TYPE_ANNOUNCEMENT event, but it may take a moment.
+        CriteriaHelper.pollUiThread(() -> !mComboboxText.value.isEmpty(), TIMEOUT_ERROR);
+
+        // Check announcement text.
+        Assert.assertEquals(
+                COMBOBOX_ERROR, "expanded, 3 autocomplete options available.", mComboboxText.value);
     }
 
     /**
diff --git a/content/public/browser/ax_inspect_factory.cc b/content/public/browser/ax_inspect_factory.cc
index b1881d1..589e945 100644
--- a/content/public/browser/ax_inspect_factory.cc
+++ b/content/public/browser/ax_inspect_factory.cc
@@ -9,7 +9,26 @@
 namespace content {
 
 std::unique_ptr<ui::AXTreeFormatter> AXInspectFactory::CreateBlinkFormatter() {
-  return std::make_unique<AccessibilityTreeFormatterBlink>();
+  return CreateFormatter(kBlink);
+}
+
+AXInspectFactory::Type::operator std::string() const {
+  switch (type_) {
+    case kAndroid:
+      return "android";
+    case kBlink:
+      return "blink";
+    case kMac:
+      return "mac";
+    case kLinux:
+      return "linux";
+    case kWinIA2:
+      return "win";
+    case kWinUIA:
+      return "uia";
+    default:
+      return "unknown";
+  }
 }
 
 }  // namespace content
diff --git a/content/public/browser/ax_inspect_factory.h b/content/public/browser/ax_inspect_factory.h
index 707a52b3..eb0ff7bd 100644
--- a/content/public/browser/ax_inspect_factory.h
+++ b/content/public/browser/ax_inspect_factory.h
@@ -28,20 +28,31 @@
   // Creates the internal accessibility tree formatter, AKA the Blink tree
   // formatter, which is used to dump the Blink accessibility tree to a string
   static std::unique_ptr<ui::AXTreeFormatter> CreateBlinkFormatter();
-};
 
-// A helper class used to instantiate platform-specific accessibility
-// tree formatters.
-class CONTENT_EXPORT AccessibilityTreeFormatter : public ui::AXTreeFormatter {
- public:
-  // Get a set of factory methods to create tree-formatters, one for each test
-  // pass; see |DumpAccessibilityTestBase|.
-  using FormatterFactory = std::unique_ptr<ui::AXTreeFormatter> (*)();
-  struct TestPass {
-    const char* name;
-    FormatterFactory create_formatter;
+  // Inspect types for all platforms.
+  enum TypeConstant {
+    kAndroid,
+    kBlink,
+    kMac,
+    kLinux,
+    kWinIA2,
+    kWinUIA,
   };
-  static std::vector<TestPass> GetTestPasses();
+
+  // Inspect type.
+  class CONTENT_EXPORT Type final {
+   public:
+    Type(TypeConstant type) : type_(type) {}
+
+    explicit operator std::string() const;
+    operator TypeConstant() const { return type_; }
+
+   private:
+    TypeConstant type_;
+  };
+
+  // Creates a tree formatter of a given inspect type if supported by platform.
+  static std::unique_ptr<ui::AXTreeFormatter> CreateFormatter(Type);
 };
 
 }  // namespace content
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index d108726..8aa1b194 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -859,6 +859,10 @@
     RenderFrameHost* render_frame_host,
     mojo::PendingReceiver<blink::mojom::WebUsbService> receiver) {}
 
+void ContentBrowserClient::CreateDeviceInfoService(
+    RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver) {}
+
 #if !defined(OS_ANDROID)
 SerialDelegate* ContentBrowserClient::GetSerialDelegate() {
   return nullptr;
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index ea9b1324..4cdd98db 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -84,6 +84,7 @@
 
 namespace blink {
 namespace mojom {
+class DeviceAPIService;
 class BadgeService;
 class RendererPreferenceWatcher;
 class WebUsbService;
@@ -1531,6 +1532,10 @@
       RenderFrameHost* render_frame_host,
       mojo::PendingReceiver<blink::mojom::WebUsbService> receiver);
 
+  virtual void CreateDeviceInfoService(
+      RenderFrameHost* render_frame_host,
+      mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver);
+
 #if !defined(OS_ANDROID)
   // Allows the embedder to provide an implementation of the Serial API.
   virtual SerialDelegate* GetSerialDelegate();
diff --git a/content/public/browser/permission_type.cc b/content/public/browser/permission_type.cc
index f39b27b7..ffb0d9f 100644
--- a/content/public/browser/permission_type.cc
+++ b/content/public/browser/permission_type.cc
@@ -22,7 +22,7 @@
         std::vector<PermissionType> all_types;
         all_types.reserve(NUM_TYPES - 4);
         for (int i = 1; i < NUM_TYPES; ++i) {
-          if (i == 2 || i == 14 || i == 15)  // Skip removed entries.
+          if (i == 2 || i == 11 || i == 14 || i == 15)  // Skip removed entries.
             continue;
           all_types.push_back(static_cast<PermissionType>(i));
         }
diff --git a/content/public/browser/permission_type.h b/content/public/browser/permission_type.h
index f0d17e4..225da95 100644
--- a/content/public/browser/permission_type.h
+++ b/content/public/browser/permission_type.h
@@ -15,8 +15,8 @@
 
 // This enum is also used for UMA purposes, so it needs to adhere to
 // the UMA guidelines.
-// Make sure you update enums.xml and GetAllPermissionTypes if you add
-// new permission types.
+// Make sure you update enums.xml and GetAllPermissionTypes if you add new
+// or deprecate permission types.
 // Never delete or reorder an entry; only add new entries
 // immediately before PermissionType::NUM
 enum class PermissionType {
@@ -30,7 +30,7 @@
   AUDIO_CAPTURE = 8,
   VIDEO_CAPTURE = 9,
   BACKGROUND_SYNC = 10,
-  FLASH = 11,
+  // FLASH = 11,
   SENSORS = 12,
   ACCESSIBILITY_EVENTS = 13,
   // CLIPBOARD_READ = 14, // Replaced by CLIPBOARD_READ_WRITE in M81.
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index f69bc5c..ed1eba9 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -191,6 +191,11 @@
 const base::Feature kDocumentPolicyNegotiation{
     "DocumentPolicyNegotiation", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Requires documents embedded via <iframe>, etc, to explicitly opt-into the
+// embedding: https://github.com/mikewest/embedding-requires-opt-in.
+const base::Feature kEmbeddingRequiresOptIn{"EmbeddingRequiresOptIn",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables new canvas 2d api features. Enabled either with either
 // enable-experimental-canvas-features or new-canvas-2d-api runtime flags
 const base::Feature kEnableNewCanvas2DAPI{"EnableNewCanvas2DAPI",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 9940f38..676c765a 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -50,6 +50,7 @@
 CONTENT_EXPORT extern const base::Feature kDesktopCaptureChangeSource;
 CONTENT_EXPORT extern const base::Feature kDocumentPolicy;
 CONTENT_EXPORT extern const base::Feature kDocumentPolicyNegotiation;
+CONTENT_EXPORT extern const base::Feature kEmbeddingRequiresOptIn;
 CONTENT_EXPORT extern const base::Feature kEnableNewCanvas2DAPI;
 CONTENT_EXPORT extern const base::Feature kEnumerateDevicesHideDeviceIDs;
 CONTENT_EXPORT extern const base::Feature kExperimentalAccessibilityLabels;
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index 70c50f555..d49cdad 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -55,10 +55,6 @@
 class SharedURLLoaderFactory;
 }  // namespace network
 
-namespace service_manager {
-class InterfaceProvider;
-}  // namespace service_manager
-
 namespace content {
 
 class ContextMenuClient;
@@ -188,11 +184,6 @@
       const std::string& interface_name,
       mojo::ScopedMessagePipeHandle interface_pipe) = 0;
 
-  // DEPRECATED. Please use GetBrowserInterfaceBroker() instead.
-  // Returns the InterfaceProvider that this process can use to bind
-  // interfaces exposed to it by the application running in this frame.
-  virtual service_manager::InterfaceProvider* GetRemoteInterfaces() = 0;
-
   // Returns the BrowserInterfaceBrokerProxy that this process can use to bind
   // interfaces exposed to it by the application running in this frame.
   virtual blink::BrowserInterfaceBrokerProxy* GetBrowserInterfaceBroker() = 0;
diff --git a/content/public/test/dump_accessibility_test_helper.cc b/content/public/test/dump_accessibility_test_helper.cc
index 41c119d..94f4068 100644
--- a/content/public/test/dump_accessibility_test_helper.cc
+++ b/content/public/test/dump_accessibility_test_helper.cc
@@ -14,7 +14,7 @@
 #include "build/build_config.h"
 #include "content/public/common/content_switches.h"
 #include "ui/accessibility/accessibility_switches.h"
-#include "ui/accessibility/platform/inspect/tree_formatter.h"
+#include "ui/base/buildflags.h"
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
@@ -125,6 +125,10 @@
 }  // namespace
 
 DumpAccessibilityTestHelper::DumpAccessibilityTestHelper(
+    AXInspectFactory::Type type)
+    : expectation_type_(type) {}
+
+DumpAccessibilityTestHelper::DumpAccessibilityTestHelper(
     const char* expectation_type)
     : expectation_type_(expectation_type) {}
 
@@ -260,6 +264,24 @@
   return {};
 }
 
+// static
+std::vector<AXInspectFactory::Type> DumpAccessibilityTestHelper::TestPasses() {
+  return
+#if !BUILDFLAG(HAS_PLATFORM_ACCESSIBILITY_SUPPORT)
+      {AXInspectFactory::kBlink};
+#elif defined(OS_WIN)
+      {AXInspectFactory::kBlink, AXInspectFactory::kWinIA2,
+       AXInspectFactory::kWinUIA};
+#elif defined(OS_MAC)
+      {AXInspectFactory::kBlink, AXInspectFactory::kMac};
+#elif defined(OS_ANDROID)
+      {AXInspectFactory::kAndroid};
+#else  // linux
+      {AXInspectFactory::kBlink, AXInspectFactory::kLinux};
+#endif
+}
+
+// static
 base::Optional<std::vector<std::string>>
 DumpAccessibilityTestHelper::LoadExpectationFile(
     const base::FilePath& expected_file) {
@@ -284,6 +306,7 @@
   return expected_lines;
 }
 
+// static
 bool DumpAccessibilityTestHelper::ValidateAgainstExpectation(
     const base::FilePath& test_file_path,
     const base::FilePath& expected_file,
diff --git a/content/public/test/dump_accessibility_test_helper.h b/content/public/test/dump_accessibility_test_helper.h
index dec3e88..7bd4182 100644
--- a/content/public/test/dump_accessibility_test_helper.h
+++ b/content/public/test/dump_accessibility_test_helper.h
@@ -8,6 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/optional.h"
+#include "content/public/browser/ax_inspect_factory.h"
 
 namespace base {
 class CommandLine;
@@ -24,6 +25,7 @@
 // A helper class for writing accessibility tree dump tests.
 class DumpAccessibilityTestHelper {
  public:
+  explicit DumpAccessibilityTestHelper(AXInspectFactory::Type type);
   explicit DumpAccessibilityTestHelper(const char* expectation_type);
   ~DumpAccessibilityTestHelper() = default;
 
@@ -79,6 +81,9 @@
   // Parses directives from the given line.
   Directive ParseDirective(const std::string& line) const;
 
+  // Returns a platform-dependent list of inspect types used in dump testing.
+  static std::vector<AXInspectFactory::Type> TestPasses();
+
   // Loads the given expectation file and returns the contents. An expectation
   // file may be empty, in which case an empty vector is returned.
   // Returns nullopt if the file contains a skip marker.
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc
index e8a88c8..7b8da43 100644
--- a/content/public/test/mock_render_thread.cc
+++ b/content/public/test/mock_render_thread.cc
@@ -241,18 +241,6 @@
   return next_routing_id_++;
 }
 
-mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-MockRenderThread::TakeInitialInterfaceProviderRequestForFrame(
-    int32_t routing_id) {
-  auto it = frame_routing_id_to_initial_interface_provider_receivers_.find(
-      routing_id);
-  if (it == frame_routing_id_to_initial_interface_provider_receivers_.end())
-    return mojo::NullReceiver();
-  auto interface_provider_receiver = std::move(it->second);
-  frame_routing_id_to_initial_interface_provider_receivers_.erase(it);
-  return interface_provider_receiver;
-}
-
 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
 MockRenderThread::TakeInitialBrowserInterfaceBrokerReceiverForFrame(
     int32_t routing_id) {
@@ -265,25 +253,10 @@
   return browser_broker_receiver;
 }
 
-void MockRenderThread::PassInitialInterfaceProviderReceiverForFrame(
-    int32_t routing_id,
-    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-        interface_provider_receiver) {
-  bool did_insertion = false;
-  std::tie(std::ignore, did_insertion) =
-      frame_routing_id_to_initial_interface_provider_receivers_.emplace(
-          routing_id, std::move(interface_provider_receiver));
-  DCHECK(did_insertion);
-}
-
 void MockRenderThread::OnCreateChildFrame(
     int32_t child_routing_id,
-    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-        interface_provider,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker) {
-  frame_routing_id_to_initial_interface_provider_receivers_.emplace(
-      child_routing_id, std::move(interface_provider));
   frame_routing_id_to_initial_browser_broker_receivers_.emplace(
       child_routing_id, std::move(browser_interface_broker));
 }
@@ -310,10 +283,6 @@
   reply->main_frame_route_id = GetNextRoutingID();
   reply->main_frame_interface_bundle =
       mojom::DocumentScopedInterfaceBundle::New();
-  frame_routing_id_to_initial_interface_provider_receivers_.emplace(
-      reply->main_frame_route_id,
-      reply->main_frame_interface_bundle->interface_provider
-          .InitWithNewPipeAndPassReceiver());
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   frame_routing_id_to_initial_browser_broker_receivers_.emplace(
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h
index 656c277..c8e77d7fc 100644
--- a/content/public/test/mock_render_thread.h
+++ b/content/public/test/mock_render_thread.h
@@ -17,7 +17,6 @@
 #include "ipc/ipc_test_sink.h"
 #include "ipc/message_filter.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "services/service_manager/public/mojom/interface_provider.mojom.h"
 #include "third_party/blink/public/mojom/browser_interface_broker.mojom.h"
 
 namespace IPC {
@@ -109,18 +108,9 @@
 
   void OnCreateChildFrame(
       int32_t child_routing_id,
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker);
 
-  // Returns the receiver end of the InterfaceProvider interface whose client
-  // end was passed in to construct RenderFrame with |routing_id|; if any. The
-  // client end will be used by the RenderFrame to service interface receivers
-  // originating from the initial empty document.
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-  TakeInitialInterfaceProviderRequestForFrame(int32_t routing_id);
-
   // Returns the receiver end of the BrowserInterfaceBroker interface whose
   // client end was passed in to construct RenderFrame with |routing_id|; if
   // any. The client end will be used by the RenderFrame to service interface
@@ -128,14 +118,6 @@
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   TakeInitialBrowserInterfaceBrokerReceiverForFrame(int32_t routing_id);
 
-  // Called from the RenderViewTest harness to supply the receiver end of the
-  // InterfaceProvider interface connection that the harness used to service the
-  // initial empty document in the RenderFrame with |routing_id|.
-  void PassInitialInterfaceProviderReceiverForFrame(
-      int32_t routing_id,
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider_receiver);
-
  protected:
   // This function operates as a regular IPC listener. Subclasses
   // overriding this should first delegate to this implementation.
@@ -146,10 +128,6 @@
   // Routing ID what will be assigned to the next view, widget, or frame.
   int32_t next_routing_id_;
 
-  std::map<int32_t,
-           mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>>
-      frame_routing_id_to_initial_interface_provider_receivers_;
-
   std::map<int32_t, mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>>
       frame_routing_id_to_initial_browser_broker_receivers_;
 
diff --git a/content/public/test/permission_type_unittest.cc b/content/public/test/permission_type_unittest.cc
index d4ab16f..ae2c48ce 100644
--- a/content/public/test/permission_type_unittest.cc
+++ b/content/public/test/permission_type_unittest.cc
@@ -16,7 +16,7 @@
 
   // All but PermissionType::NUM should be added.
   EXPECT_EQ(all_permission_types.size(),
-            static_cast<unsigned long>(PermissionType::NUM) - 4);
+            static_cast<unsigned long>(PermissionType::NUM) - 5);
 
   // Check that some arbitrary permission types are in this vector.
   // The order is not relevant.
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index f177cae6..49ca3a1 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -496,10 +496,6 @@
   view_params->main_frame_routing_id = render_thread_->GetNextRoutingID();
   view_params->main_frame_interface_bundle =
       mojom::DocumentScopedInterfaceBundle::New();
-  render_thread_->PassInitialInterfaceProviderReceiverForFrame(
-      view_params->main_frame_routing_id,
-      view_params->main_frame_interface_bundle->interface_provider
-          .InitWithNewPipeAndPassReceiver());
 
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index b52b992..7fa6996 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -143,7 +143,6 @@
     "render_view_impl.h",
     "render_widget.cc",
     "render_widget.h",
-    "render_widget_delegate.h",
     "renderer_blink_platform_impl.cc",
     "renderer_blink_platform_impl.h",
     "renderer_main.cc",
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index bdfb875..59daf7d 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -40,6 +40,7 @@
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_input_element.h"
 #include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_page_popup.h"
 #include "third_party/blink/public/web/web_settings.h"
 #include "third_party/blink/public/web/web_view.h"
 #include "ui/accessibility/accessibility_switches.h"
diff --git a/content/renderer/agent_scheduling_group.cc b/content/renderer/agent_scheduling_group.cc
index 95ea78e..bf0f637 100644
--- a/content/renderer/agent_scheduling_group.cc
+++ b/content/renderer/agent_scheduling_group.cc
@@ -187,20 +187,17 @@
 }
 
 void AgentSchedulingGroup::CreateFrame(mojom::CreateFrameParamsPtr params) {
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      interface_provider(
-          std::move(params->interface_bundle->interface_provider));
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker(
           std::move(params->interface_bundle->browser_interface_broker));
 
   RenderFrameImpl::CreateFrame(
-      *this, params->routing_id, std::move(interface_provider),
-      std::move(browser_interface_broker), params->previous_routing_id,
-      params->opener_frame_token, params->parent_routing_id,
-      params->previous_sibling_routing_id, params->frame_token,
-      params->devtools_frame_token, params->replication_state,
-      &ToImpl(render_thread_), std::move(params->widget_params),
+      *this, params->routing_id, std::move(browser_interface_broker),
+      params->previous_routing_id, params->opener_frame_token,
+      params->parent_routing_id, params->previous_sibling_routing_id,
+      params->frame_token, params->devtools_frame_token,
+      params->replication_state, &ToImpl(render_thread_),
+      std::move(params->widget_params),
       std::move(params->frame_owner_properties),
       params->has_committed_real_load, std::move(params->policy_container));
 }
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc
index 8264c40..c549065 100644
--- a/content/renderer/child_frame_compositing_helper.cc
+++ b/content/renderer/child_frame_compositing_helper.cc
@@ -84,7 +84,7 @@
   }
 }
 
-gfx::Rect ChildFrameCompositingHelper::PaintableRegion() {
+gfx::Rect ChildFrameCompositingHelper::PaintableRegion() const {
   DCHECK(crash_ui_layer_);
   return gfx::Rect(crash_ui_layer_->bounds());
 }
diff --git a/content/renderer/child_frame_compositing_helper.h b/content/renderer/child_frame_compositing_helper.h
index a735be8..be5b61f 100644
--- a/content/renderer/child_frame_compositing_helper.h
+++ b/content/renderer/child_frame_compositing_helper.h
@@ -52,7 +52,7 @@
  private:
   // cc::ContentLayerClient implementation. Called from the cc::PictureLayer
   // created for the crashed child frame to display the sad image.
-  gfx::Rect PaintableRegion() override;
+  gfx::Rect PaintableRegion() const override;
   scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() override;
   bool FillsBoundsCompletely() const override;
 
diff --git a/content/renderer/compositor/compositor_dependencies.h b/content/renderer/compositor/compositor_dependencies.h
index 7a544ab..f2b0843 100644
--- a/content/renderer/compositor/compositor_dependencies.h
+++ b/content/renderer/compositor/compositor_dependencies.h
@@ -15,10 +15,6 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
-namespace base {
-class SingleThreadTaskRunner;
-}
-
 namespace cc {
 class TaskGraphRunner;
 class UkmRecorderFactory;
@@ -38,8 +34,6 @@
   virtual bool IsElasticOverscrollEnabled() = 0;
   virtual bool IsUseZoomForDSFEnabled() = 0;
   virtual bool IsSingleThreaded() = 0;
-  virtual scoped_refptr<base::SingleThreadTaskRunner>
-  GetCleanupTaskRunner() = 0;
   virtual blink::scheduler::WebThreadScheduler* GetWebMainThreadScheduler() = 0;
   virtual cc::TaskGraphRunner* GetTaskGraphRunner() = 0;
   virtual bool IsScrollAnimatorEnabled() = 0;
diff --git a/content/renderer/discardable_memory_utils.cc b/content/renderer/discardable_memory_utils.cc
index 4ec6ef8..55ef9a8 100644
--- a/content/renderer/discardable_memory_utils.cc
+++ b/content/renderer/discardable_memory_utils.cc
@@ -25,7 +25,7 @@
 
 namespace content {
 
-std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
 CreateDiscardableMemoryAllocator() {
   DVLOG(1) << "Using shared memory for discardable memory";
 
@@ -33,7 +33,7 @@
       manager_remote;
   ChildThread::Get()->BindHostReceiver(
       manager_remote.InitWithNewPipeAndPassReceiver());
-  return std::make_unique<
+  return base::MakeRefCounted<
       discardable_memory::ClientDiscardableSharedMemoryManager>(
       std::move(manager_remote), ChildProcess::current()->io_task_runner(),
       ChildProcess::current()->main_thread()->main_thread_runner());
diff --git a/content/renderer/discardable_memory_utils.h b/content/renderer/discardable_memory_utils.h
index 0250aee..53de8ab 100644
--- a/content/renderer/discardable_memory_utils.h
+++ b/content/renderer/discardable_memory_utils.h
@@ -24,7 +24,7 @@
 namespace content {
 
 CONTENT_EXPORT
-std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
 CreateDiscardableMemoryAllocator();
 
 }  // namespace content
diff --git a/content/renderer/gpu_benchmarking_extension.cc b/content/renderer/gpu_benchmarking_extension.cc
index c99e624..6ee8be1 100644
--- a/content/renderer/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu_benchmarking_extension.cc
@@ -194,12 +194,12 @@
 // used objects from RenderFrameImpl.
 class GpuBenchmarkingContext {
  public:
-  explicit GpuBenchmarkingContext(RenderFrameImpl* frame) {
-    web_frame_ = frame->GetWebFrame();
-    web_view_ = web_frame_->View();
-    render_widget_ = frame->GetLocalRootRenderWidget();
-    layer_tree_host_ = render_widget_->layer_tree_host();
-  }
+  explicit GpuBenchmarkingContext(RenderFrameImpl* frame)
+      : web_frame_(frame->GetWebFrame()),
+        web_view_(web_frame_->View()),
+        render_widget_(frame->GetLocalRootRenderWidget()),
+        frame_widget_(frame->GetLocalRootWebFrameWidget()),
+        layer_tree_host_(render_widget_->layer_tree_host()) {}
 
   WebLocalFrame* web_frame() const {
     DCHECK(web_frame_ != nullptr);
@@ -210,16 +210,18 @@
     return web_view_;
   }
   RenderWidget* render_widget() const { return render_widget_; }
+  blink::WebFrameWidget* frame_widget() const { return frame_widget_; }
   cc::LayerTreeHost* layer_tree_host() const {
     DCHECK(layer_tree_host_ != nullptr);
     return layer_tree_host_;
   }
 
  private:
-  WebLocalFrame* web_frame_ = nullptr;
-  WebView* web_view_ = nullptr;
-  RenderWidget* render_widget_ = nullptr;
-  cc::LayerTreeHost* layer_tree_host_ = nullptr;
+  WebLocalFrame* web_frame_;
+  WebView* web_view_;
+  RenderWidget* render_widget_;
+  blink::WebFrameWidget* frame_widget_;
+  cc::LayerTreeHost* layer_tree_host_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
 };
@@ -262,7 +264,7 @@
                              gin::Arguments* args,
                              const gfx::Point& point,
                              const std::string& message) {
-  gfx::Rect rect = context->render_widget()->GetWebWidget()->ViewRect();
+  gfx::Rect rect = context->frame_widget()->ViewRect();
   rect -= rect.OffsetFromOrigin();
 
   // If the bounds are not available here, as is the case with an OOPIF,
@@ -711,7 +713,7 @@
 // SmoothScrollByXY in telemetry/internal/actions/scroll.js.
 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
   GpuBenchmarkingContext context(render_frame_.get());
-  blink::WebRect rect = context.render_widget()->GetWebWidget()->ViewRect();
+  blink::WebRect rect = context.frame_widget()->ViewRect();
 
   float pixels_to_scroll = 0;
   v8::Local<v8::Function> callback;
@@ -783,7 +785,7 @@
 // scroll left.
 bool GpuBenchmarking::SmoothScrollByXY(gin::Arguments* args) {
   GpuBenchmarkingContext context(render_frame_.get());
-  blink::WebRect rect = context.render_widget()->GetWebWidget()->ViewRect();
+  blink::WebRect rect = context.frame_widget()->ViewRect();
 
   float pixels_to_scroll_x = 0;
   float pixels_to_scroll_y = 0;
@@ -891,7 +893,7 @@
 // should change this to match with SmoothScrollBy or SmoothScrollByXY.
 bool GpuBenchmarking::Swipe(gin::Arguments* args) {
   GpuBenchmarkingContext context(render_frame_.get());
-  blink::WebRect rect = context.render_widget()->GetWebWidget()->ViewRect();
+  blink::WebRect rect = context.frame_widget()->ViewRect();
 
   std::string direction = "up";
   float pixels_to_scroll = 0;
@@ -941,8 +943,7 @@
 
 bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
   GpuBenchmarkingContext context(render_frame_.get());
-  blink::WebRect content_rect =
-      context.render_widget()->GetWebWidget()->ViewRect();
+  blink::WebRect content_rect = context.frame_widget()->ViewRect();
 
   std::string direction = "down";
   float distance_length = 0;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 9692196e..0f19ef1 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -544,7 +544,7 @@
   if (render_frame_) {  // NULL in tests or if the frame has been destroyed.
     render_frame_->PepperInstanceCreated(this);
     view_data_.is_page_visible =
-        !render_frame_->GetLocalRootRenderWidget()->GetWebWidget()->IsHidden();
+        !render_frame_->GetLocalRootWebFrameWidget()->IsHidden();
 
     if (!module_->IsProxied()) {
       created_in_process_instance_ = true;
@@ -1199,8 +1199,7 @@
   view_data_.css_scale =
       container_->PageZoomFactor() * container_->PageScaleFactor();
   if (IsUseZoomForDSFEnabled()) {
-    WebWidget* widget =
-        render_frame()->GetLocalRootRenderWidget()->GetWebWidget();
+    WebWidget* widget = render_frame()->GetLocalRootWebFrameWidget();
 
     viewport_to_dip_scale_ =
         1.0f / widget->GetOriginalScreenInfo().device_scale_factor;
@@ -2459,9 +2458,8 @@
   // All other cases: Report the screen size.
   if (!render_frame_)
     return PP_FALSE;
-  blink::ScreenInfo info = render_frame_->GetLocalRootRenderWidget()
-                               ->GetWebWidget()
-                               ->GetScreenInfo();
+  blink::ScreenInfo info =
+      render_frame_->GetLocalRootWebFrameWidget()->GetScreenInfo();
   *size = PP_MakeSize(info.rect.width(), info.rect.height());
   return PP_TRUE;
 }
@@ -2885,8 +2883,7 @@
     // e.g., the plugin would like to set an invisible cursor when there isn't
     // any user input for a while.
     if (container()->WasTargetForLastMouseEvent()) {
-      render_frame_->GetLocalRootRenderWidget()->GetWebWidget()->SetCursor(
-          *cursor_);
+      render_frame_->GetLocalRootWebFrameWidget()->SetCursor(*cursor_);
     }
   }
 }
@@ -2954,9 +2951,8 @@
   // behavior, the width and height should probably be set to 100%, rather than
   // a fixed screen size.
 
-  blink::ScreenInfo info = render_frame_->GetLocalRootRenderWidget()
-                               ->GetWebWidget()
-                               ->GetScreenInfo();
+  blink::ScreenInfo info =
+      render_frame_->GetLocalRootWebFrameWidget()->GetScreenInfo();
   screen_size_for_fullscreen_ = info.rect.size();
   std::string width = base::NumberToString(screen_size_for_fullscreen_.width());
   std::string height =
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 2d17b29..85a71bc 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -139,7 +139,6 @@
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom.h"
 #include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
 #include "third_party/blink/public/common/action_after_pagehide.h"
@@ -1523,14 +1522,11 @@
     AgentSchedulingGroup& agent_scheduling_group,
     RenderViewImpl* render_view,
     int32_t routing_id,
-    mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-        interface_provider,
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker,
     const base::UnguessableToken& devtools_frame_token) {
   DCHECK(routing_id != MSG_ROUTING_NONE);
   CreateParams params(agent_scheduling_group, render_view, routing_id,
-                      std::move(interface_provider),
                       std::move(browser_interface_broker),
                       devtools_frame_token);
 
@@ -1567,13 +1563,9 @@
   DCHECK_NE(MSG_ROUTING_NONE, params->main_frame_widget_routing_id);
 
   CHECK(params->main_frame_interface_bundle);
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      main_frame_interface_provider(
-          std::move(params->main_frame_interface_bundle->interface_provider));
 
   RenderFrameImpl* render_frame = RenderFrameImpl::Create(
       agent_scheduling_group, render_view, params->main_frame_routing_id,
-      std::move(main_frame_interface_provider),
       std::move(params->main_frame_interface_bundle->browser_interface_broker),
       params->devtools_main_frame_token);
   render_frame->InitializeBlameContext(nullptr);
@@ -1607,22 +1599,21 @@
           mojom::ViewWidgetType::kTopLevel,
       /*hidden=*/true, render_view->widgets_never_composited());
 
-  render_widget->InitForMainFrame(
-      web_frame_widget, params->visual_properties.screen_info, *render_view);
+  render_widget->InitForMainFrame(web_frame_widget,
+                                  params->visual_properties.screen_info);
 
   // The WebFrame created here was already attached to the Page as its main
   // frame, and the WebFrameWidget has been initialized, so we can call
   // WebView's DidAttachLocalMainFrame().
   render_view->GetWebView()->DidAttachLocalMainFrame();
 
-  // The RenderWidget should start with valid VisualProperties, including a
-  // non-zero size. While RenderWidget would not normally receive IPCs and
+  // The WebFrameWidget should start with valid VisualProperties, including a
+  // non-zero size. While WebFrameWidget would not normally receive IPCs and
   // thus would not get VisualProperty updates while the frame is provisional,
   // we need at least one update to them in order to meet expectations in the
   // renderer, and that update comes as part of the CreateFrame message.
-  // TODO(crbug.com/419087): This could become part of RenderWidget Init.
-  render_widget->GetWebWidget()->ApplyVisualProperties(
-      params->visual_properties);
+  // TODO(crbug.com/419087): This could become part of WebFrameWidget Init.
+  web_frame_widget->ApplyVisualProperties(params->visual_properties);
 
   render_frame->render_widget_ = render_widget.get();
   render_frame->owned_render_widget_ = std::move(render_widget);
@@ -1636,8 +1627,6 @@
 void RenderFrameImpl::CreateFrame(
     AgentSchedulingGroup& agent_scheduling_group,
     int routing_id,
-    mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-        interface_provider,
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker,
     int previous_routing_id,
@@ -1684,8 +1673,7 @@
     // Create the RenderFrame and WebLocalFrame, linking the two.
     render_frame = RenderFrameImpl::Create(
         agent_scheduling_group, parent_proxy->render_view(), routing_id,
-        std::move(interface_provider), std::move(browser_interface_broker),
-        devtools_frame_token);
+        std::move(browser_interface_broker), devtools_frame_token);
     render_frame->InitializeBlameContext(FromRoutingID(parent_routing_id));
     render_frame->unique_name_helper_.set_propagated_name(
         replicated_state.unique_name);
@@ -1727,8 +1715,7 @@
     // main frame, as in the case where a navigation to the current process'
     render_frame = RenderFrameImpl::Create(
         agent_scheduling_group, render_view, routing_id,
-        std::move(interface_provider), std::move(browser_interface_broker),
-        devtools_frame_token);
+        std::move(browser_interface_broker), devtools_frame_token);
     render_frame->InitializeBlameContext(nullptr);
     render_frame->previous_routing_id_ = previous_routing_id;
     web_frame = blink::WebLocalFrame::CreateProvisional(
@@ -1779,16 +1766,14 @@
         /*hidden=*/true, render_view->widgets_never_composited());
 
     render_widget->InitForMainFrame(
-        web_frame_widget, widget_params->visual_properties.screen_info,
-        *render_view);
-    // The RenderWidget should start with valid VisualProperties, including a
-    // non-zero size. While RenderWidget would not normally receive IPCs and
+        web_frame_widget, widget_params->visual_properties.screen_info);
+    // The WebFrameWidget should start with valid VisualProperties, including a
+    // non-zero size. While WebFrameWidget would not normally receive IPCs and
     // thus would not get VisualProperty updates while the frame is provisional,
     // we need at least one update to them in order to meet expectations in the
     // renderer, and that update comes as part of the CreateFrame message.
-    // TODO(crbug.com/419087): This could become part of RenderWidget Init.
-    render_widget->GetWebWidget()->ApplyVisualProperties(
-        widget_params->visual_properties);
+    // TODO(crbug.com/419087): This could become part of WebFrameWidget Init.
+    web_frame_widget->ApplyVisualProperties(widget_params->visual_properties);
 
     // Note that we do *not* call WebView's DidAttachLocalMainFrame() here yet
     // because this frame is provisional and not attached to the Page yet. We
@@ -1834,14 +1819,13 @@
     // and run.
     render_widget->InitForChildLocalRoot(
         web_frame_widget, widget_params->visual_properties.screen_info);
-    // The RenderWidget should start with valid VisualProperties, including a
-    // non-zero size. While RenderWidget would not normally receive IPCs and
+    // The WebFrameWidget should start with valid VisualProperties, including a
+    // non-zero size. While WebFrameWidget would not normally receive IPCs and
     // thus would not get VisualProperty updates while the frame is provisional,
     // we need at least one update to them in order to meet expectations in the
     // renderer, and that update comes as part of the CreateFrame message.
-    // TODO(crbug.com/419087): This could become part of RenderWidget Init.
-    render_widget->GetWebWidget()->ApplyVisualProperties(
-        widget_params->visual_properties);
+    // TODO(crbug.com/419087): This could become part of WebFrameWidget Init.
+    web_frame_widget->ApplyVisualProperties(widget_params->visual_properties);
 
     render_frame->render_widget_ = render_widget.get();
     render_frame->owned_render_widget_ = std::move(render_widget);
@@ -1973,15 +1957,12 @@
     AgentSchedulingGroup& agent_scheduling_group,
     RenderViewImpl* render_view,
     int32_t routing_id,
-    mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-        interface_provider,
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker,
     const base::UnguessableToken& devtools_frame_token)
     : agent_scheduling_group(&agent_scheduling_group),
       render_view(render_view),
       routing_id(routing_id),
-      interface_provider(std::move(interface_provider)),
       browser_interface_broker(std::move(browser_interface_broker)),
       devtools_frame_token(devtools_frame_token) {}
 RenderFrameImpl::CreateParams::~CreateParams() = default;
@@ -2001,8 +1982,6 @@
       previous_routing_id_(MSG_ROUTING_NONE),
       selection_text_offset_(0),
       selection_range_(gfx::Range::InvalidRange()),
-      remote_interfaces_(
-          agent_scheduling_group_.agent_group_scheduler().DefaultTaskRunner()),
       render_accessibility_manager_(
           std::make_unique<RenderAccessibilityManager>(this)),
       blame_context_(nullptr),
@@ -2018,10 +1997,6 @@
                               base::Unretained(this))),
       devtools_frame_token_(params.devtools_frame_token) {
   DCHECK(RenderThread::IsMainThread());
-  // The InterfaceProvider to access Mojo services exposed by the RFHI must be
-  // provided at construction time. See: https://crbug.com/729021/.
-  CHECK(params.interface_provider.is_valid());
-  remote_interfaces_.Bind(std::move(params.interface_provider));
   blink_interface_registry_.reset(new BlinkInterfaceRegistryImpl(
       registry_.GetWeakPtr(), associated_interfaces_.GetWeakPtr()));
 
@@ -2166,21 +2141,21 @@
   if (instance != focused_pepper_plugin_)
     return;
 
-  GetLocalRootRenderWidget()->UpdateTextInputState();
+  GetLocalRootWebFrameWidget()->UpdateTextInputState();
 }
 
 void RenderFrameImpl::PepperCaretPositionChanged(
     PepperPluginInstanceImpl* instance) {
   if (instance != focused_pepper_plugin_)
     return;
-  GetLocalRootRenderWidget()->UpdateSelectionBounds();
+  GetLocalRootWebFrameWidget()->UpdateSelectionBounds();
 }
 
 void RenderFrameImpl::PepperCancelComposition(
     PepperPluginInstanceImpl* instance) {
   if (instance != focused_pepper_plugin_)
     return;
-  GetLocalRootRenderWidget()->GetWebWidget()->CancelCompositionForPepper();
+  GetLocalRootWebFrameWidget()->CancelCompositionForPepper();
 }
 
 void RenderFrameImpl::PepperSelectionChanged(
@@ -2806,7 +2781,7 @@
 }
 
 void RenderFrameImpl::ShowVirtualKeyboard() {
-  GetLocalRootRenderWidget()->GetWebWidget()->ShowVirtualKeyboard();
+  GetLocalRootWebFrameWidget()->ShowVirtualKeyboard();
 }
 
 blink::WebPlugin* RenderFrameImpl::CreatePlugin(
@@ -2844,10 +2819,6 @@
   GetInterface(interface_name, std::move(interface_pipe));
 }
 
-service_manager::InterfaceProvider* RenderFrameImpl::GetRemoteInterfaces() {
-  return &remote_interfaces_;
-}
-
 blink::AssociatedInterfaceRegistry*
 RenderFrameImpl::GetAssociatedInterfaceRegistry() {
   return &associated_interfaces_;
@@ -2903,7 +2874,7 @@
 }
 
 bool RenderFrameImpl::IsPasting() {
-  return GetLocalRootRenderWidget()->GetFrameWidget()->IsPasting();
+  return GetLocalRootWebFrameWidget()->IsPasting();
 }
 
 // blink::mojom::FullscreenVideoElementHandler implementation ------------------
@@ -3757,7 +3728,7 @@
     const blink::WebString& sink_id) {
   return media_factory_.CreateMediaPlayer(
       source, client, inspector_context, encrypted_client, initial_cdm, sink_id,
-      GetLocalRootRenderWidget()->GetFrameWidget()->GetFrameSinkId(),
+      GetLocalRootWebFrameWidget()->GetFrameSinkId(),
       GetLocalRootRenderWidget()->layer_tree_host()->GetSettings());
 }
 
@@ -3951,15 +3922,12 @@
           name.IsEmpty() ? fallback_name.Utf8() : name.Utf8(),
           is_created_by_script);
 
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      child_interface_provider;
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
 
   // Now create the child frame in the browser via an asynchronous call.
   GetFrameHost()->CreateChildFrame(
       child_routing_id,
-      child_interface_provider.InitWithNewPipeAndPassReceiver(),
       browser_interface_broker.InitWithNewPipeAndPassReceiver(),
       std::move(policy_container_host_receiver), scope, name.Utf8(),
       frame_unique_name, is_created_by_script, frame_policy,
@@ -3974,8 +3942,7 @@
   // Create the RenderFrame and WebLocalFrame, linking the two.
   RenderFrameImpl* child_render_frame = RenderFrameImpl::Create(
       agent_scheduling_group_, render_view_, child_routing_id,
-      std::move(child_interface_provider), std::move(browser_interface_broker),
-      devtools_frame_token);
+      std::move(browser_interface_broker), devtools_frame_token);
   child_render_frame->unique_name_helper_.set_propagated_name(
       frame_unique_name);
   if (is_created_by_script)
@@ -4224,31 +4191,11 @@
   // Generate a new embedding token on each document change.
   GetWebFrame()->SetEmbeddingToken(base::UnguessableToken::Create());
 
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-      remote_interface_provider_receiver;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker_receiver;
 
   // blink passes true when the new pipe needs to be bound.
   if (should_reset_browser_interface_broker) {
-    // If we're navigating to a new document, bind |remote_interfaces_| to a new
-    // message pipe. The receiver end of the new InterfaceProvider interface
-    // will be sent over as part of DidCommitProvisionalLoad. After the RFHI
-    // receives the commit confirmation, it will immediately close the old
-    // message pipe to avoid GetInterface calls racing with navigation commit,
-    // and bind the receiver end of the message pipe created here.
-    mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-        interfaces_provider;
-    remote_interface_provider_receiver =
-        interfaces_provider.InitWithNewPipeAndPassReceiver();
-
-    // Must initialize |remote_interfaces_| with a new working pipe *before*
-    // observers receive DidCommitProvisionalLoad, so they can already request
-    // remote interfaces. The interface requests will be serviced once the
-    // InterfaceProvider interface request is bound by the RenderFrameHostImpl.
-    remote_interfaces_.Close();
-    remote_interfaces_.Bind(std::move(interfaces_provider));
-
     // If we're navigating to a new document, bind
     // |browser_interface_broker_proxy_| to a new browser interface broker. The
     // request end of the new BrowserInterfaceBroker interface will be sent over
@@ -4281,10 +4228,10 @@
     }
 
     // If the request for |audio_input_stream_factory_| is in flight when
-    // |remote_interfaces_| is reset, it will be silently dropped. We reset
-    // |audio_input_stream_factory_| to force a new mojo request to be sent
-    // the next time it's used. See https://crbug.com/795258 for implementing a
-    // nicer solution.
+    // |browser_interface_broker_proxy_| is reset, it will be silently dropped.
+    // We reset |audio_input_stream_factory_| to force a new mojo request to be
+    // sent the next time it's used. See https://crbug.com/795258 for
+    // implementing a nicer solution.
     audio_input_stream_factory_.reset();
   }
 
@@ -4301,7 +4248,6 @@
       sandbox_flags, feature_policy_header, document_policy_header,
       should_reset_browser_interface_broker
           ? mojom::DidCommitProvisionalLoadInterfaceParams::New(
-                std::move(remote_interface_provider_receiver),
                 std::move(browser_interface_broker_receiver))
           : nullptr,
       GetWebFrame()->GetEmbeddingToken());
@@ -4492,8 +4438,8 @@
 }
 
 void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) {
-  if (!GetLocalRootRenderWidget()->GetWebWidget()->HandlingInputEvent() &&
-      !GetLocalRootRenderWidget()->GetFrameWidget()->HandlingSelectRange())
+  if (!GetLocalRootWebFrameWidget()->HandlingInputEvent() &&
+      !GetLocalRootWebFrameWidget()->HandlingSelectRange())
     return;
 
   if (is_empty_selection)
@@ -4504,7 +4450,7 @@
   // was changed, and SyncSelectionIfRequired may send SelectionChanged
   // to notify the selection was changed.  Focus change should be notified
   // before selection change.
-  GetLocalRootRenderWidget()->UpdateTextInputState();
+  GetLocalRootWebFrameWidget()->UpdateTextInputState();
   SyncSelectionIfRequired();
 }
 
@@ -4525,8 +4471,7 @@
     // them to DIP coordiates relative to the WindowScreenRect.
     blink::WebRect position_in_window(params.x, params.y, 0, 0);
     GetLocalRootRenderWidget()->ConvertViewportToWindow(&position_in_window);
-    const float scale =
-        GetLocalRootRenderWidget()->GetWebWidget()->GetEmulatorScale();
+    const float scale = GetLocalRootWebFrameWidget()->GetEmulatorScale();
     params.x = position_in_window.x * scale;
     params.y = position_in_window.y * scale;
   }
@@ -4960,7 +4905,7 @@
 }
 
 bool RenderFrameImpl::IsHidden() {
-  return GetLocalRootRenderWidget()->GetWebWidget()->IsHidden();
+  return GetLocalRootWebFrameWidget()->IsHidden();
 }
 
 bool RenderFrameImpl::IsLocalRoot() const {
@@ -5214,7 +5159,7 @@
     }
   }
 
-  if (render_widget_) {
+  if (IsLocalRoot()) {
     // This goes to WebViewImpl and sets the zoom factor which will be
     // propagated down to this RenderFrameImpl's LocalFrame in blink.
     // Non-local-roots are able to grab the value off their parents but local
@@ -5230,8 +5175,8 @@
     //     IFrameZoomBrowserTest.SubframesDontZoomIndependently (and the whole
     //     suite).
     render_view_->PropagatePageZoomToNewlyAttachedFrame(
-        render_widget_->compositor_deps()->IsUseZoomForDSFEnabled(),
-        render_widget_->GetWebWidget()->GetScreenInfo().device_scale_factor);
+        render_view_->compositor_deps()->IsUseZoomForDSFEnabled(),
+        GetLocalRootWebFrameWidget()->GetScreenInfo().device_scale_factor);
   }
 
   // If we are a top frame navigation to another document we should clear any
@@ -5958,7 +5903,7 @@
     selection_range_ = range;
     SetSelectedText(text, offset, range);
   }
-  GetLocalRootRenderWidget()->UpdateSelectionBounds();
+  GetLocalRootWebFrameWidget()->UpdateSelectionBounds();
 }
 
 void RenderFrameImpl::ScrollFocusedEditableElementIntoRect(
@@ -6439,8 +6384,8 @@
   else if (focused_pepper_plugin_ == instance)
     focused_pepper_plugin_ = nullptr;
 
-  GetLocalRootRenderWidget()->UpdateTextInputState();
-  GetLocalRootRenderWidget()->UpdateSelectionBounds();
+  GetLocalRootWebFrameWidget()->UpdateTextInputState();
+  GetLocalRootWebFrameWidget()->UpdateSelectionBounds();
 }
 
 void RenderFrameImpl::PepperStartsPlayback(PepperPluginInstanceImpl* instance) {
@@ -6547,10 +6492,7 @@
 }
 
 float RenderFrameImpl::GetDeviceScaleFactor() {
-  return GetLocalRootRenderWidget()
-      ->GetWebWidget()
-      ->GetScreenInfo()
-      .device_scale_factor;
+  return GetLocalRootWebFrameWidget()->GetScreenInfo().device_scale_factor;
 }
 
 }  // namespace content
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index da0fddb..4e22016 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -68,7 +68,6 @@
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
@@ -140,10 +139,6 @@
 class MediaPermission;
 }
 
-namespace service_manager {
-class InterfaceProvider;
-}
-
 namespace url {
 class Origin;
 }
@@ -210,8 +205,6 @@
   static void CreateFrame(
       AgentSchedulingGroup& agent_scheduling_group,
       int routing_id,
-      mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-          interface_provider,
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker,
       int previous_routing_id,
@@ -238,8 +231,6 @@
     CreateParams(AgentSchedulingGroup& agent_scheduling_group,
                  RenderViewImpl* render_view,
                  int32_t routing_id,
-                 mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-                     interface_provider,
                  mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
                      browser_interface_broker,
                  const base::UnguessableToken& devtools_frame_token);
@@ -251,8 +242,6 @@
     AgentSchedulingGroup* agent_scheduling_group;
     RenderViewImpl* render_view;
     int32_t routing_id;
-    mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-        interface_provider;
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker;
     base::UnguessableToken devtools_frame_token;
@@ -379,7 +368,6 @@
   void BindLocalInterface(
       const std::string& interface_name,
       mojo::ScopedMessagePipeHandle interface_pipe) override;
-  service_manager::InterfaceProvider* GetRemoteInterfaces() override;
   blink::AssociatedInterfaceRegistry* GetAssociatedInterfaceRegistry() override;
   blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
 #if BUILDFLAG(ENABLE_PLUGINS)
@@ -887,17 +875,13 @@
   class FrameURLLoaderFactory;
 
   // Creates a new RenderFrame. |render_view| is the RenderView object that this
-  // frame belongs to, |interface_provider| is the RenderFrameHost's
-  // InterfaceProvider through which services are exposed to the RenderFrame,
-  // and |browser_interface_broker| is the RenderFrameHost's
+  // frame belongs to, and |browser_interface_broker| is the RenderFrameHost's
   // BrowserInterfaceBroker through which services are exposed to the
   // RenderFrame.
   static RenderFrameImpl* Create(
       AgentSchedulingGroup& agent_scheduling_group,
       RenderViewImpl* render_view,
       int32_t routing_id,
-      mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-          interface_provider,
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker,
       const base::UnguessableToken& devtools_frame_token);
@@ -1312,7 +1296,6 @@
   std::unique_ptr<MediaPermissionDispatcher> media_permission_dispatcher_;
 
   service_manager::BinderRegistry registry_;
-  service_manager::InterfaceProvider remote_interfaces_;
   std::unique_ptr<BlinkInterfaceRegistryImpl> blink_interface_registry_;
 
   blink::BrowserInterfaceBrokerProxy browser_interface_broker_proxy_;
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index 5e680ad..3ee8c31 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -46,8 +46,6 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "services/service_manager/public/mojom/interface_provider.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/loader/previews_state.h"
@@ -133,10 +131,6 @@
         ->OnUnload(kFrameProxyRouteId, false, frame_replication_state,
                    base::UnguessableToken::Create());
 
-    mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-        stub_interface_provider;
-    ignore_result(stub_interface_provider.InitWithNewPipeAndPassReceiver());
-
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         stub_browser_interface_broker;
     ignore_result(
@@ -144,7 +138,6 @@
 
     RenderFrameImpl::CreateFrame(
         *agent_scheduling_group_, kSubframeRouteId,
-        std::move(stub_interface_provider),
         std::move(stub_browser_interface_broker), MSG_ROUTING_NONE,
         base::nullopt, kFrameProxyRouteId, MSG_ROUTING_NONE,
         base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -241,12 +234,12 @@
   visual_properties.compositor_viewport_pixel_rect = gfx::Rect(widget_size);
   visual_properties.visible_viewport_size = visible_size;
 
-  RenderWidget* main_frame_widget =
-      GetMainRenderFrame()->GetLocalRootRenderWidget();
+  blink::WebFrameWidget* main_frame_widget =
+      GetMainRenderFrame()->GetLocalRootWebFrameWidget();
 
   // The main frame's widget will receive the resize message before the
   // subframe's widget, and it will set the size for the WebView.
-  main_frame_widget->GetWebWidget()->ApplyVisualProperties(visual_properties);
+  main_frame_widget->ApplyVisualProperties(visual_properties);
   // The main frame widget's size is the "widget size", not the visible viewport
   // size, which is given to blink separately.
   EXPECT_EQ(gfx::Size(view_->GetWebView()->MainFrameWidget()->Size()),
@@ -489,44 +482,6 @@
 
 constexpr char kNoDocumentMarkerURL[] = "data:,No document.";
 
-// A simple testing implementation of mojom::InterfaceProvider that binds
-// interface requests only for one hard-coded kind of interface.
-class TestSimpleInterfaceProviderImpl
-    : public service_manager::mojom::InterfaceProvider {
- public:
-  using BinderCallback =
-      base::RepeatingCallback<void(mojo::ScopedMessagePipeHandle)>;
-
-  // Incoming interface requests for |interface_name| will invoke |binder|.
-  // Everything else is ignored.
-  TestSimpleInterfaceProviderImpl(const std::string& interface_name,
-                                  BinderCallback binder_callback)
-      : interface_name_(interface_name), binder_callback_(binder_callback) {}
-
-  void BindAndFlush(
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          receiver) {
-    ASSERT_FALSE(receiver_.is_bound());
-    receiver_.Bind(std::move(receiver));
-    receiver_.FlushForTesting();
-  }
-
- private:
-  // mojom::InterfaceProvider:
-  void GetInterface(const std::string& interface_name,
-                    mojo::ScopedMessagePipeHandle handle) override {
-    if (interface_name == interface_name_)
-      binder_callback_.Run(std::move(handle));
-  }
-
-  mojo::Receiver<service_manager::mojom::InterfaceProvider> receiver_{this};
-
-  std::string interface_name_;
-  BinderCallback binder_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestSimpleInterfaceProviderImpl);
-};
-
 class TestSimpleBrowserInterfaceBrokerImpl
     : public blink::mojom::BrowserInterfaceBroker {
  public:
@@ -600,15 +555,7 @@
 
   void RequestTestInterfaceOnFrameEvent(const std::string& event) {
     mojo::Remote<mojom::FrameHostTestInterface> remote;
-    render_frame()->GetRemoteInterfaces()->GetInterface(
-        remote.BindNewPipeAndPassReceiver());
-
     blink::WebDocument document = render_frame()->GetWebFrame()->GetDocument();
-    remote->Ping(
-        !document.IsNull() ? GURL(document.Url()) : GURL(kNoDocumentMarkerURL),
-        event);
-
-    remote.reset();
     render_frame()->GetBrowserInterfaceBroker()->GetInterface(
         remote.BindNewPipeAndPassReceiver());
     remote->Ping(
@@ -727,29 +674,16 @@
     EXPECT_EQ(expected_loaded_url,
               GURL(frame_->GetWebFrame()->GetDocument().Url()));
 
-    interface_receiver_for_first_document_ =
-        frame_->TakeLastInterfaceProviderReceiver();
-
     browser_interface_broker_receiver_for_first_document_ =
         frame_->TakeLastBrowserInterfaceBrokerReceiver();
   }
 
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-  interface_request_for_initial_empty_document() {
-    return std::move(interface_request_for_initial_empty_document_);
-  }
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   browser_interface_broker_receiver_for_initial_empty_document() {
     return std::move(
         browser_interface_broker_receiver_for_initial_empty_document_);
   }
 
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-  interface_request_for_first_document() {
-    return std::move(interface_receiver_for_first_document_);
-  }
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   browser_interface_broker_receiver_for_first_document() {
     return std::move(browser_interface_broker_receiver_for_first_document_);
@@ -773,8 +707,6 @@
     test_request_issuer_->RequestTestInterfaceOnFrameEvent(
         kFrameEventDidCreateNewFrame);
 
-    interface_request_for_initial_empty_document_ =
-        frame->TakeLastInterfaceProviderReceiver();
     browser_interface_broker_receiver_for_initial_empty_document_ =
         frame_->TakeLastBrowserInterfaceBrokerReceiver();
     EXPECT_TRUE(frame->GetWebFrame()->GetCurrentHistoryItem().IsNull());
@@ -788,11 +720,6 @@
   base::Optional<FrameCommitWaiter> frame_commit_waiter_;
   base::Optional<FrameHostTestInterfaceRequestIssuer> test_request_issuer_;
 
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-      interface_request_for_initial_empty_document_;
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-      interface_receiver_for_first_document_;
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker_receiver_for_initial_empty_document_;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
@@ -802,29 +729,15 @@
 };
 
 // Extracts all interface receivers for FrameHostTestInterface pending on the
-// specified |interface_provider_receiver|, and returns a list of the source
-// annotations that are provided in the pending Ping() call for each of these
-// FrameHostTestInterface receivers.
+// specified |browser_interface_broker_receiver|, and returns a list of the
+// source annotations that are provided in the pending Ping() call for each of
+// these FrameHostTestInterface receivers.
 void ExpectPendingInterfaceReceiversFromSources(
-    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-        interface_provider_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     std::vector<SourceAnnotation> expected_sources) {
   std::vector<SourceAnnotation> sources;
-  ASSERT_TRUE(interface_provider_receiver.is_valid());
-  TestSimpleInterfaceProviderImpl provider(
-      mojom::FrameHostTestInterface::Name_,
-      base::BindLambdaForTesting([&sources](
-                                     mojo::ScopedMessagePipeHandle handle) {
-        FrameHostTestInterfaceImpl impl;
-        impl.BindAndFlush(mojo::PendingReceiver<mojom::FrameHostTestInterface>(
-            std::move(handle)));
-        ASSERT_TRUE(impl.ping_source().has_value());
-        sources.push_back(impl.ping_source().value());
-      }));
-  provider.BindAndFlush(std::move(interface_provider_receiver));
-  EXPECT_THAT(sources, ::testing::ElementsAreArray(expected_sources));
+  ASSERT_TRUE(browser_interface_broker_receiver.is_valid());
 
   std::vector<SourceAnnotation> browser_interface_broker_sources;
   ASSERT_TRUE(browser_interface_broker_receiver.is_valid());
@@ -897,9 +810,6 @@
 
 // Expect that |remote_interfaces_| is bound before the first committed load in
 // a child frame, and then re-bound on the first commit.
-// TODO(crbug.com/718652): when all clients are converted to use
-// BrowserInterfaceBroker, PendingReceiver<InterfaceProvider>-related code will
-// be removed.
 TEST_F(RenderFrameRemoteInterfacesTest, ChildFrameAtFirstCommittedLoad) {
   ScopedNewFrameInterfaceProviderExerciser child_frame_exerciser(
       frame_creation_observer());
@@ -915,7 +825,6 @@
   // details of frame/document creation this encodes. Need to decouple.
   const GURL initial_empty_url(kAboutBlankURL);
   ExpectPendingInterfaceReceiversFromSources(
-      child_frame_exerciser.interface_request_for_initial_empty_document(),
       child_frame_exerciser
           .browser_interface_broker_receiver_for_initial_empty_document(),
       {{GURL(kNoDocumentMarkerURL), kFrameEventDidCreateNewFrame},
@@ -927,7 +836,6 @@
        // provisional load would have even committed.
        {child_frame_url, kFrameEventDidCreateNewDocument}});
   ExpectPendingInterfaceReceiversFromSources(
-      child_frame_exerciser.interface_request_for_first_document(),
       child_frame_exerciser
           .browser_interface_broker_receiver_for_first_document(),
       {{child_frame_url, kFrameEventDidCommitProvisionalLoad},
@@ -936,9 +844,6 @@
 
 // Expect that |remote_interfaces_| is bound before the first committed load in
 // the main frame of an opened window, and then re-bound on the first commit.
-// TODO(crbug.com/718652): when all clients are converted to use
-// BrowserInterfaceBroker, PendingReceiver<InterfaceProvider>-related code will
-// be removed.
 TEST_F(RenderFrameRemoteInterfacesTest,
        MainFrameOfOpenedWindowAtFirstCommittedLoad) {
   const GURL new_window_url("data:text/html,NewWindow");
@@ -967,14 +872,12 @@
   // details of frame/document creation this encodes. Need to decouple.
   const GURL initial_empty_url;
   ExpectPendingInterfaceReceiversFromSources(
-      main_frame_exerciser.interface_request_for_initial_empty_document(),
       main_frame_exerciser
           .browser_interface_broker_receiver_for_initial_empty_document(),
       {{initial_empty_url, kFrameEventDidCreateNewFrame},
        {new_window_url, kFrameEventReadyToCommitNavigation},
        {new_window_url, kFrameEventDidCreateNewDocument}});
   ExpectPendingInterfaceReceiversFromSources(
-      main_frame_exerciser.interface_request_for_first_document(),
       main_frame_exerciser
           .browser_interface_broker_receiver_for_first_document(),
       {{new_window_url, kFrameEventDidCommitProvisionalLoad},
@@ -1029,7 +932,6 @@
         child_frame_exerciser.ExpectNewFrameAndWaitForLoad(child_frame_url));
 
     ExpectPendingInterfaceReceiversFromSources(
-        child_frame_exerciser.interface_request_for_initial_empty_document(),
         child_frame_exerciser
             .browser_interface_broker_receiver_for_initial_empty_document(),
         {{GURL(kNoDocumentMarkerURL), kFrameEventDidCreateNewFrame},
@@ -1040,8 +942,6 @@
          {child_frame_url, kFrameEventDidCommitProvisionalLoad},
          {child_frame_url, kFrameEventDidCreateDocumentElement}});
 
-    auto request = child_frame_exerciser.interface_request_for_first_document();
-    ASSERT_FALSE(request.is_valid());
     auto browser_interface_broker_receiver =
         child_frame_exerciser
             .browser_interface_broker_receiver_for_first_document();
@@ -1051,15 +951,9 @@
 
 // Expect that |remote_interfaces_| is bound to a new pipe on cross-document
 // navigations.
-// TODO(crbug.com/718652): when all clients are converted to use
-// BrowserInterfaceBroker, PendingReceiver<InterfaceProvider>-related code will
-// be removed.
 TEST_F(RenderFrameRemoteInterfacesTest, ReplacedOnNonSameDocumentNavigation) {
   LoadHTMLWithUrlOverride("", kTestFirstURL);
 
-  auto interface_provider_receiver_for_first_document =
-      GetMainRenderFrame()->TakeLastInterfaceProviderReceiver();
-
   auto browser_interface_broker_receiver_for_first_document =
       GetMainRenderFrame()->TakeLastBrowserInterfaceBrokerReceiver();
 
@@ -1068,27 +962,20 @@
 
   LoadHTMLWithUrlOverride("", kTestSecondURL);
 
-  auto interface_provider_receiver_for_second_document =
-      GetMainRenderFrame()->TakeLastInterfaceProviderReceiver();
-
   auto browser_interface_broker_receiver_for_second_document =
       GetMainRenderFrame()->TakeLastBrowserInterfaceBrokerReceiver();
 
-  ASSERT_TRUE(interface_provider_receiver_for_first_document.is_valid());
   ASSERT_TRUE(browser_interface_broker_receiver_for_first_document.is_valid());
 
   ExpectPendingInterfaceReceiversFromSources(
-      std::move(interface_provider_receiver_for_first_document),
       std::move(browser_interface_broker_receiver_for_first_document),
       {{GURL(kTestFirstURL), kFrameEventAfterCommit},
        {GURL(kTestSecondURL), kFrameEventReadyToCommitNavigation},
        {GURL(kTestSecondURL), kFrameEventDidCreateNewDocument}});
 
-  ASSERT_TRUE(interface_provider_receiver_for_second_document.is_valid());
   ASSERT_TRUE(browser_interface_broker_receiver_for_second_document.is_valid());
 
   ExpectPendingInterfaceReceiversFromSources(
-      std::move(interface_provider_receiver_for_second_document),
       std::move(browser_interface_broker_receiver_for_second_document),
       {{GURL(kTestSecondURL), kFrameEventDidCommitProvisionalLoad},
        {GURL(kTestSecondURL), kFrameEventDidCreateDocumentElement}});
@@ -1097,29 +984,18 @@
 // Expect that |remote_interfaces_| is not bound to a new pipe on same-document
 // navigations, i.e. the existing InterfaceProvider connection is continued to
 // be used.
-// TODO(crbug.com/718652): when all clients are converted to use
-// BrowserInterfaceBroker, PendingReceiver<InterfaceProvider>-related code will
-// be removed.
 TEST_F(RenderFrameRemoteInterfacesTest, ReusedOnSameDocumentNavigation) {
   LoadHTMLWithUrlOverride("", kTestFirstURL);
 
-  auto interface_provider_receiver =
-      GetMainRenderFrame()->TakeLastInterfaceProviderReceiver();
-
   auto browser_interface_broker_receiver =
       GetMainRenderFrame()->TakeLastBrowserInterfaceBrokerReceiver();
 
   FrameHostTestInterfaceRequestIssuer requester(GetMainRenderFrame());
   OnSameDocumentNavigation(GetMainFrame(), true /* is_new_navigation */);
 
-  EXPECT_FALSE(
-      GetMainRenderFrame()->TakeLastInterfaceProviderReceiver().is_valid());
-
-  ASSERT_TRUE(interface_provider_receiver.is_valid());
   ASSERT_TRUE(browser_interface_broker_receiver.is_valid());
 
   ExpectPendingInterfaceReceiversFromSources(
-      std::move(interface_provider_receiver),
       std::move(browser_interface_broker_receiver),
       {{GURL(kTestFirstURL), kFrameEventDidCommitSameDocumentLoad}});
 }
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index 789525b..4e7aa30f 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -683,10 +683,6 @@
   if (web_frame()) {
     web_frame()->SetCcLayer(layer.get(), prevent_contents_opaque_changes,
                             is_surface_layer);
-
-    // Schedule an animation so that a new frame is produced with the updated
-    // layer, otherwise this local root's visible content may not be up to date.
-    ancestor_render_widget_->ScheduleAnimation();
   }
   embedded_layer_ = std::move(layer);
 }
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 9c5d001..aa0472b 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1309,13 +1309,6 @@
   return !compositor_task_runner_;
 }
 
-scoped_refptr<base::SingleThreadTaskRunner>
-RenderThreadImpl::GetCleanupTaskRunner() {
-  return current_blink_platform_impl()
-      ->main_thread_scheduler()
-      ->DefaultTaskRunner();
-}
-
 gpu::GpuMemoryBufferManager* RenderThreadImpl::GetGpuMemoryBufferManager() {
   return gpu_->gpu_memory_buffer_manager();
 }
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 5d45653..2205187 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -197,7 +197,6 @@
   bool IsElasticOverscrollEnabled() override;
   bool IsUseZoomForDSFEnabled() override;
   bool IsSingleThreaded() override;
-  scoped_refptr<base::SingleThreadTaskRunner> GetCleanupTaskRunner() override;
   blink::scheduler::WebThreadScheduler* GetWebMainThreadScheduler() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
   bool IsScrollAnimatorEnabled() override;
@@ -499,7 +498,7 @@
   void OnRendererInterfaceReceiver(
       mojo::PendingAssociatedReceiver<mojom::Renderer> receiver);
 
-  std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+  scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
       discardable_memory_allocator_;
 
   // These objects live solely on the render thread.
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 7e0cf313..f18466e 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -94,6 +94,7 @@
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_navigation_params.h"
 #include "third_party/blink/public/web/web_origin_trials.h"
+#include "third_party/blink/public/web/web_page_popup.h"
 #include "third_party/blink/public/web/web_performance.h"
 #include "third_party/blink/public/web/web_script_source.h"
 #include "third_party/blink/public/web/web_settings.h"
@@ -291,10 +292,7 @@
   }
 
   blink::WebFrameWidget* main_frame_widget() {
-    return static_cast<blink::WebFrameWidget*>(view()
-                                                   ->GetMainRenderFrame()
-                                                   ->GetLocalRootRenderWidget()
-                                                   ->GetWebWidget());
+    return view()->GetMainRenderFrame()->GetLocalRootWebFrameWidget();
   }
 
   TestRenderFrame* frame() {
@@ -505,7 +503,7 @@
   }
 
   gfx::Size MainWidgetSizeInDIPS() {
-    blink::WebSize widget_size = main_widget()->GetWebWidget()->Size();
+    blink::WebSize widget_size = main_frame_widget()->Size();
     blink::WebRect widget_rect(0, 0, widget_size.width, widget_size.height);
     main_widget()->ConvertViewportToWindow(&widget_rect);
     return gfx::Rect(widget_rect).size();
@@ -547,14 +545,12 @@
   }
 
   void SetDeviceScaleFactor(float dsf) {
-    RenderWidget* widget = main_widget();
-    widget->GetWebWidget()->ApplyVisualProperties(
+    blink::WebFrameWidget* widget = main_frame_widget();
+    widget->ApplyVisualProperties(
         MakeVisualPropertiesWithDeviceScaleFactor(dsf));
 
     ASSERT_EQ(dsf, view()->GetMainRenderFrame()->GetDeviceScaleFactor());
-    ASSERT_EQ(
-        dsf,
-        widget->GetWebWidget()->GetOriginalScreenInfo().device_scale_factor);
+    ASSERT_EQ(dsf, widget->GetOriginalScreenInfo().device_scale_factor);
   }
 
   blink::VisualProperties MakeVisualPropertiesWithDeviceScaleFactor(float dsf) {
@@ -730,16 +726,11 @@
   gfx::Rect widget_screen_rect(5, 7, 57, 59);
 
   // Verify screen rect will be set.
-  EXPECT_EQ(gfx::Rect(main_widget()->GetWebWidget()->GetScreenInfo().rect),
-            screen_rect);
+  EXPECT_EQ(gfx::Rect(main_frame_widget()->GetScreenInfo().rect), screen_rect);
 
   {
     // Make a popup widget.
     blink::WebPagePopup* popup = view()->CreatePopup(frame()->GetWebFrame());
-    RenderWidget* popup_widget =
-        static_cast<RenderWidget*>(popup->GetClientForTesting());
-    ASSERT_TRUE(popup_widget);
-
     // Set its size.
     popup->SetScreenRects(widget_screen_rect, window_screen_rect);
 
@@ -749,7 +740,7 @@
     EXPECT_EQ(widget_screen_rect, gfx::Rect(popup->ViewRect()));
     EXPECT_EQ(screen_rect, gfx::Rect(popup->GetScreenInfo().rect));
 
-    popup->GetClientForTesting()->BrowserClosedIpcChannelForPopupWidget();
+    popup->Close();
   }
 
   // Enable device emulation on the parent widget.
@@ -766,9 +757,6 @@
     // Make a popup again. It should inherit device emulation params.
     blink::WebPagePopup* popup = view()->CreatePopup(frame()->GetWebFrame());
     popup->InitializeForTesting(view()->GetWebView());
-    RenderWidget* popup_widget =
-        static_cast<RenderWidget*>(popup->GetClientForTesting());
-    ASSERT_TRUE(popup_widget);
 
     // Set its size again.
     popup->SetScreenRects(widget_screen_rect, window_screen_rect);
@@ -795,20 +783,18 @@
     EXPECT_EQ(window_screen_rect.height(), popup->WindowRect().height());
     EXPECT_EQ(widget_screen_rect.width(), popup->ViewRect().width());
     EXPECT_EQ(widget_screen_rect.height(), popup->ViewRect().height());
+    EXPECT_EQ(emulated_widget_rect, gfx::Rect(main_frame_widget()->ViewRect()));
     EXPECT_EQ(emulated_widget_rect,
-              gfx::Rect(main_widget()->GetWebWidget()->ViewRect()));
-    EXPECT_EQ(emulated_widget_rect,
-              gfx::Rect(main_widget()->GetWebWidget()->WindowRect()));
+              gfx::Rect(main_frame_widget()->WindowRect()));
 
     // TODO(danakj): Why isn't the ScreenRect visible to the popup an emulated
     // value? The ScreenRect has been changed by emulation as demonstrated
     // below.
-    EXPECT_EQ(gfx::Rect(800, 600),
-              gfx::Rect(popup_widget->GetWebWidget()->GetScreenInfo().rect));
+    EXPECT_EQ(gfx::Rect(800, 600), gfx::Rect(popup->GetScreenInfo().rect));
     EXPECT_EQ(emulated_widget_rect,
-              gfx::Rect(main_widget()->GetWebWidget()->GetScreenInfo().rect));
+              gfx::Rect(main_frame_widget()->GetScreenInfo().rect));
 
-    popup->GetClientForTesting()->BrowserClosedIpcChannelForPopupWidget();
+    popup->Close();
   }
 }
 
@@ -1150,20 +1136,16 @@
   // Verify that the system device scale factor has propagated into the
   // RenderFrameProxy.
   EXPECT_EQ(device_scale, view()->GetMainRenderFrame()->GetDeviceScaleFactor());
-  EXPECT_EQ(device_scale, main_widget()
-                              ->GetWebWidget()
-                              ->GetOriginalScreenInfo()
-                              .device_scale_factor);
+  EXPECT_EQ(device_scale,
+            main_frame_widget()->GetOriginalScreenInfo().device_scale_factor);
   EXPECT_EQ(device_scale, child_proxy->screen_info().device_scale_factor);
 
   TestEmulatedSizeDprDsf(640, 480, 3.f, compositor_dsf);
 
   // Verify that the RenderFrameProxy device scale factor is still the same.
   EXPECT_EQ(3.f, view()->GetMainRenderFrame()->GetDeviceScaleFactor());
-  EXPECT_EQ(device_scale, main_widget()
-                              ->GetWebWidget()
-                              ->GetOriginalScreenInfo()
-                              .device_scale_factor);
+  EXPECT_EQ(device_scale,
+            main_frame_widget()->GetOriginalScreenInfo().device_scale_factor);
   EXPECT_EQ(device_scale, child_proxy->screen_info().device_scale_factor);
 
   ReceiveDisableDeviceEmulation(view());
@@ -1241,9 +1223,6 @@
   // Do the remote-to-local transition for the proxy, which is to create a
   // provisional local frame.
   int routing_id = kProxyRoutingId + 1;
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      stub_interface_provider;
-  ignore_result(stub_interface_provider.InitWithNewPipeAndPassReceiver());
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       stub_browser_interface_broker;
   ignore_result(stub_browser_interface_broker.InitWithNewPipeAndPassReceiver());
@@ -1277,7 +1256,7 @@
   widget_params->widget_host = blink_widget_host.Unbind();
 
   RenderFrameImpl::CreateFrame(
-      *agent_scheduling_group_, routing_id, std::move(stub_interface_provider),
+      *agent_scheduling_group_, routing_id,
       std::move(stub_browser_interface_broker), kProxyRoutingId, base::nullopt,
       MSG_ROUTING_NONE, MSG_ROUTING_NONE, base::UnguessableToken::Create(),
       base::UnguessableToken::Create(), replication_state,
@@ -1338,15 +1317,12 @@
   // Do the first step of a remote-to-local transition for the child proxy,
   // which is to create a provisional local frame.
   int routing_id = kProxyRoutingId + 1;
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      stub_interface_provider;
-  ignore_result(stub_interface_provider.InitWithNewPipeAndPassReceiver());
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       stub_browser_interface_broker;
   ignore_result(stub_browser_interface_broker.InitWithNewPipeAndPassReceiver());
 
   RenderFrameImpl::CreateFrame(
-      *agent_scheduling_group_, routing_id, std::move(stub_interface_provider),
+      *agent_scheduling_group_, routing_id,
       std::move(stub_browser_interface_broker), kProxyRoutingId, base::nullopt,
       frame()->GetRoutingID(), MSG_ROUTING_NONE,
       base::UnguessableToken::Create(), base::UnguessableToken::Create(),
@@ -1476,7 +1452,7 @@
 
     // Update the IME status and verify if our IME backend sends an IPC message
     // to activate IMEs.
-    main_widget()->UpdateTextInputState();
+    main_frame_widget()->UpdateTextInputState();
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(1u, updated_states().size());
     ui::TextInputType type = updated_states()[0]->type;
@@ -1493,7 +1469,7 @@
 
     // Update the IME status and verify if our IME backend sends an IPC message
     // to de-activate IMEs.
-    main_widget()->UpdateTextInputState();
+    main_frame_widget()->UpdateTextInputState();
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(1u, updated_states().size());
     type = updated_states()[0]->type;
@@ -1513,7 +1489,7 @@
 
       // Update the IME status and verify if our IME backend sends an IPC
       // message to activate IMEs.
-      main_widget()->UpdateTextInputState();
+      main_frame_widget()->UpdateTextInputState();
       base::RunLoop().RunUntilIdle();
       EXPECT_EQ(1u, updated_states().size());
       type = updated_states()[0]->type;
@@ -1559,7 +1535,7 @@
   // Focus the text field, trigger a state update and check that the right IPC
   // is sent.
   ExecuteJavaScriptForTests("document.getElementById('test').focus();");
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   EXPECT_FALSE(updated_states()[0]->always_hide_ime);
@@ -1568,7 +1544,7 @@
   // Tell the client to suppress the keyboard. Check whether always_hide_ime is
   // set correctly.
   client.SetShouldSuppressKeyboard(true);
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   EXPECT_TRUE(updated_states()[0]->always_hide_ime);
@@ -1607,7 +1583,7 @@
 
   // Update the IME status and verify if our IME backend sends an IPC message
   // to notify layout bounds of the EditContext.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   blink::WebRect edit_context_control_bounds_expected(10, 20, 30, 40);
@@ -1653,7 +1629,7 @@
   run_loop.Run();
   // Update the IME status and verify if our IME backend sends an IPC message
   // to notify layout bounds of the EditContext.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   blink::WebRect edit_context_control_bounds_expected(10, 20, 31, 41);
@@ -1700,7 +1676,7 @@
   run_loop.Run();
   // Update the IME status and verify if our IME backend sends an IPC message
   // to notify layout bounds of the EditContext.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   blink::WebRect edit_context_control_bounds_expected(-2147483648, -2147483648,
@@ -1740,7 +1716,7 @@
   run_loop.Run();
   // Update the IME status and verify if our IME backend sends an IPC message
   // to notify layout bounds of the EditContext.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   blink::WebInputMethodController* controller =
@@ -1774,7 +1750,7 @@
   run_loop.Run();
   // Update the text input state and verify the virtualkeyboardpolicy attribute
   // value.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   EXPECT_EQ(updated_states()[0]->vk_policy,
@@ -1802,7 +1778,7 @@
   run_loop.Run();
   // Update the IME status and verify if our IME backend sends an IPC message
   // to notify virtualkeyboardpolicy change of the focused element.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   EXPECT_EQ(updated_states()[0]->vk_policy,
@@ -1836,7 +1812,7 @@
   // Update the IME status and verify if our IME backend sends an IPC message
   // to notify virtualkeyboardpolicy change of the focused element and the show
   // API call.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   EXPECT_EQ(updated_states()[0]->vk_policy,
@@ -1854,7 +1830,7 @@
   // Update the IME status and verify if our IME backend sends an IPC message
   // to notify virtualkeyboardpolicy change of the focused element and the hide
   // API call.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   EXPECT_EQ(updated_states()[0]->vk_policy,
@@ -1887,7 +1863,7 @@
   // Update the IME status and verify if our IME backend sends an IPC message
   // to notify virtualkeyboardpolicy change of the focused element and the show
   // API call.
-  main_widget()->UpdateTextInputState();
+  main_frame_widget()->UpdateTextInputState();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, updated_states().size());
   EXPECT_EQ(updated_states()[0]->vk_policy,
@@ -2020,7 +1996,7 @@
 
     // Update the status of our IME back-end.
     // TODO(hbono): we should verify messages to be sent from the back-end.
-    main_widget()->UpdateTextInputState();
+    main_frame_widget()->UpdateTextInputState();
     base::RunLoop().RunUntilIdle();
     render_thread_->sink().ClearMessages();
 
@@ -2569,7 +2545,7 @@
               TextSelectionChanged(testing::_, testing::_, testing::_))
       .Times(1);
 
-  main_widget()->SetHandlingInputEvent(true);
+  main_frame_widget()->SetHandlingInputEvent(true);
   ExecuteJavaScriptForTests("document.getElementById('test').focus();");
 }
 
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 3ae03a8..acab23c 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -11,6 +11,7 @@
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_piece.h"
+#include "cc/trees/ukm_manager.h"
 #include "content/child/webthemeengine_impl_default.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_constants.h"
@@ -29,6 +30,7 @@
 #include "third_party/blink/public/web/modules/mediastream/web_media_stream_device_observer.h"
 #include "third_party/blink/public/web/web_frame_widget.h"
 #include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_page_popup.h"
 #include "third_party/blink/public/web/web_view.h"
 #include "third_party/blink/public/web/web_window_features.h"
 #include "ui/base/ui_base_features.h"
@@ -298,12 +300,6 @@
   observers_.RemoveObserver(observer);
 }
 
-// RenderWidgetOwnerDelegate -----------------------------------------
-
-bool RenderViewImpl::SupportsMultipleWindowsForWidget() {
-  return webview_->GetWebPreferences().supports_multiple_windows;
-}
-
 // IPC message handlers -----------------------------------------
 
 void RenderViewImpl::OnSetHistoryOffsetAndLength(int history_offset,
@@ -448,7 +444,6 @@
   view_params->blink_page_broadcast = std::move(reply->page_broadcast);
   view_params->main_frame_interface_bundle =
       mojom::DocumentScopedInterfaceBundle::New(
-          std::move(reply->main_frame_interface_bundle->interface_provider),
           std::move(
               reply->main_frame_interface_bundle->browser_interface_broker));
   view_params->main_frame_widget_routing_id = reply->main_frame_widget_route_id;
@@ -501,26 +496,21 @@
   RenderFrameImpl::FromWebFrame(creator)->GetFrameHost()->CreateNewPopupWidget(
       std::move(blink_popup_widget_host_receiver),
       std::move(blink_widget_host_receiver), std::move(blink_widget));
-  RenderWidget* opener_render_widget =
-      RenderFrameImpl::FromWebFrame(creator)->GetLocalRootRenderWidget();
-
-  RenderWidget* popup_widget =
-      RenderWidget::CreateForPopup(opener_render_widget->compositor_deps());
+  blink::WebFrameWidget* opener_widget =
+      RenderFrameImpl::FromWebFrame(creator)->GetLocalRootWebFrameWidget();
 
   // The returned WebPagePopup is self-referencing, so the pointer here is not
   // an owning pointer. It is de-referenced by calling Close().
-  blink::WebPagePopup* popup_web_widget = blink::WebPagePopup::Create(
-      popup_widget, std::move(blink_popup_widget_host),
-      std::move(blink_widget_host), std::move(blink_widget_receiver),
+  blink::WebPagePopup* popup = blink::WebPagePopup::Create(
+      std::move(blink_popup_widget_host), std::move(blink_widget_host),
+      std::move(blink_widget_receiver),
       agent_scheduling_group_.agent_group_scheduler().DefaultTaskRunner());
-
-  // Adds a self-reference on the |popup_widget| so it will not be destroyed
-  // when leaving scope. The WebPagePopup takes responsibility for Close()ing
-  // and thus destroying the RenderWidget.
-  popup_widget->InitForPopup(
-      opener_render_widget, popup_web_widget,
-      opener_render_widget->GetWebWidget()->GetOriginalScreenInfo());
-  return popup_web_widget;
+  popup->InitializeCompositing(compositor_deps_->GetWebMainThreadScheduler(),
+                               compositor_deps_->GetTaskGraphRunner(),
+                               opener_widget->GetOriginalScreenInfo(),
+                               compositor_deps_->CreateUkmRecorderFactory(),
+                               /*settings=*/nullptr);
+  return popup;
 }
 
 base::StringPiece RenderViewImpl::GetSessionStorageNamespaceId() {
@@ -530,10 +520,10 @@
 
 void RenderViewImpl::PrintPage(WebLocalFrame* frame) {
   RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame);
-  RenderWidget* render_widget = render_frame->GetLocalRootRenderWidget();
+  blink::WebFrameWidget* frame_widget =
+      render_frame->GetLocalRootWebFrameWidget();
 
-  render_frame->ScriptedPrint(
-      render_widget->GetWebWidget()->HandlingInputEvent());
+  render_frame->ScriptedPrint(frame_widget->HandlingInputEvent());
 }
 
 void RenderViewImpl::ZoomLevelChanged() {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 6ffea70..1592aa44 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -35,7 +35,6 @@
 #include "content/public/renderer/render_view.h"
 #include "content/renderer/render_frame_impl.h"
 #include "content/renderer/render_widget.h"
-#include "content/renderer/render_widget_delegate.h"
 #include "ipc/ipc_platform_file.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
@@ -86,19 +85,8 @@
 // placeholders behind. Each such frame tree also includes a RenderViewImpl as
 // the owner of it. Thus a tab may have multiple RenderViewImpls, one for the
 // main frame, and one for each other frame tree generated.
-//
-// When the main frame is part of this RenderViewImpl's frame tree, then this
-// object acts as the RenderWidgetDelegate for that frame's RenderWidget. Other
-// RenderWidgets would have a null RenderWidgetDelegate.
-//
-// Note: There are cases where there may be multiple main frames in tab. For
-// example, both Portals and GuestViews create their own RenderView that's
-// nested within another RenderView's frame tree. In these cases, the
-// RenderWidget for the nested view will have a non-null RenderWidgetDelegate,
-// despite the fact that it isn't the root of the hierarchy.
 class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
                                       public IPC::Listener,
-                                      public RenderWidgetDelegate,
                                       public RenderView {
  public:
   // Creates a new RenderView. Note that if the original opener has been closed,
@@ -308,10 +296,6 @@
                   bool was_created_by_renderer,
                   scoped_refptr<base::SingleThreadTaskRunner> task_runner);
 
-  // RenderWidgetDelegate implementation ----------------------------------
-
-  bool SupportsMultipleWindowsForWidget() override;
-
   // Old WebLocalFrameClient implementations
   // ----------------------------------------
 
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index fd69bffa..933cafb 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -19,42 +19,21 @@
 #include "ppapi/buildflags/buildflags.h"
 #include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/public/web/web_frame_widget.h"
-#include "third_party/blink/public/web/web_page_popup.h"
 #include "third_party/blink/public/web/web_widget.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
 namespace content {
 
-namespace {
-
-RenderWidget::CreateRenderWidgetFunction g_create_render_widget_for_frame =
-    nullptr;
-
-}  // namespace
-
 // RenderWidget ---------------------------------------------------------------
 
-// static
-void RenderWidget::InstallCreateForFrameHook(
-    CreateRenderWidgetFunction create_widget) {
-  g_create_render_widget_for_frame = create_widget;
-}
-
 std::unique_ptr<RenderWidget> RenderWidget::CreateForFrame(
     CompositorDependencies* compositor_deps) {
-  if (g_create_render_widget_for_frame) {
-    return g_create_render_widget_for_frame(compositor_deps);
-  }
-
-  return std::make_unique<RenderWidget>(compositor_deps);
+  return std::make_unique<RenderWidget>(base::PassKey<RenderWidget>(),
+                                        compositor_deps);
 }
 
-RenderWidget* RenderWidget::CreateForPopup(
-    CompositorDependencies* compositor_deps) {
-  return new RenderWidget(compositor_deps);
-}
-
-RenderWidget::RenderWidget(CompositorDependencies* compositor_deps)
+RenderWidget::RenderWidget(base::PassKey<RenderWidget>,
+                           CompositorDependencies* compositor_deps)
     : compositor_deps_(compositor_deps) {
   DCHECK(RenderThread::IsMainThread());
   DCHECK(compositor_deps_);
@@ -66,29 +45,18 @@
       << " RenderWidget must be destroyed via RenderWidget::Close()";
 }
 
-void RenderWidget::InitForPopup(RenderWidget* opener_widget,
-                                blink::WebPagePopup* web_page_popup,
-                                const blink::ScreenInfo& screen_info) {
-  for_popup_ = true;
-  Initialize(web_page_popup, screen_info);
-}
-
 void RenderWidget::InitForMainFrame(blink::WebFrameWidget* web_frame_widget,
-                                    const blink::ScreenInfo& screen_info,
-                                    RenderWidgetDelegate& delegate) {
-  delegate_ = &delegate;
+                                    const blink::ScreenInfo& screen_info) {
   Initialize(web_frame_widget, screen_info);
 }
 
 void RenderWidget::InitForChildLocalRoot(
     blink::WebFrameWidget* web_frame_widget,
     const blink::ScreenInfo& screen_info) {
-  for_child_local_root_frame_ = true;
   Initialize(web_frame_widget, screen_info);
 }
 
 void RenderWidget::CloseForFrame(std::unique_ptr<RenderWidget> widget) {
-  DCHECK(for_frame());
   DCHECK_EQ(widget.get(), this);  // This method takes ownership of |this|.
 
   Close(std::move(widget));
@@ -99,48 +67,12 @@
   DCHECK(web_widget);
 
   webwidget_ = web_widget;
-  if (auto* scheduler_state = GetWebWidget()->RendererWidgetSchedulingState())
-    scheduler_state->SetHidden(web_widget->IsHidden());
-
   InitCompositing(screen_info);
-
-  // If the widget is hidden, delay starting the compositor until the user
-  // shows it. Otherwise start the compositor immediately. If the widget is
-  // for a provisional frame, this importantly starts the compositor before
-  // the frame is inserted into the frame tree, which impacts first paint
-  // metrics.
-  if (!web_widget->IsHidden())
-    web_widget->SetCompositorVisible(true);
-}
-
-void RenderWidget::BrowserClosedIpcChannelForPopupWidget() {
-  DCHECK(for_popup_);
-
-  Close(base::WrapUnique(this));
-}
-
-void RenderWidget::ScheduleAnimation() {
-  // This call is not needed in single thread mode for tests without a
-  // scheduler, but they override this method in order to schedule a synchronous
-  // composite task themselves.
-  // TODO(dtapuska): ScheduleAnimation might get called before layer_tree_host_
-  // is assigned, inside the InitializeCompositing call. This should eventually
-  // go away when this is moved inside blink. https://crbug.com/1097816
-  if (layer_tree_host_)
-    layer_tree_host_->SetNeedsAnimate();
-}
-
-void RenderWidget::UpdateTextInputState() {
-  GetWebWidget()->UpdateTextInputState();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // WebWidgetClient
 
-void RenderWidget::SetHandlingInputEvent(bool handling_input_event) {
-  GetWebWidget()->SetHandlingInputEvent(handling_input_event);
-}
-
 void RenderWidget::InitCompositing(const blink::ScreenInfo& screen_info) {
   TRACE_EVENT0("blink", "RenderWidget::InitializeLayerTreeView");
 
@@ -160,7 +92,7 @@
 
   closing_ = true;
 
-  webwidget_->Close(compositor_deps_->GetCleanupTaskRunner());
+  webwidget_->Close();
   webwidget_ = nullptr;
 
   // |layer_tree_host_| is valid only when |webwidget_| is valid. Close may
@@ -169,17 +101,9 @@
   layer_tree_host_ = nullptr;
 }
 
-blink::WebFrameWidget* RenderWidget::GetFrameWidget() const {
-  // TODO(danakj): Remove this check and don't call this method for non-frames.
-  if (!for_frame())
-    return nullptr;
-  return static_cast<blink::WebFrameWidget*>(webwidget_);
-}
-
 void RenderWidget::ConvertViewportToWindow(blink::WebRect* rect) {
   if (compositor_deps_->IsUseZoomForDSFEnabled()) {
-    float reverse =
-        1 / GetWebWidget()->GetOriginalScreenInfo().device_scale_factor;
+    float reverse = 1 / webwidget_->GetOriginalScreenInfo().device_scale_factor;
     // TODO(oshima): We may need to allow pixel precision here as the the
     // anchor element can be placed at half pixel.
     gfx::Rect window_rect = gfx::ScaleToEnclosedRect(gfx::Rect(*rect), reverse);
@@ -190,8 +114,4 @@
   }
 }
 
-void RenderWidget::UpdateSelectionBounds() {
-  GetWebWidget()->UpdateSelectionBounds();
-}
-
 }  // namespace content
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index d0d14a8..52a9d08 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -23,6 +23,7 @@
 #include "base/observer_list.h"
 #include "base/single_thread_task_runner.h"
 #include "base/time/time.h"
+#include "base/types/pass_key.h"
 #include "build/build_config.h"
 #include "cc/input/overscroll_behavior.h"
 #include "cc/input/touch_action.h"
@@ -32,7 +33,6 @@
 #include "content/common/buildflags.h"
 #include "content/common/content_export.h"
 #include "content/common/renderer.mojom-forward.h"
-#include "content/renderer/render_widget_delegate.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_sender.h"
@@ -44,7 +44,6 @@
 #include "third_party/blink/public/mojom/page/record_content_to_visible_time_request.mojom-forward.h"
 #include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/public/platform/web_text_input_info.h"
-#include "third_party/blink/public/web/web_page_popup.h"
 #include "third_party/blink/public/web/web_widget.h"
 #include "third_party/blink/public/web/web_widget_client.h"
 #include "ui/base/ime/ime_text_span.h"
@@ -60,22 +59,16 @@
 
 namespace blink {
 class WebFrameWidget;
-class WebPagePopup;
 }  // namespace blink
 
 namespace content {
 class CompositorDependencies;
-class RenderFrameImpl;
-class RenderFrameProxy;
-class RenderViewImpl;
-class RenderWidgetDelegate;
 
 // RenderWidget provides a communication bridge between a WebWidget and
 // a RenderWidgetHost, the latter of which lives in a different process.
 //
 // RenderWidget is used to implement:
 // - RenderViewImpl (deprecated)
-// - Popup "menus" (like the color chooser and date picker)
 // - Widgets for frames (the main frame, and subframes due to out-of-process
 //   iframe support)
 //
@@ -87,49 +80,21 @@
 // RenderFrameProxy. Each local root has a corresponding RenderWidget. This
 // RenderWidget is used to route input and graphical output between the browser
 // and the renderer.
-class CONTENT_EXPORT RenderWidget
-    : public blink::WebPagePopupClient {  // Is-a WebWidgetClient also
+class CONTENT_EXPORT RenderWidget : public blink::WebWidgetClient {
  public:
-  explicit RenderWidget(CompositorDependencies* compositor_deps);
+  RenderWidget(base::PassKey<RenderWidget>,
+               CompositorDependencies* compositor_deps);
 
   ~RenderWidget() override;
 
-  // Convenience type for creation method taken by InstallCreateForFrameHook().
-  // The method signature matches the RenderWidget constructor.
-  using CreateRenderWidgetFunction =
-      std::unique_ptr<RenderWidget> (*)(CompositorDependencies*);
-  // Overrides the implementation of CreateForFrame() function below. Used by
-  // web tests to return a partial fake of RenderWidget.
-  static void InstallCreateForFrameHook(
-      CreateRenderWidgetFunction create_widget);
-
   // Creates a RenderWidget that is meant to be associated with a RenderFrame.
-  // Testing infrastructure, such as test_runner, can override this function
-  // by calling InstallCreateForFrameHook().
   static std::unique_ptr<RenderWidget> CreateForFrame(
       CompositorDependencies* compositor_deps);
 
-  // Creates a RenderWidget for a popup. This is separate from CreateForFrame()
-  // because popups do not not need to be faked out.
-  // A RenderWidget popup is owned by the browser process. The object will be
-  // destroyed when the blink::mojom::WidgetHost channel is disconnected. The
-  // object can request its own destruction via
-  // blink::mojom::PopupWidgetHost::RequestClose().
-  static RenderWidget* CreateForPopup(
-      CompositorDependencies* compositor_deps);
-
-  // Initialize a new RenderWidget for a popup. The |show_callback| is called
-  // when RenderWidget::Show() happens. The |opener_widget| is the local root
-  // of the frame that is opening the popup.
-  void InitForPopup(RenderWidget* opener_widget,
-                    blink::WebPagePopup* web_page_popup,
-                    const blink::ScreenInfo& screen_info);
-
   // Initialize a new RenderWidget that will be attached to a RenderFrame (via
   // the WebFrameWidget), for a frame that is a main frame.
   void InitForMainFrame(blink::WebFrameWidget* web_frame_widget,
-                        const blink::ScreenInfo& screen_info,
-                        RenderWidgetDelegate& delegate);
+                        const blink::ScreenInfo& screen_info);
 
   // Initialize a new RenderWidget that will be attached to a RenderFrame (via
   // the WebFrameWidget), for a frame that is a local root, but not the main
@@ -137,78 +102,33 @@
   void InitForChildLocalRoot(blink::WebFrameWidget* web_frame_widget,
                              const blink::ScreenInfo& screen_info);
 
-  RenderWidgetDelegate* delegate() const { return delegate_; }
-
   // Closes a RenderWidget that was created by |CreateForFrame|. Ownership is
   // passed into this object to asynchronously delete itself.
   void CloseForFrame(std::unique_ptr<RenderWidget> widget);
 
-  CompositorDependencies* compositor_deps() const { return compositor_deps_; }
-
   // This can return nullptr while the RenderWidget is closing. When for_frame()
   // is true, the widget returned is a blink::WebFrameWidget.
   blink::WebWidget* GetWebWidget() const { return webwidget_; }
 
-  // blink::WebWidgetClient
-  void ScheduleAnimation() override;
-  void BrowserClosedIpcChannelForPopupWidget() override;
-
   void ConvertViewportToWindow(blink::WebRect* rect);
-  void UpdateTextInputState();
 
   cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_; }
-  void SetHandlingInputEvent(bool handling_input_event);
-
-  // Checks if the selection bounds have been changed. If they are changed,
-  // the new value will be sent to the browser process.
-  void UpdateSelectionBounds();
-
- protected:
-  // Destroy the RenderWidget. The |widget| is the owning pointer of |this|.
-  virtual void Close(std::unique_ptr<RenderWidget> widget);
-
-  virtual void Initialize(blink::WebWidget* web_widget,
-                          const blink::ScreenInfo& screen_info);
 
  private:
-  // Friend RefCounted so that the dtor can be non-public. Using this class
-  // without ref-counting is an error.
-  friend class base::RefCounted<RenderWidget>;
+  // Destroy the RenderWidget. The |widget| is the owning pointer of |this|.
+  void Close(std::unique_ptr<RenderWidget> widget);
 
-  // TODO(nasko): Temporarily friend RenderFrameImpl for WasSwappedOut(),
-  // while we move frame specific code away from RenderViewImpl/RenderWidget.
-  friend class RenderFrameImpl;
-
-  // For unit tests.
-  friend class InteractiveRenderWidget;
-  friend class PopupRenderWidget;
-  friend class RenderWidgetTest;
-  friend class RenderViewImplTest;
+  void Initialize(blink::WebWidget* web_widget,
+                  const blink::ScreenInfo& screen_info);
 
   // Initializes the compositor and dependent systems, as part of the
   // Initialize() process.
   void InitCompositing(const blink::ScreenInfo& screen_info);
 
-  // Returns the WebFrameWidget associated with this RenderWidget if any.
-  // Returns nullptr if GetWebWidget() returns nullptr or returns a WebWidget
-  // that is not a WebFrameWidget. A WebFrameWidget only makes sense when there
-  // a local root associated with it.
-  blink::WebFrameWidget* GetFrameWidget() const;
-
-  // Whether this widget is for a frame. This excludes widgets that are not for
-  // a frame (eg popups, pepper), but includes both the main frame
-  // (via delegate_) and subframes (via for_child_local_root_frame_).
-  bool for_frame() const { return delegate_ || for_child_local_root_frame_; }
-
   // Dependencies for initializing a compositor, including flags for optional
   // features.
   CompositorDependencies* const compositor_deps_;
 
-  // The delegate for this object which is just a RenderViewImpl.
-  // This member is non-null if and only if the RenderWidget is associated with
-  // a RenderViewImpl.
-  RenderWidgetDelegate* delegate_ = nullptr;
-
   // We are responsible for destroying this object via its Close method, unless
   // the RenderWidget is associated with a RenderViewImpl through |delegate_|.
   // Becomes null once close is initiated on the RenderWidget.
@@ -221,17 +141,6 @@
   // verify destruction always goes through Close().
   bool closing_ = false;
 
-  // Whether this widget is for a child local root frame. This excludes widgets
-  // that are not for a frame (eg popups) and excludes the widget for the main
-  // frame (which is attached to the RenderViewImpl).
-  bool for_child_local_root_frame_ = false;
-  // RenderWidgets are created for frames and  popups. In the
-  // former case, the caller frame takes ownership and eventually passes the
-  // unique_ptr back in Close(). In the latter cases, the browser process takes
-  // ownership via IPC.  These booleans exist to allow us to confirm than an IPC
-  // message to kill the render widget is coming for a popup.
-  bool for_popup_ = false;
-
   DISALLOW_COPY_AND_ASSIGN(RenderWidget);
 };
 
diff --git a/content/renderer/render_widget_delegate.h b/content/renderer/render_widget_delegate.h
deleted file mode 100644
index 7ea2b17..0000000
--- a/content/renderer/render_widget_delegate.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_RENDER_WIDGET_DELEGATE_H_
-#define CONTENT_RENDERER_RENDER_WIDGET_DELEGATE_H_
-
-#include "content/common/content_export.h"
-
-namespace content {
-
-//
-// RenderWidgetDelegate
-//
-//  An interface to provide View-level (and/or Page-level) functionality to
-//  the main frame's RenderWidget.
-class CONTENT_EXPORT RenderWidgetDelegate {
- public:
-  virtual ~RenderWidgetDelegate() = default;
-
-  // Returns whether multiple windows are allowed for the widget. If true, then
-  // Show() may be called more than once.
-  virtual bool SupportsMultipleWindowsForWidget() = 0;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_RENDER_WIDGET_DELEGATE_H_
diff --git a/content/shell/browser/shell_permission_manager.cc b/content/shell/browser/shell_permission_manager.cc
index 23533f84..4b08f21 100644
--- a/content/shell/browser/shell_permission_manager.cc
+++ b/content/shell/browser/shell_permission_manager.cc
@@ -45,7 +45,6 @@
     case PermissionType::DURABLE_STORAGE:
     case PermissionType::AUDIO_CAPTURE:
     case PermissionType::VIDEO_CAPTURE:
-    case PermissionType::FLASH:
     case PermissionType::CLIPBOARD_READ_WRITE:
     case PermissionType::CLIPBOARD_SANITIZED_WRITE:
     case PermissionType::NUM:
diff --git a/content/test/data/android/input/input_combobox.html b/content/test/data/android/input/input_combobox.html
new file mode 100644
index 0000000..841de50
--- /dev/null
+++ b/content/test/data/android/input/input_combobox.html
@@ -0,0 +1,22 @@
+<!-- Simple combobox test html for end-to-end accessibility unit tests. -->
+<html>
+  <head>
+    <script>
+      function expandCombobox() {
+        document.getElementById('test-combobox').setAttribute('aria-expanded', 'true');
+        document.getElementById('test-listbox').removeAttribute('hidden');
+        document.getElementById('test-input').setAttribute('aria-controls', 'test-listbox');
+      }
+    </script>
+  </head>
+  <body>
+    <div id="test-combobox" role="combobox" aria-expanded="false">
+      <input id="test-input" type="text">
+      <ul id="test-listbox" role="listbox" hidden>
+        <li role="option">Chrome</li>
+        <li role="option">Chromium</li>
+        <li role="option">Clank</li>
+      </ul>
+    </div>
+  </body>
+</html>
\ No newline at end of file
diff --git a/content/test/data/android/input/input_combobox_aria1.0.html b/content/test/data/android/input/input_combobox_aria1.0.html
new file mode 100644
index 0000000..19a59cda
--- /dev/null
+++ b/content/test/data/android/input/input_combobox_aria1.0.html
@@ -0,0 +1,20 @@
+<!-- Simple aria-1.0 combobox test html for end-to-end a11y unit tests. -->
+<html>
+  <head>
+    <script>
+      function expandCombobox() {
+        document.getElementById('test-input').setAttribute('aria-expanded', 'true');
+        document.getElementById('test-listbox').removeAttribute('hidden');
+        document.getElementById('test-input').setAttribute('aria-controls', 'test-listbox');
+      }
+    </script>
+  </head>
+  <body>
+    <input id="test-input" type="text" role="combobox" aria-expanded="false">
+    <ul id="test-listbox" role="listbox" hidden>
+      <li role="option">Chrome</li>
+      <li role="option">Chromium</li>
+      <li role="option">Clank</li>
+    </ul>
+  </body>
+</html>
\ No newline at end of file
diff --git a/content/test/data/android/input/input_combobox_dialog.html b/content/test/data/android/input/input_combobox_dialog.html
new file mode 100644
index 0000000..911065bd
--- /dev/null
+++ b/content/test/data/android/input/input_combobox_dialog.html
@@ -0,0 +1,20 @@
+<!-- Simple combobox dialog test html for end-to-end a11y unit tests. -->
+<html>
+  <head>
+    <script>
+      function expandCombobox() {
+        document.getElementById('test-combobox').setAttribute('aria-expanded', 'true');
+        document.getElementById('test-dialog').removeAttribute('hidden');
+        document.getElementById('test-input').setAttribute('aria-controls', 'test-dialog');
+      }
+    </script>
+  </head>
+  <body>
+    <div id="test-combobox" role="combobox" aria-expanded="false">
+      <input id="test-input" type="text">
+      <div id="test-dialog" role="dialog" hidden>
+        <p>Example Dialog</p>
+      </ul>
+    </div>
+  </body>
+</html>
\ No newline at end of file
diff --git a/content/test/fake_compositor_dependencies.cc b/content/test/fake_compositor_dependencies.cc
index b9e219ef..d06037ff 100644
--- a/content/test/fake_compositor_dependencies.cc
+++ b/content/test/fake_compositor_dependencies.cc
@@ -39,11 +39,6 @@
   return true;
 }
 
-scoped_refptr<base::SingleThreadTaskRunner>
-FakeCompositorDependencies::GetCleanupTaskRunner() {
-  return base::ThreadTaskRunnerHandle::Get();
-}
-
 blink::scheduler::WebThreadScheduler*
 FakeCompositorDependencies::GetWebMainThreadScheduler() {
   return &main_thread_scheduler_;
diff --git a/content/test/fake_compositor_dependencies.h b/content/test/fake_compositor_dependencies.h
index b10b450..92d0f76d 100644
--- a/content/test/fake_compositor_dependencies.h
+++ b/content/test/fake_compositor_dependencies.h
@@ -25,7 +25,6 @@
   bool IsElasticOverscrollEnabled() override;
   bool IsUseZoomForDSFEnabled() override;
   bool IsSingleThreaded() override;
-  scoped_refptr<base::SingleThreadTaskRunner> GetCleanupTaskRunner() override;
   blink::scheduler::WebThreadScheduler* GetWebMainThreadScheduler() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
   bool IsScrollAnimatorEnabled() override;
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 37ccd70..a3b98e6 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -122,6 +122,9 @@
 # under crbug.com/963205 once these two failures are fixed.
 crbug.com/1136231 [ win ] conformance/extensions/s3tc-and-rgtc.html [ Failure ]
 crbug.com/1136231 [ linux ] conformance/extensions/s3tc-and-rgtc.html [ Failure ]
+crbug.com/1152259 [ win ] conformance/reading/read-pixels-test.html [ Failure ]
+crbug.com/1152259 [ linux ] conformance/reading/read-pixels-test.html [ Failure ]
+crbug.com/1152259 [ mac passthrough ] conformance/reading/read-pixels-test.html [ Failure ]
 
 crbug.com/953120 conformance/programs/program-handling.html [ Failure ]
 
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index c6e233fd..d842e1c 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -205,6 +205,8 @@
 # under crbug.com/963205 and crbug.com/964321 once these two failures are fixed.
 crbug.com/1136231 [ win ] conformance/extensions/s3tc-and-rgtc.html [ Failure ]
 crbug.com/1136231 [ linux ] conformance/extensions/s3tc-and-rgtc.html [ Failure ]
+crbug.com/1152259 [ win ] conformance/reading/read-pixels-test.html [ Failure ]
+crbug.com/1152259 [ linux ] conformance/reading/read-pixels-test.html [ Failure ]
 
 # Skipping new tests
 crbug.com/angleproject/5038 conformance/extensions/ext-color-buffer-half-float.html [ Skip ]
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index 1312bd2e..112d2bf 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -346,10 +346,6 @@
       transition_ = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
   }
 
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      stub_interface_provider;
-  interface_provider_receiver_ =
-      stub_interface_provider.InitWithNewPipeAndPassReceiver();
   browser_interface_broker_receiver_ =
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
           .InitWithNewPipeAndPassReceiver();
@@ -611,14 +607,13 @@
     drop_unload_ack_ = true;
 
   if (same_document_) {
-    interface_provider_receiver_.reset();
     browser_interface_broker_receiver_.reset();
   }
 
   auto params = BuildDidCommitProvisionalLoadParams(
       same_document_ /* same_document */, false /* failed_navigation */);
   render_frame_host_->SimulateCommitProcessed(
-      request_, std::move(params), std::move(interface_provider_receiver_),
+      request_, std::move(params),
       std::move(browser_interface_broker_receiver_), same_document_);
 
   if (previous_rfh)
@@ -762,7 +757,7 @@
   auto params = BuildDidCommitProvisionalLoadParams(
       false /* same_document */, true /* failed_navigation */);
   render_frame_host_->SimulateCommitProcessed(
-      request_, std::move(params), std::move(interface_provider_receiver_),
+      request_, std::move(params),
       std::move(browser_interface_broker_receiver_), false /* same_document */);
 
   SimulateUnloadCompletionCallbackForPreviousFrameIfNeeded(previous_rfh);
@@ -789,12 +784,10 @@
   auto params = BuildDidCommitProvisionalLoadParams(
       true /* same_document */, false /* failed_navigation */);
 
-  interface_provider_receiver_.reset();
   browser_interface_broker_receiver_.reset();
 
   render_frame_host_->SimulateCommitProcessed(
       request_, std::move(params),
-      mojo::NullReceiver() /* interface_provider_receiver_ */,
       mojo::NullReceiver() /* browser_interface_broker_receiver */,
       true /* same_document */);
 
diff --git a/content/test/navigation_simulator_impl.h b/content/test/navigation_simulator_impl.h
index 26d280a..d50cad58 100644
--- a/content/test/navigation_simulator_impl.h
+++ b/content/test/navigation_simulator_impl.h
@@ -22,7 +22,6 @@
 #include "net/base/host_port_pair.h"
 #include "net/base/ip_endpoint.h"
 #include "net/dns/public/resolve_error_info.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/mojom/loader/referrer.mojom-forward.h"
 #include "url/gurl.h"
 
@@ -288,8 +287,6 @@
   ReloadType reload_type_ = ReloadType::NONE;
   int session_history_offset_ = 0;
   bool has_user_gesture_ = true;
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-      interface_provider_receiver_;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker_receiver_;
   std::string contents_mime_type_;
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 9d22c7b..b0d41c155 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -45,11 +45,6 @@
     return std::move(last_commit_params_);
   }
 
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-  TakeLastInterfaceProviderReceiver() {
-    return std::move(last_interface_provider_receiver_);
-  }
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   TakeLastBrowserInterfaceBrokerReceiver() {
     return std::move(last_browser_interface_broker_receiver_);
@@ -60,16 +55,6 @@
     did_add_message_to_console_callback_ = std::move(callback);
   }
 
-  // Holds on to the receiver end of the InterfaceProvider interface whose
-  // client end is bound to the corresponding RenderFrame's |remote_interfaces_|
-  // to facilitate retrieving the most recent |interface_provider_receiver| in
-  // tests.
-  void PassLastInterfaceProviderReceiver(
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider_receiver) {
-    last_interface_provider_receiver_ = std::move(interface_provider_receiver);
-  }
-
   // Holds on to the receiver end of the BrowserInterfaceBroker interface whose
   // client end is bound to the corresponding RenderFrame's
   // |browser_interface_broker_proxy_| to facilitate retrieving the most recent
@@ -87,8 +72,6 @@
       override {
     last_commit_params_ = std::move(params);
     if (interface_params) {
-      last_interface_provider_receiver_ =
-          std::move(interface_params->interface_provider_receiver);
       last_browser_interface_broker_receiver_ =
           std::move(interface_params->browser_interface_broker_receiver);
     }
@@ -134,8 +117,6 @@
 
   void CreateChildFrame(
       int new_routing_id,
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider_receiver,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker_receiver,
       mojo::PendingAssociatedReceiver<blink::mojom::PolicyContainerHost>
@@ -150,8 +131,7 @@
     MockRenderThread* mock_render_thread =
         static_cast<MockRenderThread*>(RenderThread::Get());
     mock_render_thread->OnCreateChildFrame(
-        new_routing_id, std::move(interface_provider_receiver),
-        std::move(browser_interface_broker_receiver));
+        new_routing_id, std::move(browser_interface_broker_receiver));
   }
 
   void CreatePortal(mojo::PendingAssociatedReceiver<blink::mojom::Portal>,
@@ -223,8 +203,6 @@
 
  private:
   mojom::DidCommitProvisionalLoadParamsPtr last_commit_params_;
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-      last_interface_provider_receiver_;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       last_browser_interface_broker_receiver_;
 
@@ -252,9 +230,6 @@
       mock_frame_host_(std::make_unique<MockFrameHost>()) {
   MockRenderThread* mock_render_thread =
       static_cast<MockRenderThread*>(RenderThread::Get());
-  mock_frame_host_->PassLastInterfaceProviderReceiver(
-      mock_render_thread->TakeInitialInterfaceProviderRequestForFrame(
-          params.routing_id));
   mock_frame_host_->PassLastBrowserInterfaceBrokerReceiver(
       mock_render_thread->TakeInitialBrowserInterfaceBrokerReceiverForFrame(
           params.routing_id));
@@ -376,11 +351,6 @@
   mock_frame_host_->SetDidAddMessageToConsoleCallback(std::move(callback));
 }
 
-mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-TestRenderFrame::TakeLastInterfaceProviderReceiver() {
-  return mock_frame_host_->TakeLastInterfaceProviderReceiver();
-}
-
 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
 TestRenderFrame::TakeLastBrowserInterfaceBrokerReceiver() {
   return mock_frame_host_->TakeLastBrowserInterfaceBrokerReceiver();
diff --git a/content/test/test_render_frame.h b/content/test/test_render_frame.h
index 54e0d505..1a91732 100644
--- a/content/test/test_render_frame.h
+++ b/content/test/test_render_frame.h
@@ -61,9 +61,6 @@
   void SetDidAddMessageToConsoleCallback(
       base::OnceCallback<void(const base::string16& msg)> callback);
 
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-  TakeLastInterfaceProviderReceiver();
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   TakeLastBrowserInterfaceBrokerReceiver();
 
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 9cababe..a2cbc4d 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -147,7 +147,7 @@
     const blink::ParsedFeaturePolicy& allow) {
   std::string frame_unique_name = base::GenerateGUID();
   OnCreateChildFrame(
-      GetProcess()->GetNextRoutingID(), CreateStubInterfaceProviderReceiver(),
+      GetProcess()->GetNextRoutingID(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       CreateStubPolicyContainerHostReceiver(),
       blink::mojom::TreeScopeType::kDocument, frame_name, frame_unique_name,
@@ -411,8 +411,6 @@
 void TestRenderFrameHost::SimulateCommitProcessed(
     NavigationRequest* navigation_request,
     mojom::DidCommitProvisionalLoadParamsPtr params,
-    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-        interface_provider_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     bool same_document) {
@@ -427,7 +425,6 @@
         std::move(callback_it->second)
             .Run(std::move(params),
                  mojom::DidCommitProvisionalLoadInterfaceParams::New(
-                     std::move(interface_provider_receiver),
                      std::move(browser_interface_broker_receiver)));
         return;
       }
@@ -438,7 +435,6 @@
         std::move(callback_it->second)
             .Run(std::move(params),
                  mojom::DidCommitProvisionalLoadInterfaceParams::New(
-                     std::move(interface_provider_receiver),
                      std::move(browser_interface_broker_receiver)));
         return;
       }
@@ -448,7 +444,6 @@
   SendNavigateWithParamsAndInterfaceParams(
       std::move(params),
       mojom::DidCommitProvisionalLoadInterfaceParams::New(
-          std::move(interface_provider_receiver),
           std::move(browser_interface_broker_receiver)),
       same_document);
 }
@@ -556,24 +551,16 @@
 
 mojom::DidCommitProvisionalLoadInterfaceParamsPtr
 TestRenderFrameHost::BuildDidCommitInterfaceParams(bool is_same_document) {
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      interface_provider;
-  mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-      interface_provider_receiver;
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker_receiver;
 
   if (!is_same_document) {
-    interface_provider_receiver =
-        interface_provider.InitWithNewPipeAndPassReceiver();
     browser_interface_broker_receiver =
         mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
             .InitWithNewPipeAndPassReceiver();
   }
 
   auto interface_params = mojom::DidCommitProvisionalLoadInterfaceParams::New(
-      std::move(interface_provider_receiver),
       std::move(browser_interface_broker_receiver));
   return interface_params;
 }
@@ -583,14 +570,6 @@
 }
 
 // static
-mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-TestRenderFrameHost::CreateStubInterfaceProviderReceiver() {
-  mojo::PendingRemote<::service_manager::mojom::InterfaceProvider>
-      dead_interface_provider_proxy;
-  return dead_interface_provider_proxy.InitWithNewPipeAndPassReceiver();
-}
-
-// static
 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
 TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver() {
   return mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h
index 96ae738..dfcd434 100644
--- a/content/test/test_render_frame_host.h
+++ b/content/test/test_render_frame_host.h
@@ -153,8 +153,6 @@
   void SimulateCommitProcessed(
       NavigationRequest* navigation_request,
       mojom::DidCommitProvisionalLoadParamsPtr params,
-      mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-          interface_provider_receiver,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker_receiver,
       bool same_document);
@@ -162,11 +160,6 @@
   // Creates a WebBluetooth Service with a dummy InterfaceRequest.
   WebBluetoothServiceImpl* CreateWebBluetoothServiceForTesting();
 
-  // Returns a PendingReceiver<InterfaceProvider> that is safe to bind to an
-  // implementation, but will never receive any interface receivers.
-  static mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
-  CreateStubInterfaceProviderReceiver();
-
   // Returns a PendingReceiver<BrowserInterfaceBroker> that is safe to bind to
   // an implementation, but will never receive any interface requests.
   static mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc
index 1ca0dce..0ccb662 100644
--- a/content/test/test_render_view_host.cc
+++ b/content/test/test_render_view_host.cc
@@ -272,11 +272,6 @@
   RenderFrameHostImpl* main_frame =
       static_cast<RenderFrameHostImpl*>(GetMainFrame());
   if (main_frame && is_active()) {
-    mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-        stub_interface_provider_remote;
-    main_frame->BindInterfaceProviderReceiver(
-        stub_interface_provider_remote.InitWithNewPipeAndPassReceiver());
-
     mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host;
     mojo::AssociatedRemote<blink::mojom::Widget> blink_widget;
     auto blink_widget_receiver =
diff --git a/content/web_test/BUILD.gn b/content/web_test/BUILD.gn
index 65d4651..f98098b4 100644
--- a/content/web_test/BUILD.gn
+++ b/content/web_test/BUILD.gn
@@ -215,6 +215,12 @@
     check_includes = false
   }
 
+  # We allow a circular include from blink's web_test implementation. This
+  # is an incremental step to moving the renderer web_test implementation
+  # into blink.
+  allow_circular_includes_from =
+      [ "//third_party/blink/renderer/core/web_test" ]
+
   sources = [
     "renderer/accessibility_controller.cc",
     "renderer/accessibility_controller.h",
@@ -268,8 +274,6 @@
     "renderer/web_test_spell_checker.h",
     "renderer/web_view_test_proxy.cc",
     "renderer/web_view_test_proxy.h",
-    "renderer/web_widget_test_proxy.cc",
-    "renderer/web_widget_test_proxy.h",
   ]
   deps = [
     ":web_test_common",
@@ -298,6 +302,7 @@
     "//skia:test_fonts",
     "//third_party/blink/public:blink_headers",
     "//third_party/blink/public:test_headers",
+    "//third_party/blink/renderer/core/web_test",
     "//ui/accessibility:ax_base",
     "//ui/base/ime:ime_types",
     "//ui/display",
diff --git a/content/web_test/renderer/event_sender.cc b/content/web_test/renderer/event_sender.cc
index fa05810..b0ac428 100644
--- a/content/web_test/renderer/event_sender.cc
+++ b/content/web_test/renderer/event_sender.cc
@@ -88,6 +88,11 @@
 const char* const kPointerTypeStringPen = "pen";
 const char* const kPointerTypeStringEraser = "eraser";
 
+WebViewTestProxy* GetWebViewTestProxy(blink::WebFrameWidget* widget) {
+  return static_cast<WebViewTestProxy*>(
+      RenderView::FromWebView(widget->LocalRoot()->View()));
+}
+
 // Assigns |pointerType| from the provided |args|. Returns false if there was
 // any error.
 bool GetPointerType(gin::Arguments* args,
@@ -1245,9 +1250,10 @@
       modifiers(0) {}
 
 EventSender::EventSender(blink::WebFrameWidget* web_frame_widget,
-                         WebViewTestProxy* web_view_test_proxy)
+                         content::TestRunner* test_runner)
     : web_frame_widget_(web_frame_widget),
-      web_view_test_proxy_(web_view_test_proxy) {
+      web_view_test_proxy_(GetWebViewTestProxy(web_frame_widget)),
+      test_runner_(test_runner) {
   Reset();
 }
 
@@ -1834,8 +1840,8 @@
 #else
       filename = filename.ReplaceExtension(filename_extension.Utf8());
 #endif
-      test_runner()->PrintMessage(std::string("Filename being dragged: ") +
-                                  filename.AsUTF8Unsafe() + "\n");
+      test_runner_->PrintMessage(std::string("Filename being dragged: ") +
+                                 filename.AsUTF8Unsafe() + "\n");
       return;
     }
   }
@@ -1903,7 +1909,7 @@
   }
   if (!file_paths.empty()) {
     current_drag_data_->SetFilesystemId(
-        test_runner()->RegisterIsolatedFileSystem(file_paths));
+        test_runner_->RegisterIsolatedFileSystem(file_paths));
   }
   current_drag_effects_allowed_ = blink::kDragOperationCopy;
 
@@ -2790,10 +2796,6 @@
   HandleInputEventOnViewOrPopup(end_event);
 }
 
-TestRunner* EventSender::test_runner() {
-  return web_view_test_proxy_->GetTestRunner();
-}
-
 WebViewTestProxy* EventSender::web_view_proxy() {
   return web_view_test_proxy_;
 }
diff --git a/content/web_test/renderer/event_sender.h b/content/web_test/renderer/event_sender.h
index fe568e0c..d33006d 100644
--- a/content/web_test/renderer/event_sender.h
+++ b/content/web_test/renderer/event_sender.h
@@ -54,7 +54,7 @@
 
 class EventSender {
  public:
-  EventSender(blink::WebFrameWidget*, WebViewTestProxy*);
+  EventSender(blink::WebFrameWidget*, content::TestRunner* test_runner);
   virtual ~EventSender();
 
   void Reset();
@@ -108,7 +108,6 @@
 
   enum class MouseScrollType { PIXEL, TICK };
 
-  TestRunner* test_runner();
   WebViewTestProxy* web_view_proxy();
   const blink::WebView* view() const;
   blink::WebView* view();
@@ -263,6 +262,7 @@
 
   blink::WebFrameWidget* const web_frame_widget_;
   WebViewTestProxy* const web_view_test_proxy_;
+  TestRunner* const test_runner_;
 
   bool force_layout_on_events_;
 
diff --git a/content/web_test/renderer/test_runner.cc b/content/web_test/renderer/test_runner.cc
index 669af3e..753cb69 100644
--- a/content/web_test/renderer/test_runner.cc
+++ b/content/web_test/renderer/test_runner.cc
@@ -34,7 +34,6 @@
 #include "content/web_test/renderer/test_preferences.h"
 #include "content/web_test/renderer/web_frame_test_proxy.h"
 #include "content/web_test/renderer/web_view_test_proxy.h"
-#include "content/web_test/renderer/web_widget_test_proxy.h"
 #include "gin/arguments.h"
 #include "gin/array_buffer.h"
 #include "gin/handle.h"
@@ -54,6 +53,7 @@
 #include "third_party/blink/public/platform/web_isolated_world_info.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/public/test/frame_widget_test_helper.h"
 #include "third_party/blink/public/web/blink.h"
 #include "third_party/blink/public/web/web_array_buffer.h"
 #include "third_party/blink/public/web/web_array_buffer_converter.h"
@@ -1237,14 +1237,13 @@
   if (new_width <= 0 || new_height <= 0)
     return;
 
-  RenderWidget* widget = frame_->GetLocalRootRenderWidget();
+  blink::WebFrameWidget* widget = frame_->GetLocalRootWebFrameWidget();
 
   gfx::Size new_size(new_width, new_height);
   blink::WebView* web_view = GetWebFrame()->View();
   web_view->DisableAutoResizeForTesting(new_size);
 
-  gfx::Rect window_rect(widget->GetWebWidget()->WindowRect().origin(),
-                        new_size);
+  gfx::Rect window_rect(widget->WindowRect().origin(), new_size);
   web_view->SetWindowRectSynchronouslyForTesting(window_rect);
 }
 
@@ -1829,7 +1828,7 @@
 void TestRunnerBindings::UpdateAllLifecyclePhasesAndComposite() {
   if (invalid_)
     return;
-  static_cast<WebWidgetTestProxy*>(frame_->GetLocalRootRenderWidget())
+  frame_->GetLocalRootFrameWidgetTestHelper()
       ->UpdateAllLifecyclePhasesAndComposite(base::DoNothing());
 }
 
@@ -1837,7 +1836,7 @@
     v8::Local<v8::Function> v8_callback) {
   if (invalid_)
     return;
-  static_cast<WebWidgetTestProxy*>(frame_->GetLocalRootRenderWidget())
+  frame_->GetLocalRootFrameWidgetTestHelper()
       ->UpdateAllLifecyclePhasesAndComposite(
           WrapV8Closure(std::move(v8_callback)));
 }
@@ -2105,9 +2104,8 @@
   if (invalid_)
     return {};
 
-  blink::WebString tooltip_text = frame_->GetLocalRootRenderWidget()
-                                      ->GetWebWidget()
-                                      ->GetLastToolTipTextForTesting();
+  blink::WebString tooltip_text =
+      frame_->GetLocalRootWebFrameWidget()->GetLastToolTipTextForTesting();
   return tooltip_text.Utf8();
 }
 
@@ -2311,19 +2309,16 @@
   web_view->UseSynchronousResizeModeForTesting(false);
 }
 
-void TestRunner::ResetWebWidget(WebWidgetTestProxy* web_widget_test_proxy) {
-  blink::WebFrameWidget* web_widget =
-      web_widget_test_proxy->GetWebFrameWidget();
-
-  web_widget->SetDeviceScaleFactorForTesting(0);
-  web_widget->ReleaseMouseLockAndPointerCaptureForTesting();
+void TestRunner::ResetWebFrameWidget(blink::WebFrameWidget* web_frame_widget) {
+  web_frame_widget->SetDeviceScaleFactorForTesting(0);
+  web_frame_widget->ReleaseMouseLockAndPointerCaptureForTesting();
 
   // These things are only modified/valid for the main frame's widget.
-  if (web_widget_test_proxy->delegate()) {
-    web_widget->ResetZoomLevelForTesting();
+  if (!web_frame_widget->LocalRoot()->Parent()) {
+    web_frame_widget->ResetZoomLevelForTesting();
 
-    web_widget->SetMainFrameOverlayColor(SK_ColorTRANSPARENT);
-    web_widget->SetTextZoomFactor(1);
+    web_frame_widget->SetMainFrameOverlayColor(SK_ColorTRANSPARENT);
+    web_frame_widget->SetTextZoomFactor(1);
   }
 }
 
@@ -3123,7 +3118,7 @@
     return;
 
   auto* frame_proxy = static_cast<WebFrameTestProxy*>(main_frame);
-  RenderWidget* widget = frame_proxy->GetLocalRootRenderWidget();
+  blink::WebFrameWidget* widget = frame_proxy->GetLocalRootWebFrameWidget();
 
   // Web tests get multiple windows in one renderer by doing same-site
   // window.open() calls (or about:blank). They want to be able to move focus
@@ -3133,13 +3128,13 @@
   if (!focus) {
     // This path simulates losing focus on the window, without moving it to
     // another window.
-    if (widget->GetWebWidget()->HasFocus()) {
+    if (widget->HasFocus()) {
       auto* view_proxy = frame_proxy->GetWebViewTestProxy();
       // TODO(dtapuska): We should call the exact IPC the browser
       // calls. ie. WebFrameWidgetImpl::SetActive but that isn't
       // exposed outside of blink.
       view_proxy->GetWebView()->SetIsActive(false);
-      widget->GetWebWidget()->SetFocus(false);
+      widget->SetFocus(false);
     }
     return;
   }
@@ -3147,20 +3142,21 @@
   // Find the currently focused window, and remove its focus.
   for (WebFrameTestProxy* other_main_frame : main_frames_) {
     if (other_main_frame != main_frame) {
-      RenderWidget* other_widget = other_main_frame->GetLocalRootRenderWidget();
-      if (other_widget->GetWebWidget()->HasFocus()) {
+      blink::WebFrameWidget* other_widget =
+          other_main_frame->GetLocalRootWebFrameWidget();
+      if (other_widget->HasFocus()) {
         auto* other_view_proxy = other_main_frame->GetWebViewTestProxy();
         // TODO(dtapuska): We should call the exact IPC the browser
         // calls. ie. WebFrameWidgetImpl::SetActive but that isn't
         // exposed outside of blink.
         other_view_proxy->GetWebView()->SetIsActive(false);
-        other_widget->GetWebWidget()->SetFocus(false);
+        other_widget->SetFocus(false);
       }
     }
   }
 
-  if (!widget->GetWebWidget()->HasFocus()) {
-    widget->GetWebWidget()->SetFocus(true);
+  if (!widget->HasFocus()) {
+    widget->SetFocus(true);
   }
 }
 
diff --git a/content/web_test/renderer/test_runner.h b/content/web_test/renderer/test_runner.h
index 3e9c0ad..f7ce3d6f 100644
--- a/content/web_test/renderer/test_runner.h
+++ b/content/web_test/renderer/test_runner.h
@@ -42,6 +42,7 @@
 namespace blink {
 class WebContentSettingsClient;
 class WebFrame;
+class WebFrameWidget;
 class WebString;
 class WebView;
 }  // namespace blink
@@ -57,7 +58,6 @@
 class SpellCheckClient;
 class TestRunnerBindings;
 class WebFrameTestProxy;
-class WebWidgetTestProxy;
 class WebViewTestProxy;
 struct TestPreferences;
 
@@ -84,8 +84,8 @@
 
   // Resets state on the |web_view_test_proxy| for the next test.
   void ResetWebView(WebViewTestProxy* web_view_test_proxy);
-  // Resets state on the |web_widget_test_proxy| for the next test.
-  void ResetWebWidget(WebWidgetTestProxy* web_widget_test_proxy);
+  // Resets state on the |web_frame_widget| for the next test.
+  void ResetWebFrameWidget(blink::WebFrameWidget* web_frame_widget);
 
   void SetTestIsRunning(bool);
   bool TestIsRunning() const { return test_is_running_; }
diff --git a/content/web_test/renderer/text_input_controller.cc b/content/web_test/renderer/text_input_controller.cc
index c40d88d..8dc926c9 100644
--- a/content/web_test/renderer/text_input_controller.cc
+++ b/content/web_test/renderer/text_input_controller.cc
@@ -400,8 +400,9 @@
   RenderFrameImpl* main_frame = web_view_test_proxy_->GetMainRenderFrame();
   CHECK(main_frame) << "WebView does not have a local main frame and"
                     << " cannot handle input method controller tasks.";
-  RenderWidget* main_widget = main_frame->GetLocalRootRenderWidget();
-  main_widget->GetWebWidget()->ShowVirtualKeyboard();
+  blink::WebFrameWidget* frame_widget =
+      main_frame->GetLocalRootWebFrameWidget();
+  frame_widget->ShowVirtualKeyboard();
 }
 
 blink::WebView* TextInputController::view() {
diff --git a/content/web_test/renderer/web_frame_test_proxy.cc b/content/web_test/renderer/web_frame_test_proxy.cc
index f1f5386..8e2173f 100644
--- a/content/web_test/renderer/web_frame_test_proxy.cc
+++ b/content/web_test/renderer/web_frame_test_proxy.cc
@@ -15,9 +15,9 @@
 #include "content/web_test/renderer/test_plugin.h"
 #include "content/web_test/renderer/test_runner.h"
 #include "content/web_test/renderer/web_view_test_proxy.h"
-#include "content/web_test/renderer/web_widget_test_proxy.h"
 #include "third_party/blink/public/common/loader/referrer_utils.h"
 #include "third_party/blink/public/common/unique_name/unique_name_helper.h"
+#include "third_party/blink/public/web/web_frame_widget.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
 #include "third_party/blink/public/web/web_testing_support.h"
@@ -271,7 +271,8 @@
     web_view_test_proxy_->Reset();
   }
   if (IsLocalRoot()) {
-    GetLocalRootWebWidgetTestProxy()->Reset();
+    test_runner()->ResetWebFrameWidget(GetLocalRootWebFrameWidget());
+    GetLocalRootFrameWidgetTestHelper()->Reset();
   }
 
   spell_check_->Reset();
@@ -413,8 +414,9 @@
 void WebFrameTestProxy::ShowContextMenu(
     const blink::WebContextMenuData& context_menu_data,
     const base::Optional<gfx::Point>& location) {
-  WebWidgetTestProxy* widget_proxy = GetLocalRootWebWidgetTestProxy();
-  widget_proxy->event_sender()->SetContextMenuData(context_menu_data);
+  blink::FrameWidgetTestHelper* frame_widget =
+      GetLocalRootFrameWidgetTestHelper();
+  frame_widget->GetEventSender()->SetContextMenuData(context_menu_data);
 
   RenderFrameImpl::ShowContextMenu(context_menu_data, location);
 }
@@ -709,7 +711,8 @@
     GCController::Install(GetWebFrame());
     test_runner()->Install(this, spell_check_.get());
     web_view_test_proxy_->Install(GetWebFrame());
-    GetLocalRootWebWidgetTestProxy()->Install(GetWebFrame());
+    GetLocalRootFrameWidgetTestHelper()->GetEventSender()->Install(
+        GetWebFrame());
     blink::WebTestingSupport::InjectInternalsObject(GetWebFrame());
   }
   RenderFrameImpl::DidClearWindowObject();
@@ -723,8 +726,9 @@
   test_runner()->OnFrameReactivated(this);
 }
 
-WebWidgetTestProxy* WebFrameTestProxy::GetLocalRootWebWidgetTestProxy() {
-  return static_cast<WebWidgetTestProxy*>(GetLocalRootRenderWidget());
+blink::FrameWidgetTestHelper*
+WebFrameTestProxy::GetLocalRootFrameWidgetTestHelper() {
+  return GetLocalRootWebFrameWidget()->GetFrameWidgetTestHelperForTesting();
 }
 
 WebViewTestProxy* WebFrameTestProxy::GetWebViewTestProxy() {
@@ -736,7 +740,7 @@
   // When the TestFinished() occurred, if the browser is capturing pixels, it
   // asks each composited RenderFrame to submit a new frame via here.
   if (IsLocalRoot())
-    GetLocalRootWebWidgetTestProxy()->SynchronouslyCompositeAfterTest();
+    GetLocalRootFrameWidgetTestHelper()->SynchronouslyCompositeAfterTest();
   std::move(callback).Run();
 }
 
diff --git a/content/web_test/renderer/web_frame_test_proxy.h b/content/web_test/renderer/web_frame_test_proxy.h
index cce82d6..5dca48b9 100644
--- a/content/web_test/renderer/web_frame_test_proxy.h
+++ b/content/web_test/renderer/web_frame_test_proxy.h
@@ -17,6 +17,7 @@
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "third_party/blink/public/platform/web_effective_connection_type.h"
 #include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/test/frame_widget_test_helper.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "ui/accessibility/ax_event.h"
@@ -26,7 +27,6 @@
 class SpellCheckClient;
 class TestRunner;
 class WebViewTestProxy;
-class WebWidgetTestProxy;
 
 // WebFrameTestProxy is used during running web tests instead of a
 // RenderFrameImpl to inject test-only behaviour by overriding methods in the
@@ -51,8 +51,8 @@
   // tests.
   std::string GetFrameDescriptionForWebTests();
 
-  // Returns the test-subclass of RenderWidget for the local root of this frame.
-  WebWidgetTestProxy* GetLocalRootWebWidgetTestProxy();
+  // Returns the test helper of WebFrameWidget for the local root of this frame.
+  blink::FrameWidgetTestHelper* GetLocalRootFrameWidgetTestHelper();
   // Returns the test-subclass of RenderViewImpl that is hosting this frame's
   // frame tree fragment.
   WebViewTestProxy* GetWebViewTestProxy();
diff --git a/content/web_test/renderer/web_test_content_renderer_client.cc b/content/web_test/renderer/web_test_content_renderer_client.cc
index 404fde1f..225a1ba7 100644
--- a/content/web_test/renderer/web_test_content_renderer_client.cc
+++ b/content/web_test/renderer/web_test_content_renderer_client.cc
@@ -22,14 +22,15 @@
 #include "content/web_test/renderer/web_frame_test_proxy.h"
 #include "content/web_test/renderer/web_test_render_thread_observer.h"
 #include "content/web_test/renderer/web_view_test_proxy.h"
-#include "content/web_test/renderer/web_widget_test_proxy.h"
 #include "media/base/audio_latency.h"
 #include "media/base/mime_util.h"
 #include "media/media_buildflags.h"
 #include "third_party/blink/public/common/unique_name/unique_name_helper.h"
 #include "third_party/blink/public/platform/web_audio_latency_hint.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
+#include "third_party/blink/public/test/frame_widget_test_helper.h"
 #include "third_party/blink/public/web/blink.h"
+#include "third_party/blink/public/web/web_frame_widget.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
 #include "third_party/blink/public/web/web_testing_support.h"
 #include "ui/gfx/icc_profile.h"
@@ -58,15 +59,35 @@
       WebTestRenderThreadObserver::GetInstance()->test_runner());
 }
 
-std::unique_ptr<RenderWidget> CreateWebWidgetTestProxy(
-    CompositorDependencies* compositor_deps) {
-  return std::make_unique<WebWidgetTestProxy>(compositor_deps);
-}
-
 RenderFrameImpl* CreateWebFrameTestProxy(RenderFrameImpl::CreateParams params) {
   return new WebFrameTestProxy(std::move(params));
 }
 
+blink::WebFrameWidget* CreateWebTestWebFrameWidget(
+    base::PassKey<blink::WebFrameWidget> pass_key,
+    blink::WebWidgetClient& widget_client,
+    blink::CrossVariantMojoAssociatedRemote<
+        blink::mojom::FrameWidgetHostInterfaceBase> frame_widget_host,
+    blink::CrossVariantMojoAssociatedReceiver<
+        blink::mojom::FrameWidgetInterfaceBase> frame_widget,
+    blink::CrossVariantMojoAssociatedRemote<
+        blink::mojom::WidgetHostInterfaceBase> widget_host,
+    blink::CrossVariantMojoAssociatedReceiver<blink::mojom::WidgetInterfaceBase>
+        widget,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    const viz::FrameSinkId& frame_sink_id,
+    bool hidden,
+    bool never_composited,
+    bool is_for_child_local_root,
+    bool is_for_nested_main_frame) {
+  return blink::FrameWidgetTestHelper::CreateTestWebFrameWidget(
+      std::move(pass_key), widget_client, std::move(frame_widget_host),
+      std::move(frame_widget), std::move(widget_host), std::move(widget),
+      std::move(task_runner), frame_sink_id, hidden, never_composited,
+      is_for_child_local_root, is_for_nested_main_frame,
+      WebTestRenderThreadObserver::GetInstance()->test_runner());
+}
+
 }  // namespace
 
 WebTestContentRendererClient::WebTestContentRendererClient() {
@@ -74,8 +95,7 @@
   // the creation of the production type with the subclasses.
   RenderViewImpl::InstallCreateHook(CreateWebViewTestProxy);
   RenderFrameImpl::InstallCreateHook(CreateWebFrameTestProxy);
-  // For RenderWidgets, web tests only subclass the ones attached to frames.
-  RenderWidget::InstallCreateForFrameHook(CreateWebWidgetTestProxy);
+  blink::InstallCreateWebFrameWidgetHook(CreateWebTestWebFrameWidget);
 
   blink::UniqueNameHelper::PreserveStableUniqueNameForTesting();
   WebWorkerFetchContextImpl::InstallRewriteURLFunction(RewriteWebTestsURL);
diff --git a/content/web_test/renderer/web_view_test_proxy.cc b/content/web_test/renderer/web_view_test_proxy.cc
index f77b9ae..3b3d0e7 100644
--- a/content/web_test/renderer/web_view_test_proxy.cc
+++ b/content/web_test/renderer/web_view_test_proxy.cc
@@ -70,7 +70,7 @@
   // This is using the main frame for the size, but maybe it should be using the
   // frame's size.
   blink::WebSize page_size_in_pixels =
-      GetMainRenderFrame()->GetLocalRootRenderWidget()->GetWebWidget()->Size();
+      GetMainRenderFrame()->GetLocalRootWebFrameWidget()->Size();
   if (page_size_in_pixels.IsEmpty())
     return;
   blink::WebPrintParams print_params(page_size_in_pixels);
diff --git a/content/web_test/renderer/web_widget_test_proxy.cc b/content/web_test/renderer/web_widget_test_proxy.cc
deleted file mode 100644
index babbbac..0000000
--- a/content/web_test/renderer/web_widget_test_proxy.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2016 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/web_test/renderer/web_widget_test_proxy.h"
-
-#include "content/renderer/compositor/compositor_dependencies.h"
-#include "content/web_test/renderer/blink_test_helpers.h"
-#include "content/web_test/renderer/test_runner.h"
-#include "content/web_test/renderer/web_view_test_proxy.h"
-#include "third_party/blink/public/web/web_frame_widget.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-#include "third_party/blink/public/web/web_page_popup.h"
-#include "third_party/blink/public/web/web_view.h"
-#include "third_party/blink/public/web/web_widget.h"
-
-#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
-#include "ui/display/display_switches.h"
-
-namespace content {
-
-WebWidgetTestProxy::~WebWidgetTestProxy() = default;
-
-void WebWidgetTestProxy::WillBeginMainFrame() {
-  // WillBeginMainFrame occurs before we run BeginMainFrame() in the base
-  // class, which will change states. TestFinished() wants to grab the current
-  // state.
-  GetTestRunner()->FinishTestIfReady();
-
-  RenderWidget::WillBeginMainFrame();
-}
-
-void WebWidgetTestProxy::Initialize(blink::WebWidget* web_widget,
-                                    const blink::ScreenInfo& screen_info) {
-  RenderWidget::Initialize(web_widget, screen_info);
-  blink::WebFrameWidget* frame_widget =
-      static_cast<blink::WebFrameWidget*>(web_widget);
-  WebViewTestProxy* web_view_test_proxy = static_cast<WebViewTestProxy*>(
-      RenderView::FromWebView(GetWebFrameWidget()->LocalRoot()->View()));
-  test_runner_ = web_view_test_proxy->GetTestRunner();
-  event_sender_ =
-      std::make_unique<EventSender>(frame_widget, web_view_test_proxy);
-}
-
-void WebWidgetTestProxy::ScheduleAnimation() {
-  // |test_runner_| might be null if this callback occurs during the
-  // `Initialize()` call.
-  if (!test_runner_)
-    return;
-  if (test_runner_->TestIsRunning())
-    ScheduleAnimationInternal(test_runner_->animation_requires_raster());
-}
-
-void WebWidgetTestProxy::ScheduleAnimationForWebTests() {
-  // Single threaded web tests must explicitly schedule commits.
-  //
-  // Pass true for |do_raster| to ensure the compositor is actually run, rather
-  // than just doing the main frame animate step. That way we know it will
-  // submit a frame and later trigger the presentation callback in order to make
-  // progress in the test.
-  if (GetTestRunner()->TestIsRunning())
-    ScheduleAnimationInternal(/*do_raster=*/true);
-}
-
-void WebWidgetTestProxy::UpdateAllLifecyclePhasesAndComposite(
-    base::OnceClosure callback) {
-  layer_tree_host()->RequestPresentationTimeForNextFrame(base::BindOnce(
-      [](base::OnceClosure callback, const gfx::PresentationFeedback&) {
-        std::move(callback).Run();
-      },
-      std::move(callback)));
-  layer_tree_host()->SetNeedsCommitWithForcedRedraw();
-  ScheduleAnimationForWebTests();
-}
-
-void WebWidgetTestProxy::ScheduleAnimationInternal(bool do_raster) {
-  // When using threaded compositing, have the RenderWidget schedule a request
-  // for a frame, as we use the compositor's scheduler. Otherwise the testing
-  // WebWidgetClient schedules it.
-  // Note that for WebWidgetTestProxy the RenderWidget is subclassed to override
-  // the WebWidgetClient, so we must call up to the base class RenderWidget
-  // explicitly here to jump out of the test harness as intended.
-  if (!RenderWidget::compositor_deps()->IsSingleThreaded()) {
-    RenderWidget::ScheduleAnimation();
-    return;
-  }
-
-  // If an animation already scheduled we'll make it composite, otherwise we'll
-  // schedule another animation step with composite now.
-  composite_requested_ |= do_raster;
-
-  if (!animation_scheduled_) {
-    animation_scheduled_ = true;
-
-    auto* web_widget = static_cast<blink::WebFrameWidget*>(GetWebWidget());
-    blink::WebLocalFrame* frame = web_widget->LocalRoot();
-
-    frame->GetTaskRunner(blink::TaskType::kInternalTest)
-        ->PostDelayedTask(FROM_HERE,
-                          base::BindOnce(&WebWidgetTestProxy::AnimateNow,
-                                         weak_factory_.GetWeakPtr()),
-                          base::TimeDelta::FromMilliseconds(1));
-  }
-}
-
-bool WebWidgetTestProxy::InterceptStartDragging(
-    const blink::WebDragData& data,
-    blink::DragOperationsMask mask,
-    const SkBitmap& drag_image,
-    const gfx::Point& image_offset) {
-  GetTestRunner()->SetDragImage(drag_image);
-
-  // When running a test, we need to fake a drag drop operation otherwise
-  // Windows waits for real mouse events to know when the drag is over.
-  event_sender_->DoDragDrop(data, mask);
-  return true;
-}
-
-blink::WebFrameWidget* WebWidgetTestProxy::GetWebFrameWidget() {
-  return static_cast<blink::WebFrameWidget*>(GetWebWidget());
-}
-
-void WebWidgetTestProxy::Reset() {
-  event_sender_->Reset();
-  // Ends any synthetic gestures started in |event_sender_|.
-  GetWebWidget()->FlushInputProcessedCallback();
-
-  // Reset state in the RenderWidget base class.
-  GetWebFrameWidget()->ClearEditCommands();
-
-  GetTestRunner()->ResetWebWidget(this);
-}
-
-void WebWidgetTestProxy::Install(blink::WebLocalFrame* frame) {
-  event_sender_->Install(frame);
-}
-
-void WebWidgetTestProxy::SynchronouslyCompositeAfterTest() {
-  // We could DCHECK(!GetTestRunner()->TestIsRunning()) except that frames in
-  // other processes than the main frame do not hear when the test ends.
-
-  // This would be very weird and prevent us from producing pixels.
-  DCHECK(!in_synchronous_composite_);
-
-  SynchronouslyComposite(/*do_raster=*/true);
-}
-
-TestRunner* WebWidgetTestProxy::GetTestRunner() {
-  return test_runner_;
-}
-
-// static
-void WebWidgetTestProxy::DoComposite(content::RenderWidget* widget,
-                                     bool do_raster) {
-  // Ensure that there is damage so that the compositor submits, and the display
-  // compositor draws this frame.
-  if (do_raster) {
-    widget->layer_tree_host()->SetNeedsCommitWithForcedRedraw();
-  }
-
-  widget->layer_tree_host()->CompositeForTest(base::TimeTicks::Now(),
-                                              do_raster);
-}
-
-void WebWidgetTestProxy::SynchronouslyComposite(bool do_raster) {
-  DCHECK(compositor_deps()->IsSingleThreaded());
-  DCHECK(!layer_tree_host()->GetSettings().single_thread_proxy_scheduler);
-
-  if (!layer_tree_host()->IsVisible())
-    return;
-
-  if (in_synchronous_composite_) {
-    // Web tests can use a nested message loop to pump frames while inside a
-    // frame, but the compositor does not support this. In this case, we only
-    // run blink's lifecycle updates.
-    GetWebWidget()->UpdateAllLifecyclePhases(
-        blink::DocumentUpdateReason::kTest);
-    return;
-  }
-
-  in_synchronous_composite_ = true;
-
-  // Composite() can detach the frame, which would destroy |this|.
-  base::WeakPtr<WebWidgetTestProxy> weak_this = weak_factory_.GetWeakPtr();
-  DoComposite(this, do_raster);
-  if (!weak_this)
-    return;
-
-  in_synchronous_composite_ = false;
-
-  // If the RenderWidget is for the main frame, we also composite the current
-  // PagePopup afterward.
-  //
-  // TODO(danakj): This means that an OOPIF's popup, which is attached to a
-  // WebView without a main frame, would have no opportunity to execute this
-  // method call.
-  if (delegate()) {
-    blink::WebView* view = GetWebFrameWidget()->LocalRoot()->View();
-    if (blink::WebPagePopup* popup = view->GetPagePopup()) {
-      auto* popup_render_widget =
-          static_cast<RenderWidget*>(popup->GetClientForTesting());
-      DoComposite(popup_render_widget, do_raster);
-    }
-  }
-}
-
-void WebWidgetTestProxy::AnimateNow() {
-  bool do_raster = composite_requested_;
-  animation_scheduled_ = false;
-  composite_requested_ = false;
-  // Composite may destroy |this|, so don't use it afterward.
-  SynchronouslyComposite(do_raster);
-}
-
-}  // namespace content
diff --git a/content/web_test/renderer/web_widget_test_proxy.h b/content/web_test/renderer/web_widget_test_proxy.h
deleted file mode 100644
index 25167ac..0000000
--- a/content/web_test/renderer/web_widget_test_proxy.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2016 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_WEB_TEST_RENDERER_WEB_WIDGET_TEST_PROXY_H_
-#define CONTENT_WEB_TEST_RENDERER_WEB_WIDGET_TEST_PROXY_H_
-
-#include <memory>
-#include <utility>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/renderer/render_widget.h"
-#include "content/web_test/renderer/event_sender.h"
-#include "third_party/blink/public/web/web_widget_client.h"
-
-namespace blink {
-class WebLocalFrame;
-}  // namespace blink
-
-namespace content {
-
-class TestRunner;
-class EventSender;
-
-// WebWidgetTestProxy is used to run web tests. This class is a partial fake
-// implementation of RenderWidget that overrides the minimal necessary portions
-// of RenderWidget to allow for use in web tests.
-//
-// This method of injecting test functionality is an outgrowth of legacy.
-// In particular, classic dependency injection does not work easily
-// because the RenderWidget class is too large with too much entangled
-// stated, and complex creation (subclass using heavy implementation
-// inheritance, multiple modes of operation for frames/popups/fullscreen, etc)
-// making it hard to factor our creation points for injection.
-//
-// While implementing a fake via partial overriding of a class leads to
-// a fragile base class problem and implicit coupling of the test code
-// and production code, it is the most viable mechanism available with a huge
-// refactor.
-//
-// Historically, the overridden functionality has been small enough to not
-// cause too much trouble. If that changes, then this entire testing
-// architecture should be revisited.
-class WebWidgetTestProxy : public RenderWidget {
- public:
-  template <typename... Args>
-  explicit WebWidgetTestProxy(Args&&... args)
-      : RenderWidget(std::forward<Args>(args)...) {}
-  ~WebWidgetTestProxy() override;
-
-  // RenderWidget overrides.
-  void WillBeginMainFrame() override;
-
-  // WebWidgetClient implementation.
-  void ScheduleAnimation() override;
-  void ScheduleAnimationForWebTests() override;
-  bool InterceptStartDragging(const blink::WebDragData& data,
-                              blink::DragOperationsMask mask,
-                              const SkBitmap& drag_image,
-                              const gfx::Point& image_offset) override;
-
-  // WebWidgetTestProxy is always a widget for a RenderFrame, so its WebWidget
-  // is always a WebFrameWidget.
-  blink::WebFrameWidget* GetWebFrameWidget();
-
-  EventSender* event_sender() { return event_sender_.get(); }
-  void Reset();
-  void Install(blink::WebLocalFrame* frame);
-
-  // Forces a redraw and invokes the callback once the frame's been displayed
-  // to the user in the display compositor.
-  void UpdateAllLifecyclePhasesAndComposite(
-      base::OnceClosure completion_callback);
-
-  // Called to composite when the test has ended, in order to ensure the test
-  // produces up-to-date pixel output. This is a separate path as most
-  // compositing paths stop running when the test ends, to avoid tests running
-  // forever.
-  void SynchronouslyCompositeAfterTest();
-
- private:
-  TestRunner* GetTestRunner();
-
-  // RenderWidget overrides.
-  void Initialize(blink::WebWidget* web_widget,
-                  const blink::ScreenInfo& screen_info) override;
-
-  void ScheduleAnimationInternal(bool do_raster);
-  void AnimateNow();
-
-  // When |do_raster| is false, only a main frame animation step is performed,
-  // but when true, a full composite is performed and a frame submitted to the
-  // display compositor if there is any damage.
-  // Note that compositing has the potential to detach the current frame and
-  // thus destroy |this| before returning.
-  void SynchronouslyComposite(bool do_raster);
-
-  // Perform the synchronous composite step for a given RenderWidget.
-  static void DoComposite(RenderWidget* widget, bool do_raster);
-
-  std::unique_ptr<EventSender> event_sender_;
-
-  TestRunner* test_runner_ = nullptr;
-
-  // For collapsing multiple simulated ScheduleAnimation() calls.
-  bool animation_scheduled_ = false;
-  // When true, an AnimateNow() is scheduled that will perform a full composite.
-  // Otherwise, any scheduled AnimateNow() calls will only perform the animation
-  // step, which calls out to blink but doesn't composite for performance
-  // reasons. See setAnimationRequiresRaster() in
-  // https://chromium.googlesource.com/chromium/src/+/master/docs/testing/writing_web_tests.md
-  // for details on the optimization.
-  bool composite_requested_ = false;
-  // Synchronous composites should not be nested inside another
-  // composite, and this bool is used to guard against that.
-  bool in_synchronous_composite_ = false;
-
-  base::WeakPtrFactory<WebWidgetTestProxy> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(WebWidgetTestProxy);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_WEB_TEST_RENDERER_WEB_WIDGET_TEST_PROXY_H_
diff --git a/device/fido/bio/enrollment_handler.cc b/device/fido/bio/enrollment_handler.cc
index 4a283fb..80db6ce 100644
--- a/device/fido/bio/enrollment_handler.cc
+++ b/device/fido/bio/enrollment_handler.cc
@@ -165,6 +165,11 @@
     return;
   }
 
+  if (authenticator->ForcePINChange()) {
+    Finish(BioEnrollmentStatus::kForcePINChange);
+    return;
+  }
+
   authenticator_ = authenticator;
   state_ = State::kGettingRetries;
   authenticator_->GetPinRetries(base::BindOnce(
diff --git a/device/fido/bio/enrollment_handler.h b/device/fido/bio/enrollment_handler.h
index 811eda7..06eb9633 100644
--- a/device/fido/bio/enrollment_handler.h
+++ b/device/fido/bio/enrollment_handler.h
@@ -28,6 +28,7 @@
   kHardPINBlock,
   kNoPINSet,
   kAuthenticatorMissingBioEnrollment,
+  kForcePINChange,
 };
 
 // BioEnrollmentHandler exercises the CTAP2.1 authenticatorBioEnrollment
diff --git a/device/fido/bio/enrollment_handler_unittest.cc b/device/fido/bio/enrollment_handler_unittest.cc
index 7eaf1154..5ca8c07a 100644
--- a/device/fido/bio/enrollment_handler_unittest.cc
+++ b/device/fido/bio/enrollment_handler_unittest.cc
@@ -101,6 +101,24 @@
   EXPECT_EQ(error_callback_.value(), BioEnrollmentStatus::kNoPINSet);
 }
 
+// Tests bio enrollment handler against device with the forcePINChange flag on.
+TEST_F(BioEnrollmentHandlerTest, ForcePINChange) {
+  VirtualCtap2Device::Config config;
+  config.pin_support = true;
+  config.bio_enrollment_preview_support = true;
+  config.min_pin_length_support = true;
+  config.pin_uv_auth_token_support = true;
+  config.ctap2_versions = {Ctap2Version::kCtap2_1};
+  virtual_device_factory_.mutable_state()->force_pin_change = true;
+
+  virtual_device_factory_.SetCtap2Config(config);
+
+  auto handler = MakeHandler();
+  error_callback_.WaitForCallback();
+
+  EXPECT_EQ(error_callback_.value(), BioEnrollmentStatus::kForcePINChange);
+}
+
 // Tests enrollment handler PIN soft block.
 TEST_F(BioEnrollmentHandlerTest, SoftPINBlock) {
   VirtualCtap2Device::Config config;
diff --git a/device/fido/credential_management_handler.cc b/device/fido/credential_management_handler.cc
index 15b7d06..45f1865b 100644
--- a/device/fido/credential_management_handler.cc
+++ b/device/fido/credential_management_handler.cc
@@ -77,6 +77,13 @@
     return;
   }
 
+  if (authenticator->ForcePINChange()) {
+    state_ = State::kFinished;
+    std::move(finished_callback_)
+        .Run(CredentialManagementStatus::kForcePINChange);
+    return;
+  }
+
   authenticator_ = authenticator;
   authenticator_->GetPinRetries(
       base::BindOnce(&CredentialManagementHandler::OnRetriesResponse,
diff --git a/device/fido/credential_management_handler.h b/device/fido/credential_management_handler.h
index de9bd1c7..f9b6257 100644
--- a/device/fido/credential_management_handler.h
+++ b/device/fido/credential_management_handler.h
@@ -32,6 +32,7 @@
   kHardPINBlock,
   kAuthenticatorMissingCredentialManagement,
   kNoPINSet,
+  kForcePINChange,
 };
 
 // CredentialManagementHandler implements the authenticatorCredentialManagement
diff --git a/device/fido/credential_management_handler_unittest.cc b/device/fido/credential_management_handler_unittest.cc
index 35a2881f..98bbcf5 100644
--- a/device/fido/credential_management_handler_unittest.cc
+++ b/device/fido/credential_management_handler_unittest.cc
@@ -113,8 +113,28 @@
   EXPECT_FALSE(finished_callback_.was_called());
 }
 
+TEST_F(CredentialManagementHandlerTest, TestForcePINChange) {
+  virtual_device_factory_.mutable_state()->pin = kPIN;
+  virtual_device_factory_.mutable_state()->force_pin_change = true;
+
+  VirtualCtap2Device::Config ctap_config;
+  ctap_config.pin_support = true;
+  ctap_config.resident_key_support = true;
+  ctap_config.credential_management_support = true;
+  ctap_config.min_pin_length_support = true;
+  ctap_config.pin_uv_auth_token_support = true;
+  ctap_config.ctap2_versions = {Ctap2Version::kCtap2_1};
+  virtual_device_factory_.SetCtap2Config(ctap_config);
+  virtual_device_factory_.SetSupportedProtocol(device::ProtocolVersion::kCtap2);
+
+  auto handler = MakeHandler();
+  finished_callback_.WaitForCallback();
+  ASSERT_EQ(finished_callback_.value(),
+            CredentialManagementStatus::kForcePINChange);
+}
+
 TEST_F(CredentialManagementHandlerTest,
-       EnmerateCredentialResponse_TruncatedUTF8) {
+       EnumerateCredentialResponse_TruncatedUTF8) {
   // Webauthn says[1] that authenticators may truncate strings in user entities.
   // Since authenticators aren't going to do UTF-8 processing, that means that
   // they may truncate a multi-byte code point and thus produce an invalid
diff --git a/docs/testing/web_platform_tests_wptrunner.md b/docs/testing/web_platform_tests_wptrunner.md
index 54120ac..2150f75 100644
--- a/docs/testing/web_platform_tests_wptrunner.md
+++ b/docs/testing/web_platform_tests_wptrunner.md
@@ -69,14 +69,14 @@
 
 * [linux-wpt-identity-fyi-rel](https://ci.chromium.org/p/chromium/builders/ci/linux-wpt-identity-fyi-rel),
   which runs tests under `external/wpt/webauthn/`.
-* [linux-wpt-payments-fyi-rel](https://ci.chromium.org/p/chromium/builders/ci/linux-wpt-payments-fyi-rel),
-  which runs tests under `external/wpt/payment-{handler, method-basic-card,
-  request}`.
+* [linux-wpt-input-fyi-rel](https://ci.chromium.org/p/chromium/builders/ci/linux-wpt-input-fyi-rel),
+  which runs tests under `external/wpt/{input-events, pointerevents, uievents}`,
+  as well as `external/wpt/infrastructure/testdriver/actions/`
 
 These bots run on the waterfall, but can also be run on CLs by clicking the
 `Choose Tryjobs` button in Gerrit followed by searching for the bot name in the
 modal dialog that appears. One can also include the tag `Cq-Include-Trybots:
-luci.chromium.try:linux-wpt-identity-fyi-rel` (or payments) in the description
+luci.chromium.try:linux-wpt-identity-fyi-rel` (or input) in the description
 for the CL, which will make the bot mandatory for that CL.
 
 Results for the bots use the existing layout test results viewer
diff --git a/docs/testing/web_tests_in_content_shell.md b/docs/testing/web_tests_in_content_shell.md
index 3de16d9..b600380 100644
--- a/docs/testing/web_tests_in_content_shell.md
+++ b/docs/testing/web_tests_in_content_shell.md
@@ -1,5 +1,7 @@
 # Running web tests using the content shell
 
+[TOC]
+
 ## Compiling
 
 If you want to run web tests,
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc
index 26bbdf7..7d9d0d2 100644
--- a/extensions/browser/api/web_request/web_request_api_helpers.cc
+++ b/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -14,7 +14,7 @@
 
 #include "base/bind.h"
 #include "base/containers/adapters.h"
-#include "base/containers/flat_map.h"
+#include "base/containers/fixed_flat_map.h"
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_macros.h"
@@ -22,6 +22,7 @@
 #include "base/ranges/algorithm.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
@@ -126,70 +127,68 @@
   return std::none_of(s.begin(), s.end(), base::IsAsciiUpper<char>);
 }
 
-using RequestHeaderEntry = std::pair<const char*, RequestHeaderType>;
-constexpr RequestHeaderEntry kRequestHeaderEntries[] = {
-    {"accept", RequestHeaderType::kAccept},
-    {"accept-charset", RequestHeaderType::kAcceptCharset},
-    {"accept-encoding", RequestHeaderType::kAcceptEncoding},
-    {"accept-language", RequestHeaderType::kAcceptLanguage},
-    {"access-control-request-headers",
-     RequestHeaderType::kAccessControlRequestHeaders},
-    {"access-control-request-method",
-     RequestHeaderType::kAccessControlRequestMethod},
-    {"authorization", RequestHeaderType::kAuthorization},
-    {"cache-control", RequestHeaderType::kCacheControl},
-    {"connection", RequestHeaderType::kConnection},
-    {"content-encoding", RequestHeaderType::kContentEncoding},
-    {"content-language", RequestHeaderType::kContentLanguage},
-    {"content-length", RequestHeaderType::kContentLength},
-    {"content-location", RequestHeaderType::kContentLocation},
-    {"content-type", RequestHeaderType::kContentType},
-    {"cookie", RequestHeaderType::kCookie},
-    {"date", RequestHeaderType::kDate},
-    {"dnt", RequestHeaderType::kDnt},
-    {"early-data", RequestHeaderType::kEarlyData},
-    {"expect", RequestHeaderType::kExpect},
-    {"forwarded", RequestHeaderType::kForwarded},
-    {"from", RequestHeaderType::kFrom},
-    {"host", RequestHeaderType::kHost},
-    {"if-match", RequestHeaderType::kIfMatch},
-    {"if-modified-since", RequestHeaderType::kIfModifiedSince},
-    {"if-none-match", RequestHeaderType::kIfNoneMatch},
-    {"if-range", RequestHeaderType::kIfRange},
-    {"if-unmodified-since", RequestHeaderType::kIfUnmodifiedSince},
-    {"keep-alive", RequestHeaderType::kKeepAlive},
-    {"origin", RequestHeaderType::kOrigin},
-    {"pragma", RequestHeaderType::kPragma},
-    {"proxy-authorization", RequestHeaderType::kProxyAuthorization},
-    {"proxy-connection", RequestHeaderType::kProxyConnection},
-    {"range", RequestHeaderType::kRange},
-    {"referer", RequestHeaderType::kReferer},
-    {"te", RequestHeaderType::kTe},
-    {"transfer-encoding", RequestHeaderType::kTransferEncoding},
-    {"upgrade", RequestHeaderType::kUpgrade},
-    {"upgrade-insecure-requests", RequestHeaderType::kUpgradeInsecureRequests},
-    {"user-agent", RequestHeaderType::kUserAgent},
-    {"via", RequestHeaderType::kVia},
-    {"warning", RequestHeaderType::kWarning},
-    {"x-forwarded-for", RequestHeaderType::kXForwardedFor},
-    {"x-forwarded-host", RequestHeaderType::kXForwardedHost},
-    {"x-forwarded-proto", RequestHeaderType::kXForwardedProto}};
+constexpr auto kRequestHeaderEntries =
+    base::MakeFixedFlatMap<base::StringPiece, RequestHeaderType>(
+        {{"accept", RequestHeaderType::kAccept},
+         {"accept-charset", RequestHeaderType::kAcceptCharset},
+         {"accept-encoding", RequestHeaderType::kAcceptEncoding},
+         {"accept-language", RequestHeaderType::kAcceptLanguage},
+         {"access-control-request-headers",
+          RequestHeaderType::kAccessControlRequestHeaders},
+         {"access-control-request-method",
+          RequestHeaderType::kAccessControlRequestMethod},
+         {"authorization", RequestHeaderType::kAuthorization},
+         {"cache-control", RequestHeaderType::kCacheControl},
+         {"connection", RequestHeaderType::kConnection},
+         {"content-encoding", RequestHeaderType::kContentEncoding},
+         {"content-language", RequestHeaderType::kContentLanguage},
+         {"content-length", RequestHeaderType::kContentLength},
+         {"content-location", RequestHeaderType::kContentLocation},
+         {"content-type", RequestHeaderType::kContentType},
+         {"cookie", RequestHeaderType::kCookie},
+         {"date", RequestHeaderType::kDate},
+         {"dnt", RequestHeaderType::kDnt},
+         {"early-data", RequestHeaderType::kEarlyData},
+         {"expect", RequestHeaderType::kExpect},
+         {"forwarded", RequestHeaderType::kForwarded},
+         {"from", RequestHeaderType::kFrom},
+         {"host", RequestHeaderType::kHost},
+         {"if-match", RequestHeaderType::kIfMatch},
+         {"if-modified-since", RequestHeaderType::kIfModifiedSince},
+         {"if-none-match", RequestHeaderType::kIfNoneMatch},
+         {"if-range", RequestHeaderType::kIfRange},
+         {"if-unmodified-since", RequestHeaderType::kIfUnmodifiedSince},
+         {"keep-alive", RequestHeaderType::kKeepAlive},
+         {"origin", RequestHeaderType::kOrigin},
+         {"pragma", RequestHeaderType::kPragma},
+         {"proxy-authorization", RequestHeaderType::kProxyAuthorization},
+         {"proxy-connection", RequestHeaderType::kProxyConnection},
+         {"range", RequestHeaderType::kRange},
+         {"referer", RequestHeaderType::kReferer},
+         {"te", RequestHeaderType::kTe},
+         {"transfer-encoding", RequestHeaderType::kTransferEncoding},
+         {"upgrade", RequestHeaderType::kUpgrade},
+         {"upgrade-insecure-requests",
+          RequestHeaderType::kUpgradeInsecureRequests},
+         {"user-agent", RequestHeaderType::kUserAgent},
+         {"via", RequestHeaderType::kVia},
+         {"warning", RequestHeaderType::kWarning},
+         {"x-forwarded-for", RequestHeaderType::kXForwardedFor},
+         {"x-forwarded-host", RequestHeaderType::kXForwardedHost},
+         {"x-forwarded-proto", RequestHeaderType::kXForwardedProto}});
 
-constexpr bool IsValidHeaderName(const char* str) {
-  while (*str) {
-    if ((*str >= 'a' && *str <= 'z') || *str == '-') {
-      str++;
-      continue;
-    }
-    return false;
+constexpr bool IsValidHeaderName(base::StringPiece str) {
+  for (char ch : str) {
+    if ((ch < 'a' || ch > 'z') && ch != '-')
+      return false;
   }
   return true;
 }
 
 template <typename T>
 constexpr bool ValidateHeaderEntries(const T& entries) {
-  for (size_t i = 0; i < base::size(entries); ++i) {
-    if (!IsValidHeaderName(entries[i].first))
+  for (const auto& entry : entries) {
+    if (!IsValidHeaderName(entry.first))
       return false;
   }
   return true;
@@ -201,7 +200,7 @@
 // sec-origin-policy which does not have a corresponding entry in
 // kRequestHeaderEntries but does contribute to RequestHeaderType::kMaxValue.
 static_assert(static_cast<size_t>(RequestHeaderType::kMaxValue) - 2 ==
-                  base::size(kRequestHeaderEntries),
+                  kRequestHeaderEntries.size(),
               "Invalid number of request header entries");
 
 static_assert(ValidateHeaderEntries(kRequestHeaderEntries),
@@ -211,20 +210,10 @@
 // returned.
 void RecordRequestHeader(const std::string& header,
                          void (*record_func)(RequestHeaderType)) {
-  using HeaderMapType = base::flat_map<base::StringPiece, RequestHeaderType>;
-  static const base::NoDestructor<HeaderMapType> kHeaderMap([] {
-    std::vector<std::pair<base::StringPiece, RequestHeaderType>> entries;
-    entries.reserve(base::size(kRequestHeaderEntries));
-    for (const auto& entry : kRequestHeaderEntries)
-      entries.emplace_back(entry.first, entry.second);
-    return HeaderMapType(entries.begin(), entries.end());
-  }());
-
   DCHECK(IsStringLowerCaseASCII(header));
-  auto it = kHeaderMap->find(header);
-  RequestHeaderType type =
-      it != kHeaderMap->end() ? it->second : RequestHeaderType::kOther;
-  record_func(type);
+  const auto* it = kRequestHeaderEntries.find(header);
+  record_func(it != kRequestHeaderEntries.end() ? it->second
+                                                : RequestHeaderType::kOther);
 }
 
 void RecordResponseHeaderChanged(ResponseHeaderType type) {
@@ -256,97 +245,88 @@
       "Extensions.DeclarativeNetRequest.ResponseHeaderRemoved", type);
 }
 
-using ResponseHeaderEntry = std::pair<const char*, ResponseHeaderType>;
-constexpr ResponseHeaderEntry kResponseHeaderEntries[] = {
-    {"accept-patch", ResponseHeaderType::kAcceptPatch},
-    {"accept-ranges", ResponseHeaderType::kAcceptRanges},
-    {"access-control-allow-credentials",
-     ResponseHeaderType::kAccessControlAllowCredentials},
-    {"access-control-allow-headers",
-     ResponseHeaderType::kAccessControlAllowHeaders},
-    {"access-control-allow-methods",
-     ResponseHeaderType::kAccessControlAllowMethods},
-    {"access-control-allow-origin",
-     ResponseHeaderType::kAccessControlAllowOrigin},
-    {"access-control-expose-headers",
-     ResponseHeaderType::kAccessControlExposeHeaders},
-    {"access-control-max-age", ResponseHeaderType::kAccessControlMaxAge},
-    {"age", ResponseHeaderType::kAge},
-    {"allow", ResponseHeaderType::kAllow},
-    {"alt-svc", ResponseHeaderType::kAltSvc},
-    {"cache-control", ResponseHeaderType::kCacheControl},
-    {"clear-site-data", ResponseHeaderType::kClearSiteData},
-    {"connection", ResponseHeaderType::kConnection},
-    {"content-disposition", ResponseHeaderType::kContentDisposition},
-    {"content-encoding", ResponseHeaderType::kContentEncoding},
-    {"content-language", ResponseHeaderType::kContentLanguage},
-    {"content-length", ResponseHeaderType::kContentLength},
-    {"content-location", ResponseHeaderType::kContentLocation},
-    {"content-range", ResponseHeaderType::kContentRange},
-    {"content-security-policy", ResponseHeaderType::kContentSecurityPolicy},
-    {"content-security-policy-report-only",
-     ResponseHeaderType::kContentSecurityPolicyReportOnly},
-    {"content-type", ResponseHeaderType::kContentType},
-    {"date", ResponseHeaderType::kDate},
-    {"etag", ResponseHeaderType::kETag},
-    {"expect-ct", ResponseHeaderType::kExpectCT},
-    {"expires", ResponseHeaderType::kExpires},
-    {"feature-policy", ResponseHeaderType::kFeaturePolicy},
-    {"keep-alive", ResponseHeaderType::kKeepAlive},
-    {"large-allocation", ResponseHeaderType::kLargeAllocation},
-    {"last-modified", ResponseHeaderType::kLastModified},
-    {"location", ResponseHeaderType::kLocation},
-    {"pragma", ResponseHeaderType::kPragma},
-    {"proxy-authenticate", ResponseHeaderType::kProxyAuthenticate},
-    {"proxy-connection", ResponseHeaderType::kProxyConnection},
-    {"public-key-pins", ResponseHeaderType::kPublicKeyPins},
-    {"public-key-pins-report-only",
-     ResponseHeaderType::kPublicKeyPinsReportOnly},
-    {"referrer-policy", ResponseHeaderType::kReferrerPolicy},
-    {"refresh", ResponseHeaderType::kRefresh},
-    {"retry-after", ResponseHeaderType::kRetryAfter},
-    {"sec-websocket-accept", ResponseHeaderType::kSecWebSocketAccept},
-    {"server", ResponseHeaderType::kServer},
-    {"server-timing", ResponseHeaderType::kServerTiming},
-    {"set-cookie", ResponseHeaderType::kSetCookie},
-    {"sourcemap", ResponseHeaderType::kSourceMap},
-    {"strict-transport-security", ResponseHeaderType::kStrictTransportSecurity},
-    {"timing-allow-origin", ResponseHeaderType::kTimingAllowOrigin},
-    {"tk", ResponseHeaderType::kTk},
-    {"trailer", ResponseHeaderType::kTrailer},
-    {"transfer-encoding", ResponseHeaderType::kTransferEncoding},
-    {"upgrade", ResponseHeaderType::kUpgrade},
-    {"vary", ResponseHeaderType::kVary},
-    {"via", ResponseHeaderType::kVia},
-    {"warning", ResponseHeaderType::kWarning},
-    {"www-authenticate", ResponseHeaderType::kWWWAuthenticate},
-    {"x-content-type-options", ResponseHeaderType::kXContentTypeOptions},
-    {"x-dns-prefetch-control", ResponseHeaderType::kXDNSPrefetchControl},
-    {"x-frame-options", ResponseHeaderType::kXFrameOptions},
-    {"x-xss-protection", ResponseHeaderType::kXXSSProtection},
-};
+constexpr auto kResponseHeaderEntries =
+    base::MakeFixedFlatMap<base::StringPiece, ResponseHeaderType>({
+        {"accept-patch", ResponseHeaderType::kAcceptPatch},
+        {"accept-ranges", ResponseHeaderType::kAcceptRanges},
+        {"access-control-allow-credentials",
+         ResponseHeaderType::kAccessControlAllowCredentials},
+        {"access-control-allow-headers",
+         ResponseHeaderType::kAccessControlAllowHeaders},
+        {"access-control-allow-methods",
+         ResponseHeaderType::kAccessControlAllowMethods},
+        {"access-control-allow-origin",
+         ResponseHeaderType::kAccessControlAllowOrigin},
+        {"access-control-expose-headers",
+         ResponseHeaderType::kAccessControlExposeHeaders},
+        {"access-control-max-age", ResponseHeaderType::kAccessControlMaxAge},
+        {"age", ResponseHeaderType::kAge},
+        {"allow", ResponseHeaderType::kAllow},
+        {"alt-svc", ResponseHeaderType::kAltSvc},
+        {"cache-control", ResponseHeaderType::kCacheControl},
+        {"clear-site-data", ResponseHeaderType::kClearSiteData},
+        {"connection", ResponseHeaderType::kConnection},
+        {"content-disposition", ResponseHeaderType::kContentDisposition},
+        {"content-encoding", ResponseHeaderType::kContentEncoding},
+        {"content-language", ResponseHeaderType::kContentLanguage},
+        {"content-length", ResponseHeaderType::kContentLength},
+        {"content-location", ResponseHeaderType::kContentLocation},
+        {"content-range", ResponseHeaderType::kContentRange},
+        {"content-security-policy", ResponseHeaderType::kContentSecurityPolicy},
+        {"content-security-policy-report-only",
+         ResponseHeaderType::kContentSecurityPolicyReportOnly},
+        {"content-type", ResponseHeaderType::kContentType},
+        {"date", ResponseHeaderType::kDate},
+        {"etag", ResponseHeaderType::kETag},
+        {"expect-ct", ResponseHeaderType::kExpectCT},
+        {"expires", ResponseHeaderType::kExpires},
+        {"feature-policy", ResponseHeaderType::kFeaturePolicy},
+        {"keep-alive", ResponseHeaderType::kKeepAlive},
+        {"large-allocation", ResponseHeaderType::kLargeAllocation},
+        {"last-modified", ResponseHeaderType::kLastModified},
+        {"location", ResponseHeaderType::kLocation},
+        {"pragma", ResponseHeaderType::kPragma},
+        {"proxy-authenticate", ResponseHeaderType::kProxyAuthenticate},
+        {"proxy-connection", ResponseHeaderType::kProxyConnection},
+        {"public-key-pins", ResponseHeaderType::kPublicKeyPins},
+        {"public-key-pins-report-only",
+         ResponseHeaderType::kPublicKeyPinsReportOnly},
+        {"referrer-policy", ResponseHeaderType::kReferrerPolicy},
+        {"refresh", ResponseHeaderType::kRefresh},
+        {"retry-after", ResponseHeaderType::kRetryAfter},
+        {"sec-websocket-accept", ResponseHeaderType::kSecWebSocketAccept},
+        {"server", ResponseHeaderType::kServer},
+        {"server-timing", ResponseHeaderType::kServerTiming},
+        {"set-cookie", ResponseHeaderType::kSetCookie},
+        {"sourcemap", ResponseHeaderType::kSourceMap},
+        {"strict-transport-security",
+         ResponseHeaderType::kStrictTransportSecurity},
+        {"timing-allow-origin", ResponseHeaderType::kTimingAllowOrigin},
+        {"tk", ResponseHeaderType::kTk},
+        {"trailer", ResponseHeaderType::kTrailer},
+        {"transfer-encoding", ResponseHeaderType::kTransferEncoding},
+        {"upgrade", ResponseHeaderType::kUpgrade},
+        {"vary", ResponseHeaderType::kVary},
+        {"via", ResponseHeaderType::kVia},
+        {"warning", ResponseHeaderType::kWarning},
+        {"www-authenticate", ResponseHeaderType::kWWWAuthenticate},
+        {"x-content-type-options", ResponseHeaderType::kXContentTypeOptions},
+        {"x-dns-prefetch-control", ResponseHeaderType::kXDNSPrefetchControl},
+        {"x-frame-options", ResponseHeaderType::kXFrameOptions},
+        {"x-xss-protection", ResponseHeaderType::kXXSSProtection},
+    });
 
 void RecordResponseHeader(base::StringPiece header,
                           void (*record_func)(ResponseHeaderType)) {
-  using HeaderMapType = base::flat_map<base::StringPiece, ResponseHeaderType>;
-  static const base::NoDestructor<HeaderMapType> kHeaderMap([] {
-    std::vector<std::pair<base::StringPiece, ResponseHeaderType>> entries;
-    entries.reserve(base::size(kResponseHeaderEntries));
-    for (const auto& entry : kResponseHeaderEntries)
-      entries.emplace_back(entry.first, entry.second);
-    return HeaderMapType(entries.begin(), entries.end());
-  }());
-
   DCHECK(IsStringLowerCaseASCII(header));
-  auto it = kHeaderMap->find(header);
-  ResponseHeaderType type =
-      it != kHeaderMap->end() ? it->second : ResponseHeaderType::kOther;
-  record_func(type);
+  const auto* it = kResponseHeaderEntries.find(header);
+  record_func(it != kResponseHeaderEntries.end() ? it->second
+                                                 : ResponseHeaderType::kOther);
 }
 
 // All entries other than kOther and kNone are mapped.
 static_assert(static_cast<size_t>(ResponseHeaderType::kMaxValue) - 1 ==
-                  base::size(kResponseHeaderEntries),
+                  kResponseHeaderEntries.size(),
               "Invalid number of response header entries");
 
 static_assert(ValidateHeaderEntries(kResponseHeaderEntries),
diff --git a/extensions/shell/test/shell_tests_main.cc b/extensions/shell/test/shell_tests_main.cc
index 544b733..fceb6242 100644
--- a/extensions/shell/test/shell_tests_main.cc
+++ b/extensions/shell/test/shell_tests_main.cc
@@ -4,14 +4,26 @@
 
 #include "base/command_line.h"
 #include "base/test/launcher/test_launcher.h"
+#include "build/build_config.h"
 #include "extensions/shell/test/shell_test_launcher_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#endif  // defined(OS_WIN)
+
 int main(int argc, char** argv) {
   base::CommandLine::Init(argc, argv);
   size_t parallel_jobs = base::NumParallelJobs(/*cores_per_job=*/2);
   if (parallel_jobs == 0U)
     return 1;
+
+#if defined(OS_WIN)
+  // Load and pin user32.dll to avoid having to load it once tests start while
+  // on the main thread loop where blocking calls are disallowed.
+  base::win::PinUser32();
+#endif  // OS_WIN
+
   extensions::AppShellTestLauncherDelegate launcher_delegate;
   return content::LaunchTests(&launcher_delegate, parallel_jobs, argc, argv);
 }
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 804a2b8..c8590aca 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -1092,6 +1092,7 @@
     case GL_R16UI:
     case GL_RG16UI:
     case GL_RGBA16UI:
+    case GL_RGB10_A2:
     case GL_RGB10_A2UI:
     case GL_R16_EXT:
     case GL_RG16_EXT:
diff --git a/gpu/command_buffer/service/image_reader_gl_owner.cc b/gpu/command_buffer/service/image_reader_gl_owner.cc
index addcd5a..93f99ab 100644
--- a/gpu/command_buffer/service/image_reader_gl_owner.cc
+++ b/gpu/command_buffer/service/image_reader_gl_owner.cc
@@ -401,6 +401,9 @@
   }
 
   image_refs_.erase(it);
+  DCHECK_GT(max_images_, static_cast<int32_t>(image_refs_.size()));
+  if (buffer_available_cb_)
+    std::move(buffer_available_cb_).Run();
 }
 
 void ImageReaderGLOwner::ReleaseBackBuffers() {
@@ -428,6 +431,20 @@
   image_reader_ptr->frame_available_cb_.Run();
 }
 
+void ImageReaderGLOwner::RunWhenBufferIsAvailable(base::OnceClosure callback) {
+  // Note that we handle only one simultaneous request, this is not issue
+  // because FrameInfoHelper maintain request queue and has only single
+  // outstanding request on GPU thread.
+  DCHECK(!buffer_available_cb_);
+  // If `max_images` == 1 we will drop it before acquiring new buffer. Note that
+  // this must never happen with SurfaceControl and the ImageReaderGLOwner is
+  // the sole owner of the images.
+  if (max_images_ == 1 || static_cast<int>(image_refs_.size()) < max_images_)
+    std::move(callback).Run();
+  else
+    buffer_available_cb_ = std::move(callback);
+}
+
 bool ImageReaderGLOwner::GetCodedSizeAndVisibleRect(
     gfx::Size rotated_visible_size,
     gfx::Size* coded_size,
diff --git a/gpu/command_buffer/service/image_reader_gl_owner.h b/gpu/command_buffer/service/image_reader_gl_owner.h
index b6c2d2c..0917fd3 100644
--- a/gpu/command_buffer/service/image_reader_gl_owner.h
+++ b/gpu/command_buffer/service/image_reader_gl_owner.h
@@ -44,6 +44,7 @@
   bool GetCodedSizeAndVisibleRect(gfx::Size rotated_visible_size,
                                   gfx::Size* coded_size,
                                   gfx::Rect* visible_rect) override;
+  void RunWhenBufferIsAvailable(base::OnceClosure callback) override;
 
   const AImageReader* image_reader_for_testing() const { return image_reader_; }
   int32_t max_images_for_testing() const { return max_images_; }
@@ -131,6 +132,9 @@
   // in turns runs the callback function.
   base::RepeatingClosure frame_available_cb_;
 
+  // Runs when free buffer is available.
+  base::OnceClosure buffer_available_cb_;
+
   THREAD_CHECKER(thread_checker_);
 
   base::WeakPtrFactory<ImageReaderGLOwner> weak_factory_{this};
diff --git a/gpu/command_buffer/service/mock_texture_owner.cc b/gpu/command_buffer/service/mock_texture_owner.cc
index 9b6bb6e..efaa5eb 100644
--- a/gpu/command_buffer/service/mock_texture_owner.cc
+++ b/gpu/command_buffer/service/mock_texture_owner.cc
@@ -8,6 +8,7 @@
 
 namespace gpu {
 
+using testing::_;
 using testing::Invoke;
 using testing::Return;
 
@@ -26,6 +27,8 @@
   ON_CALL(*this, EnsureTexImageBound()).WillByDefault(Invoke([this] {
     CHECK(expect_update_tex_image);
   }));
+  ON_CALL(*this, RunWhenBufferIsAvailable(_))
+      .WillByDefault(Invoke([](base::OnceClosure cb) { std::move(cb).Run(); }));
 }
 
 MockTextureOwner::~MockTextureOwner() {
diff --git a/gpu/command_buffer/service/mock_texture_owner.h b/gpu/command_buffer/service/mock_texture_owner.h
index 2cf23aff..45983f4 100644
--- a/gpu/command_buffer/service/mock_texture_owner.h
+++ b/gpu/command_buffer/service/mock_texture_owner.h
@@ -40,6 +40,7 @@
                bool(gfx::Size rotated_visible_size,
                     gfx::Size* coded_size,
                     gfx::Rect* visible_rect));
+  MOCK_METHOD1(RunWhenBufferIsAvailable, void(base::OnceClosure));
 
   std::unique_ptr<base::android::ScopedHardwareBufferFenceSync>
   GetAHardwareBuffer() override {
diff --git a/gpu/command_buffer/service/surface_texture_gl_owner.cc b/gpu/command_buffer/service/surface_texture_gl_owner.cc
index a99a5c42..d088cd92 100644
--- a/gpu/command_buffer/service/surface_texture_gl_owner.cc
+++ b/gpu/command_buffer/service/surface_texture_gl_owner.cc
@@ -57,6 +57,12 @@
   surface_texture_->SetFrameAvailableCallbackOnAnyThread(frame_available_cb);
 }
 
+void SurfaceTextureGLOwner::RunWhenBufferIsAvailable(
+    base::OnceClosure callback) {
+  // SurfaceTexture can always render to front buffer.
+  std::move(callback).Run();
+}
+
 gl::ScopedJavaSurface SurfaceTextureGLOwner::CreateJavaSurface() const {
   // |surface_texture_| might be null, but that's okay.
   return gl::ScopedJavaSurface(surface_texture_.get());
diff --git a/gpu/command_buffer/service/surface_texture_gl_owner.h b/gpu/command_buffer/service/surface_texture_gl_owner.h
index d1ecf45d..e3198a8 100644
--- a/gpu/command_buffer/service/surface_texture_gl_owner.h
+++ b/gpu/command_buffer/service/surface_texture_gl_owner.h
@@ -40,6 +40,8 @@
                                   gfx::Size* coded_size,
                                   gfx::Rect* visible_rect) override;
 
+  void RunWhenBufferIsAvailable(base::OnceClosure callback) override;
+
  protected:
   void OnTextureDestroyed(gles2::AbstractTexture*) override;
 
diff --git a/gpu/command_buffer/service/texture_owner.h b/gpu/command_buffer/service/texture_owner.h
index 81bf220..f58dde4 100644
--- a/gpu/command_buffer/service/texture_owner.h
+++ b/gpu/command_buffer/service/texture_owner.h
@@ -115,6 +115,10 @@
   virtual void SetFrameAvailableCallback(
       const base::RepeatingClosure& frame_available_cb) = 0;
 
+  // Runs callback when the free buffer is available to render to front buffer.
+  // Can be run before returning from the function.
+  virtual void RunWhenBufferIsAvailable(base::OnceClosure callback) = 0;
+
   bool binds_texture_on_update() const { return binds_texture_on_update_; }
 
  protected:
diff --git a/headless/test/headless_test_launcher.cc b/headless/test/headless_test_launcher.cc
index 9ff7ebd..fdc457f8 100644
--- a/headless/test/headless_test_launcher.cc
+++ b/headless/test/headless_test_launcher.cc
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/test/launcher/test_launcher.h"
+#include "build/build_config.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/content_test_suite_base.h"
 #include "content/public/test/network_service_test_helper.h"
@@ -17,6 +18,10 @@
 #include "headless/lib/utility/headless_content_utility_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#endif  // defined(OS_WIN)
+
 namespace headless {
 namespace {
 
@@ -69,6 +74,12 @@
   if (parallel_jobs == 0U)
     return 1;
 
+#if defined(OS_WIN)
+  // Load and pin user32.dll to avoid having to load it once tests start while
+  // on the main thread loop where blocking calls are disallowed.
+  base::win::PinUser32();
+#endif  // OS_WIN
+
   // Setup a working test environment for the network service in case it's used.
   // Only create this object in the utility process, so that its members don't
   // interfere with other test objects in the browser process.
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg
index 5869554..65aa7c6 100644
--- a/infra/config/generated/commit-queue.cfg
+++ b/infra/config/generated/commit-queue.cfg
@@ -1095,7 +1095,7 @@
       }
       builders {
         name: "chromium/try/linux-rel-builderful"
-        experiment_percentage: 10
+        experiment_percentage: 5
         location_regexp: ".*"
         location_regexp_exclude: ".+/[+]/docs/.+"
         location_regexp_exclude: ".+/[+]/infra/config/.+"
@@ -1137,6 +1137,13 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/linux-warmed"
+        experiment_percentage: 5
+        location_regexp: ".*"
+        location_regexp_exclude: ".+/[+]/docs/.+"
+        location_regexp_exclude: ".+/[+]/infra/config/.+"
+      }
+      builders {
         name: "chromium/try/linux-webkit-msan-rel"
         includable_only: true
       }
@@ -1153,10 +1160,6 @@
         includable_only: true
       }
       builders {
-        name: "chromium/try/linux-wpt-payments-fyi-rel"
-        includable_only: true
-      }
-      builders {
         name: "chromium/try/linux_android_dbg_ng"
         includable_only: true
       }
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md
index 4d7805e..2985486c 100644
--- a/infra/config/generated/cq-builders.md
+++ b/infra/config/generated/cq-builders.md
@@ -393,5 +393,8 @@
   * [`//services/tracing/.+`](https://cs.chromium.org/chromium/src/services/tracing/)
 
 * [linux-rel-builderful](https://ci.chromium.org/p/chromium/builders/try/linux-rel-builderful) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux-rel-builderful)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux-rel-builderful))
-  * Experiment percentage: 10
+  * Experiment percentage: 5
+
+* [linux-warmed](https://ci.chromium.org/p/chromium/builders/try/linux-warmed) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux-warmed)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux-warmed))
+  * Experiment percentage: 5
 
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index c739705..7d64eb8c 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -18939,54 +18939,6 @@
       }
     }
     builders {
-      name: "linux-wpt-payments-fyi-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      swarming_tags: "vpython:native-python-wrapper"
-      dimensions: "builderless:1"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04"
-      dimensions: "pool:luci.chromium.ci"
-      dimensions: "ssd:0"
-      exe {
-        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
-        cipd_version: "refs/heads/master"
-        cmd: "recipes"
-      }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
-      execution_timeout_secs: 36000
-      build_numbers: YES
-      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
-      experimental: YES
-      experiments {
-        key: "chromium.resultdb.result_sink"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "ci_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "gpu_ci_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
-            }
-          }
-        }
-      }
-    }
-    builders {
       name: "mac-archive-dbg"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -20098,6 +20050,53 @@
       }
     }
     builders {
+      name: "try-warmer"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.fyi\",\"builder_to_warm\":\"linux-warmed\",\"recipe\":\"chromium/try_warmer\"}"
+      execution_timeout_secs: 300
+      build_numbers: YES
+      service_account: "chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+      }
+    }
+    builders {
       name: "win-annotator-rel"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -32054,7 +32053,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12a7209\"}"
+      properties: "{\"$build/code_coverage\":{\"coverage_exclude_sources\":\"ios_test_files_and_test_utils\",\"coverage_test_types\":[\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12a7209\"}"
       execution_timeout_secs: 14400
       expiration_secs: 7200
       caches {
@@ -32282,7 +32281,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12a7209\"}"
+      properties: "{\"$build/code_coverage\":{\"coverage_exclude_sources\":\"ios_test_files_and_test_utils\",\"coverage_test_types\":[\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12a7209\"}"
       execution_timeout_secs: 14400
       expiration_secs: 7200
       caches {
@@ -34865,6 +34864,60 @@
       }
     }
     builders {
+      name: "linux-warmed"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:linux-warmed"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+      }
+    }
+    builders {
       name: "linux-webkit-msan-rel"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -35085,61 +35138,6 @@
       }
     }
     builders {
-      name: "linux-wpt-payments-fyi-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      swarming_tags: "vpython:native-python-wrapper"
-      dimensions: "builderless:1"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04"
-      dimensions: "pool:luci.chromium.try"
-      dimensions: "ssd:0"
-      exe {
-        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
-        cipd_version: "refs/heads/master"
-        cmd: "recipes"
-      }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "chromium.resultdb.result_sink"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "gpu_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
-            }
-          }
-        }
-      }
-    }
-    builders {
       name: "linux_android_dbg_ng"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/goma-usage.pyl b/infra/config/generated/goma-usage.pyl
index 30c413c1..3d6a1491 100644
--- a/infra/config/generated/goma-usage.pyl
+++ b/infra/config/generated/goma-usage.pyl
@@ -9,9 +9,9 @@
   'scheduler': {
     '*total*': 61470,
     'triggered': {
-      '*total*': 59920,
+      '*total*': 59840,
       ('https://chromium.googlesource.com/chromium/src', 'regexp:refs/heads/master'): {
-        '*total*': 59040,
+        '*total*': 58960,
         # 4 concurrent builds x 80 jobs
         'ci/ASAN Debug': 320,
         # 5 concurrent builds x 80 jobs
@@ -335,7 +335,6 @@
         'ci/linux-wpt-fyi-rel': 80,
         'ci/linux-wpt-identity-fyi-rel': 80,
         'ci/linux-wpt-input-fyi-rel': 80,
-        'ci/linux-wpt-payments-fyi-rel': 80,
         'ci/mac-archive-dbg': 40,
         'ci/mac-archive-rel': 80,
         # jobs count assumes an 8-core machine
@@ -492,7 +491,7 @@
       },
     },
     'scheduled': {
-      '*total*': 1550,
+      '*total*': 1630,
       '0 0,12 * * *': {
         '*total*': 80,
         # jobs count assumes an 8-core machine
@@ -535,6 +534,10 @@
         'ci/mac-upload-perfetto': 80,
         'ci/win-upload-perfetto': 80,
       },
+      'with 5m interval': {
+        '*total*': 80,
+        'ci/try-warmer': 80,
+      },
     },
   },
   'cq': {
@@ -592,8 +595,10 @@
     # 80 jobs x 100% experiment
     'try/linux-perfetto-rel': 80,
     'try/linux-rel': 150,
-    # 150 jobs x 10% experiment
-    'try/linux-rel-builderful': 15,
+    # 150 jobs x 5% experiment
+    'try/linux-rel-builderful': 7.5,
+    # 150 jobs x 5% experiment
+    'try/linux-warmed': 7.5,
     'try/linux_chromium_asan_rel_ng': 150,
     'try/linux_chromium_compile_dbg_ng': 150,
     'try/linux_chromium_dbg_ng': 80,
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index 0bdcf8c..ccbbc40 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -5270,6 +5270,11 @@
     short_name: "sdk14"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/try-warmer"
+    category: "infra"
+    short_name: "warmer"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/VR Linux"
     category: "linux"
   }
@@ -5306,10 +5311,6 @@
     category: "linux"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/linux-wpt-payments-fyi-rel"
-    category: "linux"
-  }
-  builders {
     name: "buildbucket/luci.chromium.ci/Leak Detection Linux"
     category: "linux"
     short_name: "lk"
@@ -12109,6 +12110,9 @@
     name: "buildbucket/luci.chromium.try/linux-viz-rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/linux-warmed"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/linux-webkit-msan-rel"
   }
   builders {
@@ -12121,9 +12125,6 @@
     name: "buildbucket/luci.chromium.try/linux-wpt-input-fyi-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/linux-wpt-payments-fyi-rel"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/linux_android_dbg_ng"
   }
   builders {
@@ -12930,6 +12931,9 @@
     name: "buildbucket/luci.chromium.try/linux-viz-rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/linux-warmed"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/linux-webkit-msan-rel"
   }
   builders {
@@ -12942,9 +12946,6 @@
     name: "buildbucket/luci.chromium.try/linux-wpt-input-fyi-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/linux-wpt-payments-fyi-rel"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/linux_chromium_analysis"
   }
   builders {
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index b8a6f8e..dadc8d5 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -5651,16 +5651,6 @@
   }
 }
 job {
-  id: "linux-wpt-payments-fyi-rel"
-  realm: "ci"
-  acl_sets: "ci"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "linux-wpt-payments-fyi-rel"
-  }
-}
-job {
   id: "linux_chromium_bot_db_exporter"
   realm: "findit"
   schedule: "0 0,6,12,18 * * *"
@@ -6013,6 +6003,17 @@
   }
 }
 job {
+  id: "try-warmer"
+  realm: "ci"
+  schedule: "with 5m interval"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "try-warmer"
+  }
+}
+job {
   id: "win-annotator-rel"
   realm: "ci"
   acl_sets: "ci"
@@ -6708,7 +6709,6 @@
   triggers: "linux-wpt-fyi-rel"
   triggers: "linux-wpt-identity-fyi-rel"
   triggers: "linux-wpt-input-fyi-rel"
-  triggers: "linux-wpt-payments-fyi-rel"
   triggers: "mac-archive-dbg"
   triggers: "mac-archive-rel"
   triggers: "mac-arm64-rel"
diff --git a/infra/config/generated/realms.cfg b/infra/config/generated/realms.cfg
index 76062298..e7e21d8 100644
--- a/infra/config/generated/realms.cfg
+++ b/infra/config/generated/realms.cfg
@@ -57,6 +57,7 @@
     principals: "user:chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
+    principals: "user:chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:component-mapping-updater@chops-service-accounts.iam.gserviceaccount.com"
   }
   bindings {
@@ -187,6 +188,7 @@
     principals: "project:chromium-m86"
     principals: "project:chromium-m87"
     principals: "project:chromium-m88"
+    principals: "user:chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:infra-try-recipes-tester@chops-service-accounts.iam.gserviceaccount.com"
   }
 }
@@ -233,6 +235,7 @@
     principals: "group:chromium-led-users"
     principals: "group:project-chromium-mac-arm64-tests-access"
     principals: "group:project-chromium-tryjob-access"
+    principals: "user:chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:infra-try-recipes-tester@chops-service-accounts.iam.gserviceaccount.com"
   }
 }
diff --git a/infra/config/lib/builders.star b/infra/config/lib/builders.star
index 58dd6ea..c18c66f91 100644
--- a/infra/config/lib/builders.star
+++ b/infra/config/lib/builders.star
@@ -123,21 +123,25 @@
     ),
 )
 
-def xcode_enum(cache_name, cache_path):
-    return swarming.cache(name = cache_name, path = cache_path)
+def xcode_enum(version):
+    return struct(
+        version = version,
+        cache_name = "xcode_ios_{}".format(version),
+        cache_path = "xcode_ios_{}.app".format(version),
+    )
 
 # Keep this in-sync with the versions of bots in //ios/build/bots/.
-xcode_cache = struct(
+xcode = struct(
     # in use by webrtc mac builders
-    x11c29 = xcode_enum("xcode_ios_11c29", "xcode_ios_11c29.app"),
+    x11c29 = xcode_enum("11c29"),
     # in use by ci/ios-simulator-cronet and try/ios-simulator-cronet
-    x11e146 = xcode_enum("xcode_ios_11e146", "xcode_ios_11e146.app"),
+    x11e146 = xcode_enum("11e146"),
     # in use by ios-webkit-tot
-    x11e608cwk = xcode_enum("xcode_ios_11e608cwk", "xcode_ios_11e608cwk.app"),
+    x11e608cwk = xcode_enum("11e608cwk"),
     # (current default) xc12 gm seed
-    x12a7209 = xcode_enum("xcode_ios_12a7209", "xcode_ios_12a7209.app"),
+    x12a7209 = xcode_enum("12a7209"),
     # latest Xcode 12 beta version.
-    x12b5044c = xcode_enum("xcode_ios_12b5044c", "xcode_ios_12b5044c.app"),
+    x12b5044c = xcode_enum("12b5044c"),
 )
 
 ################################################################################
@@ -265,6 +269,7 @@
     os = None,
     project_trigger_overrides = None,
     pool = None,
+    xcode = None,
     ssd = args.COMPUTE,
     use_clang_coverage = False,
     use_java_coverage = False,
@@ -300,6 +305,7 @@
         builder_group = args.DEFAULT,
         pool = args.DEFAULT,
         ssd = args.DEFAULT,
+        xcode = args.DEFAULT,
         project_trigger_overrides = args.DEFAULT,
         configure_kitchen = args.DEFAULT,
         goma_backend = args.DEFAULT,
@@ -368,6 +374,13 @@
         If True, emits a 'ssd:1' dimension. If False, emits a 'ssd:0' parameter.
         By default, considered False if builderless is considered True and
         otherwise None.
+      * xcode - a member of the `xcode` enum indicating the xcode version the
+        builder requires. Emits a cache declaration of the form
+        ```{
+          name: <xcode.cache_name>
+          path: <xcode.cache_path>
+        }```. Also emits a 'xcode_build_version:<xcode.version>' property if the
+        property is not already set.
       * project_trigger_overrides - a dict mapping the LUCI projects declared in
         recipe BotSpecs to the LUCI project to use when triggering builders. When
         this builder triggers another builder, if the BotSpec for that builder has
@@ -539,6 +552,13 @@
     triggered_by = defaults.get_value("triggered_by", triggered_by)
     if triggered_by != args.COMPUTE:
         kwargs["triggered_by"] = triggered_by
+    xcode = defaults.get_value("xcode", xcode)
+    if xcode:
+        kwargs["caches"] = (kwargs.get("caches") or []) + [swarming.cache(
+            name = xcode.cache_name,
+            path = xcode.cache_path,
+        )]
+        properties.setdefault("xcode_build_version", xcode.version)
 
     return branches.builder(
         name = name,
@@ -568,5 +588,5 @@
     defaults = defaults,
     goma = goma,
     os = os,
-    xcode_cache = xcode_cache,
+    xcode = xcode,
 )
diff --git a/infra/config/lib/ci.star b/infra/config/lib/ci.star
index 822c1a9..dda3112 100644
--- a/infra/config/lib/ci.star
+++ b/infra/config/lib/ci.star
@@ -667,25 +667,17 @@
 def fyi_ios_builder(
         *,
         name,
-        caches = None,
         executable = "recipe:chromium",
         goma_backend = builders.goma.backend.RBE_PROD,
         os = builders.os.MAC_10_15,
-        properties = None,
+        xcode = builders.xcode.x12a7209,
         **kwargs):
-    # Default cache and properties sync
-    caches = caches or [builders.xcode_cache.x12a7209]
-
-    properties = properties or {}
-    properties.setdefault("xcode_build_version", "12a7209")
-
     return fyi_builder(
         name = name,
-        caches = caches,
         cores = None,
         executable = executable,
         os = os,
-        properties = properties,
+        xcode = xcode,
         **kwargs
     )
 
@@ -876,23 +868,16 @@
 def mac_ios_builder(
         *,
         name,
-        caches = None,
         executable = "recipe:chromium",
         goma_backend = builders.goma.backend.RBE_PROD,
-        properties = None,
+        xcode = builders.xcode.x12a7209,
         **kwargs):
-    caches = caches or [builders.xcode_cache.x12a7209]
-
-    properties = properties or {}
-    properties.setdefault("xcode_build_version", "12a7209")
-
     return mac_builder(
         name = name,
-        caches = caches,
         goma_backend = goma_backend,
         executable = executable,
         os = builders.os.MAC_10_15,
-        properties = properties,
+        xcode = xcode,
         **kwargs
     )
 
diff --git a/infra/config/lib/try.star b/infra/config/lib/try.star
index 5291558..ae4ef10 100644
--- a/infra/config/lib/try.star
+++ b/infra/config/lib/try.star
@@ -350,26 +350,19 @@
 def chromium_mac_ios_builder(
         *,
         name,
-        caches = None,
         executable = "recipe:chromium_trybot",
         goma_backend = builders.goma.backend.RBE_PROD,
         os = builders.os.MAC_10_15,
-        properties = None,
+        xcode = builders.xcode.x12a7209,
         **kwargs):
-    caches = caches or [builders.xcode_cache.x12a7209]
-
-    properties = properties or {}
-    properties.setdefault("xcode_build_version", "12a7209")
-
     return try_builder(
         name = name,
         builder_group = "tryserver.chromium.mac",
-        caches = caches,
         cores = None,
         executable = executable,
         goma_backend = goma_backend,
         os = os,
-        properties = properties,
+        xcode = xcode,
         **kwargs
     )
 
diff --git a/infra/config/recipes.star b/infra/config/recipes.star
index e0d73d95..ed4473a6 100644
--- a/infra/config/recipes.star
+++ b/infra/config/recipes.star
@@ -118,6 +118,10 @@
 )
 
 build_recipe(
+    name = "recipe:chromium/try_warmer",
+)
+
+build_recipe(
     name = "recipe:presubmit",
 )
 
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index 8fac0a3..36d5219 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 load("//lib/branches.star", "branches")
-load("//lib/builders.star", "builder_name", "cpu", "goma", "os", "xcode_cache")
+load("//lib/builders.star", "builder_name", "cpu", "goma", "os", "xcode")
 load("//lib/ci.star", "ci")
 load("//console-header.star", "HEADER")
 load("//project.star", "settings")
@@ -189,6 +189,7 @@
             "fuchsia",
             "chromeos",
             "iOS",
+            "infra",
             "linux",
             "recipe",
             "remote_run",
@@ -1645,33 +1646,27 @@
 ci.clang_builder(
     name = "ToTiOS",
     builderless = False,
-    caches = [xcode_cache.x12a7209],
     console_view_entry = ci.console_view_entry(
         category = "iOS|public",
         short_name = "sim",
     ),
     cores = None,
     os = os.MAC_10_15,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
     ssd = True,
+    xcode = xcode.x12a7209,
 )
 
 ci.clang_builder(
     name = "ToTiOSDevice",
     builderless = False,
-    caches = [xcode_cache.x12a7209],
     console_view_entry = ci.console_view_entry(
         category = "iOS|public",
         short_name = "dev",
     ),
     cores = None,
     os = os.MAC_10_15,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
     ssd = True,
+    xcode = xcode.x12a7209,
 )
 
 ci.clang_mac_builder(
@@ -2471,6 +2466,23 @@
 )
 
 ci.fyi_builder(
+    name = "try-warmer",
+    console_view_entry = ci.console_view_entry(
+        category = "infra",
+        short_name = "warmer",
+    ),
+    executable = "recipe:chromium/try_warmer",
+    execution_timeout = 5 * time.minute,
+    goma_backend = None,
+    properties = {
+        "builder_to_warm": "linux-warmed",
+    },
+    schedule = "with 5m interval",
+    service_account = "chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com",
+    triggered_by = [],
+)
+
+ci.fyi_builder(
     name = "linux-annotator-rel",
     console_view_entry = ci.console_view_entry(
         category = "network|traffic|annotations",
@@ -2644,15 +2656,6 @@
     goma_backend = goma.backend.RBE_PROD,
 )
 
-ci.fyi_builder(
-    name = "linux-wpt-payments-fyi-rel",
-    console_view_entry = ci.console_view_entry(
-        category = "linux",
-    ),
-    experimental = True,
-    goma_backend = goma.backend.RBE_PROD,
-)
-
 # This is launching & collecting entirely isolated tests.
 # OS shouldn't matter.
 ci.fyi_builder(
@@ -3011,7 +3014,6 @@
 
 ci.fyi_coverage_builder(
     name = "ios-simulator-code-coverage",
-    caches = [xcode_cache.x12a7209],
     console_view_entry = ci.console_view_entry(
         category = "code_coverage",
         short_name = "ios",
@@ -3021,9 +3023,7 @@
     use_clang_coverage = True,
     coverage_exclude_sources = "ios_test_files_and_test_utils",
     coverage_test_types = ["overall", "unit"],
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
+    xcode = xcode.x12a7209,
 )
 
 ci.fyi_coverage_builder(
@@ -3092,16 +3092,13 @@
 ci.fyi_ios_builder(
     name = "ios-simulator-cronet",
     branch_selector = branches.STANDARD_MILESTONE,
-    caches = [xcode_cache.x11e146],
     console_view_entry = ci.console_view_entry(
         category = "cronet",
     ),
     cq_mirrors_console_view = "mirrors",
     main_console_view = main_console_if_on_branch(),
     notifies = ["cronet"],
-    properties = {
-        "xcode_build_version": "11e146",
-    },
+    xcode = xcode.x11e146,
 )
 
 ci.fyi_ios_builder(
@@ -3114,16 +3111,13 @@
 
 ci.fyi_ios_builder(
     name = "ios-webkit-tot",
-    caches = [xcode_cache.x11e608cwk],
     console_view_entry = ci.console_view_entry(
         category = "iOS",
         short_name = "wk",
     ),
-    properties = {
-        "xcode_build_version": "11e608cwk",
-    },
     schedule = "0 1-23/6 * * *",
     triggered_by = [],
+    xcode = xcode.x11e608cwk,
 )
 
 ci.fyi_ios_builder(
@@ -3168,10 +3162,7 @@
         category = "iOS|iOS14",
         short_name = "sdk14",
     ),
-    caches = [xcode_cache.x12b5044c],
-    properties = {
-        "xcode_build_version": "12b5044c",
-    },
+    xcode = xcode.x12b5044c,
 )
 
 ci.fyi_mac_builder(
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index 4001f369..f54d0f0 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 load("//lib/branches.star", "branches")
-load("//lib/builders.star", "cpu", "goma", "os", "xcode_cache")
+load("//lib/builders.star", "cpu", "goma", "os", "xcode")
 load("//lib/try.star", "try_")
 load("//project.star", "settings")
 
@@ -1021,7 +1021,7 @@
     name = "linux-rel-builderful",
     builderless = False,
     goma_jobs = goma.jobs.J150,
-    tryjob = try_.job(experiment_percentage = 10),
+    tryjob = try_.job(experiment_percentage = 5),
     use_clang_coverage = True,
 )
 
@@ -1035,6 +1035,15 @@
     name = "linux-viz-rel",
 )
 
+# crbug.com/1149606: Experimental builder to test pre-warming
+try_.chromium_linux_builder(
+    name = "linux-warmed",
+    builderless = False,
+    goma_jobs = goma.jobs.J150,
+    tryjob = try_.job(experiment_percentage = 5),
+    use_clang_coverage = True,
+)
+
 try_.chromium_linux_builder(
     name = "linux-webkit-msan-rel",
 )
@@ -1052,10 +1061,6 @@
 )
 
 try_.chromium_linux_builder(
-    name = "linux-wpt-payments-fyi-rel",
-)
-
-try_.chromium_linux_builder(
     name = "linux_chromium_analysis",
 )
 
@@ -1322,6 +1327,9 @@
     name = "ios-simulator",
     branch_selector = branches.STANDARD_MILESTONE,
     main_list_view = "try",
+    use_clang_coverage = True,
+    coverage_exclude_sources = "ios_test_files_and_test_utils",
+    coverage_test_types = ["unit"],
     tryjob = try_.job(),
 )
 
@@ -1345,11 +1353,7 @@
 try_.chromium_mac_ios_builder(
     name = "ios-simulator-cronet",
     branch_selector = branches.STANDARD_MILESTONE,
-    caches = [xcode_cache.x11e146],
     main_list_view = "try",
-    properties = {
-        "xcode_build_version": "11e146",
-    },
     tryjob = try_.job(
         location_regexp = [
             ".+/[+]/components/cronet/.+",
@@ -1360,12 +1364,16 @@
             ".+/[+]/components/cronet/android/.+",
         ],
     ),
+    xcode = xcode.x11e146,
 )
 
 try_.chromium_mac_ios_builder(
     name = "ios-simulator-full-configs",
     branch_selector = branches.STANDARD_MILESTONE,
     main_list_view = "try",
+    use_clang_coverage = True,
+    coverage_exclude_sources = "ios_test_files_and_test_utils",
+    coverage_test_types = ["unit"],
     tryjob = try_.job(
         location_regexp = [
             ".+/[+]/ios/.+",
@@ -1409,10 +1417,7 @@
 
 try_.chromium_mac_ios_builder(
     name = "ios14-sdk-simulator",
-    caches = [xcode_cache.x12b5044c],
-    properties = {
-        "xcode_build_version": "12b5044c",
-    },
+    xcode = xcode.x12b5044c,
 )
 
 try_.chromium_updater_mac_builder(
diff --git a/infra/config/subprojects/goma/goma.star b/infra/config/subprojects/goma/goma.star
index d6727063..83dc774 100644
--- a/infra/config/subprojects/goma/goma.star
+++ b/infra/config/subprojects/goma/goma.star
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-load("//lib/builders.star", "builder", "cpu", "defaults", "goma", "os", "xcode_cache")
+load("//lib/builders.star", "builder", "cpu", "defaults", "goma", "os", "xcode")
 
 luci.bucket(
     name = "goma",
@@ -110,12 +110,9 @@
 
 fyi_goma_canary_builder(
     name = "ios-device-goma-canary-clobber",
-    caches = [xcode_cache.x12a7209],
     cores = None,
     os = os.MAC_10_15,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
+    xcode = xcode.x12a7209,
 )
 
 fyi_goma_canary_builder(
@@ -185,12 +182,9 @@
 
 fyi_goma_rbe_canary_builder(
     name = "ios-device-goma-rbe-canary-clobber",
-    caches = [xcode_cache.x12a7209],
     cores = None,
     os = os.MAC_10_15,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
+    xcode = xcode.x12a7209,
 )
 
 fyi_goma_rbe_canary_builder(
@@ -270,12 +264,9 @@
 
 fyi_goma_latest_client_builder(
     name = "ios-device-goma-latest-clobber",
-    caches = [xcode_cache.x12a7209],
     cores = None,
     os = os.MAC_10_15,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
+    xcode = xcode.x12a7209,
 )
 
 fyi_goma_latest_client_builder(
@@ -359,12 +350,9 @@
 
 fyi_goma_rbe_latest_client_builder(
     name = "ios-device-goma-rbe-latest-clobber",
-    caches = [xcode_cache.x12a7209],
     cores = None,
     os = os.MAC_10_15,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
+    xcode = xcode.x12a7209,
 )
 
 fyi_goma_rbe_latest_client_builder(
@@ -477,12 +465,9 @@
 
 goma_mac_builder(
     name = "Chromium iOS Goma RBE ToT",
-    caches = [xcode_cache.x12a7209],
     goma_backend = goma.backend.RBE_TOT,
     os = os.MAC_10_15,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
+    xcode = xcode.x12a7209,
 )
 
 goma_mac_builder(
diff --git a/infra/config/subprojects/webrtc/webrtc.fyi.star b/infra/config/subprojects/webrtc/webrtc.fyi.star
index 72ec798..ea28b1a2 100644
--- a/infra/config/subprojects/webrtc/webrtc.fyi.star
+++ b/infra/config/subprojects/webrtc/webrtc.fyi.star
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-load("//lib/builders.star", "builder", "cpu", "defaults", "goma", "os", "xcode_cache")
+load("//lib/builders.star", "builder", "cpu", "defaults", "goma", "os", "xcode")
 
 luci.bucket(
     name = "webrtc.fyi",
@@ -139,22 +139,16 @@
 
 builder(
     name = "WebRTC Chromium FYI ios-device",
-    caches = [xcode_cache.x12a7209],
     executable = "recipe:webrtc/chromium_ios",
     goma_backend = goma.backend.RBE_PROD,
     os = os.MAC_ANY,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
+    xcode = xcode.x12a7209,
 )
 
 builder(
     name = "WebRTC Chromium FYI ios-simulator",
-    caches = [xcode_cache.x12a7209],
     executable = "recipe:webrtc/chromium_ios",
     goma_backend = goma.backend.RBE_PROD,
     os = os.MAC_ANY,
-    properties = {
-        "xcode_build_version": "12a7209",
-    },
+    xcode = xcode.x12a7209,
 )
diff --git a/infra/config/swarming.star b/infra/config/swarming.star
index 58ff96a8..401c72d6 100644
--- a/infra/config/swarming.star
+++ b/infra/config/swarming.star
@@ -86,6 +86,10 @@
         # An account used by "Build Recipes Tester" builder infra/try bucket
         # used to tests changes to Chromium recipes using LED before commit.
         "infra-try-recipes-tester@chops-service-accounts.iam.gserviceaccount.com",
+
+        # crbug.com/1149606: Used for experimental pre-warming. This account will
+        # run the led-tot-warmer builder in chromium.ci.
+        "chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com",
     ],
 )
 
diff --git a/ios/chrome/app/strings/resources/ios_strings_or.xtb b/ios/chrome/app/strings/resources/ios_strings_or.xtb
index 3d75b0d..4cbfe4c 100644
--- a/ios/chrome/app/strings/resources/ios_strings_or.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_or.xtb
@@ -422,6 +422,7 @@
 <translation id="5659593005791499971">ଇମେଲ୍</translation>
 <translation id="5669528293118408608">www</translation>
 <translation id="567881659373499783"><ph name="PRODUCT_VERSION" /> ସଂସ୍କରଣ</translation>
+<translation id="5690398455483874150">{count,plural, =1{ଏବେ 1ଟି Chrome ୱିଣ୍ଡୋ ଦେଖାଉଛି}other{ଏବେ {count}ଟି Chrome ୱିଣ୍ଡୋ ଦେଖାଉଛି}}</translation>
 <translation id="5706552126692816153">1 ଦିନ ପୂର୍ବେ ସକ୍ରିୟ ଥିଲା</translation>
 <translation id="5711039611392265845">ଗୋପନୀୟତା, ସୁରକ୍ଷା ଏବଂ ଡାଟା ସଂଗ୍ରହ ସମ୍ବନ୍ଧିତ ଅଧିକ ସେଟିଂସ୍ ପାଇଁ <ph name="BEGIN_LINK" />ସିଙ୍କ୍ ଓ Google ସେବାଗୁଡ଼ିକୁ<ph name="END_LINK" /> ଦେଖନ୍ତୁ।</translation>
 <translation id="5724941645893276623">ବ୍ୟକ୍ତିଗତ ଭାବେ ୱେବ୍‍ ବ୍ରାଉଜ୍ କରିବାକୁ, ଏକ ନୂଆ ଟାବ୍ ଯୋଗ କରନ୍ତୁ</translation>
diff --git a/ios/chrome/browser/policy/browser_dm_token_storage_ios.mm b/ios/chrome/browser/policy/browser_dm_token_storage_ios.mm
index 5aa3940e..5f18807 100644
--- a/ios/chrome/browser/policy/browser_dm_token_storage_ios.mm
+++ b/ios/chrome/browser/policy/browser_dm_token_storage_ios.mm
@@ -75,7 +75,7 @@
 BrowserDMTokenStorageIOS::~BrowserDMTokenStorageIOS() {}
 
 std::string BrowserDMTokenStorageIOS::InitClientId() {
-  return ios::device_util::GetDeviceIdentifier(nullptr);
+  return ios::device_util::GetVendorId();
 }
 
 std::string BrowserDMTokenStorageIOS::InitEnrollmentToken() {
diff --git a/ios/chrome/browser/policy/reporting/report_generator_ios_unittest.mm b/ios/chrome/browser/policy/reporting/report_generator_ios_unittest.mm
index a32626d..e6c9ae5 100644
--- a/ios/chrome/browser/policy/reporting/report_generator_ios_unittest.mm
+++ b/ios/chrome/browser/policy/reporting/report_generator_ios_unittest.mm
@@ -141,6 +141,7 @@
   EXPECT_EQ(
       policy::GetBrowserDeviceIdentifier()->SerializePartialAsString(),
       basic_request->browser_device_identifier().SerializePartialAsString());
+  EXPECT_NE(std::string(), basic_request->device_model());
 
   // Verify the OS report
   EXPECT_TRUE(basic_request->has_os_report());
diff --git a/ios/chrome/browser/safe_browsing/safe_browsing_query_manager.mm b/ios/chrome/browser/safe_browsing/safe_browsing_query_manager.mm
index e3bb0d2..147d6ce1 100644
--- a/ios/chrome/browser/safe_browsing/safe_browsing_query_manager.mm
+++ b/ios/chrome/browser/safe_browsing/safe_browsing_query_manager.mm
@@ -107,9 +107,13 @@
   // execution of its completion block.
   DCHECK(!show_error_page || result.resource);
 
-  // Notify observers of the completed URL check.
+  // Notify observers of the completed URL check. |this| might get destroyed
+  // when an observer is notified.
+  auto weak_this = weak_factory_.GetWeakPtr();
   for (auto& observer : observers_) {
     observer.SafeBrowsingQueryFinished(this, query, result);
+    if (!weak_this)
+      return;
   }
 
   // Clear out the state since the query is finished.
diff --git a/ios/chrome/browser/safe_browsing/safe_browsing_query_manager_unittest.mm b/ios/chrome/browser/safe_browsing/safe_browsing_query_manager_unittest.mm
index 682d6715..dc6f14b 100644
--- a/ios/chrome/browser/safe_browsing/safe_browsing_query_manager_unittest.mm
+++ b/ios/chrome/browser/safe_browsing/safe_browsing_query_manager_unittest.mm
@@ -141,3 +141,90 @@
     SafeBrowsingQueryManagerTest,
     testing::Values(safe_browsing::ResourceType::kMainFrame,
                     safe_browsing::ResourceType::kSubFrame));
+
+namespace {
+// An observer that owns a WebState and destroys it when it gets a
+// |SafeBrowsingQueryFinished| callback.
+class WebStateDestroyingQueryManagerObserver
+    : public SafeBrowsingQueryManager::Observer {
+ public:
+  WebStateDestroyingQueryManagerObserver()
+      : web_state_(std::make_unique<web::TestWebState>()) {}
+  ~WebStateDestroyingQueryManagerObserver() override {}
+
+  void SafeBrowsingQueryFinished(
+      SafeBrowsingQueryManager* query_manager,
+      const SafeBrowsingQueryManager::Query& query,
+      const SafeBrowsingQueryManager::Result& result) override {
+    web_state_.reset();
+  }
+
+  void SafeBrowsingQueryManagerDestroyed(
+      SafeBrowsingQueryManager* manager) override {
+    manager->RemoveObserver(this);
+  }
+
+  web::WebState* web_state() { return web_state_.get(); }
+
+ private:
+  std::unique_ptr<web::WebState> web_state_;
+};
+}  // namespace
+
+// Test fixture for testing WebState destruction during a
+// SafeBrowsingQueryManager::Observer callback.
+class SafeBrowsingQueryManagerWebStateDestructionTest
+    : public testing::TestWithParam<safe_browsing::ResourceType> {
+ protected:
+  SafeBrowsingQueryManagerWebStateDestructionTest()
+      : task_environment_(web::WebTaskEnvironment::IO_MAINLOOP),
+        http_method_("GET"),
+        navigation_item_id_(
+            GetParam() == safe_browsing::ResourceType::kMainFrame ? -1 : 0) {
+    SafeBrowsingQueryManager::CreateForWebState(observer_.web_state());
+    manager()->AddObserver(&observer_);
+  }
+
+  SafeBrowsingQueryManager* manager() {
+    return SafeBrowsingQueryManager::FromWebState(observer_.web_state());
+  }
+
+  web::WebTaskEnvironment task_environment_;
+  WebStateDestroyingQueryManagerObserver observer_;
+  std::string http_method_;
+  int navigation_item_id_ = 0;
+};
+
+// Tests that a query for a safe URL doesn't cause a crash.
+TEST_P(SafeBrowsingQueryManagerWebStateDestructionTest, SafeURLQuery) {
+  GURL url("http://chromium.test");
+  // Start a URL check query for the safe URL and run the runloop until the
+  // result is received.
+  manager()->StartQuery(
+      SafeBrowsingQueryManager::Query(url, http_method_, navigation_item_id_));
+  base::RunLoop().RunUntilIdle();
+}
+
+// Tests that a query for an unsafe URL doesn't cause a crash.
+TEST_P(SafeBrowsingQueryManagerWebStateDestructionTest, UnsafeURLQuery) {
+  GURL url("http://" + FakeSafeBrowsingService::kUnsafeHost);
+
+  // Start a URL check query for the unsafe URL and run the runloop until the
+  // result is received. An UnsafeResource is stored before the query finishes
+  // to simulate the production behavior that adds a resource that will be used
+  // to populate the error page.
+  manager()->StartQuery(
+      SafeBrowsingQueryManager::Query(url, http_method_, navigation_item_id_));
+  UnsafeResource resource;
+  resource.url = url;
+  resource.threat_type = safe_browsing::SB_THREAT_TYPE_URL_PHISHING;
+  resource.resource_type = GetParam();
+  manager()->StoreUnsafeResource(resource);
+  base::RunLoop().RunUntilIdle();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    /* No InstantiationName */,
+    SafeBrowsingQueryManagerWebStateDestructionTest,
+    testing::Values(safe_browsing::ResourceType::kMainFrame,
+                    safe_browsing::ResourceType::kSubFrame));
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h
index 63faeb6..b53ebdf 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h
@@ -7,6 +7,14 @@
 
 #import <UIKit/UIKit.h>
 
+@class TabStripCell;
+
+// Informs the receiver of actions on the cell.
+@protocol TabStripCellDelegate
+// Informs the receiver that the close button on the cell was tapped.
+- (void)closeButtonTappedForCell:(TabStripCell*)cell;
+@end
+
 // UICollectionViewCell that contains a Tab title with a leading imageView
 // and a close tab button.
 @interface TabStripCell : UICollectionViewCell
@@ -17,6 +25,8 @@
 // Unique identifier for the cell's contents. This is used to ensure that
 // updates in an asynchronous callback are only made if the item is the same.
 @property(nonatomic, copy) NSString* itemIdentifier;
+// Delegate to inform the TabStrip on the cell.
+@property(nonatomic, weak) id<TabStripCellDelegate> delegate;
 
 @end
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.mm
index 7a3c688bb..730996e9 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.mm
@@ -57,6 +57,9 @@
       [closeButton.centerYAnchor
           constraintEqualToAnchor:self.contentView.centerYAnchor],
     ]];
+    [closeButton addTarget:self
+                    action:@selector(closeButtonTapped:)
+          forControlEvents:UIControlEventTouchUpInside];
 
     UILabel* titleLabel = [[UILabel alloc] init];
     [self.contentView addSubview:titleLabel];
@@ -82,4 +85,9 @@
   self.itemIdentifier = nil;
 }
 
+// Selector registered to the close button.
+- (void)closeButtonTapped:(id)sender {
+  [self.delegate closeButtonTappedForCell:self];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_consumer_delegate.h b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_consumer_delegate.h
index bd686257..9013f6ab 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_consumer_delegate.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_consumer_delegate.h
@@ -16,6 +16,10 @@
 // Tells the receiver to show to the selected tab.
 - (void)selectTab:(int)index;
 
+// Tells the receiver to close the item with identifier |itemID|. If there is
+// no item with that identifier, no item is closed.
+- (void)closeItemWithID:(NSString*)itemID;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_STRIP_TAB_STRIP_CONSUMER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.mm
index a6f3930d..531de47 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.mm
@@ -74,6 +74,18 @@
   return nullptr;
 }
 
+// Returns the index of the tab with |identifier| in |web_state_list|. Returns
+// -1 if not found.
+int GetIndexOfTabWithId(WebStateList* web_state_list, NSString* identifier) {
+  for (int i = 0; i < web_state_list->count(); i++) {
+    web::WebState* web_state = web_state_list->GetWebStateAt(i);
+    TabIdTabHelper* tab_helper = TabIdTabHelper::FromWebState(web_state);
+    if ([identifier isEqualToString:tab_helper->tab_id()])
+      return i;
+  }
+  return -1;
+}
+
 }  // namespace
 
 @interface TabStripMediator () <CRWWebStateObserver, WebStateListObserving> {
@@ -204,6 +216,12 @@
   _webStateList->ActivateWebStateAt(index);
 }
 
+- (void)closeItemWithID:(NSString*)itemID {
+  int index = GetIndexOfTabWithId(self.webStateList, itemID);
+  if (index >= 0)
+    self.webStateList->CloseWebStateAt(index, WebStateList::CLOSE_USER_ACTION);
+}
+
 #pragma mark - Private
 
 // Calls |-populateItems:selectedItemID:| on the consumer.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.mm
index 26ccafc..d63c236 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.mm
@@ -30,7 +30,7 @@
 
 }  // namespace
 
-@interface TabStripViewController ()
+@interface TabStripViewController () <TabStripCellDelegate>
 
 @property(nonatomic, strong) UIButton* buttonNewTab;
 // The local model backing the collection view.
@@ -150,6 +150,7 @@
 // theme.
 - (void)configureCell:(TabStripCell*)cell withItem:(TabSwitcherItem*)item {
   if (item) {
+    cell.delegate = self;
     cell.itemIdentifier = item.identifier;
     cell.titleLabel.text = item.title;
     NSString* itemIdentifier = item.identifier;
@@ -186,4 +187,10 @@
   [self.delegate selectTab:index];
 }
 
+#pragma mark - TabStripCellDelegate
+
+- (void)closeButtonTappedForCell:(TabStripCell*)cell {
+  [self.delegate closeItemWithID:cell.itemIdentifier];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index bc53bb0..7a61dc8 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -31,9 +31,6 @@
 const base::Feature kTestFeature{"TestFeature",
                                  base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kFirstResponderSendAction{
-    "FirstResponderSendAction", base::FEATURE_DISABLED_BY_DEFAULT};
-
 const base::Feature kEnableNativeContextMenus{
     "EnableNativeContextMenus", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h
index 2d68e0e..2b66b0d0 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.h
+++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -34,9 +34,6 @@
 // features in tests works.
 extern const base::Feature kTestFeature;
 
-// Verify if the crash in https://crbug.com/816427 is fixed on iOS 12.
-extern const base::Feature kFirstResponderSendAction;
-
 // Feature flag that enables the native UI Context Menus (not for Web content).
 extern const base::Feature kEnableNativeContextMenus;
 
diff --git a/ios/chrome/browser/ui/util/uikit_ui_util.mm b/ios/chrome/browser/ui/util/uikit_ui_util.mm
index aea31e12..86f7a99 100644
--- a/ios/chrome/browser/ui/util/uikit_ui_util.mm
+++ b/ios/chrome/browser/ui/util/uikit_ui_util.mm
@@ -33,22 +33,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-
-// Store a reference to the current first responder.
-UIResponder* g_first_responder = nil;
-
-}  // namespace
-
-// Category used to get the first responder.
-@implementation UIResponder (FirstResponder)
-
-- (void)cr_markSelfCurrentFirstResponder {
-  g_first_responder = self;
-}
-
-@end
-
 void SetA11yLabelAndUiAutomationName(
     NSObject<UIAccessibilityIdentification>* element,
     int idsAccessibilityLabel,
@@ -315,18 +299,6 @@
 
 UIResponder* GetFirstResponder() {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  if (base::FeatureList::IsEnabled(kFirstResponderSendAction)) {
-    DCHECK_CURRENTLY_ON(web::WebThread::UI);
-    DCHECK(!g_first_responder);
-    [[UIApplication sharedApplication]
-        sendAction:@selector(cr_markSelfCurrentFirstResponder)
-                to:nil
-              from:nil
-          forEvent:nil];
-    UIResponder* firstResponder = g_first_responder;
-    g_first_responder = nil;
-    return firstResponder;
-  }
   return GetFirstResponderSubview([UIApplication sharedApplication].keyWindow);
 }
 
diff --git a/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc b/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
index 9d2bc2d1..62cb3995 100644
--- a/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
+++ b/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
@@ -74,7 +74,7 @@
     case ntp_tiles::TileSource::HOMEPAGE:
       return true;
     case ntp_tiles::TileSource::CUSTOM_LINKS:
-    case ntp_tiles::TileSource::WHITELIST:
+    case ntp_tiles::TileSource::ALLOWLIST:
     case ntp_tiles::TileSource::EXPLORE:
     case ntp_tiles::TileSource::REPEATABLE_QUERIES_SERVICE:
       return false;
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 691aee0..2f7dbda 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -263,11 +263,11 @@
   ]
 
   sources = [
+    "navigation/crw_error_page_helper_unittest.mm",
     "navigation/crw_navigation_item_holder_unittest.mm",
     "navigation/crw_session_storage_unittest.mm",
     "navigation/crw_text_fragments_handler_unittest.mm",
     "navigation/crw_wk_navigation_states_unittest.mm",
-    "navigation/error_page_helper_unittest.mm",
     "navigation/error_retry_state_machine_unittest.mm",
     "navigation/navigation_context_impl_unittest.mm",
     "navigation/navigation_item_impl_unittest.mm",
@@ -563,8 +563,8 @@
     "browser_state_web_view_partition_inttest.mm",
     "cookie_blocking_inttest.mm",
     "find_in_page/find_in_page_manager_inttest.mm",
+    "navigation/crw_error_page_helper_inttest.mm",
     "navigation/crw_wk_navigation_handler_inttest.mm",
-    "navigation/error_page_helper_inttest.mm",
     "navigation/history_state_operations_inttest.mm",
     "navigation/meta_tag_inttest.mm",
     "navigation/window_location_inttest.mm",
diff --git a/ios/web/common/features.mm b/ios/web/common/features.mm
index d5e4118..23ad752 100644
--- a/ios/web/common/features.mm
+++ b/ios/web/common/features.mm
@@ -42,7 +42,7 @@
     "PreserveScrollViewProperties", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kAddWebContentDropInteraction{
-    "AddWebContentDropInteraction", base::FEATURE_DISABLED_BY_DEFAULT};
+    "AddWebContentDropInteraction", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kScrollToTextIOS{"ScrollToTextIOS",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/web/navigation/BUILD.gn b/ios/web/navigation/BUILD.gn
index 3935920..a06823d 100644
--- a/ios/web/navigation/BUILD.gn
+++ b/ios/web/navigation/BUILD.gn
@@ -98,8 +98,8 @@
   ]
 
   sources = [
-    "error_page_helper.h",
-    "error_page_helper.mm",
+    "crw_error_page_helper.h",
+    "crw_error_page_helper.mm",
     "error_retry_state_machine.h",
     "error_retry_state_machine.mm",
     "navigation_context_impl.h",
diff --git a/ios/web/navigation/error_page_helper.h b/ios/web/navigation/crw_error_page_helper.h
similarity index 87%
rename from ios/web/navigation/error_page_helper.h
rename to ios/web/navigation/crw_error_page_helper.h
index 0e162a65..206f89b 100644
--- a/ios/web/navigation/error_page_helper.h
+++ b/ios/web/navigation/crw_error_page_helper.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 IOS_WEB_NAVIGATION_ERROR_PAGE_HELPER_H_
-#define IOS_WEB_NAVIGATION_ERROR_PAGE_HELPER_H_
+#ifndef IOS_WEB_NAVIGATION_CRW_ERROR_PAGE_HELPER_H_
+#define IOS_WEB_NAVIGATION_CRW_ERROR_PAGE_HELPER_H_
 
 #import <Foundation/Foundation.h>
 
@@ -11,7 +11,7 @@
 
 // Class used to create an Error Page, constructing all the information needed
 // based on the initial error.
-@interface ErrorPageHelper : NSObject
+@interface CRWErrorPageHelper : NSObject
 
 // Failed URL of the failed navigation.
 @property(nonatomic, strong, readonly) NSURL* failedNavigationURL;
@@ -39,4 +39,4 @@
 
 @end
 
-#endif  // IOS_WEB_NAVIGATION_ERROR_PAGE_HELPER_H_
+#endif  // IOS_WEB_NAVIGATION_CRW_ERROR_PAGE_HELPER_H_
diff --git a/ios/web/navigation/error_page_helper.mm b/ios/web/navigation/crw_error_page_helper.mm
similarity index 90%
rename from ios/web/navigation/error_page_helper.mm
rename to ios/web/navigation/crw_error_page_helper.mm
index ee8a7d3..a08ac40 100644
--- a/ios/web/navigation/error_page_helper.mm
+++ b/ios/web/navigation/crw_error_page_helper.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/navigation/error_page_helper.h"
+#import "ios/web/navigation/crw_error_page_helper.h"
 
 #include "base/check.h"
 #include "base/strings/sys_string_conversions.h"
@@ -18,6 +18,11 @@
 
 const char kOriginalUrlKey[] = "url";
 
+// Returns the bundle from which the html files should be loaded.
+NSBundle* BundleForHTMLFiles() {
+  return [NSBundle bundleForClass:CRWErrorPageHelper.class];
+}
+
 // Escapes HTML characters in |text|.
 NSString* EscapeHTMLCharacters(NSString* text) {
   return base::SysUTF8ToNSString(
@@ -26,30 +31,30 @@
 
 // Resturns the path for the error page to be loaded.
 NSString* LoadedErrorPageFilePath() {
-  NSString* path = [NSBundle.mainBundle pathForResource:@"error_page_loaded"
-                                                 ofType:@"html"];
+  NSString* path = [BundleForHTMLFiles() pathForResource:@"error_page_loaded"
+                                                  ofType:@"html"];
   DCHECK(path) << "Loaded error page should exist";
   return path;
 }
 
 // Returns the path for the error page to be injected.
 NSString* InjectedErrorPageFilePath() {
-  NSString* path = [NSBundle.mainBundle pathForResource:@"error_page_injected"
-                                                 ofType:@"html"];
+  NSString* path = [BundleForHTMLFiles() pathForResource:@"error_page_injected"
+                                                  ofType:@"html"];
   DCHECK(path) << "Injected error page should exist";
   return path;
 }
 
 }  // namespace
 
-@interface ErrorPageHelper ()
+@interface CRWErrorPageHelper ()
 @property(nonatomic, strong) NSError* error;
 // The error page HTML to be injected into existing page.
 @property(nonatomic, strong) NSString* automaticReloadJavaScript;
 @property(nonatomic, strong, readonly) NSString* failedNavigationURLString;
 @end
 
-@implementation ErrorPageHelper
+@implementation CRWErrorPageHelper
 
 @synthesize failedNavigationURL = _failedNavigationURL;
 @synthesize errorPageFileURL = _errorPageFileURL;
diff --git a/ios/web/navigation/error_page_helper_inttest.mm b/ios/web/navigation/crw_error_page_helper_inttest.mm
similarity index 90%
rename from ios/web/navigation/error_page_helper_inttest.mm
rename to ios/web/navigation/crw_error_page_helper_inttest.mm
index f66cb5e..dc1e99bd 100644
--- a/ios/web/navigation/error_page_helper_inttest.mm
+++ b/ios/web/navigation/crw_error_page_helper_inttest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/navigation/error_page_helper.h"
+#import "ios/web/navigation/crw_error_page_helper.h"
 
 #include "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
@@ -30,24 +30,24 @@
 namespace web {
 
 // Class for the Error Page test.
-class ErrorPageHelperIntTest : public WebIntTest {
+class CRWErrorPageHelperIntTest : public WebIntTest {
  protected:
-  ErrorPageHelperIntTest() {
+  CRWErrorPageHelperIntTest() {
     server_.RegisterRequestHandler(base::BindRepeating(
-        &ErrorPageHelperIntTest::HandleRequest, base::Unretained(this)));
+        &CRWErrorPageHelperIntTest::HandleRequest, base::Unretained(this)));
     EXPECT_TRUE(server_.Start()) << "Server didn't start";
   }
 
   // Returns an error page helper initialized with |url| as the url of the
   // failing page (original page).
-  ErrorPageHelper* HelperForUrl(const std::string& url) {
+  CRWErrorPageHelper* HelperForUrl(const std::string& url) {
     NSString* url_string = base::SysUTF8ToNSString(url);
     NSError* error = [NSError
         errorWithDomain:NSURLErrorDomain
                    code:NSURLErrorBadURL
                userInfo:@{NSURLErrorFailingURLStringErrorKey : url_string}];
 
-    return [[ErrorPageHelper alloc] initWithError:error];
+    return [[CRWErrorPageHelper alloc] initWithError:error];
   }
 
   // Returns the initial url. This url can be seen as the url of the page loaded
@@ -92,8 +92,8 @@
 
 // Tests that injecting HTML with Reload = YES is replacing the content of the
 // page with the injected HTML and navigating back reload the original URL.
-TEST_F(ErrorPageHelperIntTest, InjectHTMLAndReload) {
-  ErrorPageHelper* helper = HelperForUrl(GetOriginalUrl().spec());
+TEST_F(CRWErrorPageHelperIntTest, InjectHTMLAndReload) {
+  CRWErrorPageHelper* helper = HelperForUrl(GetOriginalUrl().spec());
 
   // Load the initial error page.
   ASSERT_TRUE(LoadUrl(GetInitialUrl()));
@@ -122,8 +122,8 @@
 
 // Tests that injecting HTML with Reload = NO is replacing the content of the
 // page with the injected HTML and navigating back hit the cache.
-TEST_F(ErrorPageHelperIntTest, InjectHTMLWithoutReload) {
-  ErrorPageHelper* helper = HelperForUrl(GetOriginalUrl().spec());
+TEST_F(CRWErrorPageHelperIntTest, InjectHTMLWithoutReload) {
+  CRWErrorPageHelper* helper = HelperForUrl(GetOriginalUrl().spec());
 
   // Load the initial error page.
   ASSERT_TRUE(LoadUrl(GetInitialUrl()));
diff --git a/ios/web/navigation/error_page_helper_unittest.mm b/ios/web/navigation/crw_error_page_helper_unittest.mm
similarity index 71%
rename from ios/web/navigation/error_page_helper_unittest.mm
rename to ios/web/navigation/crw_error_page_helper_unittest.mm
index 0dfef8a..f5c97aaf 100644
--- a/ios/web/navigation/error_page_helper_unittest.mm
+++ b/ios/web/navigation/crw_error_page_helper_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/navigation/error_page_helper.h"
+#import "ios/web/navigation/crw_error_page_helper.h"
 
 #include "base/strings/sys_string_conversions.h"
 #import "net/base/mac/url_conversions.h"
@@ -15,50 +15,50 @@
 #error "This file requires ARC support."
 #endif
 
-using ErrorPageHelperTest = PlatformTest;
+using CRWErrorPageHelperTest = PlatformTest;
 
 // Tests that the failed navigation URL is correctly extracted from the error.
-TEST_F(ErrorPageHelperTest, FailedNavigationURL) {
+TEST_F(CRWErrorPageHelperTest, FailedNavigationURL) {
   NSString* url_string = @"https://test-error-page.com";
   NSError* error = [NSError
       errorWithDomain:NSURLErrorDomain
                  code:NSURLErrorBadURL
              userInfo:@{NSURLErrorFailingURLStringErrorKey : url_string}];
-  ErrorPageHelper* helper = [[ErrorPageHelper alloc] initWithError:error];
+  CRWErrorPageHelper* helper = [[CRWErrorPageHelper alloc] initWithError:error];
   NSURL* url = [NSURL URLWithString:url_string];
   EXPECT_NSEQ(url, helper.failedNavigationURL);
 }
 
 // Tests that the original URL is correctly extracted from the file error URL
 // created by the helper.
-TEST_F(ErrorPageHelperTest, ExtractOriginalURLFromErrorPageURL) {
+TEST_F(CRWErrorPageHelperTest, ExtractOriginalURLFromErrorPageURL) {
   NSString* url_string = @"https://test-error-page.com";
   NSError* error = [NSError
       errorWithDomain:NSURLErrorDomain
                  code:NSURLErrorBadURL
              userInfo:@{NSURLErrorFailingURLStringErrorKey : url_string}];
-  ErrorPageHelper* helper = [[ErrorPageHelper alloc] initWithError:error];
+  CRWErrorPageHelper* helper = [[CRWErrorPageHelper alloc] initWithError:error];
   GURL url_from_helper = net::GURLWithNSURL(helper.errorPageFileURL);
-  GURL result_original_url =
-      [ErrorPageHelper failedNavigationURLFromErrorPageFileURL:url_from_helper];
+  GURL result_original_url = [CRWErrorPageHelper
+      failedNavigationURLFromErrorPageFileURL:url_from_helper];
   EXPECT_EQ(GURL(base::SysNSStringToUTF8(url_string)), result_original_url);
-  EXPECT_TRUE([ErrorPageHelper isErrorPageFileURL:url_from_helper]);
+  EXPECT_TRUE([CRWErrorPageHelper isErrorPageFileURL:url_from_helper]);
 }
 
 // Tests that the error page is correctly identified as error page.
-TEST_F(ErrorPageHelperTest, IsErrorPageFileURL) {
+TEST_F(CRWErrorPageHelperTest, IsErrorPageFileURL) {
   NSString* url_string = @"https://test-error-page.com";
   NSError* error = [NSError
       errorWithDomain:NSURLErrorDomain
                  code:NSURLErrorBadURL
              userInfo:@{NSURLErrorFailingURLStringErrorKey : url_string}];
-  ErrorPageHelper* helper = [[ErrorPageHelper alloc] initWithError:error];
+  CRWErrorPageHelper* helper = [[CRWErrorPageHelper alloc] initWithError:error];
   EXPECT_TRUE([helper
       isErrorPageFileURLForFailedNavigationURL:helper.errorPageFileURL]);
 }
 
 // Tests that a normal URL isn't identified as error page.
-TEST_F(ErrorPageHelperTest, IsErrorPageFileURLWrong) {
+TEST_F(CRWErrorPageHelperTest, IsErrorPageFileURLWrong) {
   NSString* url_string = @"file://test-error-page.com";
   NSError* error =
       [NSError errorWithDomain:NSURLErrorDomain
@@ -66,7 +66,7 @@
                       userInfo:@{
                         NSURLErrorFailingURLStringErrorKey : @"http://fake.com"
                       }];
-  ErrorPageHelper* helper = [[ErrorPageHelper alloc] initWithError:error];
+  CRWErrorPageHelper* helper = [[CRWErrorPageHelper alloc] initWithError:error];
   EXPECT_FALSE([helper
       isErrorPageFileURLForFailedNavigationURL:[NSURL
                                                    URLWithString:url_string]]);
@@ -74,7 +74,7 @@
 
 // Tests that the failed navigation URL is correctly extracted from the page
 // URL.
-TEST_F(ErrorPageHelperTest, FailedNavigationURLFromErrorPageFileURLCorrect) {
+TEST_F(CRWErrorPageHelperTest, FailedNavigationURLFromErrorPageFileURLCorrect) {
   std::string expected_url = "http://expected-url.com";
   std::string path = base::SysNSStringToUTF8([NSBundle.mainBundle
       pathForResource:@"error_page_loaded"
@@ -83,14 +83,14 @@
   GURL url = GURL("file://" + path + "?file=http://not-that-url.com&url=" +
                   expected_url + "&garbage=http://still-not-that-one.com");
   GURL result_url =
-      [ErrorPageHelper failedNavigationURLFromErrorPageFileURL:url];
+      [CRWErrorPageHelper failedNavigationURLFromErrorPageFileURL:url];
   EXPECT_EQ(GURL(expected_url), result_url);
-  EXPECT_TRUE([ErrorPageHelper isErrorPageFileURL:url]);
+  EXPECT_TRUE([CRWErrorPageHelper isErrorPageFileURL:url]);
 }
 
 // Tests that the extract failed navigation URL is empty if the |url| query
 // isn't present in the page URL.
-TEST_F(ErrorPageHelperTest, FailedNavigationURLFromErrorPageFileURLNoQuery) {
+TEST_F(CRWErrorPageHelperTest, FailedNavigationURLFromErrorPageFileURLNoQuery) {
   std::string expected_url = "http://expected-url.com";
   std::string path = base::SysNSStringToUTF8([NSBundle.mainBundle
       pathForResource:@"error_page_loaded"
@@ -99,25 +99,26 @@
   GURL url = GURL("file://" + path + "?file=" + expected_url +
                   "&garbage=http://still-not-that-one.com");
   GURL result_url =
-      [ErrorPageHelper failedNavigationURLFromErrorPageFileURL:url];
+      [CRWErrorPageHelper failedNavigationURLFromErrorPageFileURL:url];
   EXPECT_TRUE(result_url.is_empty());
-  EXPECT_FALSE([ErrorPageHelper isErrorPageFileURL:url]);
+  EXPECT_FALSE([CRWErrorPageHelper isErrorPageFileURL:url]);
 }
 
 // Tests that the extracted failed navigation URL is empty if the path of the
 // current page isn't correct.
-TEST_F(ErrorPageHelperTest, FailedNavigationURLFromErrorPageFileURLWrongPath) {
+TEST_F(CRWErrorPageHelperTest,
+       FailedNavigationURLFromErrorPageFileURLWrongPath) {
   GURL url =
       GURL("file://not-the-correct-path.com?url=http://potential-url.com");
   GURL result_url =
-      [ErrorPageHelper failedNavigationURLFromErrorPageFileURL:url];
+      [CRWErrorPageHelper failedNavigationURLFromErrorPageFileURL:url];
   EXPECT_TRUE(result_url.is_empty());
-  EXPECT_FALSE([ErrorPageHelper isErrorPageFileURL:url]);
+  EXPECT_FALSE([CRWErrorPageHelper isErrorPageFileURL:url]);
 }
 
 // Tests that the extracted failed navigation URL is empty if the scheme of the
 // current page isn't file://.
-TEST_F(ErrorPageHelperTest,
+TEST_F(CRWErrorPageHelperTest,
        FailedNavigationURLFromErrorPageFileURLWrongScheme) {
   std::string path = base::SysNSStringToUTF8([NSBundle.mainBundle
       pathForResource:@"error_page_loaded"
@@ -125,7 +126,7 @@
 
   GURL url = GURL("http://" + path + "?url=http://potential-url.com");
   GURL result_url =
-      [ErrorPageHelper failedNavigationURLFromErrorPageFileURL:url];
+      [CRWErrorPageHelper failedNavigationURLFromErrorPageFileURL:url];
   EXPECT_TRUE(result_url.is_empty());
-  EXPECT_FALSE([ErrorPageHelper isErrorPageFileURL:url]);
+  EXPECT_FALSE([CRWErrorPageHelper isErrorPageFileURL:url]);
 }
diff --git a/ios/web/navigation/crw_web_view_navigation_observer.mm b/ios/web/navigation/crw_web_view_navigation_observer.mm
index 55e77783..137421b 100644
--- a/ios/web/navigation/crw_web_view_navigation_observer.mm
+++ b/ios/web/navigation/crw_web_view_navigation_observer.mm
@@ -10,12 +10,12 @@
 #import "ios/net/http_response_headers_util.h"
 #include "ios/web/common/features.h"
 #include "ios/web/common/url_util.h"
+#import "ios/web/navigation/crw_error_page_helper.h"
 #import "ios/web/navigation/crw_navigation_item_holder.h"
 #import "ios/web/navigation/crw_pending_navigation_info.h"
 #import "ios/web/navigation/crw_web_view_navigation_observer_delegate.h"
 #import "ios/web/navigation/crw_wk_navigation_handler.h"
 #import "ios/web/navigation/crw_wk_navigation_states.h"
-#import "ios/web/navigation/error_page_helper.h"
 #import "ios/web/navigation/navigation_context_impl.h"
 #import "ios/web/navigation/wk_navigation_util.h"
 #import "ios/web/public/web_client.h"
@@ -264,9 +264,9 @@
   // window.location.href will match the previous URL at this stage, not the web
   // view's current URL.
   if (!self.webView.loading) {
-    if ([ErrorPageHelper isErrorPageFileURL:URL] &&
+    if ([CRWErrorPageHelper isErrorPageFileURL:URL] &&
         self.documentURL ==
-            [ErrorPageHelper failedNavigationURLFromErrorPageFileURL:URL]) {
+            [CRWErrorPageHelper failedNavigationURLFromErrorPageFileURL:URL]) {
       // Case 4: reloading an error page.
       return;
     }
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index 7ff4abf..2da5b44 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -16,11 +16,11 @@
 #import "ios/web/common/url_scheme_util.h"
 #import "ios/web/js_messaging/crw_js_injector.h"
 #import "ios/web/js_messaging/web_frames_manager_impl.h"
+#import "ios/web/navigation/crw_error_page_helper.h"
 #import "ios/web/navigation/crw_navigation_item_holder.h"
 #import "ios/web/navigation/crw_pending_navigation_info.h"
 #import "ios/web/navigation/crw_text_fragments_handler.h"
 #import "ios/web/navigation/crw_wk_navigation_states.h"
-#import "ios/web/navigation/error_page_helper.h"
 #include "ios/web/navigation/error_retry_state_machine.h"
 #import "ios/web/navigation/navigation_context_impl.h"
 #import "ios/web/navigation/navigation_manager_impl.h"
@@ -300,7 +300,7 @@
   if ((!base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
        IsPlaceholderUrl(requestURL)) ||
       (base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
-       [ErrorPageHelper isErrorPageFileURL:requestURL])) {
+       [CRWErrorPageHelper isErrorPageFileURL:requestURL])) {
     if (action.sourceFrame.mainFrame) {
       // Disallow renderer initiated navigations to placeholder URLs.
       decisionHandler(WKNavigationActionPolicyCancel);
@@ -503,7 +503,7 @@
   if ((!base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
        IsPlaceholderUrl(responseURL)) ||
       (base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
-       [ErrorPageHelper isErrorPageFileURL:responseURL])) {
+       [CRWErrorPageHelper isErrorPageFileURL:responseURL])) {
     handler(WKNavigationResponsePolicyAllow);
     return;
   }
@@ -584,7 +584,7 @@
 
     BOOL isErrorPageNavigation =
         (base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
-         [ErrorPageHelper isErrorPageFileURL:webViewURL]) ||
+         [CRWErrorPageHelper isErrorPageFileURL:webViewURL]) ||
         (!base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
          context->IsPlaceholderNavigation());
 
@@ -623,8 +623,8 @@
           // Item may not exist if navigation was stopped (see
           // crbug.com/969915).
           item->SetURL(webViewURL);
-          if ([ErrorPageHelper isErrorPageFileURL:webViewURL]) {
-            item->SetVirtualURL([ErrorPageHelper
+          if ([CRWErrorPageHelper isErrorPageFileURL:webViewURL]) {
+            item->SetVirtualURL([CRWErrorPageHelper
                 failedNavigationURLFromErrorPageFileURL:webViewURL]);
           }
         }
@@ -945,7 +945,7 @@
   // webView has the file URL.
   BOOL isErrorPage =
       base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
-      [ErrorPageHelper isErrorPageFileURL:webViewURL];
+      [CRWErrorPageHelper isErrorPageFileURL:webViewURL];
 
   // When loading an error page that is a placeholder (legacy), the webViewURL
   // should be used as it is the actual URL we want to load.
@@ -1414,7 +1414,7 @@
   }
 
   // Allow navigation to WebUI pages from error pages.
-  if ([ErrorPageHelper isErrorPageFileURL:self.documentURL]) {
+  if ([CRWErrorPageHelper isErrorPageFileURL:self.documentURL]) {
     return YES;
   }
 
@@ -1995,7 +1995,8 @@
                          isProvisionalLoad:(BOOL)provisionalLoad {
   DCHECK(base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage));
 
-  ErrorPageHelper* errorPage = [[ErrorPageHelper alloc] initWithError:error];
+  CRWErrorPageHelper* errorPage =
+      [[CRWErrorPageHelper alloc] initWithError:error];
   WKBackForwardListItem* backForwardItem = webView.backForwardList.currentItem;
   // There are 4 possible scenarios here:
   //   1. Current nav item is an error page for failed URL;
@@ -2222,8 +2223,8 @@
       context->GetNavigationId(), base::BindOnce(^(NSString* errorHTML) {
         if (errorHTML) {
           if (base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage)) {
-            ErrorPageHelper* errorPageHelper =
-                [[ErrorPageHelper alloc] initWithError:context->GetError()];
+            CRWErrorPageHelper* errorPageHelper =
+                [[CRWErrorPageHelper alloc] initWithError:context->GetError()];
 
             [webView evaluateJavaScript:[errorPageHelper
                                             scriptForInjectingHTML:errorHTML
diff --git a/ios/web/web_state/error_page_inttest.mm b/ios/web/web_state/error_page_inttest.mm
index f4e2fb9..e6c07eea 100644
--- a/ios/web/web_state/error_page_inttest.mm
+++ b/ios/web/web_state/error_page_inttest.mm
@@ -12,7 +12,6 @@
 #import "ios/net/protocol_handler_util.h"
 #include "ios/testing/embedded_test_server_handlers.h"
 #include "ios/web/common/features.h"
-#import "ios/web/navigation/error_page_helper.h"
 #include "ios/web/navigation/web_kit_constants.h"
 #import "ios/web/public/navigation/navigation_item.h"
 #import "ios/web/public/navigation/navigation_manager.h"
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index bd6ade93..224a0be 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -26,13 +26,13 @@
 #import "ios/web/js_messaging/crw_wk_script_message_router.h"
 #import "ios/web/js_messaging/web_frames_manager_impl.h"
 #import "ios/web/js_messaging/web_view_js_utils.h"
+#import "ios/web/navigation/crw_error_page_helper.h"
 #import "ios/web/navigation/crw_js_navigation_handler.h"
 #import "ios/web/navigation/crw_navigation_item_holder.h"
 #import "ios/web/navigation/crw_web_view_navigation_observer.h"
 #import "ios/web/navigation/crw_web_view_navigation_observer_delegate.h"
 #import "ios/web/navigation/crw_wk_navigation_handler.h"
 #import "ios/web/navigation/crw_wk_navigation_states.h"
-#import "ios/web/navigation/error_page_helper.h"
 #import "ios/web/navigation/navigation_context_impl.h"
 #import "ios/web/navigation/wk_back_forward_list_item_holder.h"
 #import "ios/web/navigation/wk_navigation_util.h"
@@ -825,7 +825,7 @@
     self.navigationHandler.navigationState = web::WKNavigationState::REQUESTED;
   }
 
-  if ([ErrorPageHelper isErrorPageFileURL:URL]) {
+  if ([CRWErrorPageHelper isErrorPageFileURL:URL]) {
     context->SetLoadingErrorPage(true);
   }
 
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index 98650b09..f3abdfb 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -17,7 +17,7 @@
 #include "ios/web/common/features.h"
 #include "ios/web/common/url_util.h"
 #import "ios/web/js_messaging/crw_js_injector.h"
-#import "ios/web/navigation/error_page_helper.h"
+#import "ios/web/navigation/crw_error_page_helper.h"
 #import "ios/web/navigation/navigation_context_impl.h"
 #import "ios/web/navigation/navigation_item_impl.h"
 #import "ios/web/navigation/session_storage_builder.h"
@@ -832,7 +832,7 @@
   if ((!base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
        context->IsPlaceholderNavigation()) ||
       (base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
-       [ErrorPageHelper isErrorPageFileURL:context->GetUrl()]) ||
+       [CRWErrorPageHelper isErrorPageFileURL:context->GetUrl()]) ||
       wk_navigation_util::IsRestoreSessionUrl(context->GetUrl())) {
     return;
   }
@@ -852,7 +852,7 @@
   if ((!base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
        context->IsPlaceholderNavigation()) ||
       (base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) &&
-       [ErrorPageHelper isErrorPageFileURL:context->GetUrl()]) ||
+       [CRWErrorPageHelper isErrorPageFileURL:context->GetUrl()]) ||
       wk_navigation_util::IsRestoreSessionUrl(context->GetUrl())) {
     return;
   }
diff --git a/media/cast/cast_config.h b/media/cast/cast_config.h
index f01e9a1..67d156c6 100644
--- a/media/cast/cast_config.h
+++ b/media/cast/cast_config.h
@@ -246,15 +246,15 @@
 };
 
 // TODO(miu): Remove the CreateVEA callbacks.  http://crbug.com/454029
-typedef base::Callback<void(scoped_refptr<base::SingleThreadTaskRunner>,
-                            std::unique_ptr<media::VideoEncodeAccelerator>)>
+typedef base::OnceCallback<void(scoped_refptr<base::SingleThreadTaskRunner>,
+                                std::unique_ptr<media::VideoEncodeAccelerator>)>
     ReceiveVideoEncodeAcceleratorCallback;
-typedef base::Callback<void(const ReceiveVideoEncodeAcceleratorCallback&)>
+typedef base::RepeatingCallback<void(ReceiveVideoEncodeAcceleratorCallback)>
     CreateVideoEncodeAcceleratorCallback;
-typedef base::Callback<void(base::UnsafeSharedMemoryRegion)>
+typedef base::OnceCallback<void(base::UnsafeSharedMemoryRegion)>
     ReceiveVideoEncodeMemoryCallback;
-typedef base::Callback<void(size_t size,
-                            const ReceiveVideoEncodeMemoryCallback&)>
+typedef base::RepeatingCallback<void(size_t size,
+                                     ReceiveVideoEncodeMemoryCallback)>
     CreateVideoEncodeMemoryCallback;
 
 }  // namespace cast
diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc
index a85cbdf..e6f950f 100644
--- a/media/cast/sender/external_video_encoder.cc
+++ b/media/cast/sender/external_video_encoder.cc
@@ -182,7 +182,7 @@
         create_video_encode_memory_cb_.Run(
             media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420,
                                               frame_coded_size_),
-            base::Bind(&VEAClientImpl::OnCreateInputSharedMemory, this));
+            base::BindOnce(&VEAClientImpl::OnCreateInputSharedMemory, this));
       }
       AbortLatestEncodeAttemptDueToErrors();
       return;
@@ -657,9 +657,9 @@
   DCHECK_GT(bit_rate_, 0);
 
   create_vea_cb.Run(
-      base::Bind(&ExternalVideoEncoder::OnCreateVideoEncodeAccelerator,
-                 weak_factory_.GetWeakPtr(), video_config, first_frame_id,
-                 std::move(status_change_cb)));
+      base::BindOnce(&ExternalVideoEncoder::OnCreateVideoEncodeAccelerator,
+                     weak_factory_.GetWeakPtr(), video_config, first_frame_id,
+                     std::move(status_change_cb)));
 }
 
 ExternalVideoEncoder::~ExternalVideoEncoder() {
diff --git a/media/cast/sender/fake_video_encode_accelerator_factory.cc b/media/cast/sender/fake_video_encode_accelerator_factory.cc
index ed8a56f2..b9c7ea2 100644
--- a/media/cast/sender/fake_video_encode_accelerator_factory.cc
+++ b/media/cast/sender/fake_video_encode_accelerator_factory.cc
@@ -38,7 +38,7 @@
 }
 
 void FakeVideoEncodeAcceleratorFactory::CreateVideoEncodeAccelerator(
-      const ReceiveVideoEncodeAcceleratorCallback& callback) {
+    ReceiveVideoEncodeAcceleratorCallback callback) {
   DCHECK(!callback.is_null());
   DCHECK(!next_response_vea_);
 
@@ -46,18 +46,19 @@
       new FakeVideoEncodeAccelerator(task_runner_);
   vea->SetWillInitializationSucceed(will_init_succeed_);
   next_response_vea_.reset(vea);
-  vea_response_callback_ = callback;
+  vea_response_callback_ = std::move(callback);
   if (auto_respond_)
     RespondWithVideoEncodeAccelerator();
 }
 
 void FakeVideoEncodeAcceleratorFactory::CreateSharedMemory(
-    size_t size, const ReceiveVideoEncodeMemoryCallback& callback) {
+    size_t size,
+    ReceiveVideoEncodeMemoryCallback callback) {
   DCHECK(!callback.is_null());
   DCHECK(!next_response_shm_.IsValid());
 
   next_response_shm_ = base::UnsafeSharedMemoryRegion::Create(size);
-  shm_response_callback_ = callback;
+  shm_response_callback_ = std::move(callback);
   if (auto_respond_)
     RespondWithSharedMemory();
 }
diff --git a/media/cast/sender/fake_video_encode_accelerator_factory.h b/media/cast/sender/fake_video_encode_accelerator_factory.h
index 238ec163..819841457 100644
--- a/media/cast/sender/fake_video_encode_accelerator_factory.h
+++ b/media/cast/sender/fake_video_encode_accelerator_factory.h
@@ -45,13 +45,12 @@
   // Creates a media::FakeVideoEncodeAccelerator.  If in auto-respond mode,
   // |callback| is run synchronously (i.e., before this method returns).
   void CreateVideoEncodeAccelerator(
-      const ReceiveVideoEncodeAcceleratorCallback& callback);
+      ReceiveVideoEncodeAcceleratorCallback callback);
 
   // Creates shared memory of the requested |size|.  If in auto-respond mode,
   // |callback| is run synchronously (i.e., before this method returns).
-  void CreateSharedMemory(
-      size_t size,
-      const ReceiveVideoEncodeMemoryCallback& callback);
+  void CreateSharedMemory(size_t size,
+                          ReceiveVideoEncodeMemoryCallback callback);
 
   // Runs the |callback| provided to the last call to
   // CreateVideoEncodeAccelerator() with the new VideoEncodeAccelerator
diff --git a/media/cast/sender/video_encoder_unittest.cc b/media/cast/sender/video_encoder_unittest.cc
index 290da56b..e566564 100644
--- a/media/cast/sender/video_encoder_unittest.cc
+++ b/media/cast/sender/video_encoder_unittest.cc
@@ -74,11 +74,12 @@
         cast_environment_, video_config_,
         base::BindRepeating(&VideoEncoderTest::OnOperationalStatusChange,
                             base::Unretained(this)),
-        base::Bind(
+        base::BindRepeating(
             &FakeVideoEncodeAcceleratorFactory::CreateVideoEncodeAccelerator,
             base::Unretained(vea_factory_.get())),
-        base::Bind(&FakeVideoEncodeAcceleratorFactory::CreateSharedMemory,
-                   base::Unretained(vea_factory_.get())));
+        base::BindRepeating(
+            &FakeVideoEncodeAcceleratorFactory::CreateSharedMemory,
+            base::Unretained(vea_factory_.get())));
     RunTasksAndAdvanceClock();
     if (is_encoder_present())
       ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc
index f4b4b82..bcb8b58d 100644
--- a/media/cast/sender/video_sender_unittest.cc
+++ b/media/cast/sender/video_sender_unittest.cc
@@ -193,11 +193,12 @@
       video_sender_.reset(new PeerVideoSender(
           cast_environment_, video_config,
           base::BindRepeating(&SaveOperationalStatus, &operational_status_),
-          base::Bind(
+          base::BindRepeating(
               &FakeVideoEncodeAcceleratorFactory::CreateVideoEncodeAccelerator,
               base::Unretained(&vea_factory_)),
-          base::Bind(&FakeVideoEncodeAcceleratorFactory::CreateSharedMemory,
-                     base::Unretained(&vea_factory_)),
+          base::BindRepeating(
+              &FakeVideoEncodeAcceleratorFactory::CreateSharedMemory,
+              base::Unretained(&vea_factory_)),
           transport_sender_.get()));
     } else {
       video_sender_.reset(new PeerVideoSender(
diff --git a/media/cast/test/utility/default_config.cc b/media/cast/test/utility/default_config.cc
index c89afb7..5409bca 100644
--- a/media/cast/test/utility/default_config.cc
+++ b/media/cast/test/utility/default_config.cc
@@ -14,13 +14,13 @@
 namespace {
 
 void CreateVideoEncodeAccelerator(
-    const media::cast::ReceiveVideoEncodeAcceleratorCallback& callback) {
+    media::cast::ReceiveVideoEncodeAcceleratorCallback callback) {
   // Do nothing.
 }
 
 void CreateVideoEncodeMemory(
     size_t size,
-    const media::cast::ReceiveVideoEncodeMemoryCallback& callback) {
+    media::cast::ReceiveVideoEncodeMemoryCallback callback) {
   // Do nothing.
 }
 
@@ -95,11 +95,11 @@
 
 CreateVideoEncodeAcceleratorCallback
 CreateDefaultVideoEncodeAcceleratorCallback() {
-  return base::Bind(&CreateVideoEncodeAccelerator);
+  return base::BindRepeating(&CreateVideoEncodeAccelerator);
 }
 
 CreateVideoEncodeMemoryCallback CreateDefaultVideoEncodeMemoryCallback() {
-  return base::Bind(&CreateVideoEncodeMemory);
+  return base::BindRepeating(&CreateVideoEncodeMemory);
 }
 
 }  // namespace cast
diff --git a/media/gpu/android/frame_info_helper.cc b/media/gpu/android/frame_info_helper.cc
index f46ee94..cf18f96 100644
--- a/media/gpu/android/frame_info_helper.cc
+++ b/media/gpu/android/frame_info_helper.cc
@@ -68,7 +68,7 @@
       stub_ = nullptr;
     }
 
-    void GetFrameInfo(
+    void GetFrameInfoImpl(
         std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
         base::OnceCallback<void(std::unique_ptr<CodecOutputBufferRenderer>,
                                 base::Optional<FrameInfo>)> cb) {
@@ -95,6 +95,21 @@
       std::move(cb).Run(std::move(buffer_renderer), info);
     }
 
+    void GetFrameInfo(
+        std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
+        base::OnceCallback<void(std::unique_ptr<CodecOutputBufferRenderer>,
+                                base::Optional<FrameInfo>)> cb) {
+      DCHECK(buffer_renderer);
+
+      auto texture_owner = buffer_renderer->texture_owner();
+      DCHECK(texture_owner);
+
+      auto buffer_available_cb =
+          base::BindOnce(&OnGpu::GetFrameInfoImpl, weak_factory_.GetWeakPtr(),
+                         std::move(buffer_renderer), std::move(cb));
+      texture_owner->RunWhenBufferIsAvailable(std::move(buffer_available_cb));
+    }
+
    private:
     // Gets YCbCrInfo from last rendered frame.
     base::Optional<gpu::VulkanYCbCrInfo> GetYCbCrInfo(
@@ -117,6 +132,7 @@
     }
 
     gpu::CommandBufferStub* stub_ = nullptr;
+    base::WeakPtrFactory<OnGpu> weak_factory_{this};
   };
 
   FrameInfo GetFrameInfoWithVisibleSize(const gfx::Size& visible_size) {
diff --git a/media/gpu/android/frame_info_helper_unittest.cc b/media/gpu/android/frame_info_helper_unittest.cc
index 94dc6b5..c992740 100644
--- a/media/gpu/android/frame_info_helper_unittest.cc
+++ b/media/gpu/android/frame_info_helper_unittest.cc
@@ -12,6 +12,7 @@
 
 using testing::_;
 using testing::DoAll;
+using testing::Invoke;
 using testing::Mock;
 using testing::Return;
 using testing::SetArgPointee;
@@ -245,4 +246,50 @@
   Mock::VerifyAndClearExpectations(texture_owner.get());
 }
 
+TEST_F(FrameInfoHelperTest, TextureOwnerBufferNotAvailable) {
+  auto texture_owner = base::MakeRefCounted<NiceMock<gpu::MockTextureOwner>>(
+      0, nullptr, nullptr, true);
+
+  // Return CodedSize when GetCodedSizeAndVisibleRect is called.
+  ON_CALL(*texture_owner, GetCodedSizeAndVisibleRect(_, _, _))
+      .WillByDefault(DoAll(SetArgPointee<1>(kTestCodedSize), Return(true)));
+
+  // Save buffer available callback, we will run it manually.
+  base::OnceClosure buffer_available_cb;
+  EXPECT_CALL(*texture_owner, RunWhenBufferIsAvailable(_))
+      .WillOnce(Invoke([&buffer_available_cb](base::OnceClosure cb) {
+        buffer_available_cb = std::move(cb);
+      }));
+
+  // Verify that no GetCodedSizeAndVisibleRect will be called until buffer is
+  // available.
+  EXPECT_CALL(*texture_owner, GetCodedSizeAndVisibleRect(_, _, _)).Times(0);
+
+  // Note that we can't use helper above because the callback won't run until a
+  // buffer is available.
+  auto buffer_renderer = CreateBufferRenderer(kTestVisibleSize, texture_owner);
+  const auto* buffer_renderer_raw = buffer_renderer.get();
+  bool called = false;
+  auto callback = base::BindLambdaForTesting(
+      [&](std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
+          FrameInfoHelper::FrameInfo info) {
+        ASSERT_EQ(buffer_renderer_raw, buffer_renderer.get());
+        called = true;
+        last_frame_info_ = info;
+      });
+  helper_->GetFrameInfo(std::move(buffer_renderer), callback);
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(buffer_available_cb);
+  Mock::VerifyAndClearExpectations(texture_owner.get());
+
+  // When buffer is available we expect GetCodedSizeAndVisibleRect to be called
+  // and result should be kTestCodedSize.
+  EXPECT_CALL(*texture_owner, GetCodedSizeAndVisibleRect(_, _, _)).Times(1);
+  std::move(buffer_available_cb).Run();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(last_frame_info_.coded_size, kTestCodedSize);
+  ASSERT_TRUE(called);
+  Mock::VerifyAndClearExpectations(texture_owner.get());
+}
+
 }  // namespace media
diff --git a/media/gpu/vaapi/vaapi_unittest.cc b/media/gpu/vaapi/vaapi_unittest.cc
index 470e20b5..9e867d4 100644
--- a/media/gpu/vaapi/vaapi_unittest.cc
+++ b/media/gpu/vaapi/vaapi_unittest.cc
@@ -306,7 +306,7 @@
       // number (it could ignore it), so instead just make sure there's a
       // |pending_va_buffers_| that, when mapped, looks correct. That buffer
       // should be created by CreateContext().
-      ASSERT_TRUE(wrapper->CreateContext(gfx::Size(64, 64)));
+      ASSERT_TRUE(wrapper->CreateContext(gfx::Size(128, 128)));
       ASSERT_EQ(wrapper->pending_va_buffers_.size(), 1u);
       {
         base::AutoLock auto_lock(*wrapper->va_lock_);
diff --git a/media/video/h265_parser.cc b/media/video/h265_parser.cc
index 70653d7..295e247 100644
--- a/media/video/h265_parser.cc
+++ b/media/video/h265_parser.cc
@@ -631,12 +631,12 @@
   TRUE_OR_RETURN(sps->pic_width_in_luma_samples % min_cb_size_y == 0);
   TRUE_OR_RETURN(sps->pic_height_in_luma_samples % min_cb_size_y == 0);
   READ_UE_OR_RETURN(&sps->log2_min_luma_transform_block_size_minus2);
+  TRUE_OR_RETURN(sps->log2_min_luma_transform_block_size_minus2 <
+                 min_cb_log2_size_y - 2);
   int min_tb_log2_size_y = sps->log2_min_luma_transform_block_size_minus2 + 2;
-  TRUE_OR_RETURN(min_tb_log2_size_y < min_cb_log2_size_y);
   READ_UE_OR_RETURN(&sps->log2_diff_max_min_luma_transform_block_size);
-  sps->max_tb_log2_size_y =
-      min_tb_log2_size_y + sps->log2_diff_max_min_luma_transform_block_size;
-  TRUE_OR_RETURN(sps->max_tb_log2_size_y <= std::min(sps->ctb_log2_size_y, 5));
+  TRUE_OR_RETURN(sps->log2_diff_max_min_luma_transform_block_size <=
+                 std::min(sps->ctb_log2_size_y, 5) - min_tb_log2_size_y);
   READ_UE_OR_RETURN(&sps->max_transform_hierarchy_depth_inter);
   IN_RANGE_OR_RETURN(sps->max_transform_hierarchy_depth_inter, 0,
                      sps->ctb_log2_size_y - min_tb_log2_size_y);
diff --git a/media/video/h265_parser.h b/media/video/h265_parser.h
index 2c482292..87805b2a 100644
--- a/media/video/h265_parser.h
+++ b/media/video/h265_parser.h
@@ -255,7 +255,6 @@
   int pic_width_in_ctbs_y;
   int pic_height_in_ctbs_y;
   int pic_size_in_ctbs_y;
-  int max_tb_log2_size_y;
   int wp_offset_half_range_y;
   int wp_offset_half_range_c;
 
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index d976d11b..d453618 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -660,13 +660,13 @@
   }
 
   for (const auto& test_case : test_cases) {
-    CanonicalCookie cookie("A", "2", "example.test", "/", creation_time,
-                           expiry_time, base::Time(), true /* secure */,
-                           false /* httponly */, test_case.same_site,
-                           COOKIE_PRIORITY_DEFAULT, false);
+    auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+        "A", "2", "example.test", "/", creation_time, expiry_time, base::Time(),
+        true /* secure */, false /* httponly */, test_case.same_site,
+        COOKIE_PRIORITY_DEFAULT, false);
     EXPECT_EQ(
         test_case.effective_same_site,
-        cookie.GetEffectiveSameSiteForTesting(test_case.access_semantics));
+        cookie->GetEffectiveSameSiteForTesting(test_case.access_semantics));
   }
 }
 
@@ -1912,14 +1912,14 @@
 }
 
 TEST(CanonicalCookieTest, TestSetCreationDate) {
-  CanonicalCookie cookie(
+  auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false,
       false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false);
-  EXPECT_TRUE(cookie.CreationDate().is_null());
+  EXPECT_TRUE(cookie->CreationDate().is_null());
 
   base::Time now(base::Time::Now());
-  cookie.SetCreationDate(now);
-  EXPECT_EQ(now, cookie.CreationDate());
+  cookie->SetCreationDate(now);
+  EXPECT_EQ(now, cookie->CreationDate());
 }
 
 TEST(CanonicalCookieTest, TestPrefixHistograms) {
@@ -2501,11 +2501,11 @@
   GURL url("http://www.example.com/test");
   base::Time current_time = base::Time::Now();
 
-  CanonicalCookie cookie_scriptable(
+  auto cookie_scriptable = CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "2", "www.example.com", "/test", current_time, base::Time(),
       base::Time(), true /*secure*/, false /*httponly*/,
       CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
-  CanonicalCookie cookie_httponly(
+  auto cookie_httponly = CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "2", "www.example.com", "/test", current_time, base::Time(),
       base::Time(), true /*secure*/, true /*httponly*/,
       CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
@@ -2515,14 +2515,14 @@
   context_network.set_include_httponly();
 
   EXPECT_TRUE(cookie_scriptable
-                  .IsSetPermittedInContext(
+                  ->IsSetPermittedInContext(
                       context_network,
                       CookieAccessParams(
                           CookieAccessSemantics::UNKNOWN,
                           false /* delegate_treats_url_as_trustworthy */))
                   .status.IsInclude());
   EXPECT_TRUE(cookie_scriptable
-                  .IsSetPermittedInContext(
+                  ->IsSetPermittedInContext(
                       context_script,
                       CookieAccessParams(
                           CookieAccessSemantics::UNKNOWN,
@@ -2530,14 +2530,14 @@
                   .status.IsInclude());
 
   EXPECT_TRUE(cookie_httponly
-                  .IsSetPermittedInContext(
+                  ->IsSetPermittedInContext(
                       context_network,
                       CookieAccessParams(
                           CookieAccessSemantics::UNKNOWN,
                           false /* delegate_treats_url_as_trustworthy */))
                   .status.IsInclude());
   EXPECT_TRUE(cookie_httponly
-                  .IsSetPermittedInContext(
+                  ->IsSetPermittedInContext(
                       context_script,
                       CookieAccessParams(
                           CookieAccessSemantics::UNKNOWN,
@@ -2574,27 +2574,28 @@
           CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
 
   {
-    CanonicalCookie cookie_same_site_unrestricted(
-        "A", "2", "www.example.com", "/test", current_time, base::Time(),
-        base::Time(), true /*secure*/, false /*httponly*/,
-        CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
+    auto cookie_same_site_unrestricted =
+        CanonicalCookie::CreateUnsafeCookieForTesting(
+            "A", "2", "www.example.com", "/test", current_time, base::Time(),
+            base::Time(), true /*secure*/, false /*httponly*/,
+            CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
 
     EXPECT_TRUE(cookie_same_site_unrestricted
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unrestricted
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unrestricted
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
@@ -2608,7 +2609,7 @@
 
       CookieInclusionStatus status_strict_to_lax =
           cookie_same_site_unrestricted
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_lax,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2618,7 +2619,7 @@
       EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
       CookieInclusionStatus status_strict_to_cross =
           cookie_same_site_unrestricted
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2628,7 +2629,7 @@
       EXPECT_FALSE(status_strict_to_cross.HasDowngradeWarning());
       CookieInclusionStatus status_lax_to_cross =
           cookie_same_site_unrestricted
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_lax_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2644,7 +2645,7 @@
 
       CookieInclusionStatus status_strict_to_lax =
           cookie_same_site_unrestricted
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_lax,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2654,7 +2655,7 @@
       EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
       CookieInclusionStatus status_strict_to_cross =
           cookie_same_site_unrestricted
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2664,7 +2665,7 @@
       EXPECT_FALSE(status_strict_to_cross.HasDowngradeWarning());
       CookieInclusionStatus status_lax_to_cross =
           cookie_same_site_unrestricted
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_lax_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2676,13 +2677,13 @@
   }
 
   {
-    CanonicalCookie cookie_same_site_lax(
+    auto cookie_same_site_lax = CanonicalCookie::CreateUnsafeCookieForTesting(
         "A", "2", "www.example.com", "/test", current_time, base::Time(),
         base::Time(), true /*secure*/, false /*httponly*/,
         CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false);
 
     EXPECT_TRUE(cookie_same_site_lax
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
@@ -2690,14 +2691,14 @@
                     .status.HasExactlyExclusionReasonsForTesting(
                         {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX}));
     EXPECT_TRUE(cookie_same_site_lax
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_lax
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
@@ -2711,7 +2712,7 @@
 
       CookieInclusionStatus status_strict_to_lax =
           cookie_same_site_lax
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_lax,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2721,7 +2722,7 @@
       EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
       CookieInclusionStatus status_strict_to_cross =
           cookie_same_site_lax
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2732,7 +2733,7 @@
           CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE));
       CookieInclusionStatus status_lax_to_cross =
           cookie_same_site_lax
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_lax_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2749,7 +2750,7 @@
 
       CookieInclusionStatus status_strict_to_lax =
           cookie_same_site_lax
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_lax,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2759,7 +2760,7 @@
       EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
       CookieInclusionStatus status_strict_to_cross =
           cookie_same_site_lax
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2772,7 +2773,7 @@
           CookieInclusionStatus::EXCLUDE_SAMESITE_LAX));
       CookieInclusionStatus status_lax_to_cross =
           cookie_same_site_lax
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_lax_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2787,15 +2788,16 @@
   }
 
   {
-    CanonicalCookie cookie_same_site_strict(
-        "A", "2", "www.example.com", "/test", current_time, base::Time(),
-        base::Time(), true /*secure*/, false /*httponly*/,
-        CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false);
+    auto cookie_same_site_strict =
+        CanonicalCookie::CreateUnsafeCookieForTesting(
+            "A", "2", "www.example.com", "/test", current_time, base::Time(),
+            base::Time(), true /*secure*/, false /*httponly*/,
+            CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false);
 
     // TODO(morlovich): Do compatibility testing on whether set of strict in lax
     // context really should be accepted.
     EXPECT_TRUE(cookie_same_site_strict
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
@@ -2803,14 +2805,14 @@
                     .status.HasExactlyExclusionReasonsForTesting(
                         {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT}));
     EXPECT_TRUE(cookie_same_site_strict
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_strict
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
@@ -2824,7 +2826,7 @@
 
       CookieInclusionStatus status_strict_to_lax =
           cookie_same_site_strict
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_lax,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2834,7 +2836,7 @@
       EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
       CookieInclusionStatus status_strict_to_cross =
           cookie_same_site_strict
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2845,7 +2847,7 @@
           CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE));
       CookieInclusionStatus status_lax_to_cross =
           cookie_same_site_strict
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_lax_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2862,7 +2864,7 @@
 
       CookieInclusionStatus status_strict_to_lax =
           cookie_same_site_strict
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_lax,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2872,7 +2874,7 @@
       EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
       CookieInclusionStatus status_strict_to_cross =
           cookie_same_site_strict
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_strict_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2885,7 +2887,7 @@
           CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT));
       CookieInclusionStatus status_lax_to_cross =
           cookie_same_site_strict
-              .IsSetPermittedInContext(
+              ->IsSetPermittedInContext(
                   context_same_site_lax_to_cross,
                   CookieAccessParams(
                       CookieAccessSemantics::UNKNOWN,
@@ -2905,14 +2907,14 @@
       feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
 
       EXPECT_FALSE(cookie_same_site_strict
-                       .IsSetPermittedInContext(
+                       ->IsSetPermittedInContext(
                            context_same_site_strict_to_cross,
                            CookieAccessParams(
                                CookieAccessSemantics::UNKNOWN,
                                false /* delegate_treats_url_as_trustworthy */))
                        .status.IsInclude());
       EXPECT_FALSE(cookie_same_site_strict
-                       .IsSetPermittedInContext(
+                       ->IsSetPermittedInContext(
                            context_same_site_strict_to_cross,
                            CookieAccessParams(
                                CookieAccessSemantics::NONLEGACY,
@@ -2921,7 +2923,7 @@
       // LEGACY semantics should allow cookies which Schemeful Same-Site would
       // normally block.
       EXPECT_TRUE(cookie_same_site_strict
-                      .IsSetPermittedInContext(
+                      ->IsSetPermittedInContext(
                           context_same_site_strict_to_cross,
                           CookieAccessParams(
                               CookieAccessSemantics::LEGACY,
@@ -2931,59 +2933,60 @@
   }
 
   // Behavior of UNSPECIFIED depends on an experiment and CookieAccessSemantics.
-  CanonicalCookie cookie_same_site_unspecified(
-      "A", "2", "www.example.com", "/test", current_time, base::Time(),
-      base::Time(), true /*secure*/, false /*httponly*/,
-      CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, false);
+  auto cookie_same_site_unspecified =
+      CanonicalCookie::CreateUnsafeCookieForTesting(
+          "A", "2", "www.example.com", "/test", current_time, base::Time(),
+          base::Time(), true /*secure*/, false /*httponly*/,
+          CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, false);
 
   {
     base::test::ScopedFeatureList feature_list;
     feature_list.InitAndDisableFeature(features::kSameSiteByDefaultCookies);
 
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::NONLEGACY,
@@ -2992,14 +2995,14 @@
                         {CookieInclusionStatus::
                              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::NONLEGACY,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::NONLEGACY,
@@ -3012,7 +3015,7 @@
     feature_list.InitAndEnableFeature(features::kSameSiteByDefaultCookies);
 
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
@@ -3021,42 +3024,42 @@
                         {CookieInclusionStatus::
                              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::UNKNOWN,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::LEGACY,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::LEGACY,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::LEGACY,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_cross_site,
                         CookieAccessParams(
                             CookieAccessSemantics::NONLEGACY,
@@ -3065,14 +3068,14 @@
                         {CookieInclusionStatus::
                              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_lax,
                         CookieAccessParams(
                             CookieAccessSemantics::NONLEGACY,
                             false /* delegate_treats_url_as_trustworthy */))
                     .status.IsInclude());
     EXPECT_TRUE(cookie_same_site_unspecified
-                    .IsSetPermittedInContext(
+                    ->IsSetPermittedInContext(
                         context_same_site_strict,
                         CookieAccessParams(
                             CookieAccessSemantics::NONLEGACY,
@@ -3088,14 +3091,14 @@
 
   // Test IsSetPermitted CookieEffectiveSameSite for
   // CanonicalCookie with CookieSameSite::NO_RESTRICTION.
-  CanonicalCookie cookie_no_restriction(
+  auto cookie_no_restriction = CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "2", "www.example.com", "/test", current_time, base::Time(),
       base::Time(), true /*secure*/, false /*httponly*/,
       CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
 
   EXPECT_EQ(
       cookie_no_restriction
-          .IsSetPermittedInContext(
+          ->IsSetPermittedInContext(
               options, CookieAccessParams(
                            CookieAccessSemantics::UNKNOWN,
                            false /* delegate_treats_url_as_trustworthy */))
@@ -3104,14 +3107,14 @@
 
   // Test IsSetPermitted CookieEffectiveSameSite for
   // CanonicalCookie with CookieSameSite::LAX_MODE.
-  CanonicalCookie cookie_lax("A", "2", "www.example.com", "/test", current_time,
-                             base::Time(), base::Time(), true /*secure*/,
-                             false /*httponly*/, CookieSameSite::LAX_MODE,
-                             COOKIE_PRIORITY_DEFAULT, false);
+  auto cookie_lax = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "A", "2", "www.example.com", "/test", current_time, base::Time(),
+      base::Time(), true /*secure*/, false /*httponly*/,
+      CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false);
 
   EXPECT_EQ(
       cookie_lax
-          .IsSetPermittedInContext(
+          ->IsSetPermittedInContext(
               options, CookieAccessParams(
                            CookieAccessSemantics::UNKNOWN,
                            false /* delegate_treats_url_as_trustworthy */))
@@ -3120,14 +3123,14 @@
 
   // Test IsSetPermitted CookieEffectiveSameSite for
   // CanonicalCookie with CookieSameSite::STRICT_MODE.
-  CanonicalCookie cookie_strict(
+  auto cookie_strict = CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "2", "www.example.com", "/test", current_time, base::Time(),
       base::Time(), true /*secure*/, false /*httponly*/,
       CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false);
 
   EXPECT_EQ(
       cookie_strict
-          .IsSetPermittedInContext(
+          ->IsSetPermittedInContext(
               options, CookieAccessParams(
                            CookieAccessSemantics::UNKNOWN,
                            false /* delegate_treats_url_as_trustworthy */))
@@ -3137,18 +3140,18 @@
   // Test IsSetPermitted CookieEffectiveSameSite for
   // CanonicalCookie with CookieSameSite::UNSPECIFIED.
   base::Time creation_time = base::Time::Now() - (kLaxAllowUnsafeMaxAge * 4);
-  CanonicalCookie cookie_old_unspecified(
+  auto cookie_old_unspecified = CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "2", "www.example.com", "/test", creation_time, base::Time(),
       base::Time(), true /*secure*/, false /*httponly*/,
       CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, false);
-  CanonicalCookie cookie_unspecified(
+  auto cookie_unspecified = CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "2", "www.example.com", "/test", current_time, base::Time(),
       base::Time(), true /*secure*/, false /*httponly*/,
       CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, false);
 
   EXPECT_EQ(
       cookie_old_unspecified
-          .IsSetPermittedInContext(
+          ->IsSetPermittedInContext(
               options, CookieAccessParams(
                            CookieAccessSemantics::UNKNOWN,
                            false /* delegate_treats_url_as_trustworthy */))
@@ -3157,7 +3160,7 @@
 
   EXPECT_EQ(
       cookie_unspecified
-          .IsSetPermittedInContext(
+          ->IsSetPermittedInContext(
               options, CookieAccessParams(
                            CookieAccessSemantics::UNKNOWN,
                            false /* delegate_treats_url_as_trustworthy */))
@@ -3166,7 +3169,7 @@
 
   EXPECT_EQ(
       cookie_unspecified
-          .IsSetPermittedInContext(
+          ->IsSetPermittedInContext(
               options, CookieAccessParams(
                            CookieAccessSemantics::NONLEGACY,
                            false /* delegate_treats_url_as_trustworthy */))
@@ -3175,7 +3178,7 @@
 
   EXPECT_EQ(
       cookie_unspecified
-          .IsSetPermittedInContext(
+          ->IsSetPermittedInContext(
               options, CookieAccessParams(
                            CookieAccessSemantics::LEGACY,
                            false /* delegate_treats_url_as_trustworthy */))
diff --git a/net/cookies/cookie_deletion_info_unittest.cc b/net/cookies/cookie_deletion_info_unittest.cc
index 0c2ba6f2..f4e48d7 100644
--- a/net/cookies/cookie_deletion_info_unittest.cc
+++ b/net/cookies/cookie_deletion_info_unittest.cc
@@ -82,18 +82,18 @@
 }
 
 TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchSessionControl) {
-  CanonicalCookie persistent_cookie("persistent-cookie", "persistent-value",
-                                    "persistent-domain", "persistent-path",
-                                    /*creation=*/base::Time::Now(),
-                                    /*expiration=*/base::Time::Max(),
-                                    /*last_access=*/base::Time::Now(),
-                                    /*secure=*/true,
-                                    /*httponly=*/false,
-                                    CookieSameSite::NO_RESTRICTION,
-                                    CookiePriority::COOKIE_PRIORITY_DEFAULT,
-                                    /*sameparty=*/false);
+  auto persistent_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "persistent-cookie", "persistent-value", "persistent-domain",
+      "persistent-path",
+      /*creation=*/base::Time::Now(),
+      /*expiration=*/base::Time::Max(),
+      /*last_access=*/base::Time::Now(),
+      /*secure=*/true,
+      /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
+      CookiePriority::COOKIE_PRIORITY_DEFAULT,
+      /*sameparty=*/false);
 
-  CanonicalCookie session_cookie(
+  auto session_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
       "session-cookie", "session-value", "session-domain", "session-path",
       /*creation=*/base::Time::Now(),
       /*expiration=*/base::Time(),
@@ -105,204 +105,210 @@
 
   CookieDeletionInfo delete_info;
   EXPECT_TRUE(delete_info.Matches(
-      persistent_cookie,
+      *persistent_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_TRUE(delete_info.Matches(
-      session_cookie,
+      *session_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 
   delete_info.session_control =
       CookieDeletionInfo::SessionControl::PERSISTENT_COOKIES;
   EXPECT_TRUE(delete_info.Matches(
-      persistent_cookie,
+      *persistent_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_FALSE(delete_info.Matches(
-      session_cookie,
+      *session_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 
   delete_info.session_control =
       CookieDeletionInfo::SessionControl::SESSION_COOKIES;
   EXPECT_FALSE(delete_info.Matches(
-      persistent_cookie,
+      *persistent_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_TRUE(delete_info.Matches(
-      session_cookie,
+      *session_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 }
 
 TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchHost) {
-  CanonicalCookie domain_cookie("domain-cookie", "domain-cookie-value",
-                                /*domain=*/".example.com", "/path",
-                                /*creation=*/base::Time::Now(),
-                                /*expiration=*/base::Time::Max(),
-                                /*last_access=*/base::Time::Now(),
-                                /*secure=*/true,
-                                /*httponly=*/false,
-                                CookieSameSite::NO_RESTRICTION,
-                                CookiePriority::COOKIE_PRIORITY_DEFAULT,
-                                /*sameparty=*/false);
+  auto domain_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "domain-cookie", "domain-cookie-value",
+      /*domain=*/".example.com", "/path",
+      /*creation=*/base::Time::Now(),
+      /*expiration=*/base::Time::Max(),
+      /*last_access=*/base::Time::Now(),
+      /*secure=*/true,
+      /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
+      CookiePriority::COOKIE_PRIORITY_DEFAULT,
+      /*sameparty=*/false);
 
-  CanonicalCookie host_cookie("host-cookie", "host-cookie-value",
-                              /*domain=*/"thehost.hosting.com", "/path",
-                              /*creation=*/base::Time::Now(),
-                              /*expiration=*/base::Time::Max(),
-                              /*last_access=*/base::Time::Now(),
-                              /*secure=*/true,
-                              /*httponly=*/false,
-                              CookieSameSite::NO_RESTRICTION,
-                              CookiePriority::COOKIE_PRIORITY_DEFAULT,
-                              /*sameparty=*/false);
+  auto host_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "host-cookie", "host-cookie-value",
+      /*domain=*/"thehost.hosting.com", "/path",
+      /*creation=*/base::Time::Now(),
+      /*expiration=*/base::Time::Max(),
+      /*last_access=*/base::Time::Now(),
+      /*secure=*/true,
+      /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
+      CookiePriority::COOKIE_PRIORITY_DEFAULT,
+      /*sameparty=*/false);
 
-  EXPECT_TRUE(domain_cookie.IsDomainCookie());
-  EXPECT_TRUE(host_cookie.IsHostCookie());
+  EXPECT_TRUE(domain_cookie->IsDomainCookie());
+  EXPECT_TRUE(host_cookie->IsHostCookie());
 
   CookieDeletionInfo delete_info;
   EXPECT_TRUE(delete_info.Matches(
-      domain_cookie,
+      *domain_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_TRUE(delete_info.Matches(
-      host_cookie,
+      *host_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 
   delete_info.host = "thehost.hosting.com";
   EXPECT_FALSE(delete_info.Matches(
-      domain_cookie,
+      *domain_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_TRUE(delete_info.Matches(
-      host_cookie,
+      *host_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 
   delete_info.host = "otherhost.hosting.com";
   EXPECT_FALSE(delete_info.Matches(
-      domain_cookie,
+      *domain_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_FALSE(delete_info.Matches(
-      host_cookie,
+      *host_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 
   delete_info.host = "thehost.otherhosting.com";
   EXPECT_FALSE(delete_info.Matches(
-      domain_cookie,
+      *domain_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_FALSE(delete_info.Matches(
-      host_cookie,
+      *host_cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 }
 
 TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchName) {
-  CanonicalCookie cookie1("cookie1-name", "cookie1-value",
-                          /*domain=*/".example.com", "/path",
-                          /*creation=*/base::Time::Now(),
-                          /*expiration=*/base::Time::Max(),
-                          /*last_access=*/base::Time::Now(),
-                          /*secure=*/true,
-                          /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
-                          CookiePriority::COOKIE_PRIORITY_DEFAULT,
-                          /*sameparty=*/false);
-  CanonicalCookie cookie2("cookie2-name", "cookie2-value",
-                          /*domain=*/".example.com", "/path",
-                          /*creation=*/base::Time::Now(),
-                          /*expiration=*/base::Time::Max(),
-                          /*last_access=*/base::Time::Now(),
-                          /*secure=*/true,
-                          /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
-                          CookiePriority::COOKIE_PRIORITY_DEFAULT,
-                          /*sameparty=*/false);
+  auto cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "cookie1-name", "cookie1-value",
+      /*domain=*/".example.com", "/path",
+      /*creation=*/base::Time::Now(),
+      /*expiration=*/base::Time::Max(),
+      /*last_access=*/base::Time::Now(),
+      /*secure=*/true,
+      /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
+      CookiePriority::COOKIE_PRIORITY_DEFAULT,
+      /*sameparty=*/false);
+  auto cookie2 = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "cookie2-name", "cookie2-value",
+      /*domain=*/".example.com", "/path",
+      /*creation=*/base::Time::Now(),
+      /*expiration=*/base::Time::Max(),
+      /*last_access=*/base::Time::Now(),
+      /*secure=*/true,
+      /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
+      CookiePriority::COOKIE_PRIORITY_DEFAULT,
+      /*sameparty=*/false);
 
   CookieDeletionInfo delete_info;
   delete_info.name = "cookie1-name";
   EXPECT_TRUE(delete_info.Matches(
-      cookie1,
+      *cookie1,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_FALSE(delete_info.Matches(
-      cookie2,
+      *cookie2,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 }
 
 TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchValue) {
-  CanonicalCookie cookie1("cookie1-name", "cookie1-value",
-                          /*domain=*/".example.com", "/path",
-                          /*creation=*/base::Time::Now(),
-                          /*expiration=*/base::Time::Max(),
-                          /*last_access=*/base::Time::Now(),
-                          /*secure=*/true,
-                          /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
-                          CookiePriority::COOKIE_PRIORITY_DEFAULT,
-                          /*sameparty=*/false);
-  CanonicalCookie cookie2("cookie2-name", "cookie2-value",
-                          /*domain=*/".example.com", "/path",
-                          /*creation=*/base::Time::Now(),
-                          /*expiration=*/base::Time::Max(),
-                          /*last_access=*/base::Time::Now(),
-                          /*secure=*/true,
-                          /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
-                          CookiePriority::COOKIE_PRIORITY_DEFAULT,
-                          /*sameparty=*/false);
+  auto cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "cookie1-name", "cookie1-value",
+      /*domain=*/".example.com", "/path",
+      /*creation=*/base::Time::Now(),
+      /*expiration=*/base::Time::Max(),
+      /*last_access=*/base::Time::Now(),
+      /*secure=*/true,
+      /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
+      CookiePriority::COOKIE_PRIORITY_DEFAULT,
+      /*sameparty=*/false);
+  auto cookie2 = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "cookie2-name", "cookie2-value",
+      /*domain=*/".example.com", "/path",
+      /*creation=*/base::Time::Now(),
+      /*expiration=*/base::Time::Max(),
+      /*last_access=*/base::Time::Now(),
+      /*secure=*/true,
+      /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
+      CookiePriority::COOKIE_PRIORITY_DEFAULT,
+      /*sameparty=*/false);
 
   CookieDeletionInfo delete_info;
   delete_info.value_for_testing = "cookie2-value";
   EXPECT_FALSE(delete_info.Matches(
-      cookie1,
+      *cookie1,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
   EXPECT_TRUE(delete_info.Matches(
-      cookie2,
+      *cookie2,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 }
 
 TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchUrl) {
-  CanonicalCookie cookie("cookie-name", "cookie-value",
-                         /*domain=*/"www.example.com", "/path",
-                         /*creation=*/base::Time::Now(),
-                         /*expiration=*/base::Time::Max(),
-                         /*last_access=*/base::Time::Now(),
-                         /*secure=*/true,
-                         /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
-                         CookiePriority::COOKIE_PRIORITY_DEFAULT,
-                         /*sameparty=*/false);
+  auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "cookie-name", "cookie-value",
+      /*domain=*/"www.example.com", "/path",
+      /*creation=*/base::Time::Now(),
+      /*expiration=*/base::Time::Max(),
+      /*last_access=*/base::Time::Now(),
+      /*secure=*/true,
+      /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
+      CookiePriority::COOKIE_PRIORITY_DEFAULT,
+      /*sameparty=*/false);
 
   CookieDeletionInfo delete_info;
   delete_info.url = GURL("https://www.example.com/path");
   EXPECT_TRUE(delete_info.Matches(
-      cookie,
+      *cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 
   delete_info.url = GURL("https://www.example.com/another/path");
   EXPECT_FALSE(delete_info.Matches(
-      cookie,
+      *cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 
   delete_info.url = GURL("http://www.example.com/path");
   // Secure cookie on http:// URL -> no match.
   EXPECT_FALSE(delete_info.Matches(
-      cookie,
+      *cookie,
       CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
                          /*delegate_treats_url_as_trustworthy=*/false}));
 
   // Secure cookie on http:// URL, but delegate says treat is as trustworhy ->
   // match.
   EXPECT_TRUE(delete_info.Matches(
-      cookie, CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
-                                 /*delegate_treats_url_as_trustworthy=*/true}));
+      *cookie,
+      CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
+                         /*delegate_treats_url_as_trustworthy=*/true}));
 }
 
 TEST(CookieDeletionInfoTest, CookieDeletionInfoDomainMatchesDomain) {
@@ -314,7 +320,7 @@
   delete_info.creation_range.SetEnd(base::Time::FromDoubleT(kTestMaxEpoch));
 
   auto create_cookie = [kTestMinEpoch](std::string cookie_domain) {
-    CanonicalCookie cookie(
+    return *CanonicalCookie::CreateUnsafeCookieForTesting(
         /*name=*/"test-cookie",
         /*value=*/"cookie-value", cookie_domain,
         /*path=*/"cookie/path",
@@ -326,7 +332,6 @@
         /*same_site=*/CookieSameSite::NO_RESTRICTION,
         /*priority=*/CookiePriority::COOKIE_PRIORITY_DEFAULT,
         /*sameparty=*/false);
-    return cookie;
   };
 
   // by default empty domain list and default match action will match.
@@ -375,7 +380,7 @@
   CookieDeletionInfo delete_info;
 
   auto create_cookie = [](std::string cookie_domain) {
-    CanonicalCookie cookie(
+    return *CanonicalCookie::CreateUnsafeCookieForTesting(
         /*name=*/"test-cookie",
         /*value=*/"cookie-value", cookie_domain,
         /*path=*/"cookie/path",
@@ -387,7 +392,6 @@
         /*same_site=*/CookieSameSite::NO_RESTRICTION,
         /*priority=*/CookiePriority::COOKIE_PRIORITY_DEFAULT,
         /*sameparty=*/false);
-    return cookie;
   };
 
   // With two empty lists (default) should match any domain.
diff --git a/net/cookies/cookie_monster_store_test.cc b/net/cookies/cookie_monster_store_test.cc
index f37b1a2..63e85b3e 100644
--- a/net/cookies/cookie_monster_store_test.cc
+++ b/net/cookies/cookie_monster_store_test.cc
@@ -119,7 +119,7 @@
                       : base::Time();
   std::string cookie_path = pc.Path();
 
-  return std::make_unique<CanonicalCookie>(
+  return CanonicalCookie::CreateUnsafeCookieForTesting(
       pc.Name(), pc.Value(), "." + url.host(), cookie_path, creation_time,
       cookie_expires, base::Time(), pc.IsSecure(), pc.IsHttpOnly(),
       pc.SameSite(), pc.Priority(), pc.IsSameParty());
@@ -233,10 +233,11 @@
     // The URL must be HTTPS since |secure| can be true or false, and because
     // strict secure cookies are enforced, the cookie will fail to be created if
     // |secure| is true but the URL is an insecure scheme.
-    std::unique_ptr<CanonicalCookie> cc(std::make_unique<CanonicalCookie>(
-        "a", "1", base::StringPrintf("h%05d.izzle", i), "/path", creation_time,
-        expiration_time, base::Time(), secure, false,
-        CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
+    std::unique_ptr<CanonicalCookie> cc =
+        CanonicalCookie::CreateUnsafeCookieForTesting(
+            "a", "1", base::StringPrintf("h%05d.izzle", i), "/path",
+            creation_time, expiration_time, base::Time(), secure, false,
+            CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
     cc->SetLastAccessDate(last_access_time);
     store->AddCookie(*cc);
   }
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index 259a8ab..6300ea95b 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -207,71 +207,71 @@
     std::vector<std::unique_ptr<CanonicalCookie>> cookies;
 
     // Domain cookies
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "dom_1", "A", ".harvard.edu", "/", base::Time(), base::Time(),
         base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "dom_2", "B", ".math.harvard.edu", "/", base::Time(), base::Time(),
         base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "dom_3", "C", ".bourbaki.math.harvard.edu", "/", base::Time(),
         base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
 
     // Host cookies
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "host_1", "A", url_top_level_domain_plus_1, "/", base::Time(),
         base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "host_2", "B", url_top_level_domain_plus_2, "/", base::Time(),
         base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "host_3", "C", url_top_level_domain_plus_3, "/", base::Time(),
         base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
 
     // http_only cookie
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "httpo_check", "A", url_top_level_domain_plus_2, "/", base::Time(),
         base::Time(), base::Time(), false, true, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
 
     // same-site cookie
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "firstp_check", "A", url_top_level_domain_plus_2, "/", base::Time(),
         base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
 
     // Secure cookies
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "sec_dom", "A", ".math.harvard.edu", "/", base::Time(), base::Time(),
         base::Time(), true, false, CookieSameSite::NO_RESTRICTION,
         COOKIE_PRIORITY_DEFAULT, false));
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "sec_host", "B", url_top_level_domain_plus_2, "/", base::Time(),
         base::Time(), base::Time(), true, false, CookieSameSite::NO_RESTRICTION,
         COOKIE_PRIORITY_DEFAULT, false));
 
     // Domain path cookies
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "dom_path_1", "A", ".math.harvard.edu", "/dir1", base::Time(),
         base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "dom_path_2", "B", ".math.harvard.edu", "/dir1/dir2", base::Time(),
         base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
 
     // Host path cookies
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "host_path_1", "A", url_top_level_domain_plus_2, "/dir1", base::Time(),
         base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
         COOKIE_PRIORITY_DEFAULT, false));
-    cookies.push_back(std::make_unique<CanonicalCookie>(
+    cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
         "host_path_2", "B", url_top_level_domain_plus_2, "/dir1/dir2",
         base::Time(), base::Time(), base::Time(), false, false,
         CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false));
@@ -829,12 +829,13 @@
     CookieMonster* cm(new CookieMonster(nullptr, &net_log_));
     base::Time creation_time = base::Time::Now();
     for (int i = 0; i < num_cookies; i++) {
-      std::unique_ptr<CanonicalCookie> cc(std::make_unique<CanonicalCookie>(
-          "a", "1", base::StringPrintf("h%05d.izzle", i), "/" /* path */,
-          creation_time, base::Time() /* expiration_time */,
-          creation_time /* last_access */, true /* secure */,
-          false /* http_only */, CookieSameSite::NO_RESTRICTION,
-          COOKIE_PRIORITY_DEFAULT, false /* same_party */));
+      std::unique_ptr<CanonicalCookie> cc(
+          CanonicalCookie::CreateUnsafeCookieForTesting(
+              "a", "1", base::StringPrintf("h%05d.izzle", i), "/" /* path */,
+              creation_time, base::Time() /* expiration_time */,
+              creation_time /* last_access */, true /* secure */,
+              false /* http_only */, CookieSameSite::NO_RESTRICTION,
+              COOKIE_PRIORITY_DEFAULT, false /* same_party */));
       GURL source_url = cookie_util::SimulatedCookieSource(*cc, "https");
       cm->SetCanonicalCookieAsync(std::move(cc), source_url,
                                   CookieOptions::MakeAllInclusive(),
@@ -1008,14 +1009,14 @@
   cookie_monster_->SetPersistSessionCookies(true);
 
   CookieList list;
-  list.push_back(CanonicalCookie("A", "B", "." + http_www_foo_.domain(), "/",
-                                 base::Time::Now(), base::Time(), base::Time(),
-                                 false, true, CookieSameSite::NO_RESTRICTION,
-                                 COOKIE_PRIORITY_DEFAULT, false));
-  list.push_back(CanonicalCookie("C", "D", "." + http_www_foo_.domain(), "/",
-                                 base::Time::Now(), base::Time(), base::Time(),
-                                 false, true, CookieSameSite::NO_RESTRICTION,
-                                 COOKIE_PRIORITY_DEFAULT, false));
+  list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
+      "A", "B", "." + http_www_foo_.domain(), "/", base::Time::Now(),
+      base::Time(), base::Time(), false, true, CookieSameSite::NO_RESTRICTION,
+      COOKIE_PRIORITY_DEFAULT, false));
+  list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
+      "C", "D", "." + http_www_foo_.domain(), "/", base::Time::Now(),
+      base::Time(), base::Time(), false, true, CookieSameSite::NO_RESTRICTION,
+      COOKIE_PRIORITY_DEFAULT, false));
 
   ResultSavingCookieCallback<CookieAccessResult> call1;
   cookie_monster_->SetAllCookiesAsync(list, call1.MakeCallback());
@@ -2009,7 +2010,7 @@
     for (const auto& cookie : input_info) {
       EXPECT_TRUE(SetCanonicalCookie(
           cmout.get(),
-          std::make_unique<CanonicalCookie>(
+          CanonicalCookie::CreateUnsafeCookieForTesting(
               cookie.name, cookie.value, cookie.domain, cookie.path,
               base::Time(), cookie.expiration_time, base::Time(), cookie.secure,
               cookie.http_only, cookie.same_site, cookie.priority,
@@ -2463,15 +2464,15 @@
   EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "Y=Z; path=/"));
 
   CookieList list;
-  list.push_back(CanonicalCookie(
+  list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "." + http_www_foo_.url().host(), "/", base::Time::Now(),
       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
       COOKIE_PRIORITY_DEFAULT, false));
-  list.push_back(CanonicalCookie(
+  list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "W", "X", "." + http_www_foo_.url().host(), "/bar", base::Time::Now(),
       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
       COOKIE_PRIORITY_DEFAULT, false));
-  list.push_back(CanonicalCookie(
+  list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "Y", "Z", "." + http_www_foo_.url().host(), "/", base::Time::Now(),
       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
       COOKIE_PRIORITY_DEFAULT, false));
@@ -2554,7 +2555,7 @@
 
   std::unique_ptr<base::HistogramSamples> samples1(
       expired_histogram->SnapshotSamples());
-  auto cookie = std::make_unique<CanonicalCookie>(
+  auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
       "a", "b", "a.url", "/", base::Time(),
       base::Time::Now() + base::TimeDelta::FromMinutes(59), base::Time(), true,
       false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
@@ -2680,12 +2681,13 @@
 
   // We have to manually build this cookie because it contains a control
   // character, and our cookie line parser rejects control characters.
-  std::unique_ptr<CanonicalCookie> cc = std::make_unique<CanonicalCookie>(
-      "baz",
-      "\x05"
-      "boo",
-      "." + domain, path, now2, later, base::Time(), false, false,
-      CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
+  std::unique_ptr<CanonicalCookie> cc =
+      CanonicalCookie::CreateUnsafeCookieForTesting(
+          "baz",
+          "\x05"
+          "boo",
+          "." + domain, path, now2, later, base::Time(), false, false,
+          CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
   initial_cookies.push_back(std::move(cc));
 
   AddCookieToList(url, "hello=world; path=" + path, now3, &initial_cookies);
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index ddd5a7e6c..26857ee5 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -550,14 +550,14 @@
 
   EXPECT_TRUE(this->SetCanonicalCookie(
       cs,
-      std::make_unique<CanonicalCookie>(
+      CanonicalCookie::CreateUnsafeCookieForTesting(
           "A", "B", foo_foo_host, "/foo", one_hour_ago, one_hour_from_now,
           base::Time(), false /* secure */, false /* httponly */,
           CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false),
       this->www_foo_foo_.url(), true));
   EXPECT_TRUE(this->SetCanonicalCookie(
       cs,
-      std::make_unique<CanonicalCookie>(
+      CanonicalCookie::CreateUnsafeCookieForTesting(
           "C", "D", "." + foo_bar_domain, "/bar", two_hours_ago, base::Time(),
           one_hour_ago, false, true, CookieSameSite::LAX_MODE,
           COOKIE_PRIORITY_DEFAULT, false),
@@ -567,7 +567,7 @@
   EXPECT_TRUE(
       this->SetCanonicalCookieReturnAccessResult(
               cs,
-              std::make_unique<CanonicalCookie>(
+              CanonicalCookie::CreateUnsafeCookieForTesting(
                   "E", "F", http_foo_host, "/", base::Time(), base::Time(),
                   base::Time(), true, false, CookieSameSite::NO_RESTRICTION,
                   COOKIE_PRIORITY_DEFAULT, false),
@@ -592,7 +592,7 @@
   // a secure cookie then overwriting it from a non-secure source should fail.
   EXPECT_TRUE(this->SetCanonicalCookie(
       cs,
-      std::make_unique<CanonicalCookie>(
+      CanonicalCookie::CreateUnsafeCookieForTesting(
           "E", "F", https_foo_host, "/", base::Time(), base::Time(),
           base::Time(), true /* secure */, false /* httponly */,
           CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
@@ -601,7 +601,7 @@
 
   EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
                       cs,
-                      std::make_unique<CanonicalCookie>(
+                      CanonicalCookie::CreateUnsafeCookieForTesting(
                           "E", "F", http_foo_host, "/", base::Time(),
                           base::Time(), base::Time(), true /* secure */,
                           false /* httponly */, CookieSameSite::NO_RESTRICTION,
@@ -615,7 +615,7 @@
     // httponly cookie.
     EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
                         cs,
-                        std::make_unique<CanonicalCookie>(
+                        CanonicalCookie::CreateUnsafeCookieForTesting(
                             "G", "H", http_foo_host, "/unique", base::Time(),
                             base::Time(), base::Time(), false /* secure */,
                             true /* httponly */, CookieSameSite::LAX_MODE,
@@ -642,7 +642,7 @@
     // an httponly cookie.
     EXPECT_TRUE(this->SetCanonicalCookie(
         cs,
-        std::make_unique<CanonicalCookie>(
+        CanonicalCookie::CreateUnsafeCookieForTesting(
             "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
             base::Time(), false /* secure */, true /* httponly */,
             CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
@@ -651,7 +651,7 @@
 
     EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
                         cs,
-                        std::make_unique<CanonicalCookie>(
+                        CanonicalCookie::CreateUnsafeCookieForTesting(
                             "G", "H", http_foo_host, "/unique", base::Time(),
                             base::Time(), base::Time(), false /* secure */,
                             true /* httponly */, CookieSameSite::LAX_MODE,
@@ -663,7 +663,7 @@
     // Leave store in same state as if the above tests had been run.
     EXPECT_TRUE(this->SetCanonicalCookie(
         cs,
-        std::make_unique<CanonicalCookie>(
+        CanonicalCookie::CreateUnsafeCookieForTesting(
             "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
             base::Time(), false /* secure */, true /* httponly */,
             CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
@@ -742,28 +742,28 @@
   // but the other combinations work.
   EXPECT_FALSE(this->SetCanonicalCookie(
       cs,
-      std::make_unique<CanonicalCookie>(
+      CanonicalCookie::CreateUnsafeCookieForTesting(
           "A", "B", http_domain, "/", base::Time::Now(), base::Time(),
           base::Time(), true, false, CookieSameSite::STRICT_MODE,
           COOKIE_PRIORITY_DEFAULT, false /* same_party */),
       http_url, true /*modify_httponly*/));
   EXPECT_TRUE(this->SetCanonicalCookie(
       cs,
-      std::make_unique<CanonicalCookie>(
+      CanonicalCookie::CreateUnsafeCookieForTesting(
           "A", "B", http_domain, "/", base::Time::Now(), base::Time(),
           base::Time(), true, false, CookieSameSite::STRICT_MODE,
           COOKIE_PRIORITY_DEFAULT, false /* same_party */),
       https_url, true /*modify_httponly*/));
   EXPECT_TRUE(this->SetCanonicalCookie(
       cs,
-      std::make_unique<CanonicalCookie>(
+      CanonicalCookie::CreateUnsafeCookieForTesting(
           "A", "B", http_domain, "/", base::Time::Now(), base::Time(),
           base::Time(), false, false, CookieSameSite::STRICT_MODE,
           COOKIE_PRIORITY_DEFAULT, false /* same_party */),
       https_url, true /*modify_httponly*/));
   EXPECT_TRUE(this->SetCanonicalCookie(
       cs,
-      std::make_unique<CanonicalCookie>(
+      CanonicalCookie::CreateUnsafeCookieForTesting(
           "A", "B", http_domain, "/", base::Time::Now(), base::Time(),
           base::Time(), false, false, CookieSameSite::STRICT_MODE,
           COOKIE_PRIORITY_DEFAULT, false /* same_party */),
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index 405821a..f660c68 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -179,7 +179,7 @@
                  const std::string& domain,
                  const std::string& path,
                  const base::Time& creation) {
-    store_->AddCookie(CanonicalCookie(
+    store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
         name, value, domain, path, creation, creation, base::Time(), false,
         false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
   }
@@ -190,7 +190,7 @@
                                const std::string& path,
                                const base::Time& creation,
                                const base::Time& expiration) {
-    store_->AddCookie(CanonicalCookie(
+    store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
         name, value, domain, path, creation, expiration, base::Time(), false,
         false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
   }
@@ -528,7 +528,7 @@
   InitializeStore(false, true);
 
   // Add a session cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "D", "sessioncookie.com", "/", base::Time::Now(), base::Time(),
       base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
       COOKIE_PRIORITY_DEFAULT, false));
@@ -555,7 +555,7 @@
   InitializeStore(false, true);
 
   // Add a session cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "D", "sessioncookie.com", "/", base::Time::Now(), base::Time(),
       base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
       COOKIE_PRIORITY_DEFAULT, false));
@@ -658,12 +658,12 @@
   static const char kPersistentName[] = "persistent";
 
   // Add a session cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kSessionName, "val", "sessioncookie.com", "/", base::Time::Now(),
       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
       COOKIE_PRIORITY_DEFAULT, false));
   // Add a persistent cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kPersistentName, "val", "sessioncookie.com", "/",
       base::Time::Now() - base::TimeDelta::FromDays(1),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(), false,
@@ -704,21 +704,21 @@
   InitializeStore(false, true);
 
   // Add a low-priority persistent cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kLowName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(1),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(), false,
       false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false));
 
   // Add a medium-priority persistent cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kMediumName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(2),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(), false,
       false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_MEDIUM, false));
 
-  // Add a high-priority peristent cookie.
-  store_->AddCookie(CanonicalCookie(
+  // Add a high-priority persistent cookie.
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kHighName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(3),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(), false,
@@ -765,21 +765,21 @@
   InitializeStore(false, true);
 
   // Add a non-samesite persistent cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kNoneName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(1),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(), false,
       false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
 
   // Add a lax-samesite persistent cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kLaxName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(2),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(), false,
       false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false));
 
   // Add a strict-samesite persistent cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kStrictName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(3),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(), false,
@@ -821,7 +821,7 @@
   // Add an extended-samesite persistent cookie by first adding a strict-same
   // site cookie, then turning that into the legacy extended-samesite state with
   // direct SQL DB access.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kExtendedName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(1),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(), false,
@@ -861,7 +861,7 @@
   InitializeStore(false, true);
 
   // Add a non-SameParty persistent cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kNonSamePartyCookieName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(1),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(),
@@ -869,7 +869,7 @@
       /*same_party=*/false));
 
   // Add a SameParty persistent cookie.
-  store_->AddCookie(CanonicalCookie(
+  store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
       kSamePartyCookieName, kCookieValue, kDomain, kCookiePath,
       base::Time::Now() - base::TimeDelta::FromMinutes(1),
       base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(),
@@ -919,7 +919,7 @@
 
   for (const auto& input : kTestCookies) {
     // Add some persistent cookies.
-    store_->AddCookie(CanonicalCookie(
+    store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
         input.name, kCookieValue, kDomain, kCookiePath,
         base::Time::Now() - base::TimeDelta::FromMinutes(1),
         base::Time::Now() + base::TimeDelta::FromDays(1), base::Time(),
@@ -1119,32 +1119,32 @@
   static base::Time cookie_time(base::Time::Now());
 
   std::vector<CanonicalCookie> cookies;
-  cookies.push_back(CanonicalCookie("A", "B", "example.com", "/", cookie_time,
-                                    cookie_time, cookie_time, false, false,
-                                    CookieSameSite::NO_RESTRICTION,
-                                    COOKIE_PRIORITY_DEFAULT, false));
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
+      "A", "B", "example.com", "/", cookie_time, cookie_time, cookie_time,
+      false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+      false));
   cookie_time += base::TimeDelta::FromMicroseconds(1);
-  cookies.push_back(CanonicalCookie("C", "B", "example.com", "/", cookie_time,
-                                    cookie_time, cookie_time, false, false,
-                                    CookieSameSite::NO_RESTRICTION,
-                                    COOKIE_PRIORITY_DEFAULT, false));
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
+      "C", "B", "example.com", "/", cookie_time, cookie_time, cookie_time,
+      false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+      false));
   cookie_time += base::TimeDelta::FromMicroseconds(1);
-  cookies.push_back(CanonicalCookie("A", "B", "example2.com", "/", cookie_time,
-                                    cookie_time, cookie_time, false, false,
-                                    CookieSameSite::NO_RESTRICTION,
-                                    COOKIE_PRIORITY_DEFAULT, false));
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
+      "A", "B", "example2.com", "/", cookie_time, cookie_time, cookie_time,
+      false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+      false));
   cookie_time += base::TimeDelta::FromMicroseconds(1);
-  cookies.push_back(CanonicalCookie("C", "B", "example2.com", "/", cookie_time,
-                                    cookie_time, cookie_time, false, false,
-                                    CookieSameSite::NO_RESTRICTION,
-                                    COOKIE_PRIORITY_DEFAULT, false));
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
+      "C", "B", "example2.com", "/", cookie_time, cookie_time, cookie_time,
+      false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+      false));
   cookie_time += base::TimeDelta::FromMicroseconds(1);
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "example.com", "/path", cookie_time, cookie_time, cookie_time,
       false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
       false));
   cookie_time += base::TimeDelta::FromMicroseconds(1);
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "B", "example.com", "/path", cookie_time, cookie_time, cookie_time,
       false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
       false));
@@ -1269,21 +1269,21 @@
 
   base::Time old_time = base::Time::Now() - base::TimeDelta::FromMinutes(90);
   base::Time old_time2 = base::Time::Now() - base::TimeDelta::FromMinutes(91);
-  CanonicalCookie old_cookie1(
+  auto old_cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "old_value", "example.com", "/", old_time, old_time, old_time, false,
       false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
-  AddV9CookiesToDBImpl(&connection, {old_cookie1});
+  AddV9CookiesToDBImpl(&connection, {*old_cookie1});
 
   // Add the same set of cookies twice to create duplicates.
   ASSERT_TRUE(AddV9CookiesToDB(&connection));
   ASSERT_TRUE(AddV9CookiesToDB(&connection));
 
   // Add some others as well.
-  CanonicalCookie old_cookie2("A", "old_value", "example.com", "/path",
-                              old_time2, old_time2, old_time2, false, false,
-                              CookieSameSite::NO_RESTRICTION,
-                              COOKIE_PRIORITY_DEFAULT, false);
-  AddV9CookiesToDBImpl(&connection, {old_cookie2});
+  auto old_cookie2 = CanonicalCookie::CreateUnsafeCookieForTesting(
+      "A", "old_value", "example.com", "/path", old_time2, old_time2, old_time2,
+      false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+      false);
+  AddV9CookiesToDBImpl(&connection, {*old_cookie2});
 
   connection.Close();
 
@@ -1598,22 +1598,22 @@
   static base::Time time = base::Time::Now();
 
   std::vector<CanonicalCookie> cookies;
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "example.com", "/", time, time, time, false, false,
       CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "B", "example.com", "/", time, time, time, false, false,
       CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "example2.com", "/", time, time, time, false, false,
       CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "B", "example2.com", "/", time, time, time, false, false,
       CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "example.com", "/path", time, time, time, false, false,
       CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "B", "example.com", "/path", time, time, time, false, false,
       CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false));
   return AddV10CookiesToDBImpl(db, cookies);
@@ -1807,27 +1807,27 @@
   // v11 doesn't store that info.
   // Some of these are constructed with SameParty set to true, to test that in
   // the DB migration, the is_same_party values are all defaulted to false.
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "example.com", "/", now, now, now, true /* secure */,
       false /* httponly */, CookieSameSite::UNSPECIFIED,
       COOKIE_PRIORITY_DEFAULT, false /* same_party */));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "B", "example.com", "/", now, now, now, true /* secure */,
       false /* httponly */, CookieSameSite::UNSPECIFIED,
       COOKIE_PRIORITY_DEFAULT, true /* same_party */));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "example2.com", "/", now, now, now, true /* secure */,
       false /* httponly */, CookieSameSite::UNSPECIFIED,
       COOKIE_PRIORITY_DEFAULT, true /* same_party */));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "B", "example2.com", "/", now, now, now, false /* secure */,
       false /* httponly */, CookieSameSite::UNSPECIFIED,
       COOKIE_PRIORITY_DEFAULT, false /* same_party */));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "A", "B", "example.com", "/path", now, now, now, false /* secure */,
       false /* httponly */, CookieSameSite::UNSPECIFIED,
       COOKIE_PRIORITY_DEFAULT, false /* same_party */));
-  cookies.push_back(CanonicalCookie(
+  cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
       "C", "B", "example.com", "/path", now, now, now, false /* secure */,
       false /* httponly */, CookieSameSite::UNSPECIFIED,
       COOKIE_PRIORITY_DEFAULT, false /* same_party */));
diff --git a/remoting/resources/remoting_strings_nl.xtb b/remoting/resources/remoting_strings_nl.xtb
index aa3849d15..7faa04d 100644
--- a/remoting/resources/remoting_strings_nl.xtb
+++ b/remoting/resources/remoting_strings_nl.xtb
@@ -110,12 +110,12 @@
 <translation id="6062854958530969723">Initialisatie van host mislukt.</translation>
 <translation id="6099500228377758828">Chrome Remote Desktop-service</translation>
 <translation id="6122191549521593678">Online</translation>
-<translation id="6178645564515549384">Systeemeigen berichthost voor externe ondersteuning</translation>
+<translation id="6178645564515549384">Systeemeigen berichthost voor externe support</translation>
 <translation id="618120821413932081">Externe resolutie aanpassen aan venster</translation>
 <translation id="6223301979382383752">Voorkeuren voor Schermopname openen</translation>
 <translation id="6284412385303060032">De host die werd uitgevoerd op het console-inlogscherm, is uitgeschakeld om de gordijnmodus te ondersteunen door over te schakelen naar een host die in een gebruikersspecifieke sessie wordt uitgevoerd.</translation>
 <translation id="6542902059648396432">Een probleem melden…</translation>
-<translation id="6583902294974160967">Ondersteuning</translation>
+<translation id="6583902294974160967">Support</translation>
 <translation id="6612717000975622067">Ctrl-Alt-Del verzenden</translation>
 <translation id="6654753848497929428">Delen</translation>
 <translation id="6681800064886881394">Copyright 2013 Google Inc. Alle rechten voorbehouden.</translation>
@@ -125,7 +125,7 @@
 <translation id="6965382102122355670">OK</translation>
 <translation id="6985691951107243942">Weet je zeker dat je externe verbindingen met <ph name="HOSTNAME" /> wilt uitschakelen? Als je van gedachten verandert, moet je naar die computer gaan om de verbindingen weer in te schakelen.</translation>
 <translation id="7019153418965365059">Onbekende hostfout: <ph name="HOST_OFFLINE_REASON" />.</translation>
-<translation id="701976023053394610">Externe ondersteuning</translation>
+<translation id="701976023053394610">Externe support</translation>
 <translation id="7026930240735156896">Volg de instructies om je computer in te stellen voor externe toegang</translation>
 <translation id="7067321367069083429">Scherm werkt als een touchscreen</translation>
 <translation id="7116737094673640201">Welkom bij Chrome Remote Desktop</translation>
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index f0785ca..e3b74edb 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -110,6 +110,8 @@
     "web_sandbox_flags.h",
     "wrapper_shared_url_loader_factory.cc",
     "wrapper_shared_url_loader_factory.h",
+    "x_frame_options_parser.cc",
+    "x_frame_options_parser.h",
   ]
 
   if (!is_ios) {
@@ -344,6 +346,7 @@
     "supports_loading_mode/supports_loading_mode_parser_unittest.cc",
     "url_request_mojom_traits_unittest.cc",
     "web_sandbox_flags_unittests.cc",
+    "x_frame_options_parser_unittest.cc",
   ]
 
   if (!is_ios) {
@@ -367,6 +370,12 @@
   public_deps = [ ":buildflags" ]
 }
 
+fuzzer_test("xfo_fuzzer") {
+  sources = [ "x_frame_options_parser_fuzzer.cc" ]
+  dict = "x_frame_options.dict"
+  deps = [ ":cpp" ]
+}
+
 fuzzer_test("cors_fuzzer") {
   sources = [ "cors/cors_fuzzer.cc" ]
   deps = [ ":cpp" ]
diff --git a/services/network/public/cpp/parsed_headers.cc b/services/network/public/cpp/parsed_headers.cc
index 6b62d5ea..ab8097e 100644
--- a/services/network/public/cpp/parsed_headers.cc
+++ b/services/network/public/cpp/parsed_headers.cc
@@ -11,6 +11,7 @@
 #include "services/network/public/cpp/cross_origin_opener_policy_parser.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/origin_isolation_parser.h"
+#include "services/network/public/cpp/x_frame_options_parser.h"
 
 namespace network {
 
@@ -49,6 +50,8 @@
   if (headers->GetNormalizedHeader("Critical-CH", &critical_ch))
     parsed_headers->critical_ch = ParseClientHintsHeader(critical_ch);
 
+  parsed_headers->xfo = ParseXFrameOptions(*headers);
+
   return parsed_headers;
 }
 
diff --git a/services/network/public/cpp/x_frame_options.dict b/services/network/public/cpp/x_frame_options.dict
new file mode 100644
index 0000000..444b177
--- /dev/null
+++ b/services/network/public/cpp/x_frame_options.dict
@@ -0,0 +1,11 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+" "
+","
+"DENY"
+"SAMEORIGIN"
+"ALLOWALL"
+"ALLOW-FROM"
+"https://www.example.com/"
diff --git a/services/network/public/cpp/x_frame_options_parser.cc b/services/network/public/cpp/x_frame_options_parser.cc
new file mode 100644
index 0000000..e288d20
--- /dev/null
+++ b/services/network/public/cpp/x_frame_options_parser.cc
@@ -0,0 +1,46 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/x_frame_options_parser.h"
+
+#include <string>
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "net/http/http_response_headers.h"
+#include "services/network/public/mojom/x_frame_options.mojom-shared.h"
+
+namespace network {
+
+mojom::XFrameOptionsValue ParseXFrameOptions(
+    const net::HttpResponseHeaders& headers) {
+  // Process the 'X-Frame-Options' header:
+  // https://html.spec.whatwg.org/multipage/browsing-the-web.html#the-x-frame-options-header
+  //
+  // Note that we do not support the 'ALLOW-FROM' value defined in RFC7034.
+  mojom::XFrameOptionsValue result = mojom::XFrameOptionsValue::kNone;
+  size_t iter = 0;
+  std::string value;
+  while (headers.EnumerateHeader(&iter, "x-frame-options", &value)) {
+    mojom::XFrameOptionsValue current = mojom::XFrameOptionsValue::kInvalid;
+
+    base::StringPiece trimmed =
+        base::TrimWhitespaceASCII(value, base::TRIM_ALL);
+
+    if (base::LowerCaseEqualsASCII(trimmed, "deny"))
+      current = mojom::XFrameOptionsValue::kDeny;
+    else if (base::LowerCaseEqualsASCII(trimmed, "allowall"))
+      current = mojom::XFrameOptionsValue::kAllowAll;
+    else if (base::LowerCaseEqualsASCII(trimmed, "sameorigin"))
+      current = mojom::XFrameOptionsValue::kSameOrigin;
+
+    if (result == mojom::XFrameOptionsValue::kNone)
+      result = current;
+    else if (result != current)
+      result = mojom::XFrameOptionsValue::kConflict;
+  }
+
+  return result;
+}
+
+}  // namespace network
diff --git a/services/network/public/cpp/x_frame_options_parser.h b/services/network/public/cpp/x_frame_options_parser.h
new file mode 100644
index 0000000..793c0651
--- /dev/null
+++ b/services/network/public/cpp/x_frame_options_parser.h
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_X_FRAME_OPTIONS_PARSER_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_X_FRAME_OPTIONS_PARSER_H_
+
+#include "base/component_export.h"
+#include "services/network/public/mojom/x_frame_options.mojom-forward.h"
+
+namespace net {
+class HttpResponseHeaders;
+}
+
+namespace network {
+
+COMPONENT_EXPORT(NETWORK_CPP)
+mojom::XFrameOptionsValue ParseXFrameOptions(const net::HttpResponseHeaders&);
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_PUBLIC_CPP_X_FRAME_OPTIONS_PARSER_H_
diff --git a/services/network/public/cpp/x_frame_options_parser_fuzzer.cc b/services/network/public/cpp/x_frame_options_parser_fuzzer.cc
new file mode 100644
index 0000000..234f673
--- /dev/null
+++ b/services/network/public/cpp/x_frame_options_parser_fuzzer.cc
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/x_frame_options_parser.h"
+
+#include <string>
+#include "net/http/http_response_headers.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  const std::string test_data(reinterpret_cast<const char*>(data), size);
+  std::string header_string("HTTP/1.1 200 OK\nX-Frame-Options: ");
+  header_string += test_data;
+  header_string += "\n\n";
+
+  std::replace(header_string.begin(), header_string.end(), '\n', '\0');
+  scoped_refptr<net::HttpResponseHeaders> headers =
+      new net::HttpResponseHeaders(header_string);
+
+  network::ParseXFrameOptions(*headers);
+  return 0;
+}
diff --git a/services/network/public/cpp/x_frame_options_parser_unittest.cc b/services/network/public/cpp/x_frame_options_parser_unittest.cc
new file mode 100644
index 0000000..bad0364
--- /dev/null
+++ b/services/network/public/cpp/x_frame_options_parser_unittest.cc
@@ -0,0 +1,81 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/public/cpp/x_frame_options_parser.h"
+
+#include <string>
+#include "net/http/http_response_headers.h"
+#include "services/network/public/mojom/x_frame_options.mojom-shared.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+net::HttpResponseHeaders* ConstructHeader(const char* value) {
+  std::string header_string("HTTP/1.1 200 OK");
+  if (value) {
+    header_string += "\nX-Frame-Options: ";
+    header_string += value;
+  }
+  header_string += "\n\n";
+
+  std::replace(header_string.begin(), header_string.end(), '\n', '\0');
+  net::HttpResponseHeaders* headers =
+      new net::HttpResponseHeaders(header_string);
+
+  return headers;
+}
+
+}  // namespace
+
+namespace network {
+
+TEST(XFrameOptionsTest, Parse) {
+  struct TestCase {
+    const char* header;
+    mojom::XFrameOptionsValue expected;
+  } cases[] = {
+      // Single values:
+      {nullptr, mojom::XFrameOptionsValue::kNone},
+      {"DENY", mojom::XFrameOptionsValue::kDeny},
+      {"SAMEORIGIN", mojom::XFrameOptionsValue::kSameOrigin},
+      {"ALLOWALL", mojom::XFrameOptionsValue::kAllowAll},
+      {"NOT-A-VALUE", mojom::XFrameOptionsValue::kInvalid},
+      {"DeNy", mojom::XFrameOptionsValue::kDeny},
+      {"SaMeOrIgIn", mojom::XFrameOptionsValue::kSameOrigin},
+      {"AllOWaLL", mojom::XFrameOptionsValue::kAllowAll},
+
+      // Repeated values:
+      {"DENY,DENY", mojom::XFrameOptionsValue::kDeny},
+      {"SAMEORIGIN,SAMEORIGIN", mojom::XFrameOptionsValue::kSameOrigin},
+      {"ALLOWALL,ALLOWALL", mojom::XFrameOptionsValue::kAllowAll},
+      {"DENY,DeNy", mojom::XFrameOptionsValue::kDeny},
+      {"SAMEORIGIN,SaMeOrIgIn", mojom::XFrameOptionsValue::kSameOrigin},
+      {"ALLOWALL,AllOWaLL", mojom::XFrameOptionsValue::kAllowAll},
+      {"INVALID,INVALID", mojom::XFrameOptionsValue::kInvalid},
+      {"INVALID,DIFFERENTLY-INVALID", mojom::XFrameOptionsValue::kInvalid},
+
+      // Conflicting values:
+      {"ALLOWALL,DENY", mojom::XFrameOptionsValue::kConflict},
+      {"ALLOWALL,SAMEORIGIN", mojom::XFrameOptionsValue::kConflict},
+      {"ALLOWALL,INVALID", mojom::XFrameOptionsValue::kConflict},
+      {"DENY,ALLOWALL", mojom::XFrameOptionsValue::kConflict},
+      {"DENY,SAMEORIGIN", mojom::XFrameOptionsValue::kConflict},
+      {"DENY,INVALID", mojom::XFrameOptionsValue::kConflict},
+      {"SAMEORIGIN,ALLOWALL", mojom::XFrameOptionsValue::kConflict},
+      {"SAMEORIGIN,DENY", mojom::XFrameOptionsValue::kConflict},
+      {"SAMEORIGIN,INVALID", mojom::XFrameOptionsValue::kConflict},
+      {"INVALID,DENY", mojom::XFrameOptionsValue::kConflict},
+      {"INVALID,SAMEORIGIN", mojom::XFrameOptionsValue::kConflict},
+      {"INVALID,ALLOWALL", mojom::XFrameOptionsValue::kConflict},
+  };
+
+  for (const auto& test : cases) {
+    SCOPED_TRACE(test.header);
+    scoped_refptr<net::HttpResponseHeaders> headers =
+        ConstructHeader(test.header);
+    EXPECT_EQ(test.expected, ParseXFrameOptions(*headers));
+  }
+}
+
+}  // namespace network
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn
index 5de301a5..f49d2d4 100644
--- a/services/network/public/mojom/BUILD.gn
+++ b/services/network/public/mojom/BUILD.gn
@@ -515,6 +515,7 @@
     "url_response_head.mojom",
     "web_client_hints_types.mojom",
     "web_sandbox_flags.mojom",
+    "x_frame_options.mojom",
   ]
 
   public_deps = [
diff --git a/services/network/public/mojom/parsed_headers.mojom b/services/network/public/mojom/parsed_headers.mojom
index 6bba67b..a98545f 100644
--- a/services/network/public/mojom/parsed_headers.mojom
+++ b/services/network/public/mojom/parsed_headers.mojom
@@ -9,6 +9,7 @@
 import "services/network/public/mojom/cross_origin_embedder_policy.mojom";
 import "services/network/public/mojom/cross_origin_opener_policy.mojom";
 import "services/network/public/mojom/web_client_hints_types.mojom";
+import "services/network/public/mojom/x_frame_options.mojom";
 
 // Holds the parsed representation of several security related HTTP headers.
 // This struct should only be populated by network::PopulateParsedHeaders()
@@ -62,4 +63,7 @@
   // For more information, see:
   // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability#section-3
   array<WebClientHintsType>? critical_ch;
+
+  // The parsed value of the X-Frame-Options header.
+  XFrameOptionsValue xfo = XFrameOptionsValue.kNone;
 };
diff --git a/services/network/public/mojom/x_frame_options.mojom b/services/network/public/mojom/x_frame_options.mojom
new file mode 100644
index 0000000..9eaa02e
--- /dev/null
+++ b/services/network/public/mojom/x_frame_options.mojom
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module network.mojom;
+
+// This enum represents the possible values for the X-Frame-Options header:
+// https://html.spec.whatwg.org/multipage/browsing-the-web.html#the-x-frame-options-header.
+enum XFrameOptionsValue {
+  kNone,       // No XFO header is present.
+  kDeny,       // XFO: DENY
+  kSameOrigin, // XFO: SAMEORIGIN
+  kAllowAll,   // XFO: ALLOWALL
+  kInvalid,    // XFO: [anything other than DENY, SAMEORIGIN, or ALLOWALL]
+  kConflict    // Multiple XFO headers are present, with distinct values.
+};
diff --git a/services/network/trust_tokens/trust_token_key_commitment_parser.cc b/services/network/trust_tokens/trust_token_key_commitment_parser.cc
index 652cbc34..debb106f 100644
--- a/services/network/trust_tokens/trust_token_key_commitment_parser.cc
+++ b/services/network/trust_tokens/trust_token_key_commitment_parser.cc
@@ -242,31 +242,6 @@
 
 }  // namespace
 
-// https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#bookmark=id.6wh9crbxdizi
-// {
-//   "protocol_version" : ..., // Protocol Version; value of type string.
-//   "id" : ...,               // ID; value of type int.
-//   "batchsize" : ...,        // Batch size; value of type int.
-//
-//   // Optional operating systems on which to request issuance via system
-//   // mediation (valid values are: "android"), and (required if at least one
-//   // OS is specified) fallback behavior on other operating systems:
-//   "request_issuance_locally_on": [<os 1>, ..., <os N>],
-//   "unavailable_local_issuance_fallback": "web_issuance" | "return_with_error"
-//
-//   "1" : {                   // Key label, a number in uint32_t range; ignored
-//                             // except for checking that it is present and
-//                             // type-safe.
-//     "Y" : ...,              // Required token issuance verification key, in
-//                             // base64.
-//     "expiry" : ...,         // Required token issuance key expiry time, in
-//                             // microseconds since the Unix epoch.
-//   },
-//   "17" : {                  // No guarantee that key labels (1, 7) are dense.
-//     "Y" : ...,
-//     "expiry" : ...,
-//   }
-// }
 mojom::TrustTokenKeyCommitmentResultPtr TrustTokenKeyCommitmentParser::Parse(
     base::StringPiece response_body) {
   base::Optional<base::Value> maybe_value =
diff --git a/services/network/trust_tokens/trust_token_key_commitment_parser.h b/services/network/trust_tokens/trust_token_key_commitment_parser.h
index 2562daca..72adf18 100644
--- a/services/network/trust_tokens/trust_token_key_commitment_parser.h
+++ b/services/network/trust_tokens/trust_token_key_commitment_parser.h
@@ -41,6 +41,10 @@
 extern const char kTrustTokenLocalIssuanceFallbackWebIssuance[];
 extern const char kTrustTokenLocalIssuanceFallbackReturnWithError[];
 
+// WARNING WARNING WARNING: When updating the parser implementation, please make
+// sure the normative source(s) of the key commitment result data structure's
+// format (as of writing, the design doc and perhaps ISSUER_PROTOCOL.md in the
+// WICG repository) have been updated to reflect the change.
 class TrustTokenKeyCommitmentParser
     : public TrustTokenKeyCommitmentController::Parser {
  public:
diff --git a/services/network/trust_tokens/trust_token_request_signing_helper.h b/services/network/trust_tokens/trust_token_request_signing_helper.h
index fcf37a2..afb632d8 100644
--- a/services/network/trust_tokens/trust_token_request_signing_helper.h
+++ b/services/network/trust_tokens/trust_token_request_signing_helper.h
@@ -68,6 +68,10 @@
   // request's canonical representation. This allows rendering otherwise valid
   // signatures forwards-incompatible, which is useful in case the signing
   // data's semantics change across protocol versions but its syntax does not.
+  //
+  // NOTE: When changing this constant, please make sure it stays in sync with
+  // the normative source of the domain separator's value (currently the design
+  // doc).
   static constexpr uint8_t kRequestSigningDomainSeparator[] = {
       'T', 'r', 'u', 's', 't', 'T', 'o', 'k', 'e', 'n', 'V', '2'};
 
diff --git a/testing/android/native_test/java/AndroidManifest.xml.jinja2 b/testing/android/native_test/java/AndroidManifest.xml.jinja2
index 96780ec..cca3ca5 100644
--- a/testing/android/native_test/java/AndroidManifest.xml.jinja2
+++ b/testing/android/native_test/java/AndroidManifest.xml.jinja2
@@ -22,7 +22,13 @@
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 
+    <!-- Explicitly set the attribute requestLegacyExternalStorage to "true"
+         since it is "false" by default on apps targeting Android 10, and that
+         breaks test listing. See
+         https://developer.android.com/training/data-storage#scoped-storage and
+         https://developer.android.com/training/data-storage/compatibility. -->
     <application android:label="NativeTests"
+            android:requestLegacyExternalStorage="true"
             android:name="org.chromium.native_test.NativeTestApplication">
         <uses-library android:name="android.test.runner"/>
         {% if use_native_activity == 'true' %}
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 45814cba..8998ef6 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -8016,6 +8016,25 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
@@ -9817,6 +9836,25 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
@@ -11633,6 +11671,25 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
@@ -13425,6 +13482,25 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
@@ -15217,6 +15293,25 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index d1fc73a..b8de02d 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -2590,6 +2590,23 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
@@ -4257,6 +4274,24 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index da24421..805ee5ef 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -10363,6 +10363,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10381,6 +10384,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10399,6 +10405,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10459,6 +10468,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10511,6 +10523,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10530,6 +10545,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10553,6 +10571,9 @@
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
         "name": "gl_tests_validating",
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10571,6 +10592,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10589,6 +10613,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10607,6 +10634,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10667,6 +10697,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -10686,6 +10719,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11086,6 +11122,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11104,6 +11143,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11122,6 +11164,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11182,6 +11227,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11234,6 +11282,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11253,6 +11304,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11276,6 +11330,9 @@
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
         "name": "gl_tests_validating",
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11294,6 +11351,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11312,6 +11372,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11330,6 +11393,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11390,6 +11456,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11409,6 +11478,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11455,6 +11527,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11473,6 +11548,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11491,6 +11569,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11551,6 +11632,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11603,6 +11687,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11622,6 +11709,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11645,6 +11735,9 @@
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
         "name": "gl_tests_validating",
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11663,6 +11756,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11681,6 +11777,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11699,6 +11798,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11759,6 +11861,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -11778,6 +11883,9 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "resultdb": {
+          "enable": true
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -47363,6 +47471,24 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
@@ -55362,37 +55488,6 @@
       }
     ]
   },
-  "linux-wpt-payments-fyi-rel": {
-    "isolated_scripts": [
-      {
-        "args": [
-          "payment-handler/",
-          "payment-method-basic-card/",
-          "payment-method-id/",
-          "payment-request/"
-        ],
-        "isolate_name": "wpt_tests_isolate",
-        "merge": {
-          "args": [
-            "--verbose"
-          ],
-          "script": "//third_party/blink/tools/merge_web_test_results.py"
-        },
-        "name": "wpt_tests_suite",
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://:wpt_tests_isolate/"
-      }
-    ]
-  },
   "mac-arm64-rel-tests": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 6689b563..8003d49d 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -10785,6 +10785,7 @@
           "--xctest"
         ],
         "isolate_name": "absl_hardening_tests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10827,6 +10828,7 @@
           "--xctest"
         ],
         "isolate_name": "absl_hardening_tests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10869,6 +10871,7 @@
           "--xctest"
         ],
         "isolate_name": "base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10911,6 +10914,7 @@
           "--xctest"
         ],
         "isolate_name": "base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10953,6 +10957,7 @@
           "--xctest"
         ],
         "isolate_name": "base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -10995,6 +11000,7 @@
           "--xctest"
         ],
         "isolate_name": "base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11037,6 +11043,7 @@
           "--xctest"
         ],
         "isolate_name": "base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11079,6 +11086,7 @@
           "--xctest"
         ],
         "isolate_name": "base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11121,6 +11129,7 @@
           "--xctest"
         ],
         "isolate_name": "base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11163,6 +11172,7 @@
           "--xctest"
         ],
         "isolate_name": "base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11205,6 +11215,7 @@
           "--xctest"
         ],
         "isolate_name": "boringssl_crypto_tests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11247,6 +11258,7 @@
           "--xctest"
         ],
         "isolate_name": "boringssl_crypto_tests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11289,6 +11301,7 @@
           "--xctest"
         ],
         "isolate_name": "boringssl_ssl_tests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11331,6 +11344,7 @@
           "--xctest"
         ],
         "isolate_name": "boringssl_ssl_tests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11373,6 +11387,7 @@
           "--xctest"
         ],
         "isolate_name": "components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11415,6 +11430,7 @@
           "--xctest"
         ],
         "isolate_name": "components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11457,6 +11473,7 @@
           "--xctest"
         ],
         "isolate_name": "components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11499,6 +11516,7 @@
           "--xctest"
         ],
         "isolate_name": "components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11541,6 +11559,7 @@
           "--xctest"
         ],
         "isolate_name": "components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11583,6 +11602,7 @@
           "--xctest"
         ],
         "isolate_name": "components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11625,6 +11645,7 @@
           "--xctest"
         ],
         "isolate_name": "components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11667,6 +11688,7 @@
           "--xctest"
         ],
         "isolate_name": "components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11709,6 +11731,7 @@
           "--xctest"
         ],
         "isolate_name": "crypto_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11751,6 +11774,7 @@
           "--xctest"
         ],
         "isolate_name": "crypto_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11793,6 +11817,7 @@
           "--xctest"
         ],
         "isolate_name": "gfx_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11835,6 +11860,7 @@
           "--xctest"
         ],
         "isolate_name": "gfx_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11877,6 +11903,7 @@
           "--xctest"
         ],
         "isolate_name": "gfx_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11919,6 +11946,7 @@
           "--xctest"
         ],
         "isolate_name": "gfx_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -11961,6 +11989,7 @@
           "--xctest"
         ],
         "isolate_name": "gfx_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12003,6 +12032,7 @@
           "--xctest"
         ],
         "isolate_name": "gfx_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12045,6 +12075,7 @@
           "--xctest"
         ],
         "isolate_name": "gfx_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12087,6 +12118,7 @@
           "--xctest"
         ],
         "isolate_name": "gfx_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12129,6 +12161,7 @@
           "--xctest"
         ],
         "isolate_name": "google_apis_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12171,6 +12204,7 @@
           "--xctest"
         ],
         "isolate_name": "google_apis_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12214,6 +12248,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12258,6 +12293,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12302,6 +12338,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12345,6 +12382,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12388,6 +12426,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12432,6 +12471,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12475,6 +12515,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_chrome_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12517,6 +12558,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_chrome_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12559,6 +12601,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_chrome_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12601,6 +12644,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_chrome_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12643,6 +12687,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_chrome_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12685,6 +12730,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_chrome_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12727,6 +12773,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_chrome_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12769,6 +12816,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_chrome_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12811,6 +12859,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12853,6 +12902,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_components_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12895,6 +12945,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_net_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12937,6 +12988,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_net_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -12979,6 +13031,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_remoting_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13021,6 +13074,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_remoting_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13063,6 +13117,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_testing_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13105,6 +13160,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_testing_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13147,6 +13203,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13189,6 +13246,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13231,6 +13289,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13273,6 +13332,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13315,6 +13375,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13357,6 +13418,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13399,6 +13461,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13441,6 +13504,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13484,6 +13548,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13527,6 +13592,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13569,6 +13635,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13611,6 +13678,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13653,6 +13721,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13695,6 +13764,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13737,6 +13807,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13779,6 +13850,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13821,6 +13893,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13863,6 +13936,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13905,6 +13979,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13947,6 +14022,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -13989,6 +14065,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14031,6 +14108,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14073,6 +14151,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14115,6 +14194,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14157,6 +14237,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14199,6 +14280,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_inttests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14241,6 +14323,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14283,6 +14366,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14325,6 +14409,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14367,6 +14452,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14409,6 +14495,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14451,6 +14538,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14493,6 +14581,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14535,6 +14624,7 @@
           "--xctest"
         ],
         "isolate_name": "ios_web_view_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14577,6 +14667,7 @@
           "--xctest"
         ],
         "isolate_name": "net_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14619,6 +14710,7 @@
           "--xctest"
         ],
         "isolate_name": "net_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14661,6 +14753,7 @@
           "--xctest"
         ],
         "isolate_name": "services_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14703,6 +14796,7 @@
           "--xctest"
         ],
         "isolate_name": "services_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14745,6 +14839,7 @@
           "--xctest"
         ],
         "isolate_name": "skia_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14787,6 +14882,7 @@
           "--xctest"
         ],
         "isolate_name": "skia_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14829,6 +14925,7 @@
           "--xctest"
         ],
         "isolate_name": "skia_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14871,6 +14968,7 @@
           "--xctest"
         ],
         "isolate_name": "skia_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14913,6 +15011,7 @@
           "--xctest"
         ],
         "isolate_name": "skia_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14955,6 +15054,7 @@
           "--xctest"
         ],
         "isolate_name": "skia_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -14997,6 +15097,7 @@
           "--xctest"
         ],
         "isolate_name": "skia_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15039,6 +15140,7 @@
           "--xctest"
         ],
         "isolate_name": "skia_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15081,6 +15183,7 @@
           "--xctest"
         ],
         "isolate_name": "sql_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15123,6 +15226,7 @@
           "--xctest"
         ],
         "isolate_name": "sql_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15165,6 +15269,7 @@
           "--xctest"
         ],
         "isolate_name": "ui_base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15207,6 +15312,7 @@
           "--xctest"
         ],
         "isolate_name": "ui_base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15249,6 +15355,7 @@
           "--xctest"
         ],
         "isolate_name": "ui_base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15291,6 +15398,7 @@
           "--xctest"
         ],
         "isolate_name": "ui_base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15333,6 +15441,7 @@
           "--xctest"
         ],
         "isolate_name": "ui_base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15375,6 +15484,7 @@
           "--xctest"
         ],
         "isolate_name": "ui_base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15417,6 +15527,7 @@
           "--xctest"
         ],
         "isolate_name": "ui_base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15459,6 +15570,7 @@
           "--xctest"
         ],
         "isolate_name": "ui_base_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15501,6 +15613,7 @@
           "--xctest"
         ],
         "isolate_name": "url_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15543,6 +15656,7 @@
           "--xctest"
         ],
         "isolate_name": "url_unittests",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15593,6 +15707,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15636,6 +15751,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15679,6 +15795,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15722,6 +15839,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15765,6 +15883,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15808,6 +15927,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15851,6 +15971,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15895,6 +16016,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15939,6 +16061,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -15983,6 +16106,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16027,6 +16151,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16071,6 +16196,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16115,6 +16241,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16159,6 +16286,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16203,6 +16331,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16247,6 +16376,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16291,6 +16421,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16334,6 +16465,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16377,6 +16509,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16420,6 +16553,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16463,6 +16597,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16506,6 +16641,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16549,6 +16685,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16592,6 +16729,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16635,6 +16773,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16678,6 +16817,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16721,6 +16861,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16765,6 +16906,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16809,6 +16951,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16853,6 +16996,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16897,6 +17041,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16940,6 +17085,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -16983,6 +17129,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17026,6 +17173,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17069,6 +17217,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17112,6 +17261,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17155,6 +17305,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17198,6 +17349,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17241,6 +17393,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17284,6 +17437,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17327,6 +17481,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17370,6 +17525,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17413,6 +17569,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17456,6 +17613,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17499,6 +17657,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -17542,6 +17701,7 @@
           "--xcode-parallelization"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
+        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 32d6d91..36b110a7 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -8331,6 +8331,26 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "args": [
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
@@ -10268,6 +10288,27 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "shell_encryption_unittests",
+        "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/"
+      },
+      {
+        "args": [
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "skia_unittests",
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 27aea84..0a06d1f1 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -674,7 +674,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "device_os": "QD4A.200102.001.A1",
+              "device_os": "RQ1D.201205.012",
               "device_os_flavor": "google",
               "device_type": "sunfish",
               "os": "Android",
diff --git a/testing/buildbot/filters/android.emulator_m.chrome_public_test_apk.filter b/testing/buildbot/filters/android.emulator_m.chrome_public_test_apk.filter
index aeb30df..66131eee 100644
--- a/testing/buildbot/filters/android.emulator_m.chrome_public_test_apk.filter
+++ b/testing/buildbot/filters/android.emulator_m.chrome_public_test_apk.filter
@@ -85,4 +85,5 @@
 -org.chromium.chrome.features.start_surface.StartSurfaceLayoutTest.testShowOnlyOneTabSuggestionMessageCard_withHardCleanup
 
 # crbug.com/1146477
+-org.chromium.chrome.browser.autofill.AutofillUpstreamTest.testSaveCardInfoBarWithEmptyMonth
 -org.chromium.chrome.browser.autofill.AutofillUpstreamTest.testSaveCardInfoBarWithEmptyMonthAndYear
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 09565e1a..f026e30 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -822,7 +822,7 @@
     "type": "additional_compile_target",
   },
   "errorprone_plugin_tests": {
-    "label": "//tools/android/errorprone_plugin:errorprone_plugin_tests",
+    "label": "//tools/android/errorprone_plugin/test:errorprone_plugin_tests",
     "type": "additional_compile_target",
   },
   "events_unittests": {
@@ -1554,6 +1554,10 @@
     "label": "//chrome/installer/setup:setup_unittests",
     "type": "console_test_launcher",
   },
+  "shell_encryption_unittests": {
+    "label": "//third_party/shell-encryption:shell_encryption_unittests",
+    "type": "console_test_launcher",
+  },
   "shell_dialogs_unittests": {
     "label": "//ui/shell_dialogs:shell_dialogs_unittests",
     "type": "console_test_launcher",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 3af80154..065062d 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3783,6 +3783,7 @@
       },
       'ozone_unittests': {},
       'ozone_x11_unittests': {},
+      'shell_encryption_unittests': {},
       'ui_chromeos_unittests': {},
       'usage_time_limit_unittests': {
         'experiment_percentage': 100,
@@ -5033,28 +5034,6 @@
         },
       },
     },
-
-    'wpt_web_tests_payments': {
-      'wpt_tests_suite': {
-        'args': [
-          'payment-handler/',
-          'payment-method-basic-card/',
-          'payment-method-id/',
-          'payment-request/',
-        ],
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'isolate_name': 'wpt_tests_isolate',
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 1,
-        },
-      },
-    },
   },
 
   ##############################################################################
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index ad2c90d..5e4553e 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2768,14 +2768,6 @@
           'isolated_scripts': 'wpt_web_tests_input',
         },
       },
-      'linux-wpt-payments-fyi-rel': {
-        'mixins': [
-          'linux-xenial',
-        ],
-        'test_suites': {
-          'isolated_scripts': 'wpt_web_tests_payments',
-        },
-      },
       'mac-arm64-rel-tests': {
         'mixins': [
             'mac_arm64_apple_dtk_experimental',
@@ -4923,6 +4915,7 @@
           'all',
         ],
         'mixins': [
+          'isolate_profile_data',
           'mac_10.15',
           'mac_toolchain',
           'out_dir_arg',
@@ -4938,6 +4931,7 @@
           'all'
         ],
         'mixins': [
+          'isolate_profile_data',
           'mac_10.15',
           'mac_toolchain',
           'out_dir_arg',
diff --git a/testing/scripts/wpt_common.py b/testing/scripts/wpt_common.py
index 2cbcddc..2d7794d 100644
--- a/testing/scripts/wpt_common.py
+++ b/testing/scripts/wpt_common.py
@@ -96,8 +96,9 @@
         self.fs.write_text_file(self.wpt_output,
                                 json.dumps(output_json))
 
-    def _handle_log_artifact(self, log_artifact, root_node, results_dir,
+    def _handle_text_outputs(self, actual_metadata, root_node, results_dir,
                              path_so_far):
+        """Produces actual, expected and diff text outputs."""
         # If the test passed, there are no artifacts to output. Note that if a
         # baseline file (*.ini file) exists, an actual of PASS means that the
         # test matched the baseline, not that the test itself passed. As such,
@@ -106,9 +107,9 @@
         if root_node["actual"] == "PASS":
             return
 
-        # Note that the log_artifact is a list of strings, so we join
+        # Note that the actual_metadata is a list of strings, so we join
         # them on new lines when writing to file.
-        actual_text = "\n".join(log_artifact)
+        actual_text = "\n".join(actual_metadata)
         actual_subpath = self._write_text_artifact(
             test_failures.FILENAME_SUFFIX_ACTUAL,
             results_dir, path_so_far, actual_text)
@@ -157,21 +158,33 @@
             # Found a leaf, process it
             if "artifacts" not in root_node:
                 return
-            log_artifact = root_node["artifacts"].pop("log", None)
-            if log_artifact:
-                self._handle_log_artifact(log_artifact, root_node, results_dir,
-                                          path_so_far)
 
-            screenshot_artifact = root_node["artifacts"].pop("screenshots",
-                                                             None)
+            actual_metadata = root_node["artifacts"].pop(
+                "wpt_actual_metadata", None)
+            if actual_metadata:
+                self._handle_text_outputs(
+                    actual_metadata, root_node, results_dir, path_so_far)
+
+            screenshot_artifact = root_node["artifacts"].pop(
+                "screenshots", None)
             if screenshot_artifact:
                 screenshot_paths_dict = self._write_screenshot_artifact(
                     results_dir, path_so_far, screenshot_artifact)
                 for screenshot_key, path in screenshot_paths_dict.items():
                     root_node["artifacts"][screenshot_key] = [path]
 
-            crashlog_artifact = root_node["artifacts"].pop("wpt_crash_log",
-                                                           None)
+            log_artifact = root_node["artifacts"].pop("wpt_log", None)
+            if log_artifact:
+                artifact_subpath = self._write_text_artifact(
+                    test_failures.FILENAME_SUFFIX_STDERR,
+                    results_dir, path_so_far, "\n".join(log_artifact))
+                if artifact_subpath:
+                    # Required by fast/harness/results.html to show stderr.
+                    root_node["has_stderr"] = True
+                    root_node["artifacts"]["stderr"] = [artifact_subpath]
+
+            crashlog_artifact = root_node["artifacts"].pop(
+                "wpt_crash_log", None)
             if crashlog_artifact:
                 # Note that the crashlog_artifact is a list of strings, so we
                 # join them on new lines when writing to file.
diff --git a/testing/scripts/wpt_common_unittest.py b/testing/scripts/wpt_common_unittest.py
index b245d834..263b74f 100755
--- a/testing/scripts/wpt_common_unittest.py
+++ b/testing/scripts/wpt_common_unittest.py
@@ -81,8 +81,8 @@
         return json.loads(self.host.filesystem.read_text_file(
             OUTPUT_JSON_FILENAME))
 
-    def test_write_log_artifact(self):
-        # Ensure that log artifacts are written to the correct location.
+    def test_write_text_outputs(self):
+        # Ensure that text outputs are written to the correct location.
 
         # We only generate an actual.txt if our actual wasn't PASS, so in this
         # case we shouldn't write anything.
@@ -93,7 +93,7 @@
                     'actual': 'PASS',
                     'artifacts': {
                         'wpt_actual_status': ['OK'],
-                        'log': ['test.html actual text'],
+                        'wpt_actual_metadata': ['test.html actual text'],
                     },
                 },
             },
@@ -121,8 +121,8 @@
         # Ensure the artifact in the json was replaced with the location of
         # the newly-created file.
         updated_json = self._load_json_output()
-        self.assertFalse(
-            "log" in updated_json["tests"]["test.html"]["artifacts"])
+        self.assertFalse("wpt_actual_metadata" in
+                         updated_json["tests"]["test.html"]["artifacts"])
         self.assertEqual(
             [actual_path],
             updated_json["tests"]["test.html"]["artifacts"]["actual_text"])
@@ -142,6 +142,36 @@
             [pretty_diff_path],
             updated_json["tests"]["test.html"]["artifacts"]["pretty_text_diff"])
 
+    def test_write_log_artifact(self):
+        # Ensure that crash log artifacts are written to the correct location.
+        json_dict = {
+            'tests': {
+                'test.html': {
+                    'expected': 'PASS',
+                    'actual': 'FAIL',
+                    'artifacts': {
+                        'wpt_actual_status': ['ERROR'],
+                        'wpt_log': ['test.html exceptions'],
+                    },
+                },
+            },
+            'path_delimiter': '/',
+        }
+        self._create_json_output(json_dict)
+        self.wpt_adapter.do_post_test_run_tasks()
+        written_files = self.wpt_adapter.fs.written_files
+        stderr_path = os.path.join("layout-test-results", "test-stderr.txt")
+        self.assertEqual("test.html exceptions", written_files[stderr_path])
+        # Ensure the artifact in the json was replaced with the location of
+        # the newly-created file.
+        updated_json = self._load_json_output()
+        self.assertFalse(
+            "wpt_log" in updated_json["tests"]["test.html"]["artifacts"])
+        self.assertEqual(
+            [stderr_path],
+            updated_json["tests"]["test.html"]["artifacts"]["stderr"])
+        self.assertTrue(updated_json["tests"]["test.html"]["has_stderr"])
+
     def test_write_crashlog_artifact(self):
         # Ensure that crash log artifacts are written to the correct location.
         json_dict = {
@@ -225,7 +255,7 @@
                     'actual': 'FAIL',
                     'artifacts': {
                         'wpt_actual_status': ['OK'],
-                        'log': ['test.html actual text'],
+                        'wpt_actual_metadata': ['test.html actual text'],
                     },
                 },
             },
@@ -247,8 +277,8 @@
         # Ensure the artifacts in the json were replaced with the locations of
         # the newly-created files.
         updated_json = self._load_json_output()
-        self.assertFalse(
-            "log" in updated_json["tests"]["test.html"]["artifacts"])
+        self.assertFalse("wpt_actual_metadata" in
+                         updated_json["tests"]["test.html"]["artifacts"])
         self.assertEqual(
             [actual_path],
             updated_json["tests"]["test.html"]["artifacts"]["actual_text"])
@@ -289,7 +319,7 @@
                     'actual': 'FAIL',
                     'artifacts': {
                         'wpt_actual_status': ['OK'],
-                        'log': ['variant bar/abc actual text'],
+                        'wpt_actual_metadata': ['variant bar/abc actual text'],
                     },
                 },
             },
@@ -316,7 +346,7 @@
         # Ensure the artifacts in the json were replaced with the locations of
         # the newly-created files.
         updated_json = self._load_json_output()
-        self.assertFalse("log" in updated_json["tests"]
+        self.assertFalse("wpt_actual_metadata" in updated_json["tests"]
                          ["variant.html?foo=bar/abc"]["artifacts"])
         self.assertEqual(
             [actual_path],
@@ -343,7 +373,8 @@
                     'actual': 'FAIL',
                     'artifacts': {
                         'wpt_actual_status': ['OK'],
-                        'log': ['dir/multiglob worker actual text'],
+                        'wpt_actual_metadata':
+                        ['dir/multiglob worker actual text'],
                     },
                 },
             },
@@ -372,8 +403,8 @@
         # Ensure the artifacts in the json were replaced with the locations of
         # the newly-created files.
         updated_json = self._load_json_output()
-        self.assertFalse("log" in updated_json["tests"]
-            ["dir/multiglob.https.any.worker.html"]["artifacts"])
+        self.assertFalse("wpt_actual_metadata" in updated_json["tests"]
+                         ["dir/multiglob.https.any.worker.html"]["artifacts"])
         self.assertEqual(
             [actual_path],
             updated_json["tests"]["dir/multiglob.https.any.worker.html"]
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 356eb02..2d72c09d 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3536,21 +3536,6 @@
             ]
         }
     ],
-    "IOSWebContentDropInteraction": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AddWebContentDropInteraction"
-                    ]
-                }
-            ]
-        }
-    ],
     "Identifiability": [
         {
             "platforms": [
@@ -4840,6 +4825,9 @@
             "experiments": [
                 {
                     "name": "Enabled ",
+                    "params": {
+                        "DisplayOwner": "true"
+                    },
                     "enable_features": [
                         "OmniboxDocumentProvider"
                     ]
@@ -5392,6 +5380,24 @@
             ]
         }
     ],
+    "PermissionChip": [
+        {
+            "platforms": [
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "PermissionChip"
+                    ]
+                }
+            ]
+        }
+    ],
     "PermissionPromptUICocoa": [
         {
             "platforms": [
diff --git a/third_party/.gitignore b/third_party/.gitignore
index d445b20..e789259 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -265,3 +265,5 @@
 /xstream/lib/
 /xulrunner-sdk
 /zstd
+/zstd-linux-arm64
+/zstd-linux-x64
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index e43c2f46..146e41c 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -95,6 +95,7 @@
     "platform/scheduler/test/renderer_scheduler_test_support.h",
     "platform/scheduler/test/web_fake_thread_scheduler.h",
     "platform/scheduler/test/web_mock_thread_scheduler.h",
+    "test/frame_widget_test_helper.h",
   ]
   public_deps = [ ":blink_headers" ]
   deps = [
diff --git a/third_party/blink/public/DEPS b/third_party/blink/public/DEPS
index c5bade2..901d1a50 100644
--- a/third_party/blink/public/DEPS
+++ b/third_party/blink/public/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+    "+base/types/pass_key.h",
     "+base/unguessable_token.h",
     "-third_party/blink/renderer/bindings",
     "-third_party/blink/renderer/core",
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index dec840a..5422f60d 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -48,6 +48,7 @@
     "credentialmanager/credential_manager.mojom",
     "css/preferred_color_scheme.mojom",
     "css/preferred_contrast.mojom",
+    "device/device.mojom",
     "devtools/console_message.mojom",
     "devtools/devtools_agent.mojom",
     "devtools/devtools_frontend.mojom",
diff --git a/third_party/blink/public/mojom/device/OWNERS b/third_party/blink/public/mojom/device/OWNERS
new file mode 100644
index 0000000..6b794ee
--- /dev/null
+++ b/third_party/blink/public/mojom/device/OWNERS
@@ -0,0 +1,5 @@
+# Device API owners.
+file://chrome/browser/device_api/OWNERS
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/device/device.mojom b/third_party/blink/public/mojom/device/device.mojom
new file mode 100644
index 0000000..2a869d1
--- /dev/null
+++ b/third_party/blink/public/mojom/device/device.mojom
@@ -0,0 +1,10 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+module blink.mojom;
+
+// This interface is used to handle the information / status passed by the
+// navigator.device interface. It is exposed to trusted applications only.
+interface DeviceAPIService {
+};
+
diff --git a/third_party/blink/public/mojom/input/synchronous_compositor.mojom b/third_party/blink/public/mojom/input/synchronous_compositor.mojom
index a1a266fb5..c0a5fa3 100644
--- a/third_party/blink/public/mojom/input/synchronous_compositor.mojom
+++ b/third_party/blink/public/mojom/input/synchronous_compositor.mojom
@@ -51,7 +51,8 @@
   // the associated SynchronousCompositorControlHost.
   DemandDrawHwAsync(SyncCompositorDemandDrawHwParams draw_params);
 
-  // Synchronously hardware draws.
+  // Same as |DemandDrawHwAsync| except it's synchronous and blocks the caller
+  // thread.
   [Sync]
   DemandDrawHw(SyncCompositorDemandDrawHwParams draw_params) =>
       (SyncCompositorCommonRendererParams result,
@@ -142,7 +143,7 @@
 // execution flow (from java) returns the responses from BeginFrames must be
 // received.
 interface SynchronousCompositorControlHost {
-  // Response from DrawHwAsync.
+  // Response from DemandDrawHwAsync.
   ReturnFrame(uint32 layer_tree_frame_sink_id,
               uint32 metadata_version,
               viz.mojom.LocalSurfaceId? local_surface_id,
diff --git a/third_party/blink/public/mojom/page/page.mojom b/third_party/blink/public/mojom/page/page.mojom
index 962bbb5..e122d4f 100644
--- a/third_party/blink/public/mojom/page/page.mojom
+++ b/third_party/blink/public/mojom/page/page.mojom
@@ -27,6 +27,12 @@
   PageVisibilityState visibility;
   bool is_in_back_forward_cache;
   PagehideDispatch pagehide_dispatch;
+  // Tells the renderer whether it is allowed to evict the page from the
+  // back-forward cache. This is set to false shortly before the page is
+  // taken out of the cache to make sure that evict requests from the renderer
+  // do not race with the restoration flow on the browser. For example, if set
+  // to true the renderer must not evict the page if javascript is executed.
+  bool eviction_enabled;
 };
 
 // Additional parameters to send with SetPageLifecycleState calls when we're
diff --git a/third_party/blink/public/platform/web_private_ptr.h b/third_party/blink/public/platform/web_private_ptr.h
index 099b9d2..780fdc4e 100644
--- a/third_party/blink/public/platform/web_private_ptr.h
+++ b/third_party/blink/public/platform/web_private_ptr.h
@@ -73,9 +73,8 @@
 template <typename T>
 struct LifetimeOf {
  private:
-  static const bool kIsGarbageCollected =
-      WTF::IsSubclassOfTemplate<T, GarbageCollected>::value ||
-      IsGarbageCollectedMixin<T>::value;
+  // Covers GarbageCollected and GarbageCollectedMixin.
+  static const bool kIsGarbageCollected = WTF::IsGarbageCollectedType<T>::value;
 
  public:
   static const LifetimeManagementType value =
diff --git a/third_party/blink/public/strings/blink_strings.grd b/third_party/blink/public/strings/blink_strings.grd
index 199945e..3cd5287 100644
--- a/third_party/blink/public/strings/blink_strings.grd
+++ b/third_party/blink/public/strings/blink_strings.grd
@@ -826,6 +826,18 @@
         <message name="IDS_AX_ARIA_CURRENT_TRUE" desc="Accessibility state description for aria-current value of true.">
           current item
         </message>
+        <message name="IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_DEFAULT" desc="Accessibility utterance for when a combobox element is expanded with an unknown number of autocomplete options available to the user.">
+          expanded, autocomplete options available.
+        </message>
+        <message name="IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_X_OPTIONS_AVAILABLE" desc="Accessibility utterance for when a combobox element is expanded with a known number of autocomplete options available to the user.">
+          expanded, <ph name="COUNT">$1<ex>4</ex></ph> autocomplete options available.
+        </message>
+        <message name="IDS_AX_COMBOBOX_EXPANDED_DIALOG" desc="Accessibility utterance for when a combobox element is expanded with a child dialog pop-up that appears.">
+          expanded, dialog opened.
+        </message>
+        <message name="IDS_AX_COMBOBOX_EXPANDED" desc="Accessibility utterance for when a combobox element is expanded, but due to authoring errors we cannot say any more information than that.">
+          expanded.
+        </message>
       </if>
 
       <!-- Automatic image annotations for accessibility -->
diff --git a/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED.png.sha1 b/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED.png.sha1
new file mode 100644
index 0000000..5db09d9
--- /dev/null
+++ b/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED.png.sha1
@@ -0,0 +1 @@
+5e2cb4e32c6e9739c5990c67810540f536b62a24
\ No newline at end of file
diff --git a/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_DEFAULT.png.sha1 b/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_DEFAULT.png.sha1
new file mode 100644
index 0000000..8c93fa0
--- /dev/null
+++ b/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_DEFAULT.png.sha1
@@ -0,0 +1 @@
+5edc8049771af5d1573b3f396547b88f60eab1e4
\ No newline at end of file
diff --git a/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_X_OPTIONS_AVAILABLE.png.sha1 b/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_X_OPTIONS_AVAILABLE.png.sha1
new file mode 100644
index 0000000..d4aa776
--- /dev/null
+++ b/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_AUTOCOMPLETE_X_OPTIONS_AVAILABLE.png.sha1
@@ -0,0 +1 @@
+99024afee948e19daa31f234d71f7e3611fc4dc7
\ No newline at end of file
diff --git a/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_DIALOG.png.sha1 b/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_DIALOG.png.sha1
new file mode 100644
index 0000000..1c5fa32f
--- /dev/null
+++ b/third_party/blink/public/strings/blink_strings_grd/IDS_AX_COMBOBOX_EXPANDED_DIALOG.png.sha1
@@ -0,0 +1 @@
+fb0078d1cd48f8eac5aa10b35e580f759b8a68ef
\ No newline at end of file
diff --git a/third_party/blink/public/strings/translations/blink_strings_ar.xtb b/third_party/blink/public/strings/translations/blink_strings_ar.xtb
index 787b4a1..22ce4a1 100644
--- a/third_party/blink/public/strings/translations/blink_strings_ar.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_ar.xtb
@@ -282,6 +282,7 @@
 <translation id="8613126697340063924">التحكم في التشغيل عن بعد</translation>
 <translation id="862370744433916922">ترجمة مصاحِبة</translation>
 <translation id="8634971699417195529">عرض منتقي الشهر</translation>
+<translation id="8668988909814782445">لفّ السطر</translation>
 <translation id="8711688047404765493">الإخراج</translation>
 <translation id="8750798805984357768">يُرجى اختيار أحد هذه الخيارات.</translation>
 <translation id="8808573423886751634">فصل</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_be.xtb b/third_party/blink/public/strings/translations/blink_strings_be.xtb
index 65fffa79..180bc8a 100644
--- a/third_party/blink/public/strings/translations/blink_strings_be.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_be.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">кіраваць аддаленым прайграваннем</translation>
 <translation id="862370744433916922">субцітр</translation>
 <translation id="8634971699417195529">Паказаць сродак выбару месяца</translation>
+<translation id="8668988909814782445">Пераносіць радкі</translation>
 <translation id="8711688047404765493">выхад</translation>
 <translation id="8750798805984357768">Выберыце адзін з варыянтаў.</translation>
 <translation id="8808573423886751634">глава</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_fi.xtb b/third_party/blink/public/strings/translations/blink_strings_fi.xtb
index 4f82a4dc..14ab989 100644
--- a/third_party/blink/public/strings/translations/blink_strings_fi.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_fi.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">hallinnoi etätoistoa</translation>
 <translation id="862370744433916922">alaotsikko</translation>
 <translation id="8634971699417195529">Näytä kuukauden valitsin</translation>
+<translation id="8668988909814782445">Rivitys</translation>
 <translation id="8711688047404765493">syöte</translation>
 <translation id="8750798805984357768">Valitse yksi vaihtoehdoista.</translation>
 <translation id="8808573423886751634">luku</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb b/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb
index e09c4bc..d3d82579 100644
--- a/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_fr-CA.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">contrôler la lecture à distance</translation>
 <translation id="862370744433916922">sous-titre</translation>
 <translation id="8634971699417195529">Afficher le sélecteur de mois</translation>
+<translation id="8668988909814782445">Renvoyer à la ligne</translation>
 <translation id="8711688047404765493">sortie</translation>
 <translation id="8750798805984357768">Veuillez sélectionner l'une de ces options.</translation>
 <translation id="8808573423886751634">chapitre</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_gl.xtb b/third_party/blink/public/strings/translations/blink_strings_gl.xtb
index a6f9636..e270a06 100644
--- a/third_party/blink/public/strings/translations/blink_strings_gl.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_gl.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">control remoto da reprodución</translation>
 <translation id="862370744433916922">subtítulo</translation>
 <translation id="8634971699417195529">Mostrar o selector de mes</translation>
+<translation id="8668988909814782445">Axuste de liña</translation>
 <translation id="8711688047404765493">saída</translation>
 <translation id="8750798805984357768">Selecciona unha destas opcións.</translation>
 <translation id="8808573423886751634">capítulo</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_hu.xtb b/third_party/blink/public/strings/translations/blink_strings_hu.xtb
index 02c8ed8..b0f0d29 100644
--- a/third_party/blink/public/strings/translations/blink_strings_hu.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_hu.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">távoli lejátszás kezelése</translation>
 <translation id="862370744433916922">felirat</translation>
 <translation id="8634971699417195529">Hónapválasztó megjelenítése</translation>
+<translation id="8668988909814782445">Sorok tördelése</translation>
 <translation id="8711688047404765493">kimenet</translation>
 <translation id="8750798805984357768">Kérjük, válassza ki az egyik opciót.</translation>
 <translation id="8808573423886751634">fejezet</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_kn.xtb b/third_party/blink/public/strings/translations/blink_strings_kn.xtb
index ae5bd1a..740e5dfc 100644
--- a/third_party/blink/public/strings/translations/blink_strings_kn.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_kn.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">ರಿಮೋಟ್ ಪ್ಲೇಬ್ಯಾಕ್ ನಿಯಂತ್ರಿಸಿ</translation>
 <translation id="862370744433916922">ಉಪಶೀರ್ಷಿಕೆ</translation>
 <translation id="8634971699417195529">ತಿಂಗಳಿನ ಪಿಕರ್ ಅನ್ನು ತೋರಿಸಿ</translation>
+<translation id="8668988909814782445">ಲೈನ್ ವ್ರ್ಯಾಪ್</translation>
 <translation id="8711688047404765493">ಔಟ್‌ಪುಟ್</translation>
 <translation id="8750798805984357768">ದಯವಿಟ್ಟು ಈ ಕೆಳಗಿನ ಆಯ್ಕೆಗಳಲ್ಲಿ ಒಂದನ್ನು ಆರಿಸಿ.</translation>
 <translation id="8808573423886751634">ಅಧ್ಯಾಯ</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_ko.xtb b/third_party/blink/public/strings/translations/blink_strings_ko.xtb
index cb518f5f7..60ee7df2 100644
--- a/third_party/blink/public/strings/translations/blink_strings_ko.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_ko.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">원격 재생 제어</translation>
 <translation id="862370744433916922">부제</translation>
 <translation id="8634971699417195529">월 선택도구 표시</translation>
+<translation id="8668988909814782445">자동 줄바꿈</translation>
 <translation id="8711688047404765493">출력</translation>
 <translation id="8750798805984357768">다음 옵션 중 하나를 선택하세요.</translation>
 <translation id="8808573423886751634">장</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_pa.xtb b/third_party/blink/public/strings/translations/blink_strings_pa.xtb
index ec1b44f..e85a246 100644
--- a/third_party/blink/public/strings/translations/blink_strings_pa.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_pa.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">ਰਿਮੋਟ ਪਲੇਬੈਕ ਨੂੰ ਨਿਯੰਤਰਿਤ ਕਰੋ</translation>
 <translation id="862370744433916922">ਉਪਸਿਰੇਲਖ</translation>
 <translation id="8634971699417195529">ਮਹੀਨਾ ਚੋਣਕਾਰ ਦਿਖਾਓ</translation>
+<translation id="8668988909814782445">ਲਾਈਨ ਨੂੰ ਸੀਮਾਬੱਧ ਕਰੋ</translation>
 <translation id="8711688047404765493">ਆਊਟਪੁੱਟ</translation>
 <translation id="8750798805984357768">ਕਿਰਪਾ ਕਰਕੇ ਇਹਨਾਂ ਚੋਣਾਂ ਵਿੱਚੋਂ ਇੱਕ ਚੁਣੋ।</translation>
 <translation id="8808573423886751634">ਕਾਂਡ</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_sk.xtb b/third_party/blink/public/strings/translations/blink_strings_sk.xtb
index c862d2d..1a01743 100644
--- a/third_party/blink/public/strings/translations/blink_strings_sk.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_sk.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">ovládať vzdialené prehrávanie</translation>
 <translation id="862370744433916922">podnadpis</translation>
 <translation id="8634971699417195529">Zobraziť výber mesiaca</translation>
+<translation id="8668988909814782445">Zalomiť riadok</translation>
 <translation id="8711688047404765493">výstup</translation>
 <translation id="8750798805984357768">Vyberte jednu z týchto možností.</translation>
 <translation id="8808573423886751634">kapitola</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_sq.xtb b/third_party/blink/public/strings/translations/blink_strings_sq.xtb
index 01b868b..d07b5126 100644
--- a/third_party/blink/public/strings/translations/blink_strings_sq.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_sq.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">kontrolli i luajtjes në distancë</translation>
 <translation id="862370744433916922">nëntitull</translation>
 <translation id="8634971699417195529">Shfaq zgjedhësin e muajit</translation>
+<translation id="8668988909814782445">Thyerja e rreshtit</translation>
 <translation id="8711688047404765493">dalja</translation>
 <translation id="8750798805984357768">Përzgjidh një nga këto opsione.</translation>
 <translation id="8808573423886751634">kapitull</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_sv.xtb b/third_party/blink/public/strings/translations/blink_strings_sv.xtb
index 400ae58..1e6d12d2 100644
--- a/third_party/blink/public/strings/translations/blink_strings_sv.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_sv.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">styra fjärruppspelning</translation>
 <translation id="862370744433916922">undertext</translation>
 <translation id="8634971699417195529">Visa månadsväljare</translation>
+<translation id="8668988909814782445">Radbrytning</translation>
 <translation id="8711688047404765493">utdata</translation>
 <translation id="8750798805984357768">Välj ett av följande alternativ.</translation>
 <translation id="8808573423886751634">kapitel</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_sw.xtb b/third_party/blink/public/strings/translations/blink_strings_sw.xtb
index a714365..917f224 100644
--- a/third_party/blink/public/strings/translations/blink_strings_sw.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_sw.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">dhibiti kucheza kwa mbali</translation>
 <translation id="862370744433916922">kichwa kidogo</translation>
 <translation id="8634971699417195529">Onyesha kiteua mwezi</translation>
+<translation id="8668988909814782445">Tosheza mistari kwenye skrini</translation>
 <translation id="8711688047404765493">vifaa vya kutoa maudhui</translation>
 <translation id="8750798805984357768">Tafadhali chagua moja wapo ya chaguo hizi.</translation>
 <translation id="8808573423886751634">sura</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_tr.xtb b/third_party/blink/public/strings/translations/blink_strings_tr.xtb
index 27be33c..1275bd82 100644
--- a/third_party/blink/public/strings/translations/blink_strings_tr.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_tr.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">uzaktan oynatmayı kontrol et</translation>
 <translation id="862370744433916922">alt başlık</translation>
 <translation id="8634971699417195529">Ay seçiciyi gösterir</translation>
+<translation id="8668988909814782445">Satır kaydır</translation>
 <translation id="8711688047404765493">çıkış</translation>
 <translation id="8750798805984357768">Lütfen bu seçeneklerden birini belirleyin.</translation>
 <translation id="8808573423886751634">bölüm</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_ur.xtb b/third_party/blink/public/strings/translations/blink_strings_ur.xtb
index 018fe4e..d60b578 100644
--- a/third_party/blink/public/strings/translations/blink_strings_ur.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_ur.xtb
@@ -281,6 +281,7 @@
 <translation id="8613126697340063924">ریموٹ پلے بیک کو کنٹرول کریں</translation>
 <translation id="862370744433916922">ذیلی عنوان</translation>
 <translation id="8634971699417195529">مہینہ منتخب کرنے والا دکھائیں</translation>
+<translation id="8668988909814782445">لائن رَیپ کریں | لائن ملفوف کریں</translation>
 <translation id="8711688047404765493">آؤٹ پٹ</translation>
 <translation id="8750798805984357768">براہ کرم ان اختیارات میں سے ایک کو منتخب کریں۔</translation>
 <translation id="8808573423886751634">باب</translation>
diff --git a/third_party/blink/public/test/frame_widget_test_helper.h b/third_party/blink/public/test/frame_widget_test_helper.h
new file mode 100644
index 0000000..2a12c38
--- /dev/null
+++ b/third_party/blink/public/test/frame_widget_test_helper.h
@@ -0,0 +1,71 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_TEST_FRAME_WIDGET_TEST_HELPER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_TEST_FRAME_WIDGET_TEST_HELPER_H_
+
+#include "base/callback_forward.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/web/web_frame_widget.h"
+
+namespace content {
+class EventSender;
+class TestRunner;
+}  // namespace content
+
+namespace blink {
+
+// This class is used for content/web_test to create a subclass of
+// `WebFrameWidgetImpl` that has special test hooks for controlling web tests.
+// Since `WebFrameWidgetImpl` is not exported outside blink we need to have
+// a special interface that exposes some additional hooks. These special
+// hooks are contained on the `FrameWidgetTestHelper` class and the subclass
+// implements `WebFrameWidget::GetFrameWidgetTestHelperForTesting()`.
+//
+// We allow usage of content::EventSender/TestRunner here temporarily while
+// these methods are eventually moved into blink. This code is built and
+// linked for tests.
+class FrameWidgetTestHelper {
+ public:
+  // Creates a special subclass of WebFrameWidget that also implements
+  // the FrameWidgetTestHelper interface.
+  static WebFrameWidget* CreateTestWebFrameWidget(
+      base::PassKey<WebFrameWidget>,
+      WebWidgetClient&,
+      CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>
+          frame_widget_host,
+      CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>
+          frame_widget,
+      CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>
+          widget_host,
+      CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase> widget,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      const viz::FrameSinkId& frame_sink_id,
+      bool hidden,
+      bool never_composited,
+      bool is_for_child_local_root,
+      bool is_for_nested_main_frame,
+      content::TestRunner* test_runner);
+
+  // Reset state for web tests.
+  virtual void Reset() = 0;
+
+  // Return a handle to content::EventSender.
+  virtual content::EventSender* GetEventSender() = 0;
+
+  // Called to composite when the test has ended, in order to ensure the test
+  // produces up-to-date pixel output. This is a separate path as most
+  // compositing paths stop running when the test ends, to avoid tests running
+  // forever.
+  virtual void SynchronouslyCompositeAfterTest() = 0;
+
+  // Forces a redraw and invokes the callback once the frame's been displayed
+  // to the user in the display compositor.
+  virtual void UpdateAllLifecyclePhasesAndComposite(
+      base::OnceClosure completion_callback) = 0;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_TEST_FRAME_WIDGET_TEST_HELPER_H_
diff --git a/third_party/blink/public/web/web_frame_widget.h b/third_party/blink/public/web/web_frame_widget.h
index 727b67b7..88eb2bc 100644
--- a/third_party/blink/public/web/web_frame_widget.h
+++ b/third_party/blink/public/web/web_frame_widget.h
@@ -34,6 +34,7 @@
 #include <stdint.h>
 
 #include "base/callback_forward.h"
+#include "base/types/pass_key.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "third_party/blink/public/common/page/drag_operation.h"
 #include "third_party/blink/public/mojom/page/widget.mojom-shared.h"
@@ -45,6 +46,7 @@
 
 namespace blink {
 
+class FrameWidgetTestHelper;
 class WebDragData;
 class WebLocalFrame;
 class WebInputMethodController;
@@ -210,6 +212,10 @@
   // frames submitted from the compositor.
   virtual const viz::FrameSinkId& GetFrameSinkId() = 0;
 
+  // Returns a FrameWidgetTestHelper if this widget was created using
+  // `FrameWidgetTestHelper::CreateTestWebFrameWidget()`.
+  virtual FrameWidgetTestHelper* GetFrameWidgetTestHelperForTesting() = 0;
+
  private:
   // This private constructor and the class/friend declaration ensures that
   // WebFrameWidgetImpl is the only concrete subclass that implements
@@ -218,6 +224,32 @@
   WebFrameWidget() = default;
 };
 
+// Convenience type for creation method taken by
+// InstallCreateWebFrameWidgetHook(). The method signature matches the
+// WebFrameWidgetImpl constructor.
+using CreateWebFrameWidgetFunction =
+    WebFrameWidget* (*)(base::PassKey<WebFrameWidget>,
+                        WebWidgetClient&,
+                        CrossVariantMojoAssociatedRemote<
+                            mojom::FrameWidgetHostInterfaceBase>
+                            frame_widget_host,
+                        CrossVariantMojoAssociatedReceiver<
+                            mojom::FrameWidgetInterfaceBase> frame_widget,
+                        CrossVariantMojoAssociatedRemote<
+                            mojom::WidgetHostInterfaceBase> widget_host,
+                        CrossVariantMojoAssociatedReceiver<
+                            mojom::WidgetInterfaceBase> widget,
+                        scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                        const viz::FrameSinkId& frame_sink_id,
+                        bool hidden,
+                        bool never_composited,
+                        bool is_for_child_local_root,
+                        bool is_for_nested_main_frame);
+// Allows tests to inject their own type of WebFrameWidget in order to
+// override methods of the WebFrameWidgetImpl.
+void BLINK_EXPORT
+InstallCreateWebFrameWidgetHook(CreateWebFrameWidgetFunction create_widget);
+
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/public/web/web_page_popup.h b/third_party/blink/public/web/web_page_popup.h
index 0ed92c70..3dcff28 100644
--- a/third_party/blink/public/web/web_page_popup.h
+++ b/third_party/blink/public/web/web_page_popup.h
@@ -39,23 +39,14 @@
 
 namespace blink {
 
-class WebWidgetClient;
 class WebDocument;
 class WebView;
 
-class WebPagePopupClient : public WebWidgetClient {
- public:
-  // Request to destroy the WebPagePopupClient immediately given that the
-  // browser has closed the associated mojom connection.
-  virtual void BrowserClosedIpcChannelForPopupWidget() = 0;
-};
-
 class WebPagePopup : public WebWidget {
  public:
   // Returns a WebPagePopup which is self-referencing. It's self-reference will
   // be released when the popup is closed via Close().
   BLINK_EXPORT static WebPagePopup* Create(
-      WebPagePopupClient*,
       CrossVariantMojoAssociatedRemote<mojom::PopupWidgetHostInterfaceBase>
           popup_widget_host,
       CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>
@@ -71,10 +62,6 @@
   // Initialization is typically done after creation inside blink, but some
   // content tests call Create directly so we expose an initialization.
   virtual void InitializeForTesting(WebView* view) = 0;
-
-  // Web tests require access to the client for a WebPagePopup in order
-  // to synchronously composite.
-  virtual WebPagePopupClient* GetClientForTesting() const = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h
index 6f4e114f..5eb72a7a 100644
--- a/third_party/blink/public/web/web_widget.h
+++ b/third_party/blink/public/web/web_widget.h
@@ -92,11 +92,8 @@
       std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory,
       const cc::LayerTreeSettings* settings) = 0;
 
-  // This method closes and deletes the WebWidget. If a |cleanup_task| is
-  // provided it should run on the |cleanup_runner| after the WebWidget has
-  // added its own tasks to the |cleanup_runner|.
-  virtual void Close(
-      scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner = nullptr) {}
+  // This method closes and deletes the WebWidget.
+  virtual void Close() {}
 
   // Set the compositor as visible. If |visible| is true, then the compositor
   // will request a new layer frame sink and begin producing frames from the
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h
index c71c56c..1429912 100644
--- a/third_party/blink/public/web/web_widget_client.h
+++ b/third_party/blink/public/web/web_widget_client.h
@@ -70,16 +70,9 @@
  public:
   virtual ~WebWidgetClient() = default;
 
-  // Called to request a BeginMainFrame from the compositor. For tests with
-  // single thread and no scheduler, the impl should schedule a task to run
-  // a synchronous composite.
-  virtual void ScheduleAnimation() {}
-
-  // Called to request a BeginMainFrame from the compositor, meant to be used
-  // for web tests only, where commits must be explicitly scheduled. Contrary to
-  // ScheduleAnimation() this will be a no-op on multi-threaded environments and
-  // will unconditionally ensure that the compositor is actually run.
-  virtual void ScheduleAnimationForWebTests() {}
+  // Called to request a BeginMainFrame from the compositor. This is only
+  // called for widget's WebView's that do not composite.
+  virtual void ScheduleNonCompositedAnimation() {}
 
   // Called when the cursor for the widget changes.
   virtual void DidChangeCursor(const ui::Cursor&) {}
@@ -105,11 +98,6 @@
   // For more information on the sequence of when these callbacks are made
   // consult cc/trees/layer_tree_host_client.h.
 
-  // Indicates that the compositor is about to begin a frame. This is primarily
-  // to signal to flow control mechanisms that a frame is beginning, not to
-  // perform actual painting work.
-  virtual void WillBeginMainFrame() {}
-
   // Notifies that the layer tree host has completed a call to
   // RequestMainFrameUpdate in response to a BeginMainFrame.
   virtual void DidBeginMainFrame() {}
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index b2e36a7..30933db3 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -1375,6 +1375,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_deprecated_storage_info.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_deprecated_storage_quota.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_deprecated_storage_quota.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_service.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_service.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_dev_tools_host.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_dev_tools_host.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_device_motion_event.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index 520b3df..c9eae0d 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -170,6 +170,8 @@
           "//third_party/blink/renderer/modules/delegated_ink/ink.idl",
           "//third_party/blink/renderer/modules/delegated_ink/ink_trail_style.idl",
           "//third_party/blink/renderer/modules/delegated_ink/navigator_ink.idl",
+          "//third_party/blink/renderer/modules/device/device_service.idl",
+          "//third_party/blink/renderer/modules/device/navigator_device.idl",
           "//third_party/blink/renderer/modules/device_orientation/device_motion_event.idl",
           "//third_party/blink/renderer/modules/device_orientation/device_motion_event_acceleration.idl",
           "//third_party/blink/renderer/modules/device_orientation/device_motion_event_acceleration_init.idl",
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/union.py b/third_party/blink/renderer/bindings/scripts/bind_gen/union.py
index db135ca..9a6459c 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/union.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/union.py
@@ -14,6 +14,7 @@
 from .code_node_cxx import CxxFuncDeclNode
 from .code_node_cxx import CxxFuncDefNode
 from .code_node_cxx import CxxNamespaceNode
+from .code_node_cxx import CxxSwitchNode
 from .codegen_accumulator import CodeGenAccumulator
 from .codegen_context import CodeGenContext
 from .codegen_format import format_template as _format
@@ -43,8 +44,8 @@
         self._api_pred = "Is{}".format(self._base_name)
         self._api_get = "GetAs{}".format(self._base_name)
         self._api_set = "Set"
-        self._member_var = name_style.member_var("member", self._base_name)
-        self._member_type = None
+        self._var_name = name_style.member_var("member", self._base_name)
+        self._type_info = None
         self._typedef_aliases = ()
 
     @property
@@ -70,12 +71,12 @@
         return self._api_set
 
     @property
-    def member_var(self):
-        return self._member_var
+    def var_name(self):
+        return self._var_name
 
     @property
-    def member_type(self):
-        return self._member_type
+    def type_info(self):
+        return self._type_info
 
     @property
     def typedef_aliases(self):
@@ -95,7 +96,7 @@
         _UnionMember.__init__(self, base_name=base_name)
         self._is_null = idl_type is None
         if not self._is_null:
-            self._member_type = blink_type_info(idl_type)
+            self._type_info = blink_type_info(idl_type)
         self._typedef_aliases = tuple([
             _UnionMemberAlias(impl=self, typedef=typedef)
             for typedef in union.typedef_members
@@ -103,13 +104,43 @@
         ])
 
 
+class _UnionMemberSubunion(_UnionMember):
+    def __init__(self, union, subunion):
+        assert isinstance(union, web_idl.NewUnion)
+        assert isinstance(subunion, web_idl.NewUnion)
+
+        _UnionMember.__init__(self, base_name=blink_class_name(subunion))
+        self._type_info = blink_type_info(subunion.idl_types[0],
+                                          use_new_union=True)
+        self._typedef_aliases = tuple(
+            map(lambda typedef: _UnionMemberAlias(impl=self, typedef=typedef),
+                subunion.aliasing_typedefs))
+        self._blink_class_name = blink_class_name(subunion)
+
+    @property
+    def blink_class_name(self):
+        return self._blink_class_name
+
+
 class _UnionMemberAlias(_UnionMember):
     def __init__(self, impl, typedef):
-        assert isinstance(impl, _UnionMemberImpl)
+        assert isinstance(impl, (_UnionMemberImpl, _UnionMemberSubunion))
         assert isinstance(typedef, web_idl.Typedef)
 
         _UnionMember.__init__(self, base_name=typedef.identifier)
-        self._member_var = impl.member_var
+        self._var_name = impl.var_name
+        self._type_info = impl.type_info
+
+
+def create_union_members(union):
+    assert isinstance(union, web_idl.NewUnion)
+
+    union_members = map(
+        lambda member_type: _UnionMemberImpl(union, member_type),
+        union.flattened_member_types)
+    if union.does_include_nullable_type:
+        union_members.append(_UnionMemberImpl(union, idl_type=None))
+    return tuple(union_members)
 
 
 def make_content_type_enum_class_def(cg_context):
@@ -124,12 +155,223 @@
                 member.content_type(with_enum_name=False)))
 
     return ListNode([
+        TextNode("// The type of the content value of this IDL union."),
         TextNode("enum class ContentType {"),
         ListNode(map(TextNode, entries), separator=", "),
         TextNode("};"),
     ])
 
 
+def make_constructors(cg_context):
+    assert isinstance(cg_context, CodeGenContext)
+
+    decls = ListNode()
+
+    for member in cg_context.union_members:
+        if member.is_null:
+            func_def = CxxFuncDefNode(name=cg_context.class_name,
+                                      arg_decls=["std::nullptr_t"],
+                                      return_type="",
+                                      explicit=True,
+                                      member_initializer_list=[
+                                          "content_type_({})".format(
+                                              member.content_type()),
+                                      ])
+        else:
+            func_def = CxxFuncDefNode(
+                name=cg_context.class_name,
+                arg_decls=["{} value".format(member.type_info.member_ref_t)],
+                return_type="",
+                explicit=True,
+                member_initializer_list=[
+                    "content_type_({})".format(member.content_type()),
+                    "{}(value)".format(member.var_name),
+                ])
+        decls.append(func_def)
+
+    return decls, None
+
+
+def make_accessor_functions(cg_context):
+    assert isinstance(cg_context, CodeGenContext)
+
+    T = TextNode
+    F = lambda *args, **kwargs: T(_format(*args, **kwargs))
+
+    decls = ListNode()
+    defs = ListNode()
+
+    func_def = CxxFuncDefNode(name="GetContentType",
+                              arg_decls=[],
+                              return_type="ContentType",
+                              const=True)
+    func_def.set_base_template_vars(cg_context.template_bindings())
+    func_def.body.append(T("return content_type_;"))
+    decls.extend([
+        T("// Returns the type of the content value."),
+        func_def,
+        EmptyNode(),
+    ])
+
+    def make_api_pred(member):
+        func_def = CxxFuncDefNode(name=member.api_pred,
+                                  arg_decls=[],
+                                  return_type="bool",
+                                  const=True)
+        func_def.set_base_template_vars(cg_context.template_bindings())
+        func_def.body.append(
+            F("return content_type_ == {};", member.content_type()))
+        return func_def
+
+    def make_api_get(member):
+        func_def = CxxFuncDefNode(name=member.api_get,
+                                  arg_decls=[],
+                                  return_type=member.type_info.member_ref_t,
+                                  const=True)
+        func_def.set_base_template_vars(cg_context.template_bindings())
+        func_def.body.extend([
+            F("DCHECK_EQ(content_type_, {});", member.content_type()),
+            F("return {};", member.var_name),
+        ])
+        return func_def
+
+    def make_api_set(member):
+        func_def = CxxFuncDefNode(
+            name=member.api_set,
+            arg_decls=["{} value".format(member.type_info.member_ref_t)],
+            return_type="void")
+        func_def.set_base_template_vars(cg_context.template_bindings())
+        func_def.body.extend([
+            T("Clear();"),
+            F("{} = value;", member.var_name),
+            F("content_type_ = {};", member.content_type()),
+        ])
+        return func_def
+
+    def make_api_set_null(member):
+        func_def = CxxFuncDefNode(name=member.api_set,
+                                  arg_decls=["std::nullptr_t"],
+                                  return_type="void")
+        func_def.set_base_template_vars(cg_context.template_bindings())
+        func_def.body.extend([
+            T("Clear();"),
+            F("content_type_ = {};", member.content_type()),
+        ])
+        return func_def
+
+    for member in cg_context.union_members:
+        if member.is_null:
+            decls.append(make_api_pred(member))
+            decls.append(make_api_set_null(member))
+        else:
+            decls.append(make_api_pred(member))
+            for alias in member.typedef_aliases:
+                decls.append(make_api_pred(alias))
+            decls.append(make_api_get(member))
+            for alias in member.typedef_aliases:
+                decls.append(make_api_get(alias))
+            decls.append(make_api_set(member))
+        decls.append(EmptyNode())
+
+    def make_api_subunion_pred(subunion, subunion_members):
+        func_def = CxxFuncDefNode(name=subunion.api_pred,
+                                  arg_decls=[],
+                                  return_type="bool",
+                                  const=True)
+        func_def.set_base_template_vars(cg_context.template_bindings())
+        expr = " || ".join(
+            map(
+                lambda member: "content_type_ == {}".format(
+                    member.content_type()), subunion_members))
+        func_def.body.append(F("return {};", expr))
+        return func_def, None
+
+    def make_api_subunion_get(subunion, subunion_members):
+        func_decl = CxxFuncDeclNode(name=subunion.api_get,
+                                    arg_decls=[],
+                                    return_type=subunion.type_info.value_t,
+                                    const=True)
+        func_def = CxxFuncDefNode(name=subunion.api_get,
+                                  arg_decls=[],
+                                  return_type=subunion.type_info.value_t,
+                                  const=True,
+                                  class_name=cg_context.class_name)
+        func_def.set_base_template_vars(cg_context.template_bindings())
+        node = CxxSwitchNode(cond="content_type_")
+        node.append(case=None,
+                    body=[T("NOTREACHED();"),
+                          T("return nullptr;")],
+                    should_add_break=False)
+        for member in subunion_members:
+            node.append(case=member.content_type(),
+                        body=F("return MakeGarbageCollected<{}>({}());",
+                               subunion.blink_class_name, member.api_get),
+                        should_add_break=False)
+        func_def.body.append(node)
+        return func_decl, func_def
+
+    def make_api_subunion_set(subunion, subunion_members):
+        func_decl = CxxFuncDeclNode(
+            name=subunion.api_set,
+            arg_decls=["{} value".format(subunion.type_info.const_ref_t)],
+            return_type="void")
+        func_def = CxxFuncDefNode(
+            name=subunion.api_set,
+            arg_decls=["{} value".format(subunion.type_info.const_ref_t)],
+            return_type="void",
+            class_name=cg_context.class_name)
+        func_def.set_base_template_vars(cg_context.template_bindings())
+        node = CxxSwitchNode(cond="value->GetContentType()")
+        for member in subunion_members:
+            node.append(case=F("{}::{}", subunion.blink_class_name,
+                               member.content_type()),
+                        body=F("Set(value->{}());", member.api_get))
+        func_def.body.append(node)
+        return func_decl, func_def
+
+    for subunion in cg_context.union.union_members:
+        subunion_members = create_union_members(subunion)
+        subunion = _UnionMemberSubunion(cg_context.union, subunion)
+        func_decl, func_def = make_api_subunion_pred(subunion,
+                                                     subunion_members)
+        decls.append(func_decl)
+        defs.append(func_def)
+        defs.append(EmptyNode())
+        func_decl, func_def = make_api_subunion_get(subunion, subunion_members)
+        decls.append(func_decl)
+        defs.append(func_def)
+        defs.append(EmptyNode())
+        func_decl, func_def = make_api_subunion_set(subunion, subunion_members)
+        decls.append(func_decl)
+        defs.append(func_def)
+        defs.append(EmptyNode())
+        decls.append(EmptyNode())
+
+    return decls, defs
+
+
+def make_clear_function(cg_context):
+    assert isinstance(cg_context, CodeGenContext)
+
+    func_decl = CxxFuncDeclNode(name="Clear", arg_decls=[], return_type="void")
+
+    func_def = CxxFuncDefNode(name="Clear",
+                              arg_decls=[],
+                              return_type="void",
+                              class_name=cg_context.class_name)
+    func_def.set_base_template_vars(cg_context.template_bindings())
+    body = func_def.body
+
+    for member in cg_context.union_members:
+        if member.is_null:
+            continue
+        clear_expr = member.type_info.clear_member_var_expr(member.var_name)
+        if clear_expr:
+            body.append(TextNode("{};".format(clear_expr)))
+
+    return func_decl, func_def
+
+
 def make_trace_function(cg_context):
     assert isinstance(cg_context, CodeGenContext)
 
@@ -152,7 +394,7 @@
             continue
         body.append(
             TextNode("TraceIfNeeded<{}>::Trace(visitor, {});".format(
-                member.member_type.member_t, member.member_var)))
+                member.type_info.member_t, member.var_name)))
     body.append(TextNode("${base_class_name}::Trace(visitor);"))
 
     return func_decl, func_def
@@ -161,11 +403,19 @@
 def make_member_vars_def(cg_context):
     assert isinstance(cg_context, CodeGenContext)
 
+    member_vars_def = ListNode()
+    member_vars_def.extend([
+        TextNode("ContentType content_type_;"),
+        EmptyNode(),
+    ])
+
     entries = [
-        "{} {};".format(member.member_type.member_t, member.member_var)
+        "{} {};".format(member.type_info.member_t, member.var_name)
         for member in cg_context.union_members if not member.is_null
     ]
-    return ListNode(map(TextNode, entries))
+    member_vars_def.extend(map(TextNode, entries))
+
+    return member_vars_def
 
 
 def generate_union(union_identifier):
@@ -182,13 +432,8 @@
     # Class names
     class_name = blink_class_name(union)
 
-    union_members = map(
-        lambda member_type: _UnionMemberImpl(union=union, idl_type=member_type
-                                             ), union.flattened_member_types)
-    if union.does_include_nullable_type:
-        union_members.append(_UnionMemberImpl(union=union, idl_type=None))
     cg_context = CodeGenContext(union=union,
-                                union_members=tuple(union_members),
+                                union_members=create_union_members(union),
                                 class_name=class_name,
                                 base_class_name="bindings::UnionBase")
 
@@ -218,7 +463,10 @@
 
     # Implementation parts
     content_type_enum_class_def = make_content_type_enum_class_def(cg_context)
-    trace_decls, trace_defs = make_trace_function(cg_context)
+    ctor_decls, ctor_defs = make_constructors(cg_context)
+    accessor_decls, accessor_defs = make_accessor_functions(cg_context)
+    clear_func_decls, clear_func_defs = make_clear_function(cg_context)
+    trace_func_decls, trace_func_defs = make_trace_function(cg_context)
     member_vars_def = make_member_vars_def(cg_context)
 
     # Header part (copyright, include directives, and forward declarations)
@@ -255,6 +503,11 @@
         component_export_header(api_component, for_testing),
         "third_party/blink/renderer/platform/bindings/union_base.h",
     ])
+    header_node.accumulator.add_class_decls(
+        map(blink_class_name, union.union_members))
+    source_node.accumulator.add_include_headers(
+        map(lambda subunion: PathManager(subunion).api_path(ext="h"),
+            union.union_members))
     (header_forward_decls, header_include_headers, source_forward_decls,
      source_include_headers) = collect_forward_decls_and_include_headers(
          union.flattened_member_types)
@@ -266,16 +519,28 @@
     header_blink_ns.body.append(class_def)
     header_blink_ns.body.append(EmptyNode())
 
-    class_def.public_section.extend([
-        content_type_enum_class_def,
-        EmptyNode(),
-        trace_decls,
-        EmptyNode(),
-    ])
-    source_blink_ns.body.extend([
-        trace_defs,
-        EmptyNode(),
-    ])
+    class_def.public_section.append(content_type_enum_class_def)
+    class_def.public_section.append(EmptyNode())
+
+    class_def.public_section.append(ctor_decls)
+    class_def.public_section.append(EmptyNode())
+    source_blink_ns.body.append(ctor_defs)
+    source_blink_ns.body.append(EmptyNode())
+
+    class_def.public_section.append(accessor_decls)
+    class_def.public_section.append(EmptyNode())
+    source_blink_ns.body.append(accessor_defs)
+    source_blink_ns.body.append(EmptyNode())
+
+    class_def.public_section.append(clear_func_decls)
+    class_def.public_section.append(EmptyNode())
+    source_blink_ns.body.append(clear_func_defs)
+    source_blink_ns.body.append(EmptyNode())
+
+    class_def.public_section.append(trace_func_decls)
+    class_def.public_section.append(EmptyNode())
+    source_blink_ns.body.append(trace_func_defs)
+    source_blink_ns.body.append(EmptyNode())
 
     class_def.private_section.append(member_vars_def)
     class_def.private_section.append(EmptyNode())
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/union.py b/third_party/blink/renderer/bindings/scripts/web_idl/union.py
index 0d0b4ea..07ab9bd 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/union.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/union.py
@@ -140,7 +140,7 @@
             idl_type.type_name_with_extended_attribute_key_values)
         sort_key_identifier = lambda x: x.identifier
 
-        self._union_types = tuple(ir.union_types)
+        self._idl_types = tuple(ir.union_types)
         self._flattened_member_types = tuple(
             sorted(flattened_member_types, key=sort_key_typename))
         self._does_include_nullable_type = does_include_nullable_type
@@ -153,9 +153,14 @@
             sorted(ir.typedefs, key=sort_key_identifier))
 
         ir.public_object = self
-        # TODO(yukishiino): Replace BackwardCompatibleUnion with NewUnion
-        # for union_type in self._union_types:
-        #     union_type.set_union_definition_object(self)
+
+        for idl_type in self._idl_types:
+            idl_type.set_new_union_definition_object(self)
+
+    @property
+    def idl_types(self):
+        """Returns a list of IdlTypes which this object represents."""
+        return self._idl_types
 
     @property
     def flattened_member_types(self):
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 2dbac45b..231bad7b 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -354,6 +354,7 @@
     ":core",
     ":generated_testing_idls",
     "//build:chromeos_buildflags",
+    "//components/ukm:test_support",
     "//third_party/blink/renderer/bindings/core/v8:testing",
     "//third_party/blink/renderer/platform:test_support",
     "//ui/base/cursor:cursor_base",
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
index 89020ba1..00639a6 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -398,9 +398,6 @@
       node.GetDocument()
               .GetDisplayLockDocumentState()
               .LockedDisplayLockCount() == 0 ||
-      node.GetDocument()
-              .GetDisplayLockDocumentState()
-              .DisplayLockBlockingAllActivationCount() == 0 ||
       !node.CanParticipateInFlatTree()) {
     return true;
   }
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
index f15245a..3e881c6b 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
@@ -37,6 +37,21 @@
   }
 };
 
+TEST_F(DisplayLockUtilitiesTest, ShouldIgnoreHiddenMatchableChildren) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+    .hidden { content-visibility: hidden-matchable }
+    </style>
+    <div class=hidden>
+      <div id=target></div>
+    </div>
+  )HTML");
+
+  Node* target = GetDocument().getElementById("target");
+  EXPECT_TRUE(DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+      *target, DisplayLockActivationReason::kAccessibility));
+}
+
 TEST_F(DisplayLockUtilitiesTest, DISABLED_ActivatableLockedInclusiveAncestors) {
   SetBodyInnerHTML(R"HTML(
     <style>
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 891bb27b..4ec1fd9b 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -2743,10 +2743,8 @@
 }
 
 void Document::MarkHasFindInPageRequest() {
-  // Note that although find-in-page requests happen in non-main frames, we only
-  // record the main frame results (per UKM policy). Additionally, we only
-  // record the event once.
-  if (had_find_in_page_request_ || !IsInMainFrame())
+  // Only record the event once in a document.
+  if (had_find_in_page_request_)
     return;
 
   auto* recorder = UkmRecorder();
@@ -2759,10 +2757,8 @@
 }
 
 void Document::MarkHasFindInPageContentVisibilityActiveMatch() {
-  // Note that although find-in-page in content-visibility requests happen in
-  // non-main frames, we only record the main frame results (per UKM policy).
-  // Additionally, we only record the event once.
-  if (had_find_in_page_render_subtree_active_match_ || !IsInMainFrame())
+  // Only record the event once in a document.
+  if (had_find_in_page_render_subtree_active_match_)
     return;
 
   auto* recorder = UkmRecorder();
@@ -2776,11 +2772,8 @@
 }
 
 void Document::MarkHasFindInPageBeforematchExpandedHiddenMatchable() {
-  // Note that although find-in-page in content-visibility requests happen in
-  // non-main frames, we only record the main frame results (per UKM policy).
-  // Additionally, we only record the event once.
-  if (had_find_in_page_beforematch_expanded_hidden_matchable_ ||
-      !IsInMainFrame())
+  // Only record the event once in a document.
+  if (had_find_in_page_beforematch_expanded_hidden_matchable_)
     return;
 
   auto* recorder = UkmRecorder();
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index 7f4dc466..ecb3b6f 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -1694,6 +1694,7 @@
  private:
   friend class DocumentTest;
   friend class IgnoreDestructiveWriteCountIncrementer;
+  friend class TextFragmentSelectorGeneratorTest;
   friend class ThrowOnDynamicMarkupInsertionCountIncrementer;
   friend class IgnoreOpensDuringUnloadCountIncrementer;
   friend class NthIndexCache;
@@ -1701,10 +1702,13 @@
   FRIEND_TEST_ALL_PREFIXES(FrameFetchContextSubresourceFilterTest,
                            DuringOnFreeze);
   FRIEND_TEST_ALL_PREFIXES(DocumentTest, FindInPageUkm);
+  FRIEND_TEST_ALL_PREFIXES(DocumentTest, FindInPageUkmInFrame);
   FRIEND_TEST_ALL_PREFIXES(TextFinderSimTest,
                            BeforeMatchExpandedHiddenMatchableUkm);
   FRIEND_TEST_ALL_PREFIXES(TextFinderSimTest,
                            BeforeMatchExpandedHiddenMatchableUkmNoHandler);
+  FRIEND_TEST_ALL_PREFIXES(TextFragmentAnchorMetricsTest, LinkOpenedSuccessUKM);
+  FRIEND_TEST_ALL_PREFIXES(TextFragmentAnchorMetricsTest, LinkOpenedFailedUKM);
   class NetworkStateObserver;
 
   friend class AXContext;
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc
index f3750d5..9ed15af 100644
--- a/third_party/blink/renderer/core/dom/document_test.cc
+++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -57,13 +57,16 @@
 #include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
 #include "third_party/blink/renderer/core/dom/text.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/reporting_context.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/viewport_data.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
 #include "third_party/blink/renderer/core/html/html_head_element.h"
+#include "third_party/blink/renderer/core/html/html_iframe_element.h"
 #include "third_party/blink/renderer/core/html/html_link_element.h"
 #include "third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
@@ -79,6 +82,7 @@
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -1018,6 +1022,71 @@
   EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric(entries[1], "DidSearch"));
 }
 
+TEST_F(DocumentTest, FindInPageUkmInFrame) {
+  std::string base_url = "http://internal.test/";
+
+  url_test_helpers::RegisterMockedURLLoadFromBase(
+      WebString::FromUTF8(base_url), test::CoreTestDataPath(),
+      WebString::FromUTF8("visible_iframe.html"));
+  url_test_helpers::RegisterMockedURLLoadFromBase(
+      WebString::FromUTF8(base_url), test::CoreTestDataPath(),
+      WebString::FromUTF8("single_iframe.html"));
+
+  frame_test_helpers::WebViewHelper web_view_helper;
+  WebViewImpl* web_view_impl =
+      web_view_helper.InitializeAndLoad(base_url + "single_iframe.html");
+
+  web_view_impl->MainFrameWidget()->UpdateAllLifecyclePhases(
+      DocumentUpdateReason::kTest);
+
+  Document* top_doc = web_view_impl->MainFrameImpl()->GetFrame()->GetDocument();
+  auto* iframe = To<HTMLIFrameElement>(top_doc->QuerySelector("iframe"));
+  Document* document = iframe->contentDocument();
+  ASSERT_TRUE(document);
+  ASSERT_FALSE(document->IsInMainFrame());
+
+  // Save the old recorder and replace it with a test one.
+  auto old_recorder = std::move(document->ukm_recorder_);
+  document->ukm_recorder_ = std::make_unique<ukm::TestUkmRecorder>();
+
+  auto* recorder = static_cast<ukm::TestUkmRecorder*>(document->UkmRecorder());
+
+  EXPECT_EQ(recorder->entries_count(), 0u);
+  document->MarkHasFindInPageRequest();
+  EXPECT_EQ(recorder->entries_count(), 1u);
+  document->MarkHasFindInPageRequest();
+  EXPECT_EQ(recorder->entries_count(), 1u);
+
+  auto entries = recorder->GetEntriesByName("Blink.FindInPage");
+  EXPECT_EQ(entries.size(), 1u);
+  EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entries[0], "DidSearch"));
+  EXPECT_EQ(*ukm::TestUkmRecorder::GetEntryMetric(entries[0], "DidSearch"), 1);
+  EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric(
+      entries[0], "DidHaveRenderSubtreeMatch"));
+
+  document->MarkHasFindInPageContentVisibilityActiveMatch();
+  EXPECT_EQ(recorder->entries_count(), 2u);
+  document->MarkHasFindInPageContentVisibilityActiveMatch();
+  EXPECT_EQ(recorder->entries_count(), 2u);
+  entries = recorder->GetEntriesByName("Blink.FindInPage");
+  EXPECT_EQ(entries.size(), 2u);
+
+  EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entries[0], "DidSearch"));
+  EXPECT_EQ(*ukm::TestUkmRecorder::GetEntryMetric(entries[0], "DidSearch"), 1);
+  EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric(
+      entries[0], "DidHaveRenderSubtreeMatch"));
+
+  EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(
+      entries[1], "DidHaveRenderSubtreeMatch"));
+  EXPECT_EQ(*ukm::TestUkmRecorder::GetEntryMetric(entries[1],
+                                                  "DidHaveRenderSubtreeMatch"),
+            1);
+  EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric(entries[1], "DidSearch"));
+
+  // Restore the old recorder, since some ukm metrics are recorded at shutdown.
+  document->ukm_recorder_ = std::move(old_recorder);
+}
+
 TEST_F(DocumentTest, AtPageMarginWithDeviceScaleFactor) {
   GetDocument().GetFrame()->SetPageZoomFactor(2);
   SetBodyInnerHTML("<style>@page { margin: 50px; size: 400px 10in; }</style>");
diff --git a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
index 1fc6acc..7dfebae 100644
--- a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
@@ -606,7 +606,6 @@
     return pos;
 
   switch (pos.AnchorType()) {
-    case PositionAnchorType::kBeforeChildren:
     case PositionAnchorType::kAfterChildren:
       NOTREACHED();
       return pos;
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.cc b/third_party/blink/renderer/core/editing/editing_utilities.cc
index fe1b00a..9c037f17 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -1403,13 +1403,6 @@
   Node* container_node;
   Node* anchor_node;
   switch (position.AnchorType()) {
-    case PositionAnchorType::kBeforeChildren:
-      container_node = position.ComputeContainerNode();
-      if (!container_node ||
-          !node.IsShadowIncludingInclusiveAncestorOf(*container_node)) {
-        return position;
-      }
-      return Position::InParentBeforeNode(node);
     case PositionAnchorType::kAfterChildren:
       container_node = position.ComputeContainerNode();
       if (!container_node ||
diff --git a/third_party/blink/renderer/core/editing/position.cc b/third_party/blink/renderer/core/editing/position.cc
index 1a98cb7..d76273e 100644
--- a/third_party/blink/renderer/core/editing/position.cc
+++ b/third_party/blink/renderer/core/editing/position.cc
@@ -180,7 +180,6 @@
     return nullptr;
 
   switch (AnchorType()) {
-    case PositionAnchorType::kBeforeChildren:
     case PositionAnchorType::kAfterChildren:
     case PositionAnchorType::kOffsetInAnchor:
       return anchor_node_.Get();
@@ -215,8 +214,6 @@
     return 0;
 
   switch (AnchorType()) {
-    case PositionAnchorType::kBeforeChildren:
-      return 0;
     case PositionAnchorType::kAfterChildren:
       return LastOffsetInNode(*anchor_node_);
     case PositionAnchorType::kOffsetInAnchor:
@@ -282,8 +279,6 @@
   if (!anchor_node_)
     return nullptr;
   switch (AnchorType()) {
-    case PositionAnchorType::kBeforeChildren:
-      return nullptr;
     case PositionAnchorType::kAfterChildren:
       return Strategy::LastChild(*anchor_node_);
     case PositionAnchorType::kOffsetInAnchor:
@@ -303,8 +298,6 @@
     return nullptr;
 
   switch (AnchorType()) {
-    case PositionAnchorType::kBeforeChildren:
-      return Strategy::FirstChild(*anchor_node_);
     case PositionAnchorType::kAfterChildren:
       return nullptr;
     case PositionAnchorType::kOffsetInAnchor:
@@ -376,6 +369,13 @@
 }
 
 template <typename Strategy>
+bool PositionTemplate<Strategy>::IsBeforeChildren() const {
+  if (IsBeforeAnchor())
+    return !Strategy::PreviousSibling(*anchor_node_);
+  return IsOffsetInAnchor() && !offset_;
+}
+
+template <typename Strategy>
 bool PositionTemplate<Strategy>::IsConnected() const {
   return IsPositionConnected(*this);
 }
@@ -456,7 +456,6 @@
   switch (anchor_type_) {
     case PositionAnchorType::kOffsetInAnchor:
       return offset_ == 0;
-    case PositionAnchorType::kBeforeChildren:
     case PositionAnchorType::kBeforeAnchor:
       return true;
     case PositionAnchorType::kAfterChildren:
@@ -550,10 +549,7 @@
 template <typename Strategy>
 PositionTemplate<Strategy> PositionTemplate<Strategy>::FirstPositionInNode(
     const Node& anchor_node) {
-  if (anchor_node.IsTextNode())
-    return PositionTemplate<Strategy>(anchor_node, 0);
-  return PositionTemplate<Strategy>(&anchor_node,
-                                    PositionAnchorType::kBeforeChildren);
+  return PositionTemplate<Strategy>(anchor_node, 0);
 }
 
 // static
@@ -660,8 +656,6 @@
       return Position::LastPositionInNode(*anchor_node);
     case PositionAnchorType::kAfterAnchor:
       return Position::AfterNode(*anchor_node);
-    case PositionAnchorType::kBeforeChildren:
-      return Position::FirstPositionInNode(*anchor_node);
     case PositionAnchorType::kBeforeAnchor:
       return Position::BeforeNode(*anchor_node);
     case PositionAnchorType::kOffsetInAnchor: {
@@ -694,8 +688,6 @@
       builder.Append("]");
       return builder.ToString();
     }
-    case PositionAnchorType::kBeforeChildren:
-      return "beforeChildren";
     case PositionAnchorType::kAfterChildren:
       return "afterChildren";
     case PositionAnchorType::kBeforeAnchor:
@@ -751,8 +743,6 @@
       return ostream << "afterChildren";
     case PositionAnchorType::kBeforeAnchor:
       return ostream << "beforeAnchor";
-    case PositionAnchorType::kBeforeChildren:
-      return ostream << "beforeChildren";
     case PositionAnchorType::kOffsetInAnchor:
       return ostream << "offsetInAnchor";
   }
diff --git a/third_party/blink/renderer/core/editing/position.h b/third_party/blink/renderer/core/editing/position.h
index 71a7014..e671ec25 100644
--- a/third_party/blink/renderer/core/editing/position.h
+++ b/third_party/blink/renderer/core/editing/position.h
@@ -40,7 +40,6 @@
   kOffsetInAnchor,
   kBeforeAnchor,
   kAfterAnchor,
-  kBeforeChildren,
   kAfterChildren,
 };
 
@@ -98,9 +97,7 @@
   bool IsBeforeAnchor() const {
     return anchor_type_ == PositionAnchorType::kBeforeAnchor;
   }
-  bool IsBeforeChildren() const {
-    return anchor_type_ == PositionAnchorType::kBeforeChildren;
-  }
+  bool IsBeforeChildren() const;
   bool IsOffsetInAnchor() const {
     return anchor_type_ == PositionAnchorType::kOffsetInAnchor;
   }
@@ -135,7 +132,6 @@
   // Returns an offset for editing based on anchor type for using with
   // |AnchorNode()| function:
   //   - kOffsetInAnchor  offset_
-  //   - kBeforeChildren  0
   //   - kBeforeAnchor    0
   //   - kAfterChildren   last editing offset in anchor node
   //   - kAfterAnchor     last editing offset in anchor node
diff --git a/third_party/blink/renderer/core/editing/selection_controller_test.cc b/third_party/blink/renderer/core/editing/selection_controller_test.cc
index 34e2164..e232578d 100644
--- a/third_party/blink/renderer/core/editing/selection_controller_test.cc
+++ b/third_party/blink/renderer/core/editing/selection_controller_test.cc
@@ -35,8 +35,7 @@
 
   static PositionWithAffinity GetPositionFromHitTestResult(
       const HitTestResult& hit_test_result) {
-    return hit_test_result.InnerNode()->GetLayoutObject()->PositionForPoint(
-        hit_test_result.LocalPoint());
+    return hit_test_result.GetPosition();
   }
 
   PositionWithAffinity GetPositionAtLocation(const IntPoint& point) {
diff --git a/third_party/blink/renderer/core/editing/selection_editor.cc b/third_party/blink/renderer/core/editing/selection_editor.cc
index 8937677..31f71d5 100644
--- a/third_party/blink/renderer/core/editing/selection_editor.cc
+++ b/third_party/blink/renderer/core/editing/selection_editor.cc
@@ -318,7 +318,6 @@
   Node* const anchor_node = position.AnchorNode();
   const Node& node_to_be_removed = node_to_be_removed_with_index.GetNode();
   switch (position.AnchorType()) {
-    case PositionAnchorType::kBeforeChildren:
     case PositionAnchorType::kAfterChildren:
       return position;
     case PositionAnchorType::kBeforeAnchor:
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 c7aa8126..3a4887f4 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
@@ -206,10 +206,6 @@
 
   IntSize MinimumWindowSize() const override { return IntSize(0, 0); }
 
-  void SetCursor(const ui::Cursor& cursor, LocalFrame* local_frame) override {
-    popup_->WidgetClient()->DidChangeCursor(cursor);
-  }
-
   void SetEventListenerProperties(
       LocalFrame* frame,
       cc::EventListenerClass event_class,
@@ -274,7 +270,6 @@
 // WebPagePopupImpl ----------------------------------------------------------
 
 WebPagePopupImpl::WebPagePopupImpl(
-    WebPagePopupClient* client,
     CrossVariantMojoAssociatedRemote<mojom::blink::PopupWidgetHostInterfaceBase>
         popup_widget_host,
     CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
@@ -282,8 +277,7 @@
     CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
         widget,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-    : web_page_popup_client_(client),
-      popup_widget_host_(std::move(popup_widget_host)),
+    : popup_widget_host_(std::move(popup_widget_host)),
       widget_base_(
           std::make_unique<WidgetBase>(this,
                                        std::move(widget_host),
@@ -292,7 +286,6 @@
                                        /*hidden=*/false,
                                        /*never_composited=*/false,
                                        /*is_for_child_local_root=*/false)) {
-  DCHECK(client);
   popup_widget_host_.set_disconnect_handler(WTF::Bind(
       &WebPagePopupImpl::WidgetHostDisconnected, WTF::Unretained(this)));
 }
@@ -684,6 +677,10 @@
   return MainFrame().GetEventHandler().KeyEvent(event);
 }
 
+cc::LayerTreeHost* WebPagePopupImpl::LayerTreeHostForTesting() {
+  return widget_base_->LayerTreeHost();
+}
+
 void WebPagePopupImpl::BeginMainFrame(base::TimeTicks last_frame_time) {
   if (!page_)
     return;
@@ -862,7 +859,7 @@
 }
 
 void WebPagePopupImpl::ScheduleAnimation() {
-  WidgetClient()->ScheduleAnimation();
+  widget_base_->LayerTreeHost()->SetNeedsAnimate();
 }
 
 void WebPagePopupImpl::UpdateVisualProperties(
@@ -895,13 +892,11 @@
 }
 
 void WebPagePopupImpl::WidgetHostDisconnected() {
-  DCHECK(web_page_popup_client_);
-  web_page_popup_client_->BrowserClosedIpcChannelForPopupWidget();
+  Close();
   // Careful, this is now destroyed.
 }
 
-void WebPagePopupImpl::Close(
-    scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) {
+void WebPagePopupImpl::Close() {
   // If the popup is closed from the renderer via Cancel(), then ClosePopup()
   // has already run on another stack, and destroyed |page_|. If the popup is
   // closed from the browser via IPC to RenderWidget, then we come here first
@@ -914,9 +909,8 @@
     Cancel();
   }
 
-  widget_base_->Shutdown(std::move(cleanup_runner));
+  widget_base_->Shutdown();
   widget_base_.reset();
-  web_page_popup_client_ = nullptr;
 
   // Self-delete on Close().
   Release();
@@ -982,10 +976,6 @@
   return WebDocument(MainFrame().GetDocument());
 }
 
-WebPagePopupClient* WebPagePopupImpl::GetClientForTesting() const {
-  return web_page_popup_client_;
-}
-
 void WebPagePopupImpl::Cancel() {
   if (popup_client_)
     popup_client_->CancelPopup();
@@ -1037,7 +1027,6 @@
 // WebPagePopup ----------------------------------------------------------------
 
 WebPagePopup* WebPagePopup::Create(
-    WebPagePopupClient* client,
     CrossVariantMojoAssociatedRemote<mojom::blink::PopupWidgetHostInterfaceBase>
         popup_widget_host,
     CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
@@ -1045,16 +1034,15 @@
     CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
         widget,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-  CHECK(client);
   // A WebPagePopupImpl instance usually has two references.
   //  - One owned by the instance itself. It represents the visible widget.
   //  - One owned by a WebViewImpl. It's released when the WebViewImpl ask the
   //    WebPagePopupImpl to close.
   // We need them because the closing operation is asynchronous and the widget
   // can be closed while the WebViewImpl is unaware of it.
-  auto popup = base::AdoptRef(new WebPagePopupImpl(
-      client, std::move(popup_widget_host), std::move(widget_host),
-      std::move(widget), task_runner));
+  auto popup = base::AdoptRef(
+      new WebPagePopupImpl(std::move(popup_widget_host), std::move(widget_host),
+                           std::move(widget), task_runner));
   popup->AddRef();
   return popup.get();
 }
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.h b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
index e741d8c..2f70bf20 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.h
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
@@ -100,13 +100,10 @@
     return other && popup_client_ == other->popup_client_;
   }
 
-  WebWidgetClient* WidgetClient() const { return web_page_popup_client_; }
-
   LocalDOMWindow* Window();
 
   // WebPagePopup implementation.
   WebDocument GetDocument() override;
-  WebPagePopupClient* GetClientForTesting() const override;
   void InitializeForTesting(WebView* view) override;
 
   // PagePopup implementation.
@@ -116,6 +113,9 @@
   // PageWidgetEventHandler implementation.
   WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) override;
 
+  // Return the LayerTreeHost backing this popup widget.
+  cc::LayerTreeHost* LayerTreeHostForTesting();
+
  private:
   // WidgetBaseClient overrides:
   void BeginMainFrame(base::TimeTicks last_frame_time) override;
@@ -151,8 +151,7 @@
   void UpdateLifecycle(WebLifecycleUpdate requested_update,
                        DocumentUpdateReason reason) override;
   void Resize(const gfx::Size&) override;
-  void Close(
-      scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) override;
+  void Close() override;
   WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
   void SetFocus(bool) override;
   bool HasFocus() override;
@@ -207,7 +206,6 @@
   void SetWindowRect(const IntRect&) override;
 
   WebPagePopupImpl(
-      WebPagePopupClient*,
       CrossVariantMojoAssociatedRemote<
           mojom::blink::PopupWidgetHostInterfaceBase> popup_widget_host,
       CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
@@ -231,7 +229,6 @@
   void DidShowPopup();
   void DidSetBounds();
 
-  WebPagePopupClient* web_page_popup_client_;
   // This is the WebView that opened the popup.
   WebViewImpl* opener_web_view_ = nullptr;
   // WebPagePopupImpl wraps its own Page that renders the content in the popup.
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 391667f6..cfd091f 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -2291,6 +2291,8 @@
       (new_state->pagehide_dispatch ==
        mojom::blink::PagehideDispatch::kNotDispatched) &&
       GetPage()->DispatchedPagehideAndStillHidden();
+  bool eviction_changed =
+      new_state->eviction_enabled != old_state->eviction_enabled;
 
   if (dispatching_pagehide) {
     RemoveFocusAndTextInputState();
@@ -2311,8 +2313,6 @@
   }
   if (freezing_page)
     SetPageFrozen(true);
-  if (storing_in_bfcache)
-    HookBackForwardCacheEviction(true);
   if (restoring_from_bfcache) {
     DCHECK(page_restore_params);
     // Update the history offset and length value saved in RenderViewImpl, as
@@ -2321,8 +2321,9 @@
     web_view_client_->OnSetHistoryOffsetAndLength(
         page_restore_params->pending_history_list_offset,
         page_restore_params->current_history_list_length);
-    HookBackForwardCacheEviction(false);
   }
+  if (eviction_changed)
+    HookBackForwardCacheEviction(new_state->eviction_enabled);
   if (resuming_page)
     SetPageFrozen(false);
   if (showing_page) {
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index 7c9e811..3aba840 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -807,7 +807,6 @@
 
   base::Optional<mojom::blink::ScreenOrientation> screen_orientation_override_;
 
-  mojom::blink::PageLifecycleStatePtr lifecycle_state_;
   mojo::AssociatedReceiver<mojom::blink::PageBroadcast> receiver_;
 
   // These are observing changes in |renderer_preferences_|. This is used for
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 279b4c4..6e170ce7 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -202,9 +202,6 @@
   cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_; }
   const cc::LayerTreeHost* layer_tree_host() const { return layer_tree_host_; }
 
-  bool AnimationScheduled() const { return animation_scheduled_; }
-  void ClearAnimationScheduled() { animation_scheduled_ = false; }
-
   size_t CursorSetCount() const { return cursor_set_count_; }
 
   bool HaveScrollEventHandlers() const;
@@ -238,7 +235,6 @@
   virtual TestWidgetInputHandlerHost* GetInputHandlerHost();
 
   // WebWidgetClient overrides;
-  void ScheduleAnimation() override { animation_scheduled_ = true; }
   std::unique_ptr<cc::LayerTreeFrameSink> AllocateNewLayerTreeFrameSink()
       override;
   void WillQueueSyntheticEvent(const WebCoalescedInputEvent& event) override;
@@ -277,7 +273,6 @@
   Vector<std::unique_ptr<blink::WebCoalescedInputEvent>>
       injected_scroll_events_;
   std::unique_ptr<TestWidgetInputHandlerHost> widget_input_handler_host_;
-  bool animation_scheduled_ = false;
   size_t cursor_set_count_ = 0;
   viz::FrameSinkId frame_sink_id_;
   mojo::AssociatedReceiver<mojom::blink::WidgetHost> receiver_{this};
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index 99b4d1de..c3db543 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -805,6 +805,10 @@
     if (layout_object && layout_object->Layer())
       layout_object->Layer()->SetNeedsRepaint();
   }
+
+  // Schedule an animation so that a new frame is produced with the updated
+  // layer, otherwise this local root's visible content may not be up to date.
+  owner->GetDocument().GetFrame()->View()->ScheduleAnimation();
 }
 
 void RemoteFrame::AdvanceFocus(mojom::blink::FocusType type,
diff --git a/third_party/blink/renderer/core/frame/reporting_context.cc b/third_party/blink/renderer/core/frame/reporting_context.cc
index 53ff9082de2..83b93cc 100644
--- a/third_party/blink/renderer/core/frame/reporting_context.cc
+++ b/third_party/blink/renderer/core/frame/reporting_context.cc
@@ -5,7 +5,6 @@
 #include "third_party/blink/renderer/core/frame/reporting_context.h"
 
 #include "third_party/blink/public/common/browser_interface_broker_proxy.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/task_type.h"
 #include "third_party/blink/renderer/core/dom/document.h"
diff --git a/third_party/blink/renderer/core/frame/reporting_context_test.cc b/third_party/blink/renderer/core/frame/reporting_context_test.cc
index 3dc9aaf..766ec6f 100644
--- a/third_party/blink/renderer/core/frame/reporting_context_test.cc
+++ b/third_party/blink/renderer/core/frame/reporting_context_test.cc
@@ -31,7 +31,7 @@
   MockReportingServiceProxy(BrowserInterfaceBrokerProxy& broker,
                             base::OnceClosure reached_callback)
       : broker_(broker), reached_callback_(std::move(reached_callback)) {
-    broker.SetBinderForTesting(
+    broker_.SetBinderForTesting(
         ReportingServiceProxy::Name_,
         WTF::BindRepeating(&MockReportingServiceProxy::BindReceiver,
                            WTF::Unretained(this)));
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 f7dcf9c..09cae8a1 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
@@ -218,12 +218,11 @@
 
 // WebFrameWidget ------------------------------------------------------------
 
-static CreateMainFrameWebFrameWidgetFunction
-    g_create_main_frame_web_frame_widget = nullptr;
+static CreateWebFrameWidgetFunction g_create_web_frame_widget = nullptr;
 
-void InstallCreateMainFrameWebFrameWidgetHook(
-    CreateMainFrameWebFrameWidgetFunction create_widget) {
-  g_create_main_frame_web_frame_widget = create_widget;
+void InstallCreateWebFrameWidgetHook(
+    CreateWebFrameWidgetFunction create_widget) {
+  g_create_web_frame_widget = create_widget;
 }
 
 WebFrameWidget* WebFrameWidget::CreateForMainFrame(
@@ -254,14 +253,14 @@
   WebViewImpl& web_view_impl = *main_frame_impl.ViewImpl();
 
   WebFrameWidgetImpl* widget = nullptr;
-  if (g_create_main_frame_web_frame_widget) {
-    widget = g_create_main_frame_web_frame_widget(
+  if (g_create_web_frame_widget) {
+    widget = static_cast<WebFrameWidgetImpl*>(g_create_web_frame_widget(
         base::PassKey<WebFrameWidget>(), *client,
         std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
         std::move(mojo_widget_host), std::move(mojo_widget),
         main_frame->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
         frame_sink_id, hidden, never_composited,
-        /*is_for_child_local_root=*/false, is_for_nested_main_frame);
+        /*is_for_child_local_root=*/false, is_for_nested_main_frame));
   } else {
     // Note: this isn't a leak, as the object has a self-reference that the
     // caller needs to release by calling Close().
@@ -300,15 +299,26 @@
   // root.
   DCHECK(local_root->Parent()->IsWebRemoteFrame());
 
-  // Note: this isn't a leak, as the object has a self-reference that the
-  // caller needs to release by calling Close().
-  auto* widget = MakeGarbageCollected<WebFrameWidgetImpl>(
-      base::PassKey<WebFrameWidget>(), *client,
-      std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
-      std::move(mojo_widget_host), std::move(mojo_widget),
-      local_root->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
-      frame_sink_id, hidden, never_composited, /*is_for_child_local_root=*/true,
-      /*is_for_nested_main_frame=*/false);
+  WebFrameWidgetImpl* widget = nullptr;
+  if (g_create_web_frame_widget) {
+    widget = static_cast<WebFrameWidgetImpl*>(g_create_web_frame_widget(
+        base::PassKey<WebFrameWidget>(), *client,
+        std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
+        std::move(mojo_widget_host), std::move(mojo_widget),
+        local_root->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
+        frame_sink_id, hidden, never_composited,
+        /*is_for_child_local_root=*/true, /*is_for_nested_main_frame=*/false));
+  } else {
+    // Note: this isn't a leak, as the object has a self-reference that the
+    // caller needs to release by calling Close().
+    widget = MakeGarbageCollected<WebFrameWidgetImpl>(
+        base::PassKey<WebFrameWidget>(), *client,
+        std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
+        std::move(mojo_widget_host), std::move(mojo_widget),
+        local_root->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
+        frame_sink_id, hidden, never_composited,
+        /*is_for_child_local_root=*/true, /*is_for_nested_main_frame=*/false);
+  }
   widget->BindLocalRoot(*local_root);
   return widget;
 }
@@ -371,8 +381,7 @@
   main_data().is_for_nested_main_frame = is_nested;
 }
 
-void WebFrameWidgetImpl::Close(
-    scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) {
+void WebFrameWidgetImpl::Close() {
   LocalFrameView* frame_view;
   if (is_for_child_local_root_) {
     frame_view = LocalRootImpl()->GetFrame()->View();
@@ -395,7 +404,7 @@
   local_root_->SetFrameWidget(nullptr);
   local_root_ = nullptr;
   client_ = nullptr;
-  widget_base_->Shutdown(std::move(cleanup_runner));
+  widget_base_->Shutdown();
   widget_base_.reset();
   receiver_.reset();
   input_target_receiver_.reset();
@@ -1237,11 +1246,6 @@
     const PaintImage& image,
     base::OnceCallback<void(bool)> callback) {
   widget_base_->LayerTreeHost()->QueueImageDecode(image, std::move(callback));
-
-  // In web tests the request does not actually cause a commit, because the
-  // compositor is scheduled by the test runner to avoid flakiness. So for this
-  // case we must request a main frame.
-  Client()->ScheduleAnimationForWebTests();
 }
 
 void WebFrameWidgetImpl::Trace(Visitor* visitor) const {
@@ -1383,10 +1387,6 @@
   }
 }
 
-void WebFrameWidgetImpl::WillBeginMainFrame() {
-  Client()->WillBeginMainFrame();
-}
-
 void WebFrameWidgetImpl::DidCompletePageScaleAnimation() {
   // Page scale animations only happen on the main frame.
   DCHECK(ForMainFrame());
@@ -1397,7 +1397,11 @@
 }
 
 void WebFrameWidgetImpl::ScheduleAnimation() {
-  Client()->ScheduleAnimation();
+  if (!View()->does_composite()) {
+    Client()->ScheduleNonCompositedAnimation();
+    return;
+  }
+  widget_base_->LayerTreeHost()->SetNeedsAnimate();
 }
 
 void WebFrameWidgetImpl::FocusChanged(bool enable) {
@@ -1578,10 +1582,6 @@
   }
 }
 
-void WebFrameWidgetImpl::ScheduleAnimationForWebTests() {
-  Client()->ScheduleAnimationForWebTests();
-}
-
 int WebFrameWidgetImpl::GetLayerTreeId() {
   if (!View()->does_composite())
     return 0;
@@ -3938,6 +3938,11 @@
   }
 }
 
+FrameWidgetTestHelper*
+WebFrameWidgetImpl::GetFrameWidgetTestHelperForTesting() {
+  return nullptr;
+}
+
 WebPlugin* WebFrameWidgetImpl::GetFocusedPluginContainer() {
   LocalFrame* focused_frame = FocusedLocalFrameInWidget();
   if (!focused_frame)
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 9c5dc158..b10482b2 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
@@ -128,7 +128,7 @@
   WebRect ComputeBlockBound(const gfx::Point& point_in_root_frame,
                             bool ignore_clipping) const;
 
-  void BindLocalRoot(WebLocalFrame&);
+  virtual void BindLocalRoot(WebLocalFrame&);
 
   // If this widget is for the top most main frame. This is different than
   // |ForMainFrame| because |ForMainFrame| could return true but this method
@@ -181,7 +181,7 @@
   void SetRootLayer(scoped_refptr<cc::Layer>) override;
   void RegisterSelection(cc::LayerSelection selection) final;
   void RequestDecode(const cc::PaintImage&,
-                     base::OnceCallback<void(bool)>) final;
+                     base::OnceCallback<void(bool)>) override;
   void NotifySwapAndPresentationTimeInBlink(
       WebReportTimeCallback swap_callback,
       WebReportTimeCallback presentation_callback) final;
@@ -344,12 +344,13 @@
   void SetZoomLevelForTesting(double zoom_level) override;
   void ResetZoomLevelForTesting() override;
   void SetDeviceScaleFactorForTesting(float factor) override;
+  FrameWidgetTestHelper* GetFrameWidgetTestHelperForTesting() override;
 
   // Called when a drag-n-drop operation should begin.
-  void StartDragging(const WebDragData&,
-                     DragOperationsMask,
-                     const SkBitmap& drag_image,
-                     const gfx::Point& drag_image_offset);
+  virtual void StartDragging(const WebDragData&,
+                             DragOperationsMask,
+                             const SkBitmap& drag_image,
+                             const gfx::Point& drag_image_offset);
 
   bool DoingDragAndDrop() { return doing_drag_and_drop_; }
   static void SetIgnoreInputEvents(bool value) { ignore_input_events_ = value; }
@@ -368,8 +369,7 @@
       const ScreenInfo& screen_info,
       std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory,
       const cc::LayerTreeSettings* settings) override;
-  void Close(
-      scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) override;
+  void Close() override;
   void SetCompositorVisible(bool visible) override;
   gfx::Size Size() override;
   void Resize(const gfx::Size& size_with_dsf) override;
@@ -601,6 +601,12 @@
   // Return the focused WebPlugin if there is one.
   WebPlugin* GetFocusedPluginContainer();
 
+ protected:
+  // WidgetBaseClient overrides:
+  void ScheduleAnimation() override;
+
+  bool doing_drag_and_drop_ = false;
+
  private:
   friend class WebViewImpl;
   friend class ReportTimeSwapPromise;
@@ -629,7 +635,6 @@
       base::TimeDelta first_scroll_delay,
       base::TimeTicks first_scroll_timestamp) override;
   void DidBeginMainFrame() override;
-  void WillBeginMainFrame() override;
   void DidCompletePageScaleAnimation() override;
   void FocusChangeComplete() override;
   bool WillHandleGestureEvent(const WebGestureEvent& event) override;
@@ -644,12 +649,10 @@
   WebTextInputType GetTextInputType() override;
   void SetCursorVisibilityState(bool is_visible) override;
   blink::FrameWidget* FrameWidget() override { return this; }
-  void ScheduleAnimation() override;
   void FocusChanged(bool enable) override;
   bool ShouldAckSyntheticInputImmediately() override;
   void UpdateVisualProperties(
       const VisualProperties& visual_properties) override;
-  void ScheduleAnimationForWebTests() override;
   bool UpdateScreenRects(const gfx::Rect& widget_screen_rect,
                          const gfx::Rect& window_screen_rect) override;
   void OrientationChanged() override;
@@ -808,8 +811,6 @@
   // A copy of the web drop data object we received from the browser.
   Member<DataObject> current_drag_data_;
 
-  bool doing_drag_and_drop_ = false;
-
   // The available drag operations (copy, move link...) allowed by the source.
   DragOperation operations_allowed_ = kDragOperationNone;
 
@@ -993,35 +994,6 @@
   SelfKeepAlive<WebFrameWidgetImpl> self_keep_alive_;
 };
 
-// Convenience type for creation method taken by
-// InstallCreateMainFrameWebFrameWidgetHook(). The method signature matches the
-// WebFrameWidgetImpl constructor.
-using CreateMainFrameWebFrameWidgetFunction =
-    WebFrameWidgetImpl* (*)(base::PassKey<WebFrameWidget>,
-                            WebWidgetClient&,
-                            CrossVariantMojoAssociatedRemote<
-                                mojom::blink::FrameWidgetHostInterfaceBase>
-                                frame_widget_host,
-                            CrossVariantMojoAssociatedReceiver<
-                                mojom::blink::FrameWidgetInterfaceBase>
-                                frame_widget,
-                            CrossVariantMojoAssociatedRemote<
-                                mojom::blink::WidgetHostInterfaceBase>
-                                widget_host,
-                            CrossVariantMojoAssociatedReceiver<
-                                mojom::blink::WidgetInterfaceBase> widget,
-                            scoped_refptr<base::SingleThreadTaskRunner>
-                                task_runner,
-                            const viz::FrameSinkId& frame_sink_id,
-                            bool hidden,
-                            bool never_composited,
-                            bool is_for_child_local_root,
-                            bool is_for_nested_main_frame);
-// Overrides the implementation of WebFrameWidget::CreateForMainFrame() function
-// below. Used by tests to override some functionality on WebFrameWidgetImpl.
-void CORE_EXPORT InstallCreateMainFrameWebFrameWidgetHook(
-    CreateMainFrameWebFrameWidgetFunction create_widget);
-
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_test.cc b/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
index 7b5e664..315b26f 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
@@ -240,7 +240,7 @@
   MOCK_METHOD1(WillHandleGestureEvent, bool(const WebGestureEvent& event));
 };
 
-WebFrameWidgetImpl* CreateMainFrameWebFrameWidget(
+WebFrameWidget* CreateWebFrameWidget(
     base::PassKey<WebFrameWidget> pass_key,
     WebWidgetClient& client,
     CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>
@@ -266,7 +266,7 @@
 class WebFrameWidgetImplSimTest : public SimTest {
  public:
   void SetUp() override {
-    InstallCreateMainFrameWebFrameWidgetHook(CreateMainFrameWebFrameWidget);
+    InstallCreateWebFrameWidgetHook(CreateWebFrameWidget);
     SimTest::SetUp();
   }
 
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
index fdff389..ec4550e0 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -295,7 +295,9 @@
 
  private:
   // cc::ContentLayerClient implementation
-  gfx::Rect PaintableRegion() override { return gfx::Rect(layer_->bounds()); }
+  gfx::Rect PaintableRegion() const override {
+    return gfx::Rect(layer_->bounds());
+  }
   bool FillsBoundsCompletely() const override { return false; }
 
   scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() override {
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.cc b/third_party/blink/renderer/core/layout/hit_test_result.cc
index 493aec23..774783b 100644
--- a/third_party/blink/renderer/core/layout/hit_test_result.cc
+++ b/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -186,8 +186,13 @@
   // relayout?
   if (box_fragment_ &&
       RuntimeEnabledFeatures::LayoutNGFullPositionForPointEnabled() &&
-      !box_fragment_->IsLayoutObjectDestroyedOrMoved())
-    return box_fragment_->PostLayout()->PositionForPoint(LocalPoint());
+      !box_fragment_->IsLayoutObjectDestroyedOrMoved()) {
+    const NGPhysicalBoxFragment* fragment = box_fragment_->PostLayout();
+    // When the node is an inline object, |fragment| is the container fragment,
+    // and |LocalPoint()| is relative to the content.
+    const bool is_content_offset = fragment->GetLayoutObject() != layout_object;
+    return fragment->PositionForPoint(LocalPoint(), is_content_offset);
+  }
   return layout_object->PositionForPoint(LocalPoint());
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
index 9e60515c..c7118d7 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -36,6 +36,14 @@
 
 template <typename Base>
 void LayoutNGMixin<Base>::Paint(const PaintInfo& paint_info) const {
+  // When |this| is NG block fragmented, the painter should traverse fragments
+  // instead of |LayoutObject|, because this function cannot handle block
+  // fragmented objects. We can come here only when |this| cannot traverse
+  // fragments, or the parent is legacy.
+  DCHECK(!Base::CanTraversePhysicalFragments() ||
+         !Base::Parent()->CanTraversePhysicalFragments());
+  DCHECK_LE(Base::PhysicalFragmentCount(), 1u);
+
   // Avoid painting dirty objects because descendants maybe already destroyed.
   if (UNLIKELY(Base::NeedsLayout() &&
                !Base::ChildLayoutBlockedByDisplayLock())) {
@@ -43,8 +51,11 @@
     return;
   }
 
-  if (const NGPhysicalBoxFragment* fragment = CurrentFragment())
+  if (Base::PhysicalFragmentCount()) {
+    const NGPhysicalBoxFragment* fragment = Base::GetPhysicalFragment(0);
+    DCHECK(fragment);
     NGBoxFragmentPainter(*fragment).Paint(paint_info);
+  }
 }
 
 template <typename Base>
@@ -52,8 +63,14 @@
                                       const HitTestLocation& hit_test_location,
                                       const PhysicalOffset& accumulated_offset,
                                       HitTestAction action) {
-  if (const NGPhysicalBoxFragment* fragment = CurrentFragment()) {
-    DCHECK_EQ(Base::PhysicalFragmentCount(), 1u);
+  // See |Paint()|.
+  DCHECK(!Base::CanTraversePhysicalFragments() ||
+         !Base::Parent()->CanTraversePhysicalFragments());
+  DCHECK_LE(Base::PhysicalFragmentCount(), 1u);
+
+  if (Base::PhysicalFragmentCount()) {
+    const NGPhysicalBoxFragment* fragment = Base::GetPhysicalFragment(0);
+    DCHECK(fragment);
     return NGBoxFragmentPainter(*fragment).NodeAtPoint(
         result, hit_test_location, accumulated_offset, action);
   }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index a9d61e9..16373e3 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -802,7 +802,8 @@
 }
 
 PositionWithAffinity NGPhysicalBoxFragment::PositionForPoint(
-    PhysicalOffset point) const {
+    PhysicalOffset point,
+    bool is_content_offset) const {
   if (layout_object_->IsBox() && !layout_object_->IsLayoutNGObject()) {
     // Layout engine boundary. Enter legacy PositionForPoint().
     return layout_object_->PositionForPoint(point);
@@ -816,7 +817,7 @@
   DCHECK(!IsAtomicInline() ||
          PhysicalRect(PhysicalOffset(), Size()).Contains(point));
 
-  if (IsScrollContainer())
+  if (!is_content_offset && IsScrollContainer())
     point += PhysicalOffset(PixelSnappedScrolledContentOffset());
 
   if (const NGFragmentItems* items = Items()) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
index 58cd4b5..5aaee83f 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -246,7 +246,10 @@
                        NGOutlineType include_block_overflows,
                        Vector<PhysicalRect>* outline_rects) const;
 
-  PositionWithAffinity PositionForPoint(PhysicalOffset) const;
+  // When |is_content_offset|, the offset is relative to the content, not to the
+  // scroll container.
+  PositionWithAffinity PositionForPoint(PhysicalOffset,
+                                        bool is_content_offset = false) const;
 
   UBiDiLevel BidiLevel() const;
 
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources.cc b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
index 6b8522c..4d016f8 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_resources.cc
+++ b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
@@ -698,16 +698,14 @@
   LayoutObject* layout_object = element_->GetLayoutObject();
   if (!layout_object)
     return;
-  ClearFilterData();
+  // TODO(fs): If the resource element (for a filter) doesn't actually change
+  // we don't need to perform the associated invalidations.
+  InvalidateFilterData();
   if (layout_object->Parent()) {
     SVGResourcesCache::UpdateResources(*layout_object);
     LayoutSVGResourceContainer::MarkForLayoutAndParentResourceInvalidation(
         *layout_object, true);
   }
-  // TODO(fs): If the resource element (for a filter) doesn't actually change
-  // we don't need to perform the associated invalidations.
-  layout_object->SetNeedsPaintPropertyUpdate();
-  MarkFilterDataDirty();
 }
 
 void SVGElementResourceClient::ResourceDestroyed(
@@ -773,20 +771,17 @@
 }
 
 void SVGElementResourceClient::InvalidateFilterData() {
-  if (!ClearFilterData())
+  // If we performed an "optimized" invalidation via FilterPrimitiveChanged(),
+  // we could have set |filter_data_dirty_| but not cleared |filter_data_|.
+  if (filter_data_dirty_ && !filter_data_)
     return;
+  if (FilterData* filter_data = filter_data_.Release())
+    filter_data->Dispose();
   LayoutObject* layout_object = element_->GetLayoutObject();
   layout_object->SetNeedsPaintPropertyUpdate();
   MarkFilterDataDirty();
 }
 
-bool SVGElementResourceClient::ClearFilterData() {
-  FilterData* filter_data = filter_data_.Release();
-  if (filter_data)
-    filter_data->Dispose();
-  return !!filter_data;
-}
-
 void SVGElementResourceClient::MarkFilterDataDirty() {
   DCHECK(element_->GetLayoutObject());
   DCHECK(element_->GetLayoutObject()->NeedsPaintPropertyUpdate());
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources.h b/third_party/blink/renderer/core/layout/svg/svg_resources.h
index d830137..34c7ca8f 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_resources.h
+++ b/third_party/blink/renderer/core/layout/svg/svg_resources.h
@@ -225,7 +225,6 @@
 
   void UpdateFilterData(CompositorFilterOperations&);
   void InvalidateFilterData();
-  bool ClearFilterData();
   void MarkFilterDataDirty();
 
   void Trace(Visitor*) const override;
diff --git a/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc b/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
index 58d9f3e2..61018715 100644
--- a/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
+++ b/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
@@ -472,9 +472,9 @@
 
     // adjust table max width if needed
     if (cell_logical_width.IsPercentOrCalc()) {
-      if (total_percent > cell_logical_width.Percent() ||
+      if (total_percent >= cell_logical_width.Percent() ||
           all_cols_are_percent) {
-        // can't satify this condition, treat as variable
+        // can't satisfy this condition, treat as variable
         cell_logical_width = Length();
       } else {
         max_logical_width =
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
index 8461220..dce0028 100644
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -945,6 +945,11 @@
   if (scrolling_coordinator_)
     scrolling_coordinator_->WillCloseAnimationHost(view);
   GetLinkHighlight().WillCloseAnimationHost();
+
+  // We may have disconnected the associated LayerTreeHost during
+  // the frame lifecycle so ensure the PageAnimator is reset to the
+  // default state.
+  animator_->SetSuppressFrameRequestsWorkaroundFor704763Only(false);
 }
 
 void Page::WillBeDestroyed() {
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
index 2f5a71d..f8fe224 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
@@ -9,6 +9,7 @@
 #include "base/strings/strcat.h"
 #include "base/time/default_tick_clock.h"
 #include "base/trace_event/trace_event.h"
+#include "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 
@@ -93,6 +94,11 @@
     UseCounter::Count(document_, WebFeature::kTextFragmentAnchorMatchFound);
   }
 
+  shared_highlighting::LogLinkOpenedUkmEvent(
+      document_->UkmRecorder(), document_->UkmSourceID(),
+      KURL(document_->referrer()),
+      /*success=*/matches_.size() == selector_count_);
+
   std::string uma_prefix = GetPrefixForHistograms();
 
   base::UmaHistogramCounts100(base::StrCat({uma_prefix, "SelectorCount"}),
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
index d311586..b15c8dc 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
@@ -5,6 +5,8 @@
 #include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h"
 
 #include "base/test/simple_test_tick_clock.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/scroll/scroll_enums.mojom-blink.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -20,10 +22,11 @@
 
 namespace blink {
 
-namespace {
-
 using test::RunPendingTasks;
 
+const char kSuccessUkmMetric[] = "Success";
+const char kSourceUkmMetric[] = "Source";
+
 class TextFragmentAnchorMetricsTest : public SimTest {
  public:
   void SetUp() override {
@@ -59,7 +62,12 @@
     Compositor().BeginFrame();
   }
 
+ protected:
   HistogramTester histogram_tester_;
+
+  // TODO(crbug.com/1153990): Find a better mocking solution and clean up this
+  // variable.
+  std::unique_ptr<ukm::UkmRecorder> old_ukm_recorder_;
 };
 
 // Test UMA metrics collection
@@ -1533,6 +1541,91 @@
       "TextFragmentAnchor.Unknown.SpansMultipleBlocks", 0, 1);
 }
 
-}  // namespace
+// Tests that a LinkOpened UKM Event is recorded upon a successful fragment
+// highlight.
+TEST_F(TextFragmentAnchorMetricsTest, LinkOpenedSuccessUKM) {
+  SimRequest request("https://example.com/test.html#:~:text=test%20page",
+                     "text/html");
+  LoadURL("https://example.com/test.html#:~:text=test%20page");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      body {
+        height: 2200px;
+      }
+      p {
+        position: absolute;
+        top: 1000px;
+      }
+    </style>
+    <p>This is a test page</p>
+  )HTML");
+  RunAsyncMatchingTasks();
+
+  // Stub UKM Recorder. Set the older recorder as member variable as other
+  // instances might depend on it. Its destruction would cause the test to crash
+  // during teardown.
+  old_ukm_recorder_ = std::move(GetDocument().ukm_recorder_);
+  GetDocument().ukm_recorder_ = std::make_unique<ukm::TestUkmRecorder>();
+
+  // Render two frames to handle the async step added by the beforematch event.
+  Compositor().BeginFrame();
+  BeginEmptyFrame();
+
+  auto* recorder =
+      static_cast<ukm::TestUkmRecorder*>(GetDocument().UkmRecorder());
+
+  auto entries = recorder->GetEntriesByName(
+      ukm::builders::SharedHighlights_LinkOpened::kEntryName);
+  ASSERT_EQ(1u, entries.size());
+  const ukm::mojom::UkmEntry* entry = entries[0];
+  EXPECT_EQ(GetDocument().UkmSourceID(), entry->source_id);
+  recorder->ExpectEntryMetric(entry, kSuccessUkmMetric, /*success=*/true);
+  EXPECT_TRUE(recorder->GetEntryMetric(entry, kSourceUkmMetric));
+}
+
+// Tests that a LinkOpened UKM Event is recorded upon a failed fragment
+// highlight.
+TEST_F(TextFragmentAnchorMetricsTest, LinkOpenedFailedUKM) {
+  SimRequest request(
+      "https://example.com/test.html#:~:text=not%20on%20the%20page",
+      "text/html");
+  LoadURL("https://example.com/test.html#:~:text=not%20on%20the%20page");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      body {
+        height: 2200px;
+      }
+      p {
+        position: absolute;
+        top: 1000px;
+      }
+    </style>
+    <p>This is a test page</p>
+  )HTML");
+  RunAsyncMatchingTasks();
+
+  // Stub UKM Recorder. Set the older recorder as member variable as other
+  // instances might depend on it. Its destruction would cause the test to crash
+  // during teardown.
+  old_ukm_recorder_ = std::move(GetDocument().ukm_recorder_);
+  GetDocument().ukm_recorder_ = std::make_unique<ukm::TestUkmRecorder>();
+
+  // Render two frames to handle the async step added by the beforematch event.
+  Compositor().BeginFrame();
+  BeginEmptyFrame();
+
+  auto* recorder =
+      static_cast<ukm::TestUkmRecorder*>(GetDocument().UkmRecorder());
+
+  auto entries = recorder->GetEntriesByName(
+      ukm::builders::SharedHighlights_LinkOpened::kEntryName);
+  ASSERT_EQ(1u, entries.size());
+  const ukm::mojom::UkmEntry* entry = entries[0];
+  EXPECT_EQ(GetDocument().UkmSourceID(), entry->source_id);
+  recorder->ExpectEntryMetric(entry, kSuccessUkmMetric, /*success=*/false);
+  EXPECT_TRUE(recorder->GetEntryMetric(entry, kSourceUkmMetric));
+}
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
index 11cda75..bc342d2 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
@@ -363,6 +363,9 @@
       "SharedHighlights.LinkGenerated",
       selector.Type() != TextFragmentSelector::SelectorType::kInvalid);
 
+  ukm::UkmRecorder* recorder = selection_frame_->GetDocument()->UkmRecorder();
+  ukm::SourceId source_id = selection_frame_->GetDocument()->UkmSourceID();
+
   if (selector.Type() != TextFragmentSelector::SelectorType::kInvalid) {
     UMA_HISTOGRAM_COUNTS_1000("SharedHighlights.LinkGenerated.ParamLength",
                               selector.ToString().length());
@@ -375,6 +378,8 @@
     UMA_HISTOGRAM_ENUMERATION(
         "SharedHighlights.LinkGenerated.SelectorParameters",
         TextFragmentAnchorMetrics::GetParametersForSelector(selector));
+
+    shared_highlighting::LogLinkGeneratedSuccessUkmEvent(recorder, source_id);
   } else {
     UMA_HISTOGRAM_EXACT_LINEAR(
         "SharedHighlights.LinkGenerated.Error.Iterations", iteration_,
@@ -383,8 +388,11 @@
                         base::DefaultTickClock::GetInstance()->NowTicks() -
                             generation_start_time_);
 
-    shared_highlighting::LogLinkGenerationErrorReason(
-        error_.has_value() ? error_.value() : LinkGenerationError::kUnknown);
+    LinkGenerationError error =
+        error_.has_value() ? error_.value() : LinkGenerationError::kUnknown;
+    shared_highlighting::LogLinkGenerationErrorReason(error);
+    shared_highlighting::LogLinkGeneratedErrorUkmEvent(recorder, source_id,
+                                                       error);
   }
 
   std::move(pending_generate_selector_callback_).Run(selector.ToString());
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
index a2affb3..65cdfb4ef 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
@@ -10,7 +10,9 @@
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
+#include "components/ukm/test_ukm_recorder.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/mojom/link_to_text/link_to_text.mojom-blink.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
@@ -23,6 +25,11 @@
 
 namespace blink {
 
+namespace {
+const char kSuccessUkmMetric[] = "Success";
+const char kErrorUkmMetric[] = "Error";
+}  // namespace
+
 class TextFragmentSelectorGeneratorTest : public SimTest {
  public:
   void SetUp() override {
@@ -39,6 +46,16 @@
     // Should not have logged errors in a success case.
     histogram_tester_.ExpectTotalCount("SharedHighlights.LinkGenerated.Error",
                                        0);
+
+    auto* recorder =
+        static_cast<ukm::TestUkmRecorder*>(GetDocument().UkmRecorder());
+    auto entries = recorder->GetEntriesByName(
+        ukm::builders::SharedHighlights_LinkGenerated::kEntryName);
+    ASSERT_EQ(1u, entries.size());
+    const ukm::mojom::UkmEntry* entry = entries[0];
+    EXPECT_EQ(GetDocument().UkmSourceID(), entry->source_id);
+    recorder->ExpectEntryMetric(entry, kSuccessUkmMetric, true);
+    EXPECT_FALSE(recorder->GetEntryMetric(entry, kErrorUkmMetric));
   }
 
   void VerifySelectorFails(Position selected_start,
@@ -49,9 +66,22 @@
 
     histogram_tester_.ExpectBucketCount("SharedHighlights.LinkGenerated.Error",
                                         error, 1);
+
+    auto* recorder =
+        static_cast<ukm::TestUkmRecorder*>(GetDocument().UkmRecorder());
+    auto entries = recorder->GetEntriesByName(
+        ukm::builders::SharedHighlights_LinkGenerated::kEntryName);
+    ASSERT_EQ(1u, entries.size());
+    const ukm::mojom::UkmEntry* entry = entries[0];
+    EXPECT_EQ(GetDocument().UkmSourceID(), entry->source_id);
+    recorder->ExpectEntryMetric(entry, kSuccessUkmMetric, false);
+    recorder->ExpectEntryMetric(entry, kErrorUkmMetric,
+                                static_cast<int64_t>(error));
   }
 
   String GenerateSelector(Position selected_start, Position selected_end) {
+    StubUkmRecorder();
+
     GetDocument()
         .GetFrame()
         ->GetTextFragmentSelectorGenerator()
@@ -78,8 +108,19 @@
     return selector;
   }
 
- private:
+ protected:
+  void StubUkmRecorder() {
+    // Needed to keep old recorders alive, as other instances might depend on
+    // one of them, causing tests to crash during teardown.
+    old_ukm_recorders_.push_back(std::move(GetDocument().ukm_recorder_));
+    GetDocument().ukm_recorder_ = std::make_unique<ukm::TestUkmRecorder>();
+  }
+
   base::HistogramTester histogram_tester_;
+
+  // TODO(crbug.com/1153990): Find a better mocking solution and clean up this
+  // variable.
+  std::vector<std::unique_ptr<ukm::UkmRecorder>> old_ukm_recorders_;
 };
 
 // Basic exact selector case.
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
index 0b1bf61..40815af 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -52,8 +52,8 @@
         previous_interest_rect, new_interest_rect, layer_size);
   }
 
-  IntRect PreviousInterestRect(const GraphicsLayer* graphics_layer) {
-    return graphics_layer->previous_interest_rect_;
+  gfx::Rect PaintableRegion(const GraphicsLayer* graphics_layer) {
+    return graphics_layer->PaintableRegion();
   }
 
   static const GraphicsLayerPaintInfo* GetSquashedLayer(
@@ -620,8 +620,7 @@
   UpdateAllLifecyclePhasesForTest();
   GraphicsLayer* root_scrolling_layer =
       GetDocument().GetLayoutView()->Layer()->GraphicsLayerBacking();
-  EXPECT_EQ(IntRect(0, 0, 800, 4600),
-            PreviousInterestRect(root_scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 4600), PaintableRegion(root_scrolling_layer));
 
   GetDocument().View()->LayoutViewport()->SetScrollOffset(
       ScrollOffset(0, 300), mojom::blink::ScrollType::kProgrammatic);
@@ -630,8 +629,7 @@
   // changed enough.
   EXPECT_EQ(IntRect(0, 0, 800, 4900),
             RecomputeInterestRect(root_scrolling_layer));
-  EXPECT_EQ(IntRect(0, 0, 800, 4600),
-            PreviousInterestRect(root_scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 4600), PaintableRegion(root_scrolling_layer));
 
   GetDocument().View()->LayoutViewport()->SetScrollOffset(
       ScrollOffset(0, 600), mojom::blink::ScrollType::kProgrammatic);
@@ -639,16 +637,15 @@
   // Use recomputed interest rect because it changed enough.
   EXPECT_EQ(IntRect(0, 0, 800, 5200),
             RecomputeInterestRect(root_scrolling_layer));
-  EXPECT_EQ(IntRect(0, 0, 800, 5200),
-            PreviousInterestRect(root_scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 5200), PaintableRegion(root_scrolling_layer));
 
   GetDocument().View()->LayoutViewport()->SetScrollOffset(
       ScrollOffset(0, 5400), mojom::blink::ScrollType::kProgrammatic);
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(IntRect(0, 1400, 800, 8600),
             RecomputeInterestRect(root_scrolling_layer));
-  EXPECT_EQ(IntRect(0, 1400, 800, 8600),
-            PreviousInterestRect(root_scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 1400, 800, 8600),
+            PaintableRegion(root_scrolling_layer));
 
   GetDocument().View()->LayoutViewport()->SetScrollOffset(
       ScrollOffset(0, 9000), mojom::blink::ScrollType::kProgrammatic);
@@ -657,8 +654,8 @@
   // interest rect.
   EXPECT_EQ(IntRect(0, 5000, 800, 5000),
             RecomputeInterestRect(root_scrolling_layer));
-  EXPECT_EQ(IntRect(0, 1400, 800, 8600),
-            PreviousInterestRect(root_scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 1400, 800, 8600),
+            PaintableRegion(root_scrolling_layer));
 
   GetDocument().View()->LayoutViewport()->SetScrollOffset(
       ScrollOffset(0, 2000), mojom::blink::ScrollType::kProgrammatic);
@@ -666,8 +663,7 @@
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(IntRect(0, 0, 800, 6600),
             RecomputeInterestRect(root_scrolling_layer));
-  EXPECT_EQ(IntRect(0, 0, 800, 6600),
-            PreviousInterestRect(root_scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 6600), PaintableRegion(root_scrolling_layer));
 }
 
 TEST_F(CompositedLayerMappingTest, InterestRectChangeOnShrunkenViewport) {
@@ -682,16 +678,14 @@
   UpdateAllLifecyclePhasesForTest();
   GraphicsLayer* root_scrolling_layer =
       GetDocument().GetLayoutView()->Layer()->GraphicsLayerBacking();
-  EXPECT_EQ(IntRect(0, 0, 800, 4600),
-            PreviousInterestRect(root_scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 4600), PaintableRegion(root_scrolling_layer));
 
   GetDocument().View()->SetFrameRect(IntRect(0, 0, 800, 60));
   UpdateAllLifecyclePhasesForTest();
   // Repaint required, so interest rect should be updated to shrunken size.
   EXPECT_EQ(IntRect(0, 0, 800, 4060),
             RecomputeInterestRect(root_scrolling_layer));
-  EXPECT_EQ(IntRect(0, 0, 800, 4060),
-            PreviousInterestRect(root_scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 4060), PaintableRegion(root_scrolling_layer));
 }
 
 TEST_F(CompositedLayerMappingTest, InterestRectChangeOnScroll) {
@@ -713,26 +707,26 @@
   Element* scroller = GetDocument().getElementById("scroller");
   GraphicsLayer* scrolling_layer =
       scroller->GetLayoutBox()->Layer()->GraphicsLayerBacking();
-  EXPECT_EQ(IntRect(0, 0, 400, 4400), PreviousInterestRect(scrolling_layer));
+  EXPECT_EQ(IntRect(0, 0, 400, 4400), PaintableRegion(scrolling_layer));
 
   scroller->setScrollTop(300);
   UpdateAllLifecyclePhasesForTest();
   // Still use the previous interest rect because the recomputed rect hasn't
   // changed enough.
   EXPECT_EQ(IntRect(0, 0, 400, 4700), RecomputeInterestRect(scrolling_layer));
-  EXPECT_EQ(IntRect(0, 0, 400, 4400), PreviousInterestRect(scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 400, 4400), PaintableRegion(scrolling_layer));
 
   scroller->setScrollTop(600);
   UpdateAllLifecyclePhasesForTest();
   // Use recomputed interest rect because it changed enough.
   EXPECT_EQ(IntRect(0, 0, 400, 5000), RecomputeInterestRect(scrolling_layer));
-  EXPECT_EQ(IntRect(0, 0, 400, 5000), PreviousInterestRect(scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 400, 5000), PaintableRegion(scrolling_layer));
 
   scroller->setScrollTop(5600);
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(IntRect(0, 1600, 400, 8400),
             RecomputeInterestRect(scrolling_layer));
-  EXPECT_EQ(IntRect(0, 1600, 400, 8400), PreviousInterestRect(scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 1600, 400, 8400), PaintableRegion(scrolling_layer));
 
   scroller->setScrollTop(9000);
   UpdateAllLifecyclePhasesForTest();
@@ -740,13 +734,13 @@
   // interest rect.
   EXPECT_EQ(IntRect(0, 5000, 400, 5000),
             RecomputeInterestRect(scrolling_layer));
-  EXPECT_EQ(IntRect(0, 1600, 400, 8400), PreviousInterestRect(scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 1600, 400, 8400), PaintableRegion(scrolling_layer));
 
   scroller->setScrollTop(2000);
   // Use recomputed interest rect because it changed enough.
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(IntRect(0, 0, 400, 6400), RecomputeInterestRect(scrolling_layer));
-  EXPECT_EQ(IntRect(0, 0, 400, 6400), PreviousInterestRect(scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 0, 400, 6400), PaintableRegion(scrolling_layer));
 }
 
 TEST_F(CompositedLayerMappingTest,
@@ -776,14 +770,14 @@
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(IntRect(0, 5400, 400, 4600),
             RecomputeInterestRect(scrolling_layer));
-  EXPECT_EQ(IntRect(0, 5400, 400, 4600), PreviousInterestRect(scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 5400, 400, 4600), PaintableRegion(scrolling_layer));
 
   // Paint invalidation and repaint should change previous paint interest rect.
   GetDocument().getElementById("content")->setTextContent("Change");
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(IntRect(0, 5400, 400, 4600),
             RecomputeInterestRect(scrolling_layer));
-  EXPECT_EQ(IntRect(0, 5400, 400, 4600), PreviousInterestRect(scrolling_layer));
+  EXPECT_EQ(gfx::Rect(0, 5400, 400, 4600), PaintableRegion(scrolling_layer));
 }
 
 TEST_F(CompositedLayerMappingTest,
@@ -1426,8 +1420,8 @@
   UpdateAllLifecyclePhasesForTest();
 
   EXPECT_EQ(
-      IntRect(0, 1000, 200, 5000),
-      squashed->GroupedMapping()->SquashingLayer(*squashed)->InterestRect());
+      gfx::Rect(0, 1000, 200, 5000),
+      PaintableRegion(squashed->GroupedMapping()->SquashingLayer(*squashed)));
 }
 
 TEST_F(CompositedLayerMappingTest,
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index 666a9cf..e3174ca3 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -154,7 +154,7 @@
   layer_->ClearClient();
 }
 
-gfx::Rect LinkHighlightImpl::LinkHighlightFragment::PaintableRegion() {
+gfx::Rect LinkHighlightImpl::LinkHighlightFragment::PaintableRegion() const {
   return gfx::Rect(layer_->bounds());
 }
 
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.h b/third_party/blink/renderer/core/paint/link_highlight_impl.h
index d4a41d2..d4f6df1 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.h
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.h
@@ -101,7 +101,7 @@
 
    private:
     // cc::ContentLayerClient implementation.
-    gfx::Rect PaintableRegion() override;
+    gfx::Rect PaintableRegion() const override;
     scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() override;
     bool FillsBoundsCompletely() const override { return false; }
 
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
index 409273d..ea61d52 100644
--- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
+++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -219,7 +219,8 @@
                 "max-height", "VerticalAlignLength", "box-sizing", "align-content",
                 "align-items", "align-self", "justify-content", "justify-items",
                 "justify-self", "contain", "contain-intrinsic-size", "aspect-ratio",
-                "overflow-clip-margin", "-internal-align-self-block"],
+                "overflow-clip-margin", "-internal-align-self-block", "orphans",
+                "widows"],
         methods_to_diff: [
           {
             method: "VerticalAlign()",
diff --git a/third_party/blink/renderer/core/testing/DEPS b/third_party/blink/renderer/core/testing/DEPS
index fecfd93..9c2773d 100644
--- a/third_party/blink/renderer/core/testing/DEPS
+++ b/third_party/blink/renderer/core/testing/DEPS
@@ -7,7 +7,7 @@
     "+content/renderer/compositor",
     "+content/test",
     "+gpu/command_buffer/client/gles2_interface.h",
-    "+ui/events/blink/blink_event_util.h"
+    "+ui/events/blink/blink_event_util.h",
 ]
 
 specific_include_rules = {
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
index 92f9ed5..2d616092 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -43,8 +43,6 @@
   DCHECK(NeedsBeginFrame());
   DCHECK_GT(time_delta_in_seconds, 0);
 
-  ClearAnimationScheduled();
-
   last_frame_time_ += base::TimeDelta::FromSecondsD(time_delta_in_seconds);
 
   SimCanvas::Commands commands;
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.h b/third_party/blink/renderer/core/testing/sim/sim_compositor.h
index d0c0701..aa6cb343 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_compositor.h
+++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.h
@@ -52,12 +52,9 @@
   // Helpers to query the state of the compositor from tests.
   //
   // Returns true if a main frame has been requested from blink, until the
-  // BeginFrame() step occurs. The AnimationScheduled() checks if an explicit
-  // requet for BeginFrame() was made, vs an implicit one by making changes
-  // to the compositor's state.
+  // BeginFrame() step occurs.
   bool NeedsBeginFrame() const {
-    return AnimationScheduled() ||
-           layer_tree_host()->RequestedMainFramePendingForTesting();
+    return layer_tree_host()->RequestedMainFramePendingForTesting();
   }
   // Returns true if commits are deferred in the compositor. Since these tests
   // use synchronous compositing through BeginFrame(), the deferred state has no
diff --git a/third_party/blink/renderer/core/web_test/BUILD.gn b/third_party/blink/renderer/core/web_test/BUILD.gn
new file mode 100644
index 0000000..f952ba63
--- /dev/null
+++ b/third_party/blink/renderer/core/web_test/BUILD.gn
@@ -0,0 +1,36 @@
+# 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/dcheck_always_on.gni")
+import("//third_party/blink/renderer/core/core.gni")
+
+source_set("web_test") {
+  testonly = true
+
+  visibility = [ "//content/web_test:web_test_renderer" ]
+
+  configs += [
+    "//third_party/blink/renderer:config",
+    "//third_party/blink/renderer:inside_blink",
+  ]
+
+  deps = [
+    "//base:base",
+
+    # There is a circular dependency with test runner. This
+    # will eventually be removed when all dependent classes move
+    # into blink.
+    # We do not include the dependency here but it is marked as allowing
+    # circular includes in the web_test_renderer config.
+    # "//content/web_test:web_test_renderer",
+
+    "//third_party/blink/public:blink_headers",
+    "//third_party/blink/public:test_headers",
+    "//third_party/blink/renderer/core:core",
+  ]
+
+  sources = [
+    "web_test_web_frame_widget_impl.cc",
+    "web_test_web_frame_widget_impl.h",
+  ]
+}
diff --git a/third_party/blink/renderer/core/web_test/DEPS b/third_party/blink/renderer/core/web_test/DEPS
new file mode 100644
index 0000000..e963884
--- /dev/null
+++ b/third_party/blink/renderer/core/web_test/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+content/web_test/renderer/event_sender.h",
+  "+content/web_test/renderer/test_runner.h",
+]
diff --git a/third_party/blink/renderer/core/web_test/OWNERS b/third_party/blink/renderer/core/web_test/OWNERS
new file mode 100644
index 0000000..d2f8ec5
--- /dev/null
+++ b/third_party/blink/renderer/core/web_test/OWNERS
@@ -0,0 +1,4 @@
+mkwst@chromium.org
+peter@chromium.org
+danakj@chromium.org
+
diff --git a/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.cc b/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.cc
new file mode 100644
index 0000000..90dc532
--- /dev/null
+++ b/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.cc
@@ -0,0 +1,277 @@
+// Copyright 2016 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/web_test/web_test_web_frame_widget_impl.h"
+
+#include "content/web_test/renderer/event_sender.h"
+#include "content/web_test/renderer/test_runner.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
+#include "third_party/blink/public/web/web_frame_widget.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_page_popup.h"
+#include "third_party/blink/public/web/web_view.h"
+#include "third_party/blink/public/web/web_widget.h"
+#include "third_party/blink/renderer/core/exported/web_view_impl.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+
+namespace blink {
+
+WebFrameWidget* FrameWidgetTestHelper::CreateTestWebFrameWidget(
+    base::PassKey<WebFrameWidget> pass_key,
+    WebWidgetClient& widget_client,
+    CrossVariantMojoAssociatedRemote<mojom::blink::FrameWidgetHostInterfaceBase>
+        frame_widget_host,
+    CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
+        frame_widget,
+    CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
+        widget_host,
+    CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
+        widget,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    const viz::FrameSinkId& frame_sink_id,
+    bool hidden,
+    bool never_composited,
+    bool is_for_child_local_root,
+    bool is_for_nested_main_frame,
+    content::TestRunner* test_runner) {
+  return MakeGarbageCollected<WebTestWebFrameWidgetImpl>(
+      pass_key, widget_client, std::move(frame_widget_host),
+      std::move(frame_widget), std::move(widget_host), std::move(widget),
+      std::move(task_runner), frame_sink_id, hidden, never_composited,
+      is_for_child_local_root, is_for_nested_main_frame, test_runner);
+}
+
+WebTestWebFrameWidgetImpl::WebTestWebFrameWidgetImpl(
+    base::PassKey<WebFrameWidget> pass_key,
+    WebWidgetClient& widget_client,
+    CrossVariantMojoAssociatedRemote<mojom::blink::FrameWidgetHostInterfaceBase>
+        frame_widget_host,
+    CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
+        frame_widget,
+    CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
+        widget_host,
+    CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
+        widget,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    const viz::FrameSinkId& frame_sink_id,
+    bool hidden,
+    bool never_composited,
+    bool is_for_child_local_root,
+    bool is_for_nested_main_frame,
+    content::TestRunner* test_runner)
+    : WebFrameWidgetImpl(pass_key,
+                         widget_client,
+                         std::move(frame_widget_host),
+                         std::move(frame_widget),
+                         std::move(widget_host),
+                         std::move(widget),
+                         std::move(task_runner),
+                         frame_sink_id,
+                         hidden,
+                         never_composited,
+                         is_for_child_local_root,
+                         is_for_nested_main_frame),
+      test_runner_(test_runner) {}
+
+WebTestWebFrameWidgetImpl::~WebTestWebFrameWidgetImpl() = default;
+
+void WebTestWebFrameWidgetImpl::BindLocalRoot(WebLocalFrame& local_root) {
+  WebFrameWidgetImpl::BindLocalRoot(local_root);
+  // We need to initialize EventSender after the binding of the local root
+  // as the EventSender constructor accesses LocalRoot and that is not
+  // set until BindLocalRoot is called.
+  event_sender_ = std::make_unique<content::EventSender>(this, test_runner_);
+}
+
+void WebTestWebFrameWidgetImpl::WillBeginMainFrame() {
+  // WillBeginMainFrame occurs before we run BeginMainFrame() in the base
+  // class, which will change states. TestFinished() wants to grab the current
+  // state.
+  GetTestRunner()->FinishTestIfReady();
+
+  WebFrameWidgetImpl::WillBeginMainFrame();
+}
+
+void WebTestWebFrameWidgetImpl::ScheduleAnimation() {
+  if (GetTestRunner()->TestIsRunning())
+    ScheduleAnimationInternal(GetTestRunner()->animation_requires_raster());
+}
+
+void WebTestWebFrameWidgetImpl::ScheduleAnimationForWebTests() {
+  // Single threaded web tests must explicitly schedule commits.
+  //
+  // Pass true for |do_raster| to ensure the compositor is actually run, rather
+  // than just doing the main frame animate step. That way we know it will
+  // submit a frame and later trigger the presentation callback in order to make
+  // progress in the test.
+  if (GetTestRunner()->TestIsRunning())
+    ScheduleAnimationInternal(/*do_raster=*/true);
+}
+
+void WebTestWebFrameWidgetImpl::UpdateAllLifecyclePhasesAndComposite(
+    base::OnceClosure callback) {
+  LayerTreeHost()->RequestPresentationTimeForNextFrame(WTF::Bind(
+      [](base::OnceClosure callback, const gfx::PresentationFeedback&) {
+        std::move(callback).Run();
+      },
+      std::move(callback)));
+  LayerTreeHost()->SetNeedsCommitWithForcedRedraw();
+  ScheduleAnimationForWebTests();
+}
+
+void WebTestWebFrameWidgetImpl::ScheduleAnimationInternal(bool do_raster) {
+  // When using threaded compositing, have the WeFrameWidgetImpl normally
+  // schedule a request for a frame, as we use the compositor's scheduler.
+  if (scheduler::WebThreadScheduler::CompositorThreadScheduler()) {
+    WebFrameWidgetImpl::ScheduleAnimation();
+    return;
+  }
+
+  // If an animation already scheduled we'll make it composite, otherwise we'll
+  // schedule another animation step with composite now.
+  composite_requested_ |= do_raster;
+
+  if (!animation_scheduled_) {
+    animation_scheduled_ = true;
+
+    WebLocalFrame* frame = LocalRoot();
+
+    frame->GetTaskRunner(TaskType::kInternalTest)
+        ->PostDelayedTask(FROM_HERE,
+                          WTF::Bind(&WebTestWebFrameWidgetImpl::AnimateNow,
+                                    WrapWeakPersistent(this)),
+                          base::TimeDelta::FromMilliseconds(1));
+  }
+}
+
+void WebTestWebFrameWidgetImpl::StartDragging(const WebDragData& data,
+                                              DragOperationsMask mask,
+                                              const SkBitmap& drag_image,
+                                              const gfx::Point& image_offset) {
+  doing_drag_and_drop_ = true;
+  GetTestRunner()->SetDragImage(drag_image);
+
+  // When running a test, we need to fake a drag drop operation otherwise
+  // Windows waits for real mouse events to know when the drag is over.
+  event_sender_->DoDragDrop(data, mask);
+}
+
+FrameWidgetTestHelper*
+WebTestWebFrameWidgetImpl::GetFrameWidgetTestHelperForTesting() {
+  return this;
+}
+
+void WebTestWebFrameWidgetImpl::Reset() {
+  event_sender_->Reset();
+  // Ends any synthetic gestures started in |event_sender_|.
+  FlushInputProcessedCallback();
+
+  // Reset state in the  base class.
+  ClearEditCommands();
+
+  SetDeviceScaleFactorForTesting(0);
+  ReleaseMouseLockAndPointerCaptureForTesting();
+
+  // These things are only modified/valid for the main frame's widget.
+  if (ForMainFrame()) {
+    ResetZoomLevelForTesting();
+
+    SetMainFrameOverlayColor(SK_ColorTRANSPARENT);
+    SetTextZoomFactor(1);
+  }
+}
+
+content::EventSender* WebTestWebFrameWidgetImpl::GetEventSender() {
+  return event_sender_.get();
+}
+
+void WebTestWebFrameWidgetImpl::SynchronouslyCompositeAfterTest() {
+  // We could DCHECK(!GetTestRunner()->TestIsRunning()) except that frames in
+  // other processes than the main frame do not hear when the test ends.
+
+  // This would be very weird and prevent us from producing pixels.
+  DCHECK(!in_synchronous_composite_);
+
+  SynchronouslyComposite(/*do_raster=*/true);
+}
+
+content::TestRunner* WebTestWebFrameWidgetImpl::GetTestRunner() {
+  return test_runner_;
+}
+
+// static
+void WebTestWebFrameWidgetImpl::DoComposite(cc::LayerTreeHost* layer_tree_host,
+                                            bool do_raster) {
+  // Ensure that there is damage so that the compositor submits, and the display
+  // compositor draws this frame.
+  if (do_raster) {
+    layer_tree_host->SetNeedsCommitWithForcedRedraw();
+  }
+
+  layer_tree_host->CompositeForTest(base::TimeTicks::Now(), do_raster);
+}
+
+void WebTestWebFrameWidgetImpl::SynchronouslyComposite(bool do_raster) {
+  if (!LocalRootImpl()->ViewImpl()->does_composite())
+    return;
+  DCHECK(!LayerTreeHost()->GetSettings().single_thread_proxy_scheduler);
+
+  if (!LayerTreeHost()->IsVisible())
+    return;
+
+  if (in_synchronous_composite_) {
+    // Web tests can use a nested message loop to pump frames while inside a
+    // frame, but the compositor does not support this. In this case, we only
+    // run blink's lifecycle updates.
+    UpdateAllLifecyclePhases(DocumentUpdateReason::kTest);
+    return;
+  }
+
+  in_synchronous_composite_ = true;
+
+  // DoComposite() can detach the frame.
+  DoComposite(LayerTreeHost(), do_raster);
+  if (!LocalRoot())
+    return;
+
+  in_synchronous_composite_ = false;
+
+  // If this widget is for the main frame, we also composite the current
+  // PagePopup afterward.
+  //
+  // TODO(danakj): This means that an OOPIF's popup, which is attached to a
+  // WebView without a main frame, would have no opportunity to execute this
+  // method call.
+  if (ForMainFrame()) {
+    WebViewImpl* view = LocalRootImpl()->ViewImpl();
+    if (WebPagePopupImpl* popup = view->GetPagePopup()) {
+      DoComposite(popup->LayerTreeHostForTesting(), do_raster);
+    }
+  }
+}
+
+void WebTestWebFrameWidgetImpl::AnimateNow() {
+  // If we have been Closed but not destroyed yet, return early.
+  if (!LocalRootImpl()) {
+    return;
+  }
+  bool do_raster = composite_requested_;
+  animation_scheduled_ = false;
+  composite_requested_ = false;
+  // Composite may destroy |this|, so don't use it afterward.
+  SynchronouslyComposite(do_raster);
+}
+
+void WebTestWebFrameWidgetImpl::RequestDecode(
+    const PaintImage& image,
+    base::OnceCallback<void(bool)> callback) {
+  WebFrameWidgetImpl::RequestDecode(image, std::move(callback));
+
+  // In web tests the request does not actually cause a commit, because the
+  // compositor is scheduled by the test runner to avoid flakiness. So for this
+  // case we must request a main frame.
+  ScheduleAnimationForWebTests();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.h b/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.h
new file mode 100644
index 0000000..095cd10
--- /dev/null
+++ b/third_party/blink/renderer/core/web_test/web_test_web_frame_widget_impl.h
@@ -0,0 +1,113 @@
+// Copyright 2016 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_WEB_TEST_WEB_TEST_WEB_FRAME_WIDGET_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_WEB_TEST_WEB_TEST_WEB_FRAME_WIDGET_IMPL_H_
+
+#include <memory>
+#include <utility>
+
+#include "base/macros.h"
+#include "third_party/blink/public/test/frame_widget_test_helper.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
+
+namespace blink {
+
+// WebTestWebFrameWidgetImpl is used to run web tests. This class is a subclass
+// of WebFrameWidgetImpl that overrides the minimal necessary portions. These
+// portions are limited:
+// 1) Handling single threaded compositing.
+// 2) Emulating drag and drop.
+//
+// This class exists inside blink so that it can subclass the WebFrameWidgetImpl
+// yet still depends on content/web_test/renderer classes. This will eventually
+// be cleaned up with more content code moving into blink but it is fine for
+// now since it is only used in tests.
+class WebTestWebFrameWidgetImpl : public WebFrameWidgetImpl,
+                                  public FrameWidgetTestHelper {
+ public:
+  WebTestWebFrameWidgetImpl(
+      base::PassKey<WebFrameWidget>,
+      WebWidgetClient&,
+      CrossVariantMojoAssociatedRemote<
+          mojom::blink::FrameWidgetHostInterfaceBase> frame_widget_host,
+      CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
+          frame_widget,
+      CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
+          widget_host,
+      CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
+          widget,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      const viz::FrameSinkId& frame_sink_id,
+      bool hidden,
+      bool never_composited,
+      bool is_for_child_local_root,
+      bool is_for_nested_main_frame,
+      content::TestRunner* test_runner);
+
+  ~WebTestWebFrameWidgetImpl() override;
+
+  // FrameWidgetTestHelper overrides.
+  void Reset() override;
+  content::EventSender* GetEventSender() override;
+  void SynchronouslyCompositeAfterTest() override;
+  void UpdateAllLifecyclePhasesAndComposite(
+      base::OnceClosure completion_callback) override;
+
+  // WebFrameWidget overrides.
+  FrameWidgetTestHelper* GetFrameWidgetTestHelperForTesting() override;
+
+  // FrameWidget overrides.
+  void RequestDecode(const cc::PaintImage&,
+                     base::OnceCallback<void(bool)>) override;
+
+ private:
+  // WebFrameWidgetImpl overrides.
+  void BindLocalRoot(WebLocalFrame&) override;
+  void StartDragging(const WebDragData& drag_data,
+                     DragOperationsMask operations_allowed,
+                     const SkBitmap& drag_image,
+                     const gfx::Point& drag_image_offset) override;
+
+  // WidgetBaseClient overrides:
+  void ScheduleAnimation() override;
+  void WillBeginMainFrame() override;
+  void ScheduleAnimationForWebTests() override;
+
+  content::TestRunner* GetTestRunner();
+
+  void ScheduleAnimationInternal(bool do_raster);
+  void AnimateNow();
+
+  // When |do_raster| is false, only a main frame animation step is performed,
+  // but when true, a full composite is performed and a frame submitted to the
+  // display compositor if there is any damage.
+  // Note that compositing has the potential to detach the current frame and
+  // thus destroy |this| before returning.
+  void SynchronouslyComposite(bool do_raster);
+
+  // Perform the synchronous composite step for a given LayerTreeHost.
+  static void DoComposite(cc::LayerTreeHost* layer_tree_host, bool do_raster);
+
+  std::unique_ptr<content::EventSender> event_sender_;
+
+  content::TestRunner* const test_runner_;
+
+  // For collapsing multiple simulated ScheduleAnimation() calls.
+  bool animation_scheduled_ = false;
+  // When true, an AnimateNow() is scheduled that will perform a full composite.
+  // Otherwise, any scheduled AnimateNow() calls will only perform the animation
+  // step, which calls out to blink but doesn't composite for performance
+  // reasons. See setAnimationRequiresRaster() in
+  // https://chromium.googlesource.com/chromium/src/+/master/docs/testing/writing_web_tests.md
+  // for details on the optimization.
+  bool composite_requested_ = false;
+  // Synchronous composites should not be nested inside another
+  // composite, and this bool is used to guard against that.
+  bool in_synchronous_composite_ = false;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_WEB_TEST_WEB_TEST_WEB_FRAME_WIDGET_IMPL_H_
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 11d7a47..161a9a7 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -75,6 +75,7 @@
     "//third_party/blink/renderer/modules/background_fetch",
     "//third_party/blink/renderer/modules/background_sync",
     "//third_party/blink/renderer/modules/badging",
+    "//third_party/blink/renderer/modules/device",
     "//third_party/blink/renderer/modules/battery",
     "//third_party/blink/renderer/modules/beacon",
     "//third_party/blink/renderer/modules/bluetooth",
diff --git a/third_party/blink/renderer/modules/device/BUILD.gn b/third_party/blink/renderer/modules/device/BUILD.gn
new file mode 100644
index 0000000..0bfbee6
--- /dev/null
+++ b/third_party/blink/renderer/modules/device/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("device") {
+  sources = [
+    "device_service.cc",
+    "device_service.h",
+  ]
+
+  public_deps = [ "//third_party/blink/renderer/platform" ]
+}
diff --git a/third_party/blink/renderer/modules/device/OWNERS b/third_party/blink/renderer/modules/device/OWNERS
new file mode 100644
index 0000000..62fa406
--- /dev/null
+++ b/third_party/blink/renderer/modules/device/OWNERS
@@ -0,0 +1,2 @@
+# Device API owners.
+file://chrome/browser/device_api/OWNERS
diff --git a/third_party/blink/renderer/modules/device/device_service.cc b/third_party/blink/renderer/modules/device/device_service.cc
new file mode 100644
index 0000000..c191e16
--- /dev/null
+++ b/third_party/blink/renderer/modules/device/device_service.cc
@@ -0,0 +1,77 @@
+// 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/modules/device/device_service.h"
+
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/navigator.h"
+
+namespace blink {
+
+namespace {
+
+const DOMExceptionCode kDOMExceptionCode = DOMExceptionCode::kNotAllowedError;
+const char kDOMExceptionMessage[] =
+    "This API is available only for high trusted apps.";
+
+}  // namespace
+
+const char DeviceService::kSupplementName[] = "DeviceService";
+
+DeviceService* DeviceService::device(Navigator& navigator) {
+  if (!navigator.DomWindow())
+    return nullptr;
+
+  DeviceService* device_service =
+      Supplement<Navigator>::From<DeviceService>(navigator);
+  if (!device_service) {
+    device_service = MakeGarbageCollected<DeviceService>(navigator);
+    ProvideTo(navigator, device_service);
+  }
+  return device_service;
+}
+
+DeviceService::DeviceService(Navigator& navigator)
+    : Supplement<Navigator>(navigator),
+      device_api_service_(navigator.DomWindow()) {}
+
+ExecutionContext* DeviceService::GetExecutionContext() const {
+  return GetSupplementable()->DomWindow();
+}
+
+void DeviceService::Trace(Visitor* visitor) const {
+  ScriptWrappable::Trace(visitor);
+  Supplement<Navigator>::Trace(visitor);
+
+  visitor->Trace(device_api_service_);
+  visitor->Trace(pending_promises_);
+}
+
+mojom::blink::DeviceAPIService* DeviceService::GetService() {
+  if (!device_api_service_.is_bound()) {
+    GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface(
+        device_api_service_.BindNewPipeAndPassReceiver(
+            GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+    // The access status of Device API can change dynamically. Hence, we have to
+    // properly handle cases when we are losing this access.
+    device_api_service_.set_disconnect_handler(WTF::Bind(
+        &DeviceService::OnServiceConnectionError, WrapWeakPersistent(this)));
+  }
+
+  return device_api_service_.get();
+}
+
+void DeviceService::OnServiceConnectionError() {
+  device_api_service_.reset();
+  // Resolve all pending promises with a failure.
+  for (ScriptPromiseResolver* resolver : pending_promises_)
+    resolver->Reject(MakeGarbageCollected<DOMException>(kDOMExceptionCode,
+                                                        kDOMExceptionMessage));
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/device/device_service.h b/third_party/blink/renderer/modules/device/device_service.h
new file mode 100644
index 0000000..231bbb05
--- /dev/null
+++ b/third_party/blink/renderer/modules/device/device_service.h
@@ -0,0 +1,55 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_DEVICE_SERVICE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_DEVICE_SERVICE_H_
+
+#include "third_party/blink/public/mojom/device/device.mojom-blink.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.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/supplementable.h"
+
+namespace blink {
+
+class Navigator;
+class ExecutionContext;
+class ScriptPromiseResolver;
+class ScriptPromise;
+class ScriptState;
+
+class MODULES_EXPORT DeviceService final : public ScriptWrappable,
+                                           public Supplement<Navigator> {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static const char kSupplementName[];
+
+  // Web-based getter for navigator.device.
+  static DeviceService* device(Navigator&);
+
+  ExecutionContext* GetExecutionContext() const;
+
+  explicit DeviceService(Navigator&);
+  DeviceService(const DeviceService&) = delete;
+  DeviceService& operator=(const DeviceService&) = delete;
+
+  void Trace(Visitor*) const override;
+
+ private:
+  // Lazily binds mojo interface.
+  mojom::blink::DeviceAPIService* GetService();
+
+  void OnServiceConnectionError();
+
+  HeapMojoRemote<mojom::blink::DeviceAPIService,
+                 HeapMojoWrapperMode::kWithoutContextObserver>
+      device_api_service_;
+  HeapHashSet<Member<ScriptPromiseResolver>> pending_promises_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_DEVICE_SERVICE_H_
diff --git a/third_party/blink/renderer/modules/device/device_service.idl b/third_party/blink/renderer/modules/device/device_service.idl
new file mode 100644
index 0000000..6954386a
--- /dev/null
+++ b/third_party/blink/renderer/modules/device/device_service.idl
@@ -0,0 +1,11 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+  Exposed=Window,
+  RuntimeEnabled=DeviceInterface,
+  SecureContext
+] interface DeviceService {
+  // Here we define methods for the navigator.device.
+};
diff --git a/third_party/blink/renderer/modules/device/idls.gni b/third_party/blink/renderer/modules/device/idls.gni
new file mode 100644
index 0000000..942beca8
--- /dev/null
+++ b/third_party/blink/renderer/modules/device/idls.gni
@@ -0,0 +1,7 @@
+# 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.
+
+modules_idl_files = [ "device_service.idl" ]
+
+modules_dependency_idl_files = [ "navigator_device.idl" ]
diff --git a/third_party/blink/renderer/modules/device/navigator_device.idl b/third_party/blink/renderer/modules/device/navigator_device.idl
new file mode 100644
index 0000000..85128da
--- /dev/null
+++ b/third_party/blink/renderer/modules/device/navigator_device.idl
@@ -0,0 +1,12 @@
+// 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.
+//
+[
+  ImplementedAs=DeviceService,
+  RuntimeEnabled=DeviceInterface,
+  SecureContext
+] partial interface Navigator {
+  [SameObject]
+  readonly attribute DeviceService device;
+};
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index 1784c21d..a24c83d8 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -70,6 +70,7 @@
   "//third_party/blink/renderer/modules/crypto/idls.gni",
   "//third_party/blink/renderer/modules/csspaint/idls.gni",
   "//third_party/blink/renderer/modules/delegated_ink/idls.gni",
+  "//third_party/blink/renderer/modules/device/idls.gni",
   "//third_party/blink/renderer/modules/device_orientation/idls.gni",
   "//third_party/blink/renderer/modules/donottrack/idls.gni",
   "//third_party/blink/renderer/modules/encoding/idls.gni",
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
index c2702ad..f1c1a73f 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
@@ -5527,6 +5527,7 @@
         return false;
       }
       return true;
+    case GL_UNSIGNED_SHORT:
     case GL_UNSIGNED_SHORT_5_6_5:
     case GL_UNSIGNED_SHORT_4_4_4_4:
     case GL_UNSIGNED_SHORT_5_5_5_1:
@@ -5537,23 +5538,6 @@
         return false;
       }
       return true;
-    case GL_UNSIGNED_SHORT:
-      if (buffer && buffer->GetType() != DOMArrayBufferView::kTypeUint16) {
-        SynthesizeGLError(
-            GL_INVALID_OPERATION, "readPixels",
-            "type GL_UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
-        return false;
-      }
-      if (format == GL_RGBA) {
-        if (!ExtensionEnabled(kEXTTextureNorm16Name)) {
-          SynthesizeGLError(
-              GL_INVALID_ENUM, "readPixels",
-              "invalid format/type combination RGBA/UNSIGNED_SHORT without "
-              "EXT_texture_norm16 support");
-          return false;
-        }
-      }
-      return true;
     case GL_SHORT:
       if (buffer && buffer->GetType() != DOMArrayBufferView::kTypeInt16) {
         SynthesizeGLError(GL_INVALID_OPERATION, "readPixels",
diff --git a/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h b/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
index d68b79f4..865c5c5c 100644
--- a/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
+++ b/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
@@ -7,8 +7,11 @@
 
 #include <utility>
 
+#include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/vector_traits.h"
 #include "v8/include/v8.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
index 9d38804f..ee9fd78 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
@@ -30,13 +30,13 @@
   ~ContentLayerClientImpl() override;
 
   // cc::ContentLayerClient
-  gfx::Rect PaintableRegion() override {
+  gfx::Rect PaintableRegion() const final {
     return gfx::Rect(raster_invalidator_.LayerBounds().size());
   }
-  scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() override {
+  scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() final {
     return cc_display_item_list_;
   }
-  bool FillsBoundsCompletely() const override { return false; }
+  bool FillsBoundsCompletely() const final { return false; }
 
   // LayerAsJSONClient implementation
   void AppendAdditionalInfoAsJSON(LayerTreeFlags,
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
index 15a434d..ec84fdf 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
@@ -104,10 +104,11 @@
 
  private:
   // ContentLayerClient implementation.
-  gfx::Rect PaintableRegion() final { return gfx::Rect(layer_->bounds()); }
-  bool FillsBoundsCompletely() const final { return false; }
-
+  gfx::Rect PaintableRegion() const final {
+    return gfx::Rect(layer_->bounds());
+  }
   scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() final;
+  bool FillsBoundsCompletely() const final { return false; }
 
  private:
   scoped_refptr<cc::PictureLayer> layer_;
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index 29c9b6f..af42aa4 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -264,10 +264,6 @@
   Invalidate(PaintInvalidationReason::kFullLayer);  // As DisplayItemClient.
 }
 
-IntRect GraphicsLayer::InterestRect() {
-  return previous_interest_rect_;
-}
-
 void GraphicsLayer::ClearPaintStateRecursively() {
   ForAllGraphicsLayers(
       *this,
@@ -374,7 +370,7 @@
     // when unifying PaintController.
     Validate();
     DVLOG(2) << "Painted GraphicsLayer: " << DebugName()
-             << " interest_rect=" << InterestRect().ToString();
+             << " paintable region: " << PaintableRegion().ToString();
   }
 
   PaintChunkSubset chunks(paint_controller.GetPaintArtifactShared());
@@ -399,8 +395,8 @@
     if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
         PaintsContentOrHitTest()) {
       raster_under_invalidation_params.emplace(
-          EnsureRasterInvalidator().EnsureTracking(), InterestRect(),
-          DebugName());
+          EnsureRasterInvalidator().EnsureTracking(),
+          IntRect(PaintableRegion()), DebugName());
     }
 
     // If nothing changed in the layer, keep the original display item list.
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h
index 31ccfbd..4d2d118 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -180,8 +180,6 @@
                                const IntRect&,
                                PaintInvalidationReason);
 
-  IntRect InterestRect();
-
   // Returns true if any layer is repainted.
   bool PaintRecursively(GraphicsContext&,
                         Vector<PreCompositedLayerInfo>&,
@@ -244,9 +242,9 @@
   friend class GraphicsLayerTest;
 
   // cc::ContentLayerClient implementation.
-  gfx::Rect PaintableRegion() final { return InterestRect(); }
+  gfx::Rect PaintableRegion() const final { return previous_interest_rect_; }
   scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() final;
-  bool FillsBoundsCompletely() const override { return false; }
+  bool FillsBoundsCompletely() const final { return false; }
 
   void ClearPaintStateRecursively();
   void Paint(Vector<PreCompositedLayerInfo>&,
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/garbage_collected.h b/third_party/blink/renderer/platform/heap/v8_wrapper/garbage_collected.h
index 94cabcd..30a62187 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/garbage_collected.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/garbage_collected.h
@@ -5,6 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_GARBAGE_COLLECTED_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_GARBAGE_COLLECTED_H_
 
+#include "v8/include/cppgc/type-traits.h"
+
 // GC_PLUGIN_IGNORE is used to make the plugin ignore a particular class or
 // field when checking for proper usage.  When using GC_PLUGIN_IGNORE
 // a bug-number should be provided as an argument where the bug describes
@@ -16,4 +18,14 @@
 #define GC_PLUGIN_IGNORE(bug)
 #endif
 
+namespace blink {
+
+template <typename T>
+struct IsGarbageCollectedMixin {
+ public:
+  static const bool value = cppgc::IsGarbageCollectedMixinTypeV<T>;
+};
+
+}  // namespace blink
+
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_GARBAGE_COLLECTED_H_
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h b/third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h
index dd0b82dc..28398f5 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_PERSISTENT_H_
 
 #include "base/bind.h"
+#include "third_party/blink/renderer/platform/bindings/buildflags.h"
 #include "third_party/blink/renderer/platform/wtf/type_traits.h"
 #include "v8/include/cppgc/cross-thread-persistent.h"
 #include "v8/include/cppgc/persistent.h"
@@ -66,6 +67,12 @@
   return value;
 }
 
+#if BUILDFLAG(RAW_HEAP_SNAPSHOTS)
+#define PERSISTENT_FROM_HERE PersistentLocation::Current()
+#else
+#define PERSISTENT_FROM_HERE PersistentLocation()
+#endif  // BUILDFLAG(RAW_HEAP_SNAPSHOTS)
+
 }  // namespace blink
 
 namespace base {
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc
index 8aec303..06cb2110 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc
@@ -13,7 +13,8 @@
     ThreadState::thread_specific_ = LAZY_INSTANCE_INITIALIZER;
 
 // static
-uint8_t ThreadState::main_thread_state_storage_[sizeof(ThreadState)];
+alignas(ThreadState) uint8_t
+    ThreadState::main_thread_state_storage_[sizeof(ThreadState)];
 
 // static
 ThreadState* ThreadState::AttachMainThread(v8::CppHeap& cpp_heap) {
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
index 25289ae4..c759d89 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
@@ -72,7 +72,7 @@
  private:
   // Main-thread ThreadState avoids TLS completely by using a regular global.
   // The object is manually managed and should not rely on global ctor/dtor.
-  static uint8_t main_thread_state_storage_[] alignas(ThreadState);
+  static uint8_t main_thread_state_storage_[];
   // Storage for all ThreadState objects. This includes the main-thread
   // ThreadState as well.
   static base::LazyInstance<WTF::ThreadSpecific<ThreadState*>>::Leaky
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/unified_heap_marking_visitor.h b/third_party/blink/renderer/platform/heap/v8_wrapper/unified_heap_marking_visitor.h
index 0a4d66e..0496046 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/unified_heap_marking_visitor.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/unified_heap_marking_visitor.h
@@ -5,6 +5,23 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_UNIFIED_HEAP_MARKING_VISITOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_UNIFIED_HEAP_MARKING_VISITOR_H_
 
-// TODO(chromium:1056170): Implement wrapper.
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+template <typename T>
+class TraceWrapperV8Reference;
+
+class UnifiedHeapMarkingVisitor final {
+  STATIC_ONLY(UnifiedHeapMarkingVisitor);
+
+ public:
+  static void WriteBarrier(const TraceWrapperV8Reference<v8::Value>&) {
+    // TODO(mlippautz): Delegate to cppgc write barrier.
+  }
+};
+
+}  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_UNIFIED_HEAP_MARKING_VISITOR_H_
diff --git a/third_party/blink/renderer/platform/network/http_parsers.cc b/third_party/blink/renderer/platform/network/http_parsers.cc
index 0038044c..443f141f 100644
--- a/third_party/blink/renderer/platform/network/http_parsers.cc
+++ b/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -209,7 +209,8 @@
       parsed_headers->critical_ch.has_value()
           ? base::make_optional(
                 ConvertToBlink(parsed_headers->critical_ch.value()))
-          : base::nullopt);
+          : base::nullopt,
+      parsed_headers->xfo);
 }
 
 }  // namespace mojom
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index be7aa465..8e3998e 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -706,9 +706,13 @@
       status: "experimental",
     },
     {
+      name: "DeviceInterface",
+      status: "experimental",
+    },
+    {
       name: "DigitalGoods",
       origin_trial_feature_name: "DigitalGoods",
-      origin_trial_os: ["android"],
+      origin_trial_os: ["android", "chromeos"],
       status: {
         "Android": "experimental",
         "ChromeOS": "experimental",
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc
index 8d3ea5f..3aced59 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc
@@ -91,7 +91,7 @@
 }
 
 WorkerThread::SimpleThreadImpl::SimpleThreadImpl(
-    const String& name_prefix,
+    const WTF::String& name_prefix,
     const base::SimpleThread ::Options& options,
     NonMainThreadSchedulerFactory factory,
     bool supports_gc,
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h b/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h
index f2ede13..2caf785 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h
@@ -70,7 +70,7 @@
         std::unique_ptr<scheduler::NonMainThreadSchedulerImpl>(
             base::sequence_manager::SequenceManager*)>;
 
-    explicit SimpleThreadImpl(const String& name_prefix,
+    explicit SimpleThreadImpl(const WTF::String& name_prefix,
                               const base::SimpleThread::Options& options,
                               NonMainThreadSchedulerFactory factory,
                               bool supports_gc,
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
index 352962d..8cc6a54 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -161,6 +161,7 @@
           scheduler::WebThreadScheduler::MainThreadScheduler()) {
     render_widget_scheduling_state_ =
         main_thread_scheduler->NewRenderWidgetSchedulingState();
+    render_widget_scheduling_state_->SetHidden(is_hidden_);
   }
 }
 
@@ -228,13 +229,19 @@
     widget_input_handler_manager_->AllowPreCommitInput();
 
   UpdateScreenInfo(screen_info);
+
+  // If the widget is hidden, delay starting the compositor until the user
+  // shows it. Otherwise start the compositor immediately. If the widget is
+  // for a provisional frame, this importantly starts the compositor before
+  // the frame is inserted into the frame tree, which impacts first paint
+  // metrics.
+  if (!is_hidden_)
+    SetCompositorVisible(true);
 }
 
-void WidgetBase::Shutdown(
-    scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) {
-  if (!cleanup_runner)
-    cleanup_runner = base::ThreadTaskRunnerHandle::Get();
-
+void WidgetBase::Shutdown() {
+  scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner =
+      base::ThreadTaskRunnerHandle::Get();
   // The |input_event_queue_| is refcounted and will live while an event is
   // being handled. This drops the connection back to this WidgetBase which
   // is being destroyed.
@@ -286,9 +293,10 @@
       base::BindOnce(&OnDidPresentForceDrawFrame, std::move(callback)));
   LayerTreeHost()->SetNeedsCommitWithForcedRedraw();
 
-  // ScheduleAnimationForWebTests() which is implemented by WebWidgetTestProxy,
-  // providing the additional control over the lifecycle of compositing required
-  // by web tests. This will be a no-op on production.
+  // ScheduleAnimationForWebTests() which is implemented by
+  // WebTestWebFrameWidgetImpl, providing the additional control over the
+  // lifecycle of compositing required by web tests. This will be a no-op on
+  // production.
   client_->ScheduleAnimationForWebTests();
 }
 
diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h
index 287443a..8f8400c 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.h
+++ b/third_party/blink/renderer/platform/widget/widget_base.h
@@ -84,7 +84,7 @@
       const cc::LayerTreeSettings* settings);
 
   // Shutdown the compositor.
-  void Shutdown(scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner);
+  void Shutdown();
 
   // Set the compositor as visible. If |visible| is true, then the compositor
   // will request a new layer frame sink, begin producing frames from the
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index c66ec87..df2684ee 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -1347,8 +1347,8 @@
     basename, ext = os.path.splitext(path)
     # Only check code. Ignore tests and fuzzers.
     if (ext not in ('.cc', '.cpp', '.h', '.mm') or path.find('/testing/') >= 0
-            or path.find('/tests/') >= 0 or basename.endswith('_test')
-            or basename.endswith('_test_helpers')
+            or path.find('/core/web_test/') >= 0 or path.find('/tests/') >= 0
+            or basename.endswith('_test') or basename.endswith('_test_helpers')
             or basename.endswith('_unittest') or basename.endswith('_fuzzer')):
         return results
     entries = _find_matching_entries(path)
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 8227144..c9c679d 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -217,11 +217,11 @@
 crbug.com/1093466 virtual/portals/wpt_internal/portals/* [ Pass ]
 
 # Subpixel differences
-crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ]
-crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ]
+crbug.com/997202 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ]
+crbug.com/997202 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ]
 crbug.com/997202 external/wpt/css/css-backgrounds/border-radius-clip-001.html [ Failure ]
 crbug.com/997202 external/wpt/css/css-backgrounds/border-radius-clip-002.htm [ Failure ]
-crbug.com/986110 external/wpt/css/css-transforms/perspective-transforms-equivalence.html [ Failure ]
+crbug.com/997202 external/wpt/css/css-transforms/perspective-transforms-equivalence.html [ Failure ]
 
 crbug.com/807395 fast/multicol/mixed-opacity-test.html [ Failure ]
 
@@ -263,9 +263,9 @@
 crbug.com/974720 [ Mac10.13 ] virtual/text-antialias/firstline/capitalize-transform.html [ Pass Crash ]
 
 # Subpixel differences due to compositing on Mac10.14+.
-crbug.com/1079418 [ Mac10.14 ] external/wpt/svg/extensibility/foreignObject/foreign-object-scale-scroll.html [ Failure ]
-crbug.com/1079418 [ Mac10.15 ] external/wpt/svg/extensibility/foreignObject/foreign-object-scale-scroll.html [ Failure ]
-crbug.com/1079418 [ Mac11.0 ] external/wpt/svg/extensibility/foreignObject/foreign-object-scale-scroll.html [ Failure ]
+crbug.com/997202 [ Mac10.14 ] external/wpt/svg/extensibility/foreignObject/foreign-object-scale-scroll.html [ Failure ]
+crbug.com/997202 [ Mac10.15 ] external/wpt/svg/extensibility/foreignObject/foreign-object-scale-scroll.html [ Failure ]
+crbug.com/997202 [ Mac11.0 ] external/wpt/svg/extensibility/foreignObject/foreign-object-scale-scroll.html [ Failure ]
 
 # This test depends on synchronous focus() which does not exist (anymore?).
 crbug.com/1074482 external/wpt/html/interaction/focus/the-autofocus-attribute/update-the-rendering.html [ Failure ]
@@ -347,9 +347,9 @@
 crbug.com/1024151 http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Failure Pass ]
 
 # Subpixel rounding differences that are incorrect.
-crbug.com/836886 compositing/overflow/scaled-overflow.html [ Failure ]
+crbug.com/997202 compositing/overflow/scaled-overflow.html [ Failure ]
 # Flaky subpixel AA difference (not necessarily incorrect, but flaky)
-crbug.com/921105 virtual/threaded-no-composited-antialiasing/animations/skew-notsequential-compositor.html [ Failure Pass ]
+crbug.com/997202 virtual/threaded-no-composited-antialiasing/animations/skew-notsequential-compositor.html [ Failure Pass ]
 
 crbug.com/954591 external/wpt/css/css-transforms/composited-under-rotateY-180deg.html [ Failure ]
 crbug.com/954591 external/wpt/css/css-transforms/composited-under-rotateY-180deg-clip.html [ Failure ]
@@ -1787,7 +1787,7 @@
 # In this configuration, the pixel smoothed glyphs will be created from subpixel smoothed glyphs.
 # This means that CoreGraphics may draw outside the reported glyph bounds, and in this case does.
 # By about a quarter or less of a pixel.
-crbug.com/421412 [ Mac ] virtual/text-antialias/international/bdo-bidi-width.html [ Failure ]
+crbug.com/997202 [ Mac ] virtual/text-antialias/international/bdo-bidi-width.html [ Failure ]
 
 crbug.com/574283 [ Mac ] fast/scroll-behavior/smooth-scroll/ongoing-smooth-scroll-anchors.html [ Skip ]
 crbug.com/574283 [ Mac ] virtual/threaded-prefer-compositing/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe.html [ Skip ]
@@ -2004,6 +2004,9 @@
 
 crbug.com/332189 external/wpt/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html [ Pass Failure ]
 
+# Temporarily disable for incoming DevTools changes
+crbug.com/1150797 http/tests/devtools/console/console-command-copy.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 ]
@@ -5935,10 +5938,7 @@
 
 # Lack of support for reftest fuzzy matching
 # Reftests have minor pixel differences due to antialiasing.
-crbug.com/997202 [ Mac ] external/wpt/css/css-transforms/animation/transform-interpolation-rotate-slerp.html [ Failure ]
-crbug.com/997202 [ Mac ] virtual/composite-relative-keyframes/external/wpt/css/css-transforms/animation/transform-interpolation-rotate-slerp.html [ Failure ]
-crbug.com/997202 [ Mac ] virtual/threaded/external/wpt/css/css-transforms/animation/transform-interpolation-rotate-slerp.html [ Failure ]
-crbug.com/997202 [ Mac ] virtual/transform-interop/external/wpt/css/css-transforms/animation/transform-interpolation-rotate-slerp.html [ Failure ]
+crbug.com/997202 external/wpt/css/css-transforms/animation/transform-interpolation-rotate-slerp.html [ Failure ]
 
 # Sheriff 2020-11-04
 crbug.com/1144273 http/tests/devtools/sources/debugger-ui/continue-to-location-markers-in-top-level-function.js [ Pass Failure Timeout ]
@@ -5995,6 +5995,3 @@
 # for waitings in web tests to trigger a detection event.
 crbug.com/1032681 http/tests/subresource_filter/overlay_popup_ad/* [ Skip ]
 crbug.com/1032681 virtual/disable-frequency-capping-for-overlay-popup-detection/http/tests/subresource_filter/overlay_popup_ad/* [ Pass ]
-
-#Sheriff 2020-12-01
-crbug.com/1153626 http/tests/wasm/wasm_worker_termination_while_compiling.html [ Pass Crash ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/transform-animation-under-large-scale-ref.html b/third_party/blink/web_tests/external/wpt/css/css-animations/transform-animation-under-large-scale-ref.html
new file mode 100644
index 0000000..14b4136
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/transform-animation-under-large-scale-ref.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<div style="width: 200px; height: 100px; background: blue"></div>
+<div style="width: 200px; height: 100px; background: green"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/transform-animation-under-large-scale.html b/third_party/blink/web_tests/external/wpt/css/css-animations/transform-animation-under-large-scale.html
new file mode 100644
index 0000000..359380d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/transform-animation-under-large-scale.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Transform animation under large scale</title>
+<link rel="author" title="Xianzhu Wang" href="mailto:wangxianzhu@chromium.org">
+<link rel="help" href="https://crbug.com/1153428">
+<link rel="match" href="transform-animation-under-large-scale-ref.html">
+<style>
+@keyframes move {
+  0% {transform: translateX(-1px);}
+  100% {transform: translateX(0);}
+}
+</style>
+<div style="width: 2px; height: 2px; transform: scale(100); transform-origin: 0 0; overflow: hidden">
+  <div style="animation: move 1s infinite alternate">
+    <div style="width: 4px; height: 1px; background: blue"></div>
+    <div style="width: 4px; height: 1px; background: green"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/widows-orphans-006.html b/third_party/blink/web_tests/external/wpt/css/css-break/widows-orphans-006.html
new file mode 100644
index 0000000..3991326
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/widows-orphans-006.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-break-3/#widows-orphans">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1153517">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<style>
+  #mc > div { display:inline-block; width:100%; height:20px; }
+  #mc > div.red { background:red; }
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div id="mc" style="overflow:hidden; columns:1; column-fill:auto; width:100px; height:100px; orphans:1; widows:1; line-height:0; background:green;">
+  <div></div>
+  <div class="red"></div>
+  <div class="red"></div>
+  <div class="red"></div>
+  <div class="red"></div>
+  <div class="red"></div>
+</div>
+<script>
+  document.body.offsetTop,
+  mc.style.widows = 5;
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/widows-orphans-007.html b/third_party/blink/web_tests/external/wpt/css/css-break/widows-orphans-007.html
new file mode 100644
index 0000000..23809c8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/widows-orphans-007.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-break-3/#widows-orphans">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1153517">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<style>
+  #mc > div { display:inline-block; width:100%; height:20px; }
+  #mc > div.green { height:100px; background:green; }
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; height:100px; background:red;">
+  <div id="mc" style="columns:4; orphans:3; widows:1; column-gap:0; line-height:0;">
+    <div class="green"></div>
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+    <div class="green"></div>
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+    <div class="green"></div>
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+    <div class="green"></div>
+  </div>
+</div>
+<script>
+  document.body.offsetTop;
+  mc.style.orphans = 5;
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-empty-container-with-filter-content-added.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-empty-container-with-filter-content-added.html
new file mode 100644
index 0000000..6436461f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-empty-container-with-filter-content-added.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Adding content to a previously empty filtered container</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty">
+<link rel="match" href="reference/green-100x100.html">
+<link rel="bookmark" href="https://crbug.com/1154050">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <filter id="f" color-interpolation-filters="sRGB">
+    <feComponentTransfer><feFuncA/></feComponentTransfer>
+  </filter>
+  <rect width="100" height="100" fill="red"/>
+  <g id="target" filter="url(#f)"/>
+</svg>
+<script>
+waitForAtLeastOneFrame().then(() => {
+  const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+  rect.setAttribute('fill', 'green');
+  rect.setAttribute('width', '100');
+  rect.setAttribute('height', '100');
+  document.getElementById('target').appendChild(rect);
+  takeScreenshot();
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/chromium.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
index 3c52f76..2ff2bd1 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
@@ -31,48 +31,55 @@
         # the trie and the leaf contains the dict of per-test data.
         self.tests = {}
 
-        # Message dictionary, keyed by test name. Value is a list of strings:
-        # see _append_test_message for the format.
+        # Two dictionaries keyed by test name. Values are lists of strings:
+        # actual metadata content and other messages, respectively.
+        # See _append_test_message for examples.
+        self.actual_metadata = defaultdict(list)
         self.messages = defaultdict(list)
 
         # List of tests that have failing subtests.
         self.tests_with_subtest_fails = set()
 
         # Browser log for the current test under execution.
-        self.test_log = []
+        # These logs are from ChromeDriver's stdout/err, so we cannot say for
+        # sure which test a message is from, but instead we correlate them based
+        # on timing.
+        self.browser_log = []
 
     def _append_test_message(self, test, subtest, wpt_actual_status, message):
-        """
+        r"""
         Appends the message data for a test or subtest.
+
         :param str test: the name of the test
         :param str subtest: the name of the subtest with the message. Will be
                             None if this is called for a test.
         :param str wpt_actual_status: the test status as reported by WPT
         :param str message: the string to append to the message for this test
 
-        Example:
-          [test_or_subtest_name]
-            expected: FAIL
-            message: some test message eg assert failure
+        Example actual_metadata of a test with a subtest:
+            "[test_name]\n  expected: OK\n"
+            "  [subtest_name]\n    expected: FAIL\n"
+
+        NOTE: throughout this function we output a key called "expected" but
+        fill it in with the actual status. This is by design. The goal of this
+        output is to look exactly like WPT's expectation metadata so that it
+        can be easily diff-ed.
+
+        Messages are appended verbatim to self.messages[test].
         """
-        # NOTE: throughout this function we output a key called "expected" but
-        # fill it in with the actual status. This is by design. The goal of this
-        # output is to look exactly like WPT's expectation metadata so that it
-        # can be easily diff-ed.
         if subtest:
             result = "  [%s]\n    expected: %s\n" % (subtest, wpt_actual_status)
+            self.actual_metadata[test].append(result)
             if message:
-                result += "    message: %s\n" % message
-            self.messages[test].append(result)
+                self.messages[test].append("%s: %s\n" % (subtest, message))
         else:
             # No subtest, so this is the top-level test. The result must be
-            # prepended to the list of messages, so that the message for the
-            # test comes before any subtest messages.
+            # prepended to the list, so that it comes before any subtest.
             test_name_last_part = test.split("/")[-1]
             result = "[%s]\n  expected: %s\n" % (test_name_last_part, wpt_actual_status)
+            self.actual_metadata[test].insert(0, result)
             if message:
-                result += "  message: %s\n" % message
-            self.messages[test].insert(0, result)
+                self.messages[test].insert(0, "Harness: %s\n" % message)
 
     def _append_artifact(self, cur_dict, artifact_name, artifact_value):
         """
@@ -86,13 +93,16 @@
             cur_dict["artifacts"] = defaultdict(list)
         cur_dict["artifacts"][artifact_name].append(artifact_value)
 
-    def _store_test_result(self, name, actual, expected, messages, wpt_actual,
-                           subtest_failure, reftest_screenshots):
+    def _store_test_result(self, name, actual, expected, actual_metadata,
+                           messages, wpt_actual, subtest_failure,
+                           reftest_screenshots=None):
         """
         Stores the result of a single test in |self.tests|
+
         :param str name: name of the test.
         :param str actual: actual status of the test.
         :param str expected: expected statuses of the test.
+        :param list actual_metadata: a list of metadata items.
         :param list messages: a list of test messages.
         :param str wpt_actual: actual status reported by wpt, may differ from |actual|.
         :param bool subtest_failure: whether this test failed because of subtests.
@@ -112,10 +122,12 @@
         if wpt_actual != actual:
             self._append_artifact(cur_dict, "wpt_actual_status", wpt_actual)
         if wpt_actual == 'CRASH':
-            for line in self.test_log:
+            for line in self.browser_log:
                 self._append_artifact(cur_dict, "wpt_crash_log", line)
+        for metadata in actual_metadata:
+            self._append_artifact(cur_dict, "wpt_actual_metadata", metadata)
         for message in messages:
-            self._append_artifact(cur_dict, "log", message)
+            self._append_artifact(cur_dict, "wpt_log", message)
 
         # Store screenshots (if any).
         for item in reftest_screenshots or []:
@@ -230,19 +242,21 @@
         self._store_test_result(test_name,
                                 actual_status,
                                 expected_statuses,
+                                self.actual_metadata[test_name],
                                 self.messages[test_name],
                                 wpt_actual_status,
                                 subtest_failure,
                                 data.get("extra", {}).get("reftest_screenshots"))
 
-        # Remove the test from messages dict to avoid accumulating too many.
+        # Remove the test from dicts to avoid accumulating too many.
+        self.actual_metadata.pop(test_name)
         self.messages.pop(test_name)
 
         # Update the count of how many tests ran with each status.
         self.num_failures_by_status[actual_status] += 1
 
         # New test, new browser logs.
-        self.test_log = []
+        self.browser_log = []
 
     def suite_end(self, data):
         # Create the final result dictionary
@@ -259,4 +273,4 @@
 
     def process_output(self, data):
         if 'command' in data and 'chromedriver' in data['command']:
-            self.test_log.append(data['data'])
+            self.browser_log.append(data['data'])
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
index 807f583..55a12b1d7 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
@@ -157,17 +157,24 @@
     output_json = json.load(output)
 
     t1_artifacts = output_json["tests"]["t1"]["artifacts"]
-    assert t1_artifacts["log"] == [
+    assert t1_artifacts["wpt_actual_metadata"] == [
         "[t1]\n  expected: PASS\n",
-        "  [t1_a]\n    expected: FAIL\n    message: t1_a_message\n",
-        "  [t1_b]\n    expected: PASS\n    message: t1_b_message\n",
+        "  [t1_a]\n    expected: FAIL\n",
+        "  [t1_b]\n    expected: PASS\n",
+    ]
+    assert t1_artifacts["wpt_log"] == [
+        "t1_a: t1_a_message\n",
+        "t1_b: t1_b_message\n",
     ]
     assert t1_artifacts["wpt_subtest_failure"] == ["true"]
     t2_artifacts = output_json["tests"]["t2"]["artifacts"]
-    assert t2_artifacts["log"] == [
-        "[t2]\n  expected: TIMEOUT\n  message: t2_message\n",
+    assert t2_artifacts["wpt_actual_metadata"] == [
+        "[t2]\n  expected: TIMEOUT\n",
         "  [t2_a]\n    expected: PASS\n",
     ]
+    assert t2_artifacts["wpt_log"] == [
+        "Harness: t2_message\n"
+    ]
     assert "wpt_subtest_failure" not in t2_artifacts.keys()
 
 
@@ -210,11 +217,17 @@
 
     test_obj = output_json["tests"]["t1"]
     t1_artifacts = test_obj["artifacts"]
-    assert t1_artifacts["log"] == [
-        "[t1]\n  expected: PASS\n  message: top_message\n",
-        "  [t1_a]\n    expected: FAIL\n    message: t1_a_message\n",
-        "  [t1_b]\n    expected: PASS\n    message: t1_b_message\n",
-        "  [t1_c]\n    expected: TIMEOUT\n    message: t1_c_message\n",
+    assert t1_artifacts["wpt_actual_metadata"] == [
+        "[t1]\n  expected: PASS\n",
+        "  [t1_a]\n    expected: FAIL\n",
+        "  [t1_b]\n    expected: PASS\n",
+        "  [t1_c]\n    expected: TIMEOUT\n",
+    ]
+    assert t1_artifacts["wpt_log"] == [
+        "Harness: top_message\n",
+        "t1_a: t1_a_message\n",
+        "t1_b: t1_b_message\n",
+        "t1_c: t1_c_message\n",
     ]
     assert t1_artifacts["wpt_subtest_failure"] == ["true"]
     # The status of the test in the output is a failure because subtests failed,
@@ -266,13 +279,16 @@
     output_json = json.load(output)
 
     test_obj = output_json["tests"]["t1"]
-    t1_log = test_obj["artifacts"]["log"]
-    print("Lpz t1log=%s" % t1_log)
-    assert t1_log == [
+    assert test_obj["artifacts"]["wpt_actual_metadata"] == [
         "[t1]\n  expected: OK\n",
-        "  [t1_a]\n    expected: FAIL\n    message: t1_a_message\n",
-        "  [t1_b]\n    expected: PASS\n    message: t1_b_message\n",
-        "  [t1_c]\n    expected: TIMEOUT\n    message: t1_c_message\n",
+        "  [t1_a]\n    expected: FAIL\n",
+        "  [t1_b]\n    expected: PASS\n",
+        "  [t1_c]\n    expected: TIMEOUT\n",
+    ]
+    assert test_obj["artifacts"]["wpt_log"] == [
+        "t1_a: t1_a_message\n",
+        "t1_b: t1_b_message\n",
+        "t1_c: t1_c_message\n",
     ]
     # The status of the test in the output is a pass because the subtest
     # failures were all expected.
@@ -316,9 +332,12 @@
 
     test_obj = output_json["tests"]["t1"]
     t1_artifacts = test_obj["artifacts"]
-    assert t1_artifacts["log"] == [
+    assert t1_artifacts["wpt_actual_metadata"] == [
         "[t1]\n  expected: PASS\n",
-        "  [t1_a]\n    expected: PASS\n    message: t1_a_message\n",
+        "  [t1_a]\n    expected: PASS\n",
+    ]
+    assert t1_artifacts["wpt_log"] == [
+        "t1_a: t1_a_message\n",
     ]
     assert t1_artifacts["wpt_subtest_failure"] == ["true"]
     # Since the subtest status is unexpected, we fail the test. But we report
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCOAuthCredential-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCOAuthCredential-expected.txt
new file mode 100644
index 0000000..e7fb284d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCOAuthCredential-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+FAIL new RTCPeerConnection(config) - with turns server, credentialType oauth, and string credential should throw InvalidAccessError assert_throws_dom: function "() =>
+    makePc({ iceServers: [{
+      urls: 'turns:turn.example.org',
+      credentialType: 'oauth',
+      username: 'user',
+      credential: 'cred'
+    }] })" did not throw
+FAIL setConfiguration(config) - with turns server, credentialType oauth, and string credential should throw InvalidAccessError assert_throws_dom: function "() =>
+    makePc({ iceServers: [{
+      urls: 'turns:turn.example.org',
+      credentialType: 'oauth',
+      username: 'user',
+      credential: 'cred'
+    }] })" did not throw
+FAIL new RTCPeerConnection(config) - with turns server, credential type and credential from spec should not throw assert_equals: expected (string) "oauth" but got (undefined) undefined
+FAIL setConfiguration(config) - with turns server, credential type and credential from spec should not throw assert_equals: expected (string) "oauth" but got (undefined) undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCOAuthCredential.html b/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCOAuthCredential.html
new file mode 100644
index 0000000..63e92c6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCOAuthCredential.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>RTCConfiguration iceServers with OAuth credentials</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='../webrtc/RTCConfiguration-helper.js'></script>
+<script>
+  'use strict';
+
+// These tests are based on
+// https://w3c.github.io/webrtc-extensions/#rtcoauthcredential-dictionary
+
+/*
+    4.3.2.  To set a configuration
+    11.6. If scheme name is turn or turns, and server.credentialType is "oauth",
+    and server.credential is not an RTCOAuthCredential, then throw an
+    InvalidAccessError and abort these steps.
+*/
+config_test(makePc => {
+  assert_throws_dom('InvalidAccessError', () =>
+    makePc({ iceServers: [{
+      urls: 'turns:turn.example.org',
+      credentialType: 'oauth',
+      username: 'user',
+      credential: 'cred'
+    }] }));
+}, 'with turns server, credentialType oauth, and string credential should throw InvalidAccessError');
+
+config_test(makePc => {
+  const pc = makePc({ iceServers: [{
+    urls: 'turns:turn2.example.net',
+    username: '22BIjxU93h/IgwEb',
+    credential: {
+      macKey: 'WmtzanB3ZW9peFhtdm42NzUzNG0=',
+      accessToken: 'AAwg3kPHWPfvk9bDFL936wYvkoctMADzQ5VhNDgeMR3+ZlZ35byg972fW8QjpEl7bx91YLBPFsIhsxloWcXPhA=='
+    },
+    credentialType: 'oauth'
+  }]});
+  const { iceServers } = pc.getConfiguration();
+  const server = iceServers[0];
+  assert_equals(server.credentialType, 'oauth');
+}, 'with turns server, credential type and credential from spec should not throw');
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCConfiguration-iceServers-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCConfiguration-iceServers-expected.txt
index 33430edd..fc38ca8 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCConfiguration-iceServers-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCConfiguration-iceServers-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 67 tests; 33 PASS, 34 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 65 tests; 33 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL new RTCPeerConnection() should have default configuration.iceServers of undefined assert_equals: expected (undefined) undefined but got (object) []
 PASS new RTCPeerConnection(config) - {} should succeed
 PASS setConfiguration(config) - {} should succeed
@@ -120,19 +120,5 @@
           accessToken: ''
         }
       }] })" did not throw
-FAIL new RTCPeerConnection(config) - with turns server, credentialType oauth, and string credential should throw InvalidAccessError assert_throws_dom: function "() =>
-      makePc({ iceServers: [{
-        urls: 'turns:turn.example.org',
-        credentialType: 'oauth',
-        username: 'user',
-        credential: 'cred'
-      }] })" did not throw
-FAIL setConfiguration(config) - with turns server, credentialType oauth, and string credential should throw InvalidAccessError assert_throws_dom: function "() =>
-      makePc({ iceServers: [{
-        urls: 'turns:turn.example.org',
-        credentialType: 'oauth',
-        username: 'user',
-        credential: 'cred'
-      }] })" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCConfiguration-iceServers.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCConfiguration-iceServers.html
index 1cbf1d6c..36f1277 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCConfiguration-iceServers.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCConfiguration-iceServers.html
@@ -370,36 +370,4 @@
       }] }));
   }, 'with turns server, credentialType password, and object credential should throw InvalidAccessError');
 
-  /*
-    4.3.2.  To set a configuration
-      11.6. If scheme name is turn or turns, and server.credentialType is "oauth",
-            and server.credential is not an RTCOAuthCredential, then throw an
-            InvalidAccessError and abort these steps.
-   */
-  config_test(makePc => {
-    assert_throws_dom('InvalidAccessError', () =>
-      makePc({ iceServers: [{
-        urls: 'turns:turn.example.org',
-        credentialType: 'oauth',
-        username: 'user',
-        credential: 'cred'
-      }] }));
-  }, 'with turns server, credentialType oauth, and string credential should throw InvalidAccessError');
-
-  /*
-    Tested
-      4.3.2.  To set a configuration
-        11.1-6.
-
-    Untestable
-      4.3.2.  To set a configuration
-        11.7.  Append server to validatedServers.
-
-    Coverage Report
-      Tested         9
-      Not Tested     0
-      Untestable     1
-      Total         10
-   */
-
 </script>
diff --git a/third_party/blink/web_tests/media/video-currentTime.html b/third_party/blink/web_tests/media/video-currentTime.html
index dbd5abc0..28f4cd2 100644
--- a/third_party/blink/web_tests/media/video-currentTime.html
+++ b/third_party/blink/web_tests/media/video-currentTime.html
@@ -8,15 +8,18 @@
     var video = document.querySelector("video");
     assert_equals(video.currentTime, 0);
 
-    video.oncanplaythrough = t.step_func(function() {
-        assert_equals(video.currentTime, 0);
-        video.play();
+    video.requestVideoFrameCallback(t.step_func(() => {
+        assert_equals(video.currentTime, 0)
 
-        setTimeout(t.step_func_done(function() {
-            assert_greater_than(video.currentTime, 0);
-        }), 500);
+        var endTest =
+            t.step_func_done(() => assert_greater_than(video.currentTime, 0));
+
+        videos.ontimeupdate = endTest;
+        videos.onended = endTest;
+
+        video.play();
     });
 
     video.src = "content/test.ogv";
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index e997058..2bbc1e27 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -1569,6 +1569,9 @@
     getter beta
     getter gamma
     method constructor
+interface DeviceService
+    attribute @@toStringTag
+    method constructor
 interface Document : Node
     attribute @@toStringTag
     attribute @@unscopables
@@ -5445,6 +5448,7 @@
     getter contacts
     getter cookieEnabled
     getter credentials
+    getter device
     getter deviceMemory
     getter doNotTrack
     getter geolocation
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index cc943454..1bf55f6 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-10-4-18-g56c610b14
-Revision: 56c610b145212b7acfb24a17e86fc0ba15aa3052
+Version: VER-2-10-4-19-g8cc4d0dc3
+Revision: 8cc4d0dc32a1f8734e77266bb6abdd11f18a631c
 CPEPrefix: cpe:/a:freetype:freetype:2.10.1
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/grpc/BUILD.gn b/third_party/grpc/BUILD.gn
index 48e5081..16c9c78 100644
--- a/third_party/grpc/BUILD.gn
+++ b/third_party/grpc/BUILD.gn
@@ -78,7 +78,8 @@
 template("grpc_so") {
   # TODO(169395837): Somehow gRPC symbols cannot be found on Android.
   # Keep using static linking for now.
-  if (is_android) {
+  # In windows use static linking.
+  if (is_android || is_win) {
     source_set(target_name) {
       forward_variables_from(invoker, "*")
     }
diff --git a/third_party/grpc/template/BUILD.chromium.gn.template b/third_party/grpc/template/BUILD.chromium.gn.template
index cef612df..90015a8 100644
--- a/third_party/grpc/template/BUILD.chromium.gn.template
+++ b/third_party/grpc/template/BUILD.chromium.gn.template
@@ -83,7 +83,8 @@
   template("grpc_so") {
     # TODO(169395837): Somehow gRPC symbols cannot be found on Android.
     # Keep using static linking for now.
-    if (is_android) {
+    # In windows use static linking.
+    if (is_android || is_win) {
       source_set(target_name) {
         forward_variables_from(invoker, "*")
       }
diff --git a/third_party/mozilla/NSPasteboard+Utils.h b/third_party/mozilla/NSPasteboard+Utils.h
index a44470f0..affdc33 100644
--- a/third_party/mozilla/NSPasteboard+Utils.h
+++ b/third_party/mozilla/NSPasteboard+Utils.h
@@ -44,12 +44,10 @@
 MOZILLA_EXPORT extern NSString* const kCorePasteboardFlavorType_urln;
 MOZILLA_EXPORT extern NSString* const kCorePasteboardFlavorType_urld;
 
-MOZILLA_EXPORT extern NSString* const kCaminoBookmarkListPBoardType;
 MOZILLA_EXPORT extern NSString* const kWebURLsWithTitlesPboardType;
 
 @interface NSPasteboard(ChimeraPasteboardURLUtils)
 
-- (int) declareURLPasteboardWithAdditionalTypes:(NSArray*)additionalTypes owner:(id)newOwner;
 - (void) setDataForURL:(NSString*)url title:(NSString*)title;
 
 - (void) setURLs:(NSArray*)inUrls withTitles:(NSArray*)inTitles;
diff --git a/third_party/mozilla/NSPasteboard+Utils.mm b/third_party/mozilla/NSPasteboard+Utils.mm
index f9f2d2a..98070cae 100644
--- a/third_party/mozilla/NSPasteboard+Utils.mm
+++ b/third_party/mozilla/NSPasteboard+Utils.mm
@@ -44,7 +44,6 @@
 NSString* const kCorePasteboardFlavorType_urln = @"CorePasteboardFlavorType 0x75726C6E"; // 'urln'  title
 NSString* const kCorePasteboardFlavorType_urld = @"CorePasteboardFlavorType 0x75726C64"; // 'urld' URL description
 
-NSString* const kCaminoBookmarkListPBoardType = @"MozBookmarkType"; // list of Camino bookmark UIDs
 NSString* const kWebURLsWithTitlesPboardType  = @"WebURLsWithTitlesPboardType"; // Safari-compatible URL + title arrays
 
 @interface NSPasteboard(ChimeraPasteboardURLUtilsPrivate)
@@ -70,19 +69,6 @@
 
 @implementation NSPasteboard(ChimeraPasteboardURLUtils)
 
-- (int)declareURLPasteboardWithAdditionalTypes:(NSArray*)additionalTypes owner:(id)newOwner
-{
-  NSArray* allTypes = [additionalTypes arrayByAddingObjectsFromArray:
-                            [NSArray arrayWithObjects:
-                                        kWebURLsWithTitlesPboardType,
-                                        NSURLPboardType,
-                                        NSStringPboardType,
-                                        kCorePasteboardFlavorType_url,
-                                        kCorePasteboardFlavorType_urln,
-                                        nil]];
-       return [self declareTypes:allTypes owner:newOwner];
-}
-
 //
 // Copy a single URL (with an optional title) to the clipboard in all relevant
 // formats. Convenience method for clients that can only ever deal with one
diff --git a/third_party/mozilla/NSString+Utils.h b/third_party/mozilla/NSString+Utils.h
index cf35d61b..4274d9f 100644
--- a/third_party/mozilla/NSString+Utils.h
+++ b/third_party/mozilla/NSString+Utils.h
@@ -37,69 +37,21 @@
 
 #import <Foundation/Foundation.h>
 
-typedef enum
-{
-  kTruncateAtStart,
-  kTruncateAtMiddle,
-  kTruncateAtEnd
-} ETruncationType;
-
-
 // a category to extend NSString
 @interface NSString (ChimeraStringUtils)
 
-+ (id)ellipsisString;
-+ (NSString*)stringWithUUID;
-
-- (BOOL)isEqualToStringIgnoringCase:(NSString*)inString;
 - (BOOL)hasCaseInsensitivePrefix:(NSString*)inString;
 
 // Some URIs can contain spaces and still work, even though they aren't strictly valid
 // per RFC2396. This method allows us to account for those URIs.
 - (BOOL)isLooselyValidatedURI;
 
-// Utility method to identify URIs that can be run in the context of the current page.
-// These URIs could be used as attack vectors via AppleScript, for example.
-- (BOOL)isPotentiallyDangerousURI;
-
 // Utility method to ensure validity of URI strings. NSURL is used to validate
 // most of them, but the NSURL test may fail for |javascript:| and |data:| URIs
 // because they often contain invalid (per RFC2396) characters such as spaces.
 - (BOOL)isValidURI;
 
 - (NSString *)stringByRemovingCharactersInSet:(NSCharacterSet*)characterSet;
-- (NSString *)stringByReplacingCharactersInSet:(NSCharacterSet*)characterSet withString:(NSString*)string;
-- (NSString *)stringByTruncatingTo:(unsigned int)maxCharacters at:(ETruncationType)truncationType;
-- (NSString *)stringByTruncatingToWidth:(float)inWidth at:(ETruncationType)truncationType withAttributes:(NSDictionary *)attributes;
 - (NSString *)stringByTrimmingWhitespace;
-- (NSString *)stringByRemovingAmpEscapes;
-- (NSString *)stringByAddingAmpEscapes;
-
-@end
-
-@interface NSMutableString (ChimeraMutableStringUtils)
-
-- (void)truncateTo:(unsigned)maxCharacters at:(ETruncationType)truncationType;
-- (void)truncateToWidth:(float)maxWidth at:(ETruncationType)truncationType withAttributes:(NSDictionary *)attributes;
-
-@end
-
-@interface NSString (ChimeraFilePathStringUtils)
-
-- (NSString*)volumeNamePathComponent;
-- (NSString*)displayNameOfLastPathComponent;
-
-@end
-
-@interface NSString (CaminoURLStringUtils)
-
-// Returns true if the string represents a "blank" URL ("" or "about:blank")
-- (BOOL)isBlankURL;
-// Begin Google Modified
-#if 0
-// Returns a URI that looks good in a location field
-- (NSString *)unescapedURI;
-#endif
-// End Google Modified
 
 @end
diff --git a/third_party/mozilla/NSString+Utils.mm b/third_party/mozilla/NSString+Utils.mm
index 25d35577..c4eb904 100644
--- a/third_party/mozilla/NSString+Utils.mm
+++ b/third_party/mozilla/NSString+Utils.mm
@@ -44,33 +44,6 @@
 
 @implementation NSString (ChimeraStringUtils)
 
-+ (id)ellipsisString
-{
-  static NSString* sEllipsisString = nil;
-  if (!sEllipsisString) {
-    unichar ellipsisChar = 0x2026;
-    sEllipsisString = [[NSString alloc] initWithCharacters:&ellipsisChar length:1];
-  }
-
-  return sEllipsisString;
-}
-
-+ (NSString*)stringWithUUID
-{
-  NSString* uuidString = nil;
-  CFUUIDRef newUUID = CFUUIDCreate(kCFAllocatorDefault);
-  if (newUUID) {
-    uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, newUUID);
-    CFRelease(newUUID);
-  }
-  return [uuidString autorelease];
-}
-
-- (BOOL)isEqualToStringIgnoringCase:(NSString*)inString
-{
-  return ([self compare:inString options:NSCaseInsensitiveSearch] == NSOrderedSame);
-}
-
 - (BOOL)hasCaseInsensitivePrefix:(NSString*)inString
 {
   if ([self length] < [inString length])
@@ -83,11 +56,6 @@
   return ([self hasCaseInsensitivePrefix:@"javascript:"] || [self hasCaseInsensitivePrefix:@"data:"]);
 }
 
-- (BOOL)isPotentiallyDangerousURI
-{
-  return ([self hasCaseInsensitivePrefix:@"javascript:"] || [self hasCaseInsensitivePrefix:@"data:"]);
-}
-
 - (BOOL)isValidURI
 {
   // isValid() will only be true for valid, well-formed URI strings
@@ -95,7 +63,7 @@
 
   // |javascript:| and |data:| URIs might not have passed the test,
   // but spaces will work OK, so evaluate them separately.
-  if ((testURL.is_valid()) || [self isLooselyValidatedURI]) {
+  if (testURL.is_valid() || [self isLooselyValidatedURI]) {
     return YES;
   }
   return NO;
@@ -119,249 +87,10 @@
   return cleanString;
 }
 
-- (NSString *)stringByReplacingCharactersInSet:(NSCharacterSet*)characterSet
-                                    withString:(NSString*)string
-{
-  NSScanner*       cleanerScanner = [NSScanner scannerWithString:self];
-  NSMutableString* cleanString    = [NSMutableString stringWithCapacity:[self length]];
-  // Make sure we don't skip whitespace, which NSScanner does by default
-  [cleanerScanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@""]];
-
-  while (![cleanerScanner isAtEnd])
-  {
-    NSString* stringFragment;
-    if ([cleanerScanner scanUpToCharactersFromSet:characterSet intoString:&stringFragment])
-      [cleanString appendString:stringFragment];
-
-    if ([cleanerScanner scanCharactersFromSet:characterSet intoString:nil])
-      [cleanString appendString:string];
-  }
-
-  return cleanString;
-}
-
-- (NSString*)stringByTruncatingTo:(unsigned int)maxCharacters at:(ETruncationType)truncationType
-{
-  if ([self length] > maxCharacters)
-  {
-    NSMutableString *mutableCopy = [self mutableCopy];
-    [mutableCopy truncateTo:maxCharacters at:truncationType];
-    return [mutableCopy autorelease];
-  }
-
-  return self;
-}
-
-- (NSString *)stringByTruncatingToWidth:(float)inWidth at:(ETruncationType)truncationType
-                         withAttributes:(NSDictionary *)attributes
-{
-  if ([self sizeWithAttributes:attributes].width > inWidth)
-  {
-    NSMutableString *mutableCopy = [self mutableCopy];
-    [mutableCopy truncateToWidth:inWidth at:truncationType withAttributes:attributes];
-    return [mutableCopy autorelease];
-  }
-
-  return self;
-}
-
 - (NSString *)stringByTrimmingWhitespace
 {
   return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
 }
 
--(NSString *)stringByRemovingAmpEscapes
-{
-  NSMutableString* dirtyStringMutant = [NSMutableString stringWithString:self];
-  [dirtyStringMutant replaceOccurrencesOfString:@"&amp;"
-                                     withString:@"&"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  [dirtyStringMutant replaceOccurrencesOfString:@"&quot;"
-                                     withString:@"\""
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  [dirtyStringMutant replaceOccurrencesOfString:@"&lt;"
-                                     withString:@"<"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  [dirtyStringMutant replaceOccurrencesOfString:@"&gt;"
-                                     withString:@">"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  [dirtyStringMutant replaceOccurrencesOfString:@"&mdash;"
-                                     withString:@"-"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  [dirtyStringMutant replaceOccurrencesOfString:@"&apos;"
-                                     withString:@"'"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  // fix import from old Firefox versions, which exported &#39; instead of a plain apostrophe
-  [dirtyStringMutant replaceOccurrencesOfString:@"&#39;"
-                                     withString:@"'"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  return [dirtyStringMutant stringByRemovingCharactersInSet:[NSCharacterSet controlCharacterSet]];
-}
-
--(NSString *)stringByAddingAmpEscapes
-{
-  NSMutableString* dirtyStringMutant = [NSMutableString stringWithString:self];
-  [dirtyStringMutant replaceOccurrencesOfString:@"&"
-                                     withString:@"&amp;"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  [dirtyStringMutant replaceOccurrencesOfString:@"\""
-                                     withString:@"&quot;"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  [dirtyStringMutant replaceOccurrencesOfString:@"<"
-                                     withString:@"&lt;"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  [dirtyStringMutant replaceOccurrencesOfString:@">"
-                                     withString:@"&gt;"
-                                        options:NSLiteralSearch
-                                          range:NSMakeRange(0,[dirtyStringMutant length])];
-  return [NSString stringWithString:dirtyStringMutant];
-}
-
 @end
 
-
-@implementation NSMutableString (ChimeraMutableStringUtils)
-
-- (void)truncateTo:(unsigned)maxCharacters at:(ETruncationType)truncationType
-{
-  if ([self length] <= maxCharacters)
-    return;
-
-  NSRange replaceRange;
-  replaceRange.length = [self length] - maxCharacters;
-
-  switch (truncationType) {
-    case kTruncateAtStart:
-      replaceRange.location = 0;
-      break;
-
-    case kTruncateAtMiddle:
-      replaceRange.location = maxCharacters / 2;
-      break;
-
-    case kTruncateAtEnd:
-      replaceRange.location = maxCharacters;
-      break;
-
-    default:
-#if DEBUG
-      NSLog(@"Unknown truncation type in stringByTruncatingTo::");
-#endif
-      replaceRange.location = maxCharacters;
-      break;
-  }
-
-  [self replaceCharactersInRange:replaceRange withString:[NSString ellipsisString]];
-}
-
-
-- (void)truncateToWidth:(float)maxWidth
-                     at:(ETruncationType)truncationType
-         withAttributes:(NSDictionary *)attributes
-{
-  // First check if we have to truncate at all.
-  if ([self sizeWithAttributes:attributes].width <= maxWidth)
-    return;
-
-  // Essentially, we perform a binary search on the string length
-  // which fits best into maxWidth.
-
-  float width = maxWidth;
-  int lo = 0;
-  int hi = [self length];
-  int mid;
-
-  // Make a backup copy of the string so that we can restore it if we fail low.
-  NSMutableString *backup = [self mutableCopy];
-
-  while (hi >= lo) {
-    mid = (hi + lo) / 2;
-
-    // Cut to mid chars and calculate the resulting width
-    [self truncateTo:mid at:truncationType];
-    width = [self sizeWithAttributes:attributes].width;
-
-    if (width > maxWidth) {
-      // Fail high - string is still to wide. For the next cut, we can simply
-      // work on the already cut string, so we don't restore using the backup.
-      hi = mid - 1;
-    }
-    else if (width == maxWidth) {
-      // Perfect match, abort the search.
-      break;
-    }
-    else {
-      // Fail low - we cut off too much. Restore the string before cutting again.
-      lo = mid + 1;
-      [self setString:backup];
-    }
-  }
-  // Perform the final cut (unless this was already a perfect match).
-  if (width != maxWidth)
-    [self truncateTo:hi at:truncationType];
-  [backup release];
-}
-
-@end
-
-@implementation NSString (ChimeraFilePathStringUtils)
-
-- (NSString*)volumeNamePathComponent
-{
-  // if the file doesn't exist, then componentsToDisplayForPath will return nil,
-  // so back up to the nearest existing dir
-  NSString* curPath = self;
-  while (![[NSFileManager defaultManager] fileExistsAtPath:curPath])
-  {
-    NSString* parentDirPath = [curPath stringByDeletingLastPathComponent];
-    if ([parentDirPath isEqualToString:curPath])
-      break;  // avoid endless loop
-    curPath = parentDirPath;
-  }
-
-  NSArray* displayComponents = [[NSFileManager defaultManager] componentsToDisplayForPath:curPath];
-  if ([displayComponents count] > 0)
-    return [displayComponents objectAtIndex:0];
-
-  return self;
-}
-
-- (NSString*)displayNameOfLastPathComponent
-{
-  return [[NSFileManager defaultManager] displayNameAtPath:self];
-}
-
-@end
-
-@implementation NSString (CaminoURLStringUtils)
-
-- (BOOL)isBlankURL
-{
-  return ([self isEqualToString:@"about:blank"] || [self isEqualToString:@""]);
-}
-
-// Begin Google Modified
-#if 0
-// Excluded character list comes from RFC2396 and by examining Safari's behaviour
-- (NSString*)unescapedURI
-{
-  NSString *unescapedURI = (NSString*)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
-                                                                            (CFStringRef)self,
-                                                                            CFSTR(" \"\';/?:@&=+$,#"),
-                                                                            kCFStringEncodingUTF8);
-  return unescapedURI ? [unescapedURI autorelease] : self;
-}
-#endif
-// End Google Modified
-
-@end
diff --git a/third_party/mozilla/NSURL+Utils.h b/third_party/mozilla/NSURL+Utils.h
index dc7501e..6bed0618 100644
--- a/third_party/mozilla/NSURL+Utils.h
+++ b/third_party/mozilla/NSURL+Utils.h
@@ -40,11 +40,6 @@
 
 @interface NSURL (CaminoExtensions) 
 
-// This takes an NSURL to a local file, and if that file is a file that
-// represents a URL, returns the URL it contains. Otherwise, returns the
-// passed URL. Supports .url, .webloc and .ftploc files.
-+ (NSURL*)decodeLocalFileURL:(NSURL*)url;
-
 +(NSURL*)URLFromInetloc:(NSString*)inFile;
 +(NSURL*)URLFromIEURLFile:(NSString*)inFile;
 
diff --git a/third_party/mozilla/NSURL+Utils.m b/third_party/mozilla/NSURL+Utils.m
index 0ea5559a..00ea3aaf 100644
--- a/third_party/mozilla/NSURL+Utils.m
+++ b/third_party/mozilla/NSURL+Utils.m
@@ -40,24 +40,6 @@
 
 @implementation NSURL (CaminoExtensions)
 
-+ (NSURL*)decodeLocalFileURL:(NSURL*)url
-{
-  NSString* urlPathString = [url path];
-  NSString* ext = [[urlPathString pathExtension] lowercaseString];
-  OSType fileType = NSHFSTypeCodeFromFileType(NSHFSTypeOfFile(urlPathString));
-
-  if ([ext isEqualToString:@"url"] || fileType == 'LINK') {
-    url = [NSURL URLFromIEURLFile:urlPathString];
-  }
-  else if ([ext isEqualToString:@"webloc"] || [ext isEqualToString:@"ftploc"] ||
-           fileType == 'ilht' || fileType == 'ilft')
-  {
-    url = [NSURL URLFromInetloc:urlPathString];
-  }
-
-  return url;
-}
-
 //
 // Reads the URL from a .webloc/.ftploc file.
 // Returns the URL, or nil on failure.
diff --git a/third_party/mozilla/NSWorkspace+Utils.h b/third_party/mozilla/NSWorkspace+Utils.h
index a1ea48c1..3c49b65 100644
--- a/third_party/mozilla/NSWorkspace+Utils.h
+++ b/third_party/mozilla/NSWorkspace+Utils.h
@@ -41,23 +41,7 @@
 
 @interface NSWorkspace(CaminoDefaultBrowserAdditions)
 
-- (NSArray*)installedBrowserIdentifiers;    // sort order not specified
-- (NSString*)defaultBrowserIdentifier;
-
-- (NSArray*)installedFeedViewerIdentifiers;
-- (NSString*)defaultFeedViewerIdentifier;
-
 - (void)setDefaultBrowserWithIdentifier:(NSString*)bundleID;
-- (void)setDefaultFeedViewerWithIdentifier:(NSString*)bundleID;
-
-- (NSString*)identifierForBundle:(NSURL*)inBundleURL;
-- (NSString*)displayNameForFile:(NSURL*)inFileURL;
-
-// OS feature checks
-+ (NSString*)osVersionString;
-// Begin Google Modified
-//+ (BOOL)isLeopardOrHigher;
-// End Google Modified
 
 @end
 
diff --git a/third_party/mozilla/NSWorkspace+Utils.m b/third_party/mozilla/NSWorkspace+Utils.m
index 1fbc6b1..3c55e4d 100644
--- a/third_party/mozilla/NSWorkspace+Utils.m
+++ b/third_party/mozilla/NSWorkspace+Utils.m
@@ -42,45 +42,6 @@
 
 @implementation NSWorkspace(CaminoDefaultBrowserAdditions)
 
-- (NSArray*)installedBrowserIdentifiers
-{
-  NSArray* apps = [(NSArray*)LSCopyAllHandlersForURLScheme(CFSTR("https")) autorelease];
-
-  // add the default if it isn't there
-  NSString* defaultHandler = [self defaultBrowserIdentifier];
-  if (defaultHandler && ([apps indexOfObject:defaultHandler] == NSNotFound))
-    apps = [apps arrayByAddingObject:defaultHandler];
-
-  return apps;
-}
-
-- (NSArray*)installedFeedViewerIdentifiers
-{
-  NSArray* apps = [(NSArray*)LSCopyAllHandlersForURLScheme(CFSTR("feed")) autorelease];
-
-  // add the default if it isn't there
-  NSString* defaultHandler = [self defaultFeedViewerIdentifier];
-  if (defaultHandler && ([apps indexOfObject:defaultHandler] == NSNotFound))
-    apps = [apps arrayByAddingObject:defaultHandler];
-
-  return apps;
-}
-
-- (NSString*)defaultBrowserIdentifier
-{
-  NSString* defaultBundleId = [(NSString*)LSCopyDefaultHandlerForURLScheme(CFSTR("http")) autorelease];
-  // Sometimes LaunchServices likes to pretend there's no default browser.
-  // If that happens, we'll assume it's probably Safari.
-  if (!defaultBundleId)
-    defaultBundleId = @"com.apple.safari";
-  return defaultBundleId;
-}
-
-- (NSString*)defaultFeedViewerIdentifier
-{
-  return [(NSString*)LSCopyDefaultHandlerForURLScheme(CFSTR("feed")) autorelease];
-}
-
 - (void)setDefaultBrowserWithIdentifier:(NSString*)bundleID
 {
   LSSetDefaultHandlerForURLScheme(CFSTR("http"), (CFStringRef)bundleID);
@@ -89,76 +50,4 @@
   LSSetDefaultRoleHandlerForContentType(kUTTypeURL, kLSRolesViewer, (CFStringRef)bundleID);
 }
 
-- (void)setDefaultFeedViewerWithIdentifier:(NSString*)bundleID
-{
-  LSSetDefaultHandlerForURLScheme(CFSTR("feed"), (CFStringRef)bundleID);
-}
-
-- (NSString*)identifierForBundle:(NSURL*)inBundleURL
-{
-  if (!inBundleURL) return nil;
-
-  NSBundle* tmpBundle = [NSBundle bundleWithPath:[[inBundleURL path] stringByStandardizingPath]];
-  if (tmpBundle)
-  {
-    NSString* tmpBundleID = [tmpBundle bundleIdentifier];
-    if (tmpBundleID && ([tmpBundleID length] > 0)) {
-      return tmpBundleID;
-    }
-  }
-  return nil;
-}
-
-- (NSString*)displayNameForFile:(NSURL*)inFileURL
-{
-  NSString *name = nil;
-  [inFileURL getResourceValue:&name forKey:NSURLLocalizedNameKey error:nil];
-  return name;
-}
-
-//
-// +osVersionString
-//
-// Returns the system version string from
-// /System/Library/CoreServices/SystemVersion.plist
-// (as recommended by Apple).
-//
-+ (NSString*)osVersionString
-{
-  NSDictionary* versionInfo = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
-  return [versionInfo objectForKey:@"ProductVersion"];
-}
-
-// Begin Google Modified
-#if 0
-//
-// +systemVersion
-//
-// Returns the host's OS version as returned by the 'sysv' gestalt selector,
-// 10.x.y = 0x000010xy
-//
-+ (long)systemVersion
-{
-  static SInt32 sSystemVersion = 0;
-  if (!sSystemVersion)
-    Gestalt(gestaltSystemVersion, &sSystemVersion);
-  return (long)sSystemVersion;
-}
-
-//
-// +isLeopardOrHigher
-//
-// returns YES if we're on 10.5 or better
-//
-+ (BOOL)isLeopardOrHigher
-{
-#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
-  return YES;
-#else
-  return [self systemVersion] >= 0x1050;
-#endif
-}
-#endif
-// End Google Modified
-
 @end
diff --git a/third_party/mozilla/README.chromium b/third_party/mozilla/README.chromium
index 58b692b..9103429e 100644
--- a/third_party/mozilla/README.chromium
+++ b/third_party/mozilla/README.chromium
@@ -16,6 +16,7 @@
     NSWorkspace+Utils.h/m
 
 Local modifications:
+- All methods that are not used in Chromium have been removed.
 - NSURL+Utils.m was modified to use non-deprecated Cocoa APIs to allow
   compilation on modern versions of Mac OS X.
 - NSString+Utils.m was renamed to NSString+Utils.mm and modified to use GURL
@@ -32,13 +33,3 @@
   interpreted as a URL if possible.
 - NSWorkspace+Utils.m was modified to compile on the x86_64 architecture.
 - MOZILLA_EXPORT was added to some constants in NSPasteboard+Utils.h.
-- +[NSWorkspace(CaminoDefaultBrowserAdditions) isLeopardOrHigher] hidden since
-  it relies on methods deprecated in 10.8 (and is unused in Chrome).
-- NSWorkspace(CaminoDefaultBrowserAdditions) methods defaultBrowserURL,
-  defaultFeedViewerURL, and urlOfApplicationWithIdentifier: removed since they
-  are unused in Chrome and rely on deprecated APIs as of 10.10.
-- -[NSWorkspace(CaminoDefaultBrowserAdditions) displayNameForFile] was modified
-  to use the NSURLLocalizedNameKey rather than LSCopyDisplayNameForURL(), which
-  is deprecated as of 10.11.
-- -[NString(CaminoURLStringUtils) unescapedURI] was removed because it used
-  a deprecated CFString function.
diff --git a/tools/android/errorprone_plugin/BUILD.gn b/tools/android/errorprone_plugin/BUILD.gn
index 0f205ff..0c13ec0 100644
--- a/tools/android/errorprone_plugin/BUILD.gn
+++ b/tools/android/errorprone_plugin/BUILD.gn
@@ -35,31 +35,3 @@
     "//third_party/android_deps:com_google_errorprone_javac_java",
   ]
 }
-
-android_library("no_redundant_field_init_check_int_test_java") {
-  testonly = true
-  enable_errorprone = true
-  errorprone_expected_warning_regex = "NoRedundantFieldInitCheck"
-  sources = [ "test/src/org/chromium/tools/errorprone/plugin/NoRedundantFieldInitCheckIntTest.java" ]
-  deps = []
-}
-
-android_library("test_class_name_check_test_java") {
-  testonly = true
-  enable_errorprone = true
-  errorprone_expected_warning_regex = "TestClassNameCheck"
-  sources = [ "test/src/org/chromium/tools/errorprone/plugin/TestClassNameCheckTesting.java" ]
-  deps = [
-    "//base:base_java_test_support",
-    "//third_party/android_support_test_runner:runner_java",
-    "//third_party/junit:junit",
-  ]
-}
-
-group("errorprone_plugin_tests") {
-  testonly = true
-  deps = [
-    ":no_redundant_field_init_check_int_test_java",
-    ":test_class_name_check_test_java",
-  ]
-}
diff --git a/tools/android/errorprone_plugin/test/BUILD.gn b/tools/android/errorprone_plugin/test/BUILD.gn
new file mode 100644
index 0000000..3cd3645
--- /dev/null
+++ b/tools/android/errorprone_plugin/test/BUILD.gn
@@ -0,0 +1,30 @@
+# 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/android_nocompile.gni")
+import("nocompile_gn/nocompile_sources.gni")
+
+android_nocompile_test_suite("errorprone_plugin_tests") {
+  # Depend on errorprone_plugin so that the action is re-run whenever any custom
+  # errorprone check is modified.
+  deps = [ "//tools/android/errorprone_plugin" ]
+  tests = [
+    {
+      target = "nocompile_gn:no_redundant_field_init_check_int_test_java"
+      nocompile_sources =
+          rebase_path(no_redundant_field_init_check_int_test_nocompile_sources,
+                      "",
+                      "nocompile_gn")
+      expected_compile_output = "warning: [NoRedundantFieldInit]"
+    },
+    {
+      target = "nocompile_gn:test_class_name_check_test_java"
+      nocompile_sources =
+          rebase_path(test_class_name_check_test_nocompile_sources,
+                      "",
+                      "nocompile_gn")
+      expected_compile_output = "warning: [TestClassNameCheck]"
+    },
+  ]
+}
diff --git a/tools/android/errorprone_plugin/test/nocompile_gn/BUILD.gn b/tools/android/errorprone_plugin/test/nocompile_gn/BUILD.gn
new file mode 100644
index 0000000..a662f06
--- /dev/null
+++ b/tools/android/errorprone_plugin/test/nocompile_gn/BUILD.gn
@@ -0,0 +1,32 @@
+# 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/android_nocompile.gni")
+import("//build/config/android/rules.gni")
+import("nocompile_sources.gni")
+
+empty_java = "../src/org/chromium/tools/errorprone/plugin/Empty.java"
+
+android_library("no_redundant_field_init_check_int_test_java") {
+  testonly = true
+  enable_errorprone = true
+  sources = [ empty_java ]
+  if (enable_android_nocompile_tests) {
+    sources += no_redundant_field_init_check_int_test_nocompile_sources
+  }
+}
+
+android_library("test_class_name_check_test_java") {
+  testonly = true
+  enable_errorprone = true
+  sources = [ empty_java ]
+  if (enable_android_nocompile_tests) {
+    sources += test_class_name_check_test_nocompile_sources
+  }
+  deps = [
+    "//base:base_java_test_support",
+    "//third_party/android_support_test_runner:runner_java",
+    "//third_party/junit:junit",
+  ]
+}
diff --git a/tools/android/errorprone_plugin/test/nocompile_gn/nocompile_sources.gni b/tools/android/errorprone_plugin/test/nocompile_gn/nocompile_sources.gni
new file mode 100644
index 0000000..1be38a1
--- /dev/null
+++ b/tools/android/errorprone_plugin/test/nocompile_gn/nocompile_sources.gni
@@ -0,0 +1,9 @@
+# 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.
+
+no_redundant_field_init_check_int_test_nocompile_sources = [ "../src/org/chromium/tools/errorprone/plugin/NoRedundantFieldInitCheckIntTest.java" ]
+
+test_class_name_check_test_nocompile_sources = [
+  "../src/org/chromium/tools/errorprone/plugin/TestClassNameCheckTesting.java",
+]
diff --git a/tools/android/errorprone_plugin/test/src/org/chromium/tools/errorprone/plugin/Empty.java b/tools/android/errorprone_plugin/test/src/org/chromium/tools/errorprone/plugin/Empty.java
new file mode 100644
index 0000000..1c32d43
--- /dev/null
+++ b/tools/android/errorprone_plugin/test/src/org/chromium/tools/errorprone/plugin/Empty.java
@@ -0,0 +1,10 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.tools.errorprone.plugin;
+
+/**
+ * Empty class.
+ */
+public class Empty {}
diff --git a/tools/infra/builder-cache-clobber.py b/tools/infra/builder-cache-clobber.py
index f74ccb8..b50c69099 100755
--- a/tools/infra/builder-cache-clobber.py
+++ b/tools/infra/builder-cache-clobber.py
@@ -21,6 +21,7 @@
   parser.add_argument('--builder', required=True)
   parser.add_argument('--bucket', required=True)
   parser.add_argument('--project', default='chromium')
+  parser.add_argument('--bot-id', default=None)
   args = parser.parse_args(raw_args)
 
   # Matches http://bit.ly/2WZO33P
@@ -28,8 +29,12 @@
   cache = 'builder_%s_v2' % (h.hexdigest())
   pool = 'luci.%s.%s' % (args.project, args.bucket)
 
-  clobber_cache_utils.clobber_caches(args.swarming_server, pool, cache,
-                                     'cache/builder', args.dry_run)
+  clobber_cache_utils.clobber_caches(args.swarming_server,
+                                     pool,
+                                     cache,
+                                     'cache/builder',
+                                     args.dry_run,
+                                     bot_id=args.bot_id)
 
   return 0
 
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index d458ef6..5cbb8ce 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -318,7 +318,6 @@
       'linux-wpt-fyi-rel': 'release_bot_minimal_symbols',
       'linux-wpt-identity-fyi-rel': 'release_bot_minimal_symbols',
       'linux-wpt-input-fyi-rel': 'release_bot_minimal_symbols',
-      'linux-wpt-payments-fyi-rel': 'release_bot_minimal_symbols',
       'mac-code-coverage': 'clang_code_coverage',
       'mac-hermetic-upgrade-rel': 'release_bot',
       'mac-paeverywhere-x64-fyi-dbg': 'debug_bot_paeverywhere_x64',
@@ -969,7 +968,6 @@
       'linux-wpt-fyi-rel': 'release_trybot',
       'linux-wpt-identity-fyi-rel': 'release_trybot',
       'linux-wpt-input-fyi-rel': 'release_trybot',
-      'linux-wpt-payments-fyi-rel': 'release_trybot',
       'linux-webkit-msan-rel': 'msan_release_bot',
       'linux_chromium_archive_rel_ng': 'release_bot',
       'linux_chromium_asan_rel_ng': 'asan_lsan_release_trybot',
@@ -1030,12 +1028,12 @@
       'ios13-sdk-simulator': 'ios_simulator_debug_static_rbe_bot_xctest',
       'ios14-beta-simulator': 'ios_simulator_debug_static_rbe_bot_xctest',
       'ios14-sdk-simulator': 'ios_simulator_debug_static_rbe_bot_xctest',
-      'ios-simulator': 'ios_simulator_debug_static_rbe_bot_xctest',
-      'ios-simulator-coverage-exp': 'clang_code_coverage_ios_partial_instrumentation_xctest',
-      'ios-simulator-full-configs': 'ios_simulator_debug_static_bot_xctest',
-      'ios-simulator-full-configs-coverage-exp': 'clang_code_coverage_ios_partial_instrumentation_xctest',
+      'ios-simulator': 'ios_simulator_rbe_code_coverage_partial_instrumentation_xctest',
+      'ios-simulator-coverage-exp': 'ios_simulator_rbe_code_coverage_partial_instrumentation_xctest',
+      'ios-simulator-full-configs': 'ios_simulator_code_coverage_partial_instrumentation_xctest',
+      'ios-simulator-full-configs-coverage-exp': 'ios_simulator_rbe_code_coverage_partial_instrumentation_xctest',
       'ios-simulator-cronet': 'ios_cronet_xctest',
-      'ios-simulator-code-coverage': 'clang_code_coverage_ios_partial_instrumentation_xctest',
+      'ios-simulator-code-coverage': 'ios_simulator_rbe_code_coverage_partial_instrumentation_xctest',
       'ios-simulator-cr-recipe': 'ios_simulator_debug_static_bot_xctest',
       'ios-simulator-noncq': 'ios_simulator_debug_static_rbe_bot_xctest',
       'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_multi_window_xctest',
@@ -1696,8 +1694,12 @@
       'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'ios_use_goma_rbe', 'xctest',
     ],
 
-    'clang_code_coverage_ios_partial_instrumentation_xctest': [
-      'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'ios_use_goma_rbe', 'partial_code_coverage_instrumentation', 'xctest',
+    'ios_simulator_code_coverage_partial_instrumentation_xctest': [
+      'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'ios_simulator', 'partial_code_coverage_instrumentation', 'xctest',
+    ],
+
+    'ios_simulator_rbe_code_coverage_partial_instrumentation_xctest': [
+      'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'ios_simulator', 'ios_use_goma_rbe', 'partial_code_coverage_instrumentation', 'xctest',
     ],
 
     'clang_tot_asan_lsan_static_release': [
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index 05b31b01..b124180b 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -693,14 +693,6 @@
       "use_goma": true
     }
   },
-  "linux-wpt-payments-fyi-rel": {
-    "gn_args": {
-      "is_component_build": false,
-      "is_debug": false,
-      "symbol_level": 1,
-      "use_goma": true
-    }
-  },
   "mac-code-coverage": {
     "gn_args": {
       "is_clang": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
index 9767140..00467cf3 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
@@ -587,15 +587,6 @@
       "use_goma": true
     }
   },
-  "linux-wpt-payments-fyi-rel": {
-    "gn_args": {
-      "dcheck_always_on": true,
-      "is_component_build": false,
-      "is_debug": false,
-      "symbol_level": 1,
-      "use_goma": true
-    }
-  },
   "linux_chromium_archive_rel_ng": {
     "gn_args": {
       "is_component_build": false,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
index 5e33d584..3adce53 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -237,6 +237,7 @@
   },
   "ios-simulator": {
     "gn_args": {
+      "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt",
       "enable_run_ios_unittests_with_xctest": true,
       "ios_use_goma_rbe": true,
       "is_component_build": false,
@@ -245,6 +246,7 @@
       "target_cpu": "x64",
       "target_environment": "simulator",
       "target_os": "ios",
+      "use_clang_coverage": true,
       "use_goma": true
     }
   },
@@ -257,6 +259,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_clang_coverage": true,
       "use_goma": true
@@ -271,6 +274,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_clang_coverage": true,
       "use_goma": true
@@ -316,6 +320,7 @@
   },
   "ios-simulator-full-configs": {
     "gn_args": {
+      "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt",
       "enable_run_ios_unittests_with_xctest": true,
       "is_component_build": false,
       "is_debug": true,
@@ -323,6 +328,7 @@
       "target_cpu": "x64",
       "target_environment": "simulator",
       "target_os": "ios",
+      "use_clang_coverage": true,
       "use_goma": true
     }
   },
@@ -335,6 +341,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_clang_coverage": true,
       "use_goma": true
diff --git a/tools/memory/asan/blacklist.txt b/tools/memory/asan/blacklist.txt
deleted file mode 100644
index 35fa055..0000000
--- a/tools/memory/asan/blacklist.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# The rules in this file are only applied at compile time. If you can modify the
-# source in question, consider function attributes to disable instrumentation.
-#
-# Please think twice before you add or remove these rules.
diff --git a/tools/memory/asan/blacklist_win.txt b/tools/memory/asan/blocklist_win.txt
similarity index 100%
rename from tools/memory/asan/blacklist_win.txt
rename to tools/memory/asan/blocklist_win.txt
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index a6af6634..1fda9e7 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -8529,6 +8529,11 @@
   <int value="1" label="Sent"/>
 </enum>
 
+<enum name="BooleanSet">
+  <int value="0" label="Not set"/>
+  <int value="1" label="Set"/>
+</enum>
+
 <enum name="BooleanShareGroup">
   <int value="0" label="No share group"/>
   <int value="1" label="Using share group"/>
@@ -9911,6 +9916,25 @@
   </int>
 </enum>
 
+<enum name="ChromeOSProfileRecordStatus">
+  <int value="0" label="Metrics recording is disabled">
+    Profile data was not recorded since metric recording is disabled.
+  </int>
+  <int value="1" label="Profile manager is unset">
+    Profile data was redacted since the profile manager used to obtain user
+    profile(s) is unset.
+  </int>
+  <int value="2" label="No loaded user profile is found">
+    Profile data was redacted since there is no user profile initialized.
+  </int>
+  <int value="3" label="App sync is disabled">
+    Profile data was redacted since App Sync is disabled.
+  </int>
+  <int value="4" label="App sync is enabled">
+    Profile data was recorded in full since App Sync is enabled.
+  </int>
+</enum>
+
 <enum name="ChromeOSRecoveryReason">
   <summary>
     Reason for entering Recovery Mode. See
@@ -21413,6 +21437,19 @@
   <int value="2144565498" label="en-ZA,bs"/>
 </enum>
 
+<enum name="EndRecordingReason">
+  <int value="0" label="Stop recording button"/>
+  <int value="1" label="Display or window closing"/>
+  <int value="2" label="Active user changed"/>
+  <int value="3" label="Session blocked"/>
+  <int value="4" label="Shutting down"/>
+  <int value="5" label="Imminent suspend"/>
+  <int value="6" label="Recording service disconnected"/>
+  <int value="7" label="File IO error"/>
+  <int value="8" label="Dlp interruption"/>
+  <int value="9" label="Low disk space"/>
+</enum>
+
 <enum name="EnhancedBookmarkViewMode">
   <obsolete>
     Deprecated 9/2015.
diff --git a/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml b/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
index b7e25d5..aa90d0d9 100644
--- a/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
@@ -309,7 +309,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosSelectToSpeak" enum="BooleanEnabled"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>dmazzoni@chromium.org</owner>
   <owner>katie@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -390,7 +390,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosSpokenFeedback" enum="BooleanEnabled"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>aleventhal@google.com</owner>
@@ -682,7 +682,7 @@
 </histogram>
 
 <histogram name="Accessibility.Mac.ReduceTransparency" enum="BooleanEnabled"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>ellyjones@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
@@ -718,7 +718,7 @@
 </histogram>
 
 <histogram name="Accessibility.ModeFlag" enum="AccessibilityModeFlagEnum"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>dmazzoni@chromium.org</owner>
   <owner>aboxhall@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/android/histograms.xml b/tools/metrics/histograms/histograms_xml/android/histograms.xml
index 36f0fec..f8f438e8 100644
--- a/tools/metrics/histograms/histograms_xml/android/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/android/histograms.xml
@@ -477,7 +477,7 @@
 </histogram>
 
 <histogram name="Android.DefaultBrowserPromo.DialogShown"
-    enum="AndroidDefaultBrowserPromoType" expires_after="2021-03-26">
+    enum="AndroidDefaultBrowserPromoType" expires_after="2021-05-30">
   <owner>lazzzis@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <owner>pavely@chromium.org</owner>
@@ -501,7 +501,7 @@
 </histogram>
 
 <histogram name="Android.DefaultBrowserPromo.Outcome.NoDefault"
-    enum="AndroidDefaultBrowserPromoOutcomeType" expires_after="2021-03-26">
+    enum="AndroidDefaultBrowserPromoOutcomeType" expires_after="2021-05-30">
   <owner>lazzzis@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <owner>pavely@chromium.org</owner>
@@ -514,7 +514,7 @@
 </histogram>
 
 <histogram name="Android.DefaultBrowserPromo.Outcome.OtherDefault"
-    enum="AndroidDefaultBrowserPromoOutcomeType" expires_after="2021-03-26">
+    enum="AndroidDefaultBrowserPromoOutcomeType" expires_after="2021-05-30">
   <owner>lazzzis@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <owner>pavely@chromium.org</owner>
@@ -527,7 +527,7 @@
 </histogram>
 
 <histogram name="Android.DefaultBrowserPromo.RoleManagerShown"
-    enum="AndroidDefaultBrowserPromoType" expires_after="2021-03-26">
+    enum="AndroidDefaultBrowserPromoType" expires_after="2021-05-30">
   <owner>lazzzis@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <owner>pavely@chromium.org</owner>
@@ -549,7 +549,7 @@
 </histogram>
 
 <histogram name="Android.DefaultBrowserPromo.UIDismissalReason.OtherDefault"
-    enum="AndroidDefaultBrowserPromoUserActionType" expires_after="2021-03-26">
+    enum="AndroidDefaultBrowserPromoUserActionType" expires_after="2021-05-30">
   <owner>lazzzis@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <owner>pavely@chromium.org</owner>
@@ -613,7 +613,7 @@
 </histogram>
 
 <histogram name="Android.Download.Rename.Dialog.Action"
-    enum="Android.Download.Rename.Dialog.Action" expires_after="2021-03-28">
+    enum="Android.Download.Rename.Dialog.Action" expires_after="2021-05-30">
   <owner>hesen@chromium.org</owner>
   <owner>clank-downloads@google.com</owner>
   <summary>
@@ -623,7 +623,7 @@
 </histogram>
 
 <histogram name="Android.Download.Rename.Result"
-    enum="Android.Download.Rename.Result" expires_after="2021-03-28">
+    enum="Android.Download.Rename.Result" expires_after="2021-05-30">
   <owner>hesen@chromium.org</owner>
   <owner>clank-downloads@google.com</owner>
   <summary>
@@ -745,7 +745,7 @@
 </histogram>
 
 <histogram name="Android.DownloadManager.OpenSource.Other"
-    enum="AndroidDownloadOpenSource" expires_after="2021-03-28">
+    enum="AndroidDownloadOpenSource" expires_after="2021-05-30">
   <owner>xingliu@chromium.org</owner>
   <owner>clank-downloads@google.com</owner>
   <summary>
@@ -755,7 +755,7 @@
 </histogram>
 
 <histogram name="Android.DownloadManager.OpenSource.Video"
-    enum="AndroidDownloadOpenSource" expires_after="2021-03-28">
+    enum="AndroidDownloadOpenSource" expires_after="2021-05-30">
   <owner>xingliu@chromium.org</owner>
   <owner>clank-downloads@google.com</owner>
   <summary>Records how users open video download files on Android.</summary>
@@ -898,7 +898,7 @@
 </histogram>
 
 <histogram base="true" name="Android.FeatureModules.InstallStatus"
-    enum="FeatureModuleInstallStatus" expires_after="2021-01-31">
+    enum="FeatureModuleInstallStatus" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes
        name="AndroidFeatureModuleName" -->
 
@@ -1134,7 +1134,7 @@
 </histogram>
 
 <histogram name="Android.KernelVersion" enum="AndroidKernelVersion"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>rsesek@chromium.org</owner>
   <summary>
     Reports the kernel major and minor version from the utsname.release field.
@@ -1266,7 +1266,7 @@
 </histogram>
 
 <histogram base="true" name="Android.MemoryPressureNotification"
-    enum="Android.MemoryPressureNotification" expires_after="2021-03-28">
+    enum="Android.MemoryPressureNotification" expires_after="2021-05-30">
   <owner>ssid@chromium.org</owner>
   <summary>
     Memory pressure notifications sent by Android through ComponentCallbacks2.
@@ -1966,7 +1966,7 @@
 </histogram>
 
 <histogram name="Android.StrictMode.OverrideUrlLoadingTime" units="ms"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>yfriedman@chromium.org</owner>
   <owner>wnwen@chromium.org</owner>
   <summary>
@@ -1976,7 +1976,7 @@
 </histogram>
 
 <histogram name="Android.StrictMode.TabPersistentStore" units="ms"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wnwen@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/apps/histograms.xml b/tools/metrics/histograms/histograms_xml/apps/histograms.xml
index 76cafc5..274ea02d 100644
--- a/tools/metrics/histograms/histograms_xml/apps/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/apps/histograms.xml
@@ -130,7 +130,7 @@
 </histogram>
 
 <histogram name="Apps.AppList.AppSearchProvider.QueryTime" units="ms"
-    expires_after="2021-03-15">
+    expires_after="2021-05-30">
   <owner>jennyz@chromium.org</owner>
   <owner>newcomer@chromium.org</owner>
   <summary>
@@ -431,7 +431,7 @@
 </histogram>
 
 <histogram name="Apps.AppList.SuggestedFiles.LaunchType"
-    enum="LauncherRankingItemType" expires_after="2021-03-12">
+    enum="LauncherRankingItemType" expires_after="2021-05-30">
   <owner>tby@chromium.org</owner>
   <owner>jiameng@chromium.org</owner>
   <summary>
@@ -601,7 +601,7 @@
 </histogram>
 
 <histogram name="Apps.AppList.ZeroStateResultsList.ContainsDriveFiles"
-    enum="Boolean" expires_after="2021-02-07">
+    enum="Boolean" expires_after="2021-05-30">
   <owner>wrong@chromium.org</owner>
   <owner>tby@chromium.org</owner>
   <owner>jiameng@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/arc/histograms.xml b/tools/metrics/histograms/histograms_xml/arc/histograms.xml
index 6106732..076f8a03 100644
--- a/tools/metrics/histograms/histograms_xml/arc/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/arc/histograms.xml
@@ -138,7 +138,7 @@
 </histogram>
 
 <histogram name="Arc.AppListRecommendedImp.AllImpression" units="count"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>robsc@chromium.org</owner>
   <owner>napper@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/ash/histograms.xml b/tools/metrics/histograms/histograms_xml/ash/histograms.xml
index 66b0825..2995fa1 100644
--- a/tools/metrics/histograms/histograms_xml/ash/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/ash/histograms.xml
@@ -233,6 +233,19 @@
   </summary>
 </histogram>
 
+<histogram
+    name="Ash.CaptureModeController.EndRecordingReason.{TabletOrClamshell}"
+    enum="EndRecordingReason" expires_after="2021-11-23">
+  <owner>afakhry@chromium.org</owner>
+  <owner>gzadina@google.com</owner>
+  <summary>
+    Recorded whenever capture mode screen recording is ended in
+    {TabletOrClamshell}. The recorded enum value indicates the reason that lead
+    to ending the screen recording.
+  </summary>
+  <token key="TabletOrClamshell" variants="DisplayModes"/>
+</histogram>
+
 <histogram name="Ash.CaptureModeController.EntryPoint.{TabletOrClamshell}"
     enum="CaptureModeEntryType" expires_after="2021-09-29">
   <owner>chinsenj@chromium.org</owner>
@@ -971,7 +984,7 @@
 </histogram>
 
 <histogram name="Ash.Login.PinAutosubmit.Backfill"
-    enum="PinAutosubmitBackfillEvent" expires_after="2021-03-30">
+    enum="PinAutosubmitBackfillEvent" expires_after="2021-05-30">
   <owner>rrsilva@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <summary>
@@ -1936,7 +1949,7 @@
 </histogram>
 
 <histogram name="Ash.Window.AnimationSmoothness.CrossFade" units="%"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wutao@chromium.org</owner>
   <summary>
     Relative smoothness of cross fade animation when setting window bounds. 100%
@@ -2209,7 +2222,7 @@
 
 <histogram
     name="Ash.WorkspaceWindowResizer.TabDragging.PresentationTime.ClamshellMode"
-    units="ms" expires_after="2021-02-03">
+    units="ms" expires_after="2021-05-30">
   <owner>yichenz@chromium.org</owner>
   <owner>chromeos-wmp@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/assistant/histograms.xml b/tools/metrics/histograms/histograms_xml/assistant/histograms.xml
index 970e1ec01..36dea56 100644
--- a/tools/metrics/histograms/histograms_xml/assistant/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/assistant/histograms.xml
@@ -50,7 +50,7 @@
 </histogram>
 
 <histogram name="Assistant.ContextEnabledUserCount" enum="BooleanEnabled"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>updowndota@chromium.org</owner>
   <owner>xiaohuic@chromium.org</owner>
   <summary>
@@ -292,7 +292,7 @@
 </histogram>
 
 <histogram name="QuickAnswers.ContextMenu.Close" enum="BooleanClicked"
-    expires_after="2021-02-14">
+    expires_after="2021-05-30">
   <owner>updowndota@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/background/histograms.xml b/tools/metrics/histograms/histograms_xml/background/histograms.xml
index 91c9827..ddf81fb 100644
--- a/tools/metrics/histograms/histograms_xml/background/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/background/histograms.xml
@@ -189,7 +189,7 @@
 </histogram>
 
 <histogram name="BackgroundMode.OnStartup.AutoLaunchState"
-    enum="AutoLaunchState" expires_after="2021-03-30">
+    enum="AutoLaunchState" expires_after="2021-05-30">
   <owner>mvanouwerkerk@chromium.org</owner>
   <owner>rdevlin.cronin@chromium.org</owner>
   <summary>
@@ -199,7 +199,7 @@
 </histogram>
 
 <histogram name="BackgroundMode.OnStartup.IsBackgroundModePrefEnabled"
-    enum="BooleanEnabled" expires_after="2021-03-30">
+    enum="BooleanEnabled" expires_after="2021-05-30">
   <owner>mvanouwerkerk@chromium.org</owner>
   <owner>rdevlin.cronin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/blink/histograms.xml b/tools/metrics/histograms/histograms_xml/blink/histograms.xml
index b540da0..fd07e6cd 100644
--- a/tools/metrics/histograms/histograms_xml/blink/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/blink/histograms.xml
@@ -423,7 +423,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.Compositing.LayerPromotionCount"
-    units="units" expires_after="2021-03-28">
+    units="units" expires_after="2021-05-30">
   <owner>pdr@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -883,7 +883,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.ChunkCount" units="chunks"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -896,7 +896,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.ParsingTimeMax" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -909,7 +909,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.ParsingTimeMin" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -922,7 +922,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.ParsingTimeTotal" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -935,7 +935,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.TokensParsedAverage" units="tokens"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -944,7 +944,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.TokensParsedMax" units="tokens"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -953,7 +953,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.TokensParsedMin" units="tokens"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -962,7 +962,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.YieldedTimeAverage" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -975,7 +975,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.YieldedTimeMax" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -988,7 +988,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.YieldedTimeMin" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>schenney@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -2104,7 +2104,7 @@
 </histogram>
 
 <histogram name="Blink.UseCounter.DocumentPolicy.Header"
-    enum="DocumentPolicyFeature" expires_after="2021-03-31">
+    enum="DocumentPolicyFeature" expires_after="2021-05-30">
   <owner>iclelland@chromium.org</owner>
   <owner>feature-control@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/browser/histograms.xml b/tools/metrics/histograms/histograms_xml/browser/histograms.xml
index 47f111a..9216524 100644
--- a/tools/metrics/histograms/histograms_xml/browser/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/browser/histograms.xml
@@ -454,7 +454,7 @@
 </histogram>
 
 <histogram name="BrowserDialogs.ExternalProtocol.HandleState"
-    enum="HandleStateType" expires_after="2021-03-28">
+    enum="HandleStateType" expires_after="2021-05-30">
   <owner>dominickn@chromium.org</owner>
   <owner>meacer@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/chromeos/histograms.xml b/tools/metrics/histograms/histograms_xml/chromeos/histograms.xml
index 3d45817..7bfb0d5 100644
--- a/tools/metrics/histograms/histograms_xml/chromeos/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/chromeos/histograms.xml
@@ -292,6 +292,18 @@
   </summary>
 </histogram>
 
+<histogram name="ChromeOS.CWP.RecordPerf" enum="ChromeOSProfileRecordStatus"
+    expires_after="2021-11-30">
+  <owner>dubin@google.com</owner>
+  <owner>cwp-team@google.com</owner>
+  <summary>
+    A count of the various outcomes related to recording the profile data
+    collected via &quot;perf events&quot; on Chrome OS. The histogram is
+    recorded when system-wide CPU profiling finishes and the collected data is
+    being saved to memory for later upload.
+  </summary>
+</histogram>
+
 <histogram name="ChromeOS.CWP.UploadPerf" units="reports"
     expires_after="2021-05-16">
   <owner>aalexand@google.com</owner>
@@ -672,7 +684,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Settings.Languages.Browser.Interaction"
-    enum="SettingsLanguagesPageBrowserInteraction" expires_after="2021-03-31">
+    enum="SettingsLanguagesPageBrowserInteraction" expires_after="2021-05-30">
   <owner>myy@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -682,7 +694,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Settings.Languages.Browser.OfferToTranslateCheckbox"
-    enum="BooleanChecked" expires_after="2021-03-31">
+    enum="BooleanChecked" expires_after="2021-05-30">
   <owner>myy@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -692,7 +704,7 @@
 </histogram>
 
 <histogram base="true" name="ChromeOS.Settings.Languages.Browser.Toggle"
-    enum="BooleanToggled" expires_after="2021-03-31">
+    enum="BooleanToggled" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="SettingsLanguagesPageToggle" -->
 
   <owner>myy@chromium.org</owner>
@@ -704,7 +716,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Settings.Languages.Interaction"
-    enum="SettingsLanguagesPageInteraction" expires_after="2021-03-31">
+    enum="SettingsLanguagesPageInteraction" expires_after="2021-05-30">
   <owner>myy@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -714,7 +726,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Settings.Languages.OfferToTranslateCheckbox"
-    enum="BooleanChecked" expires_after="2021-03-31">
+    enum="BooleanChecked" expires_after="2021-05-30">
   <owner>myy@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -724,7 +736,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Settings.Languages.SupportPageVisits"
-    enum="SettingsLanguagesSupportPage" expires_after="2021-03-31">
+    enum="SettingsLanguagesSupportPage" expires_after="2021-05-30">
   <owner>myy@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -733,7 +745,7 @@
 </histogram>
 
 <histogram base="true" name="ChromeOS.Settings.Languages.Toggle"
-    enum="BooleanToggled" expires_after="2021-03-31">
+    enum="BooleanToggled" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="SettingsLanguagesPageToggle" -->
 
   <owner>myy@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/compositing/histograms.xml b/tools/metrics/histograms/histograms_xml/compositing/histograms.xml
index f1197542..b6c85a7 100644
--- a/tools/metrics/histograms/histograms_xml/compositing/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/compositing/histograms.xml
@@ -236,7 +236,7 @@
 </histogram>
 
 <histogram name="Compositing.Display.Draw.Occlusion.Calculation.Time"
-    units="microseconds" expires_after="2021-03-28">
+    units="microseconds" expires_after="2021-05-30">
   <owner>yiyix@chromium.org</owner>
   <owner>chromeos-gfx@chromium.org</owner>
   <summary>
@@ -575,7 +575,7 @@
 </histogram>
 
 <histogram name="Compositing.SurfaceAggregator.FrameContainsVideo"
-    enum="TypeOfVideoInFrame" expires_after="2021-03-28">
+    enum="TypeOfVideoInFrame" expires_after="2021-05-30">
   <owner>vikassoni@chromium.org</owner>
   <owner>khushalsagar@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/crostini/histograms.xml b/tools/metrics/histograms/histograms_xml/crostini/histograms.xml
index 5f97c0e..51add91 100644
--- a/tools/metrics/histograms/histograms_xml/crostini/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/crostini/histograms.xml
@@ -32,7 +32,7 @@
 </histogram>
 
 <histogram name="Crostini.AppLaunchResult" enum="CrostiniResult"
-    expires_after="2021-01-31">
+    expires_after="2021-05-30">
   <owner>clumptini@google.com</owner>
   <owner>tbuckley@chromium.org</owner>
   <summary>
@@ -194,7 +194,7 @@
 </histogram>
 
 <histogram name="Crostini.DiskResize.Result" enum="CrostiniDiskImageStatus"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>clumptini@google.com</owner>
   <owner>davidmunro@google.com</owner>
   <summary>
@@ -204,7 +204,7 @@
 </histogram>
 
 <histogram name="Crostini.DiskResize.Started" enum="BooleanAttempted"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>clumptini@google.com</owner>
   <owner>davidmunro@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/dev/histograms.xml b/tools/metrics/histograms/histograms_xml/dev/histograms.xml
index 05f59ab0..b3df47f 100644
--- a/tools/metrics/histograms/histograms_xml/dev/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/dev/histograms.xml
@@ -203,7 +203,7 @@
 </histogram>
 
 <histogram name="DevTools.IssuesPanelOpenedFrom"
-    enum="DevToolsIssuesPanelOpenedFrom" expires_after="2021-03-28">
+    enum="DevToolsIssuesPanelOpenedFrom" expires_after="2021-05-30">
   <owner>yangguo@chromium.org</owner>
   <owner>bmeurer@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/event/histograms.xml b/tools/metrics/histograms/histograms_xml/event/histograms.xml
index cc5e2f8..2cd518b 100644
--- a/tools/metrics/histograms/histograms_xml/event/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/event/histograms.xml
@@ -928,9 +928,9 @@
 
 <histogram
     name="Event.Latency.ScrollUpdate.Scrollbar.BrowserNotifiedToBeforeGpuSwap2"
-    units="microseconds" expires_after="2020-12-01">
-  <owner>nzolghadr@chromium.org</owner>
-  <owner>dlibby@microsoft.com</owner>
+    units="microseconds" expires_after="2021-12-01">
+  <owner>flackr@chromium.org</owner>
+  <owner>arakeri@microsoft.com</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
     Time between the display compositor receives the notification of the first
@@ -945,9 +945,9 @@
 </histogram>
 
 <histogram name="Event.Latency.ScrollUpdate.Scrollbar.GpuSwap2"
-    units="microseconds" expires_after="2020-12-01">
-  <owner>nzolghadr@chromium.org</owner>
-  <owner>dlibby@microsoft.com</owner>
+    units="microseconds" expires_after="2021-12-01">
+  <owner>flackr@chromium.org</owner>
+  <owner>arakeri@microsoft.com</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
     Time between gpu starts to swap a ScrollUpdate gesture event with scrollbar
@@ -964,9 +964,9 @@
 </histogram>
 
 <histogram name="Event.Latency.ScrollUpdate.Scrollbar.HandledToRendererSwap2"
-    units="microseconds" expires_after="2020-12-01">
-  <owner>nzolghadr@chromium.org</owner>
-  <owner>dlibby@microsoft.com</owner>
+    units="microseconds" expires_after="2021-12-01">
+  <owner>flackr@chromium.org</owner>
+  <owner>arakeri@microsoft.com</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
     Time between the ScrollUpdate gesture event with scrollbar source, is
@@ -985,9 +985,9 @@
 
 <histogram
     name="Event.Latency.ScrollUpdate.Scrollbar.RendererSwapToBrowserNotified2"
-    units="microseconds" expires_after="2020-12-01">
-  <owner>nzolghadr@chromium.org</owner>
-  <owner>dlibby@microsoft.com</owner>
+    units="microseconds" expires_after="2021-12-01">
+  <owner>flackr@chromium.org</owner>
+  <owner>arakeri@microsoft.com</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
     Time between the renderer starts to swap a frame (generates compositor
@@ -1002,9 +1002,9 @@
 </histogram>
 
 <histogram name="Event.Latency.ScrollUpdate.Scrollbar.TimeToHandled2"
-    units="microseconds" expires_after="2020-12-01">
-  <owner>nzolghadr@chromium.org</owner>
-  <owner>dlibby@microsoft.com</owner>
+    units="microseconds" expires_after="2021-12-01">
+  <owner>flackr@chromium.org</owner>
+  <owner>arakeri@microsoft.com</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
     Time between initial creation of an input event that results in a scrollbar
@@ -1024,9 +1024,9 @@
 
 <histogram
     name="Event.Latency.ScrollUpdate.Scrollbar.TimeToScrollUpdateSwapBegin4"
-    units="microseconds" expires_after="2021-04-04">
-  <owner>nzolghadr@chromium.org</owner>
-  <owner>dlibby@microsoft.com</owner>
+    units="microseconds" expires_after="2021-12-01">
+  <owner>flackr@chromium.org</owner>
+  <owner>arakeri@microsoft.com</owner>
   <owner>input-dev@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/extensions/histograms.xml b/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
index 6dd5847b..cd395c91 100644
--- a/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
@@ -398,7 +398,7 @@
 </histogram>
 
 <histogram name="Extensions.ContentVerification.FetchResult"
-    enum="BooleanSuccess" expires_after="2021-03-28">
+    enum="BooleanSuccess" expires_after="2021-05-30">
   <owner>lazyboy@chromium.org</owner>
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
@@ -627,7 +627,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.IsLargeRegexRule"
-    enum="RegexRuleStatus" expires_after="2021-03-31">
+    enum="RegexRuleStatus" expires_after="2021-05-30">
   <owner>karandeepb@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -647,7 +647,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.ManifestEnabledRulesCount2"
-    units="rules" expires_after="2021-03-31">
+    units="rules" expires_after="2021-05-30">
   <owner>karandeepb@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -1309,7 +1309,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledAndBlackListed" units="count"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>swapnilgupta@google.com</owner>
   <owner>burunduk@chromium.org</owner>
   <owner>managed-devices@google.com</owner>
@@ -1322,7 +1322,7 @@
 
 <histogram name="Extensions.ForceInstalledCacheStatus"
     enum="ExtensionInstallationDownloadingCacheStatus"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>swapnilgupta@google.com</owner>
   <owner>burunduk@chromium.org</owner>
   <owner>poromov@chromium.org</owner>
@@ -1348,7 +1348,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledDownloadingStage"
-    enum="ExtensionInstallationDownloadingStage" expires_after="2021-03-28">
+    enum="ExtensionInstallationDownloadingStage" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1364,7 +1364,7 @@
 
 <histogram name="Extensions.ForceInstalledFailureCacheStatus"
     enum="ExtensionInstallationDownloadingCacheStatus"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1378,7 +1378,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledFailureCrxInstallError"
-    enum="ExtensionInstallationCrxInstallError" expires_after="2021-03-28">
+    enum="ExtensionInstallationCrxInstallError" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1439,7 +1439,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledFailureReason3"
-    enum="ExtensionInstallationFailureReason" expires_after="2021-03-28">
+    enum="ExtensionInstallationFailureReason" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="ExtensionSource" -->
 
   <owner>burunduk@chromium.org</owner>
@@ -1458,7 +1458,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledFailureSandboxUnpackFailureReason"
-    enum="ExtensionUnpackFailureReason" expires_after="2021-03-28">
+    enum="ExtensionUnpackFailureReason" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1471,7 +1471,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledFailureSessionType"
-    enum="SessionType" expires_after="2021-03-28">
+    enum="SessionType" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1513,7 +1513,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledFetchTries" units="retries"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1544,7 +1544,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledLoadTime" units="ms"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1555,7 +1555,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledManifestFetchFailedFetchTries"
-    units="retries" expires_after="2021-03-28">
+    units="retries" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1587,7 +1587,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledManifestFetchFailedNetworkErrorCode"
-    enum="NetErrorCodes" expires_after="2021-03-28">
+    enum="NetErrorCodes" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1601,7 +1601,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledNetworkErrorCode"
-    enum="NetErrorCodes" expires_after="2021-03-28">
+    enum="NetErrorCodes" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1615,7 +1615,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledNotLoadedDisableReason"
-    enum="ExtensionDisableReason" expires_after="2021-03-28">
+    enum="ExtensionDisableReason" expires_after="2021-05-30">
   <owner>swapnilgupta@google.com</owner>
   <owner>burunduk@chromium.org</owner>
   <owner>managed-devices@google.com</owner>
@@ -1641,7 +1641,7 @@
 
 <histogram
     name="Extensions.ForceInstalledSessionsWithNonMisconfigurationFailureOccured"
-    enum="Boolean" expires_after="2021-03-28">
+    enum="Boolean" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1686,7 +1686,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledTimedOutAndNotInstalledCount"
-    units="units" expires_after="2021-03-28">
+    units="units" expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1697,7 +1697,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledTimedOutCount" units="units"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
@@ -1708,7 +1708,7 @@
 </histogram>
 
 <histogram name="Extensions.ForceInstalledTotalCandidateCount" units="units"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/gpu/histograms.xml b/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
index c4c4ef9..1d4dea2 100644
--- a/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
@@ -294,7 +294,7 @@
 </histogram>
 
 <histogram name="GPU.ContextLost" enum="ContextLostReason"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>sievers@chromium.org</owner>
   <summary>
     The reason a GPU command buffer context of a given type was lost.
@@ -645,7 +645,7 @@
 </histogram>
 
 <histogram name="GPU.GLImplementation" enum="GLImplementation"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>magchen@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
index 862fd27..8156d64 100644
--- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -6572,24 +6572,6 @@
   <affected-histogram name="FileBrowser.CrostiniSharedPaths.Depth"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="FileOperations" separator=".">
-  <suffix name="DeleteFile.NonRecursive" label=""/>
-  <suffix name="DeleteFile.Recursive" label=""/>
-  <affected-histogram name="Windows.FilesystemError"/>
-  <affected-histogram name="Windows.PostOperationState"/>
-</histogram_suffixes>
-
-<histogram_suffixes name="FindInPageRequestEndState" separator=".">
-  <suffix name="Aborted"
-      label="The request got aborted before it went through every text in the
-             document."/>
-  <suffix name="Finished"
-      label="The request finished going through every text in the document."/>
-  <affected-histogram name="WebCore.FindInPage.NumberOfTasksPerRequest"/>
-  <affected-histogram name="WebCore.FindInPage.RequestDuration"/>
-  <affected-histogram name="WebCore.FindInPage.TotalTaskDuration"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="FirstDownload" separator=".">
   <obsolete>
     Removed 2020-10.
@@ -7909,15 +7891,6 @@
   <affected-histogram name="InProductHelp.ShouldTriggerHelpUI"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="IPProtocolType" separator="_">
-  <suffix name="TCP" label=""/>
-  <suffix name="UDP" label=""/>
-  <affected-histogram name="WebRTC.PeerConnection.CandidatePairType"/>
-  <affected-histogram name="WebRTC.SystemMaxConsecutiveBytesDelayed"/>
-  <affected-histogram name="WebRTC.SystemPercentPacketsDelayed"/>
-  <affected-histogram name="WebRTC.SystemSendPacketDuration"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="IPv6_Probe" separator="_">
   <suffix name="IPv6_probe_done"
       label="with IPv6 probed for and possibly disabled"/>
@@ -9413,16 +9386,6 @@
   <affected-histogram name="NativeFileSystemAPI.WritePermissionRequestOutcome"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="NatType" separator=".">
-  <suffix name="NoNAT" label=""/>
-  <suffix name="NonSymNAT" label=""/>
-  <suffix name="SymNAT" label=""/>
-  <suffix name="UnknownNAT" label=""/>
-  <affected-histogram name="WebRTC.Stun.BatchSuccessPercent"/>
-  <affected-histogram name="WebRTC.Stun.ResponseLatency"/>
-  <affected-histogram name="WebRTC.Stun.SuccessPercent"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="NavigationCharacteristic" separator="_">
   <suffix name="ExistingRenderer_BeforeUnloadDiscounted"
       label="Navigation reused an existing renderer process. Time spent in
@@ -9435,8 +9398,8 @@
              (whether from a crash or a continued session) either spawning or
              reusing a renderer. Time spent in beforeunload subtracted.">
     <obsolete>
-      Replaced by the likely named entry. It had a misleading name as it also
-      has the before-unload time discounted.
+      Replaced by SessionRestored_BeforeUnloadDiscounte. It had a misleading
+      name as it also has the before-unload time discounted.
     </obsolete>
   </suffix>
   <suffix name="SessionRestored_BeforeUnloadDiscounted"
@@ -11180,6 +11143,8 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="NewTabPageProviders" separator=".">
+  <suffix name="allowlist"
+      label="Installed allowlist entry point suggestions."/>
   <suffix name="client" label="Suggestions coming from the client."/>
   <suffix name="client0" label="">
     <obsolete>
@@ -11228,8 +11193,11 @@
       Has never been used.
     </obsolete>
   </suffix>
-  <suffix name="whitelist"
-      label="Installed whitelist entry point suggestions."/>
+  <suffix name="whitelist" label="Installed whitelist entry point suggestions.">
+    <obsolete>
+      Replaced with allowlist (M89).
+    </obsolete>
+  </suffix>
   <affected-histogram name="NewTabPage.MostVisited"/>
   <affected-histogram name="NewTabPage.MostVisitedAge"/>
   <affected-histogram name="NewTabPage.SuggestionsImpression"/>
@@ -13759,7 +13727,11 @@
   <suffix name="AR" label="AR permission"/>
   <suffix name="AudioAndVideoCapture" label="Mic+Camera permission"/>
   <suffix name="AudioCapture" label="Microphone permission"/>
-  <suffix name="Flash" label="Flash permission"/>
+  <suffix name="Flash" label="Flash permission">
+    <obsolete>
+      Removed in M88, as the feature will not be included in the M89 launch.
+    </obsolete>
+  </suffix>
   <suffix name="Geolocation" label="Geolocation permission"/>
   <suffix name="MidiSysEx" label="Midi SysEx permission"/>
   <suffix name="MultipleDownload" label="Multiple downloads permission"/>
@@ -13784,7 +13756,11 @@
   <suffix name="AR" label="AR permission actions"/>
   <suffix name="AudioCapture" label="Microphone permission actions"/>
   <suffix name="ClipboardReadWrite" label="Clipboard permission actions"/>
-  <suffix name="Flash" label="Flash permission actions"/>
+  <suffix name="Flash" label="Flash permission actions">
+    <obsolete>
+      Removed in M88, as the feature will not be included in the M89 launch.
+    </obsolete>
+  </suffix>
   <suffix name="Geolocation" label="Geolocation permission actions"/>
   <suffix name="MidiSysEx" label="Midi SysEx permsision actions"/>
   <suffix name="Nfc" label="Nfc permsision actions"/>
@@ -16264,24 +16240,6 @@
       name="Scheduler.Experimental.Renderer.TotalTime.Wall.MainThread"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="ScreenshareLayerStats" separator=".">
-  <suffix name="FrameRate"
-      label="Frames per second sent, in fps. The value is reported when a
-             stream is removed and is calculated as the total number of
-             frames in this layer, divided by the duration of the call."/>
-  <suffix name="Qp"
-      label="Average quantizer (qp) of frames sent. The value is reported
-             when a stream is removed and is calculated, for this layer, as
-             the sum of all qp values divided the number of frames."/>
-  <suffix name="TargetBitrate"
-      label="Average target bitrate in kbps. The value is reported when a
-             stream is removed and is calculated as the sum of all target
-             bitrates for this layer (sampled after frame has been encoded)
-             divided by the total number of frames for this layer."/>
-  <affected-histogram name="WebRTC.Video.Screenshare.Layer0"/>
-  <affected-histogram name="WebRTC.Video.Screenshare.Layer1"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="ScrollSourceDevice" separator=".">
   <suffix name="Touch" label="Touch"/>
   <suffix name="Wheel" label="Wheel"/>
@@ -19391,15 +19349,6 @@
   <affected-histogram name="VRSessionVideoTime"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="WebApkDistributorType" separator=".">
-  <suffix name="Browser" label="Installed by Chrome"/>
-  <suffix name="DevicePolicy" label="Installed by device policy"/>
-  <suffix name="Other" label="Installed by other sources"/>
-  <affected-histogram name="WebApk.Session.TotalDuration2"/>
-  <affected-histogram name="WebApk.ShellApkVersion2"/>
-  <affected-histogram name="WebApk.Uninstall"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="WebApkType" separator=".">
   <suffix name="BrowserApk" label="Installed by Chrome"/>
   <suffix name="UnboundApk" label="Not installed by Chrome"/>
@@ -19589,14 +19538,6 @@
   <affected-histogram name="Media.UnderflowDuration2"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="WebRTCEchoCancellerEstimate" separator=".">
-  <suffix name="Max" label="The maximum over the time interval"/>
-  <suffix name="Min" label="The minimum over the time interval"/>
-  <suffix name="Value" label="The last estimated value of the time interval"/>
-  <affected-histogram name="WebRTC.Audio.EchoCanceller.Erl"/>
-  <affected-histogram name="WebRTC.Audio.EchoCanceller.Erle"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="WebRTCEchoCancellerStatisticType" separator=".">
   <suffix name="Average" label="The average over the time interval"/>
   <suffix name="Max" label="The maximum over the time interval"/>
@@ -19611,50 +19552,6 @@
   <affected-histogram name="WebRTC.Audio.EchoCanceller.SuppressorGainBand1"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="WebRTCMediaType" separator=".">
-  <suffix name="Audio" label="Audio"/>
-  <suffix name="Data" label="Data"/>
-  <suffix name="Video" label="Video"/>
-  <affected-histogram name="WebRTC.PeerConnection.SrtpCryptoSuite"/>
-  <affected-histogram name="WebRTC.PeerConnection.SslCipherSuite"/>
-</histogram_suffixes>
-
-<histogram_suffixes name="WebRTCVideoExperimentGroupId" separator=".">
-  <owner>ilnik@chromium.org</owner>
-  <owner>webrtc-video@google.com</owner>
-  <suffix name="ExperimentGroup0" label=""/>
-  <suffix name="ExperimentGroup1" label=""/>
-  <suffix name="ExperimentGroup2" label=""/>
-  <suffix name="ExperimentGroup3" label=""/>
-  <suffix name="ExperimentGroup4" label=""/>
-  <suffix name="S0" label=""/>
-  <suffix name="S1" label=""/>
-  <suffix name="S2" label=""/>
-  <affected-histogram name="WebRTC.Video.Decoded.Vp8.Qp"/>
-  <affected-histogram name="WebRTC.Video.EndToEndDelayInMs"/>
-  <affected-histogram name="WebRTC.Video.EndToEndDelayMaxInMs"/>
-  <affected-histogram name="WebRTC.Video.InterframeDelay95PercentileInMs"/>
-  <affected-histogram name="WebRTC.Video.InterframeDelayInMs"/>
-  <affected-histogram name="WebRTC.Video.InterframeDelayMaxInMs"/>
-  <affected-histogram name="WebRTC.Video.KeyFramesReceivedInPermille"/>
-  <affected-histogram name="WebRTC.Video.MediaBitrateReceivedInKbps"/>
-  <affected-histogram name="WebRTC.Video.ReceivedHeightInPixels"/>
-  <affected-histogram name="WebRTC.Video.ReceivedWidthInPixels"/>
-  <affected-histogram name="WebRTC.Video.Screenshare.Decoded.Vp8.Qp"/>
-  <affected-histogram name="WebRTC.Video.Screenshare.EndToEndDelayInMs"/>
-  <affected-histogram name="WebRTC.Video.Screenshare.EndToEndDelayMaxInMs"/>
-  <affected-histogram
-      name="WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"/>
-  <affected-histogram name="WebRTC.Video.Screenshare.InterframeDelayInMs"/>
-  <affected-histogram name="WebRTC.Video.Screenshare.InterframeDelayMaxInMs"/>
-  <affected-histogram
-      name="WebRTC.Video.Screenshare.KeyFramesReceivedInPermille"/>
-  <affected-histogram
-      name="WebRTC.Video.Screenshare.MediaBitrateReceivedInKbps"/>
-  <affected-histogram name="WebRTC.Video.Screenshare.ReceivedHeightInPixels"/>
-  <affected-histogram name="WebRTC.Video.Screenshare.ReceivedWidthInPixels"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="WebSocketErrorCodesVariants" separator="_">
   <suffix name="Localhost" label=""/>
   <suffix name="NotLocalhost" label=""/>
diff --git a/tools/metrics/histograms/histograms_xml/history/histograms.xml b/tools/metrics/histograms/histograms_xml/history/histograms.xml
index d6533e5e..ed523e2 100644
--- a/tools/metrics/histograms/histograms_xml/history/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/history/histograms.xml
@@ -332,7 +332,7 @@
 </histogram>
 
 <histogram name="History.ClearBrowsingData.UserDeletedFromTab"
-    enum="ClearBrowsingDataTab" expires_after="2021-03-28">
+    enum="ClearBrowsingDataTab" expires_after="2021-05-30">
   <owner>dullweber@chromium.org</owner>
   <owner>msramek@chromium.org</owner>
   <summary>
@@ -683,7 +683,7 @@
 </histogram>
 
 <histogram name="History.MonthlyURLCount" units="urls"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>mpearson@chromium.org</owner>
   <owner>sky@chromium.org</owner>
   <summary>
@@ -694,7 +694,7 @@
 </histogram>
 
 <histogram name="History.MonthlyVisitCount" units="visits"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>mpearson@chromium.org</owner>
   <owner>sky@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/image/histograms.xml b/tools/metrics/histograms/histograms_xml/image/histograms.xml
index 4048882..7b2add68 100644
--- a/tools/metrics/histograms/histograms_xml/image/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/image/histograms.xml
@@ -42,7 +42,7 @@
 </histogram>
 
 <histogram name="ImageAnnotationService.AccessibilityV1.ClientResult"
-    enum="ImageAnnotationServiceClientResult" expires_after="2021-03-28">
+    enum="ImageAnnotationServiceClientResult" expires_after="2021-05-30">
   <owner>dmazzoni@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>martis@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/input/histograms.xml b/tools/metrics/histograms/histograms_xml/input/histograms.xml
index 2f21c8f..f15fea78 100644
--- a/tools/metrics/histograms/histograms_xml/input/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/input/histograms.xml
@@ -22,7 +22,7 @@
 <histograms>
 
 <histogram name="InputMethod.ActiveCount" units="units"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>myy@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -651,7 +651,7 @@
 </histogram>
 
 <histogram name="InputMethod.VirtualKeyboard.InitLatency.KeyboardShownLongTail"
-    units="ms" expires_after="2021-03-28">
+    units="ms" expires_after="2021-05-30">
   <owner>jopalmer@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/ios/histograms.xml b/tools/metrics/histograms/histograms_xml/ios/histograms.xml
index 7baf968..569f4a2 100644
--- a/tools/metrics/histograms/histograms_xml/ios/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/ios/histograms.xml
@@ -233,7 +233,7 @@
 </histogram>
 
 <histogram name="IOS.CriticalActionBackgroundTimeRemaining" units="ms"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>justincohen@chromium.org</owner>
   <owner>eugenebut@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/media/histograms.xml b/tools/metrics/histograms/histograms_xml/media/histograms.xml
index dd4535a4..6501d63 100644
--- a/tools/metrics/histograms/histograms_xml/media/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/media/histograms.xml
@@ -339,7 +339,7 @@
 </histogram>
 
 <histogram name="Media.Audio.Capture.Win.Open" enum="AudioStreamOpenResult"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>gudiou@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <summary>
@@ -1226,7 +1226,7 @@
 </histogram>
 
 <histogram name="Media.Controls.Show.Audio" enum="MediaControlsShowReason"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>mlamouri@chromium.org</owner>
   <summary>
     Record whether the default media controls of an audio element were shown and
@@ -1237,7 +1237,7 @@
 </histogram>
 
 <histogram name="Media.Controls.Show.Video" enum="MediaControlsShowReason"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>mlamouri@chromium.org</owner>
   <summary>
     Record whether the default media controls of a video element were shown and
@@ -1937,7 +1937,7 @@
 </histogram>
 
 <histogram name="Media.GlobalMediaControls.UserActionFocus"
-    enum="BooleanFocused" expires_after="2021-03-28">
+    enum="BooleanFocused" expires_after="2021-05-30">
   <owner>steimel@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -2033,7 +2033,7 @@
 </histogram>
 
 <histogram name="Media.HighLatencyAudioCaptureStartupSuccess"
-    enum="AudioCaptureStartupResult" expires_after="2021-03-28">
+    enum="AudioCaptureStartupResult" expires_after="2021-05-30">
   <owner>armax@chromium.org</owner>
   <owner>guidou@chromium.org</owner>
   <owner>olka@chromium.org</owner>
@@ -2346,7 +2346,7 @@
 </histogram>
 
 <histogram name="Media.LowLatencyAudioCaptureStartupSuccess"
-    enum="AudioCaptureStartupResult" expires_after="2021-03-28">
+    enum="AudioCaptureStartupResult" expires_after="2021-05-30">
   <owner>armax@chromium.org</owner>
   <owner>guidou@chromium.org</owner>
   <owner>olka@chromium.org</owner>
@@ -2524,7 +2524,7 @@
 </histogram>
 
 <histogram base="true" name="Media.MSE.CodecChangeTime" units="ms"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wolenetz@chromium.org</owner>
   <owner>sandersd@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
@@ -2567,7 +2567,7 @@
 </histogram>
 
 <histogram name="Media.MSE.Mp4ConsecutiveEmptySamples" units="samples"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wolenetz@chromium.org</owner>
   <owner>sandersd@chromium.org</owner>
   <summary>
@@ -2580,7 +2580,7 @@
 </histogram>
 
 <histogram name="Media.MSE.Mp4EmptySamplesInTRun" units="samples"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wolenetz@chromium.org</owner>
   <owner>sandersd@chromium.org</owner>
   <summary>
@@ -2591,7 +2591,7 @@
 </histogram>
 
 <histogram name="Media.MSE.Mp4SampleSize" units="bytes"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wolenetz@chromium.org</owner>
   <owner>sandersd@chromium.org</owner>
   <summary>
@@ -2602,7 +2602,7 @@
 </histogram>
 
 <histogram name="Media.MSE.Mp4TrunSampleCount" units="samples"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wolenetz@chromium.org</owner>
   <owner>sandersd@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/memory/histograms.xml b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
index f6732f39..e0024a5 100644
--- a/tools/metrics/histograms/histograms_xml/memory/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
@@ -82,7 +82,7 @@
 
 <histogram base="true"
     name="Memory.BackgroundTask.Browser.PrivateMemoryFootprint" units="MiB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="BrowserRunningMode" -->
 
   <owner>hanxi@chromium.org</owner>
@@ -111,7 +111,7 @@
 </histogram>
 
 <histogram base="true" name="Memory.BackgroundTask.Browser.ResidentSet"
-    units="MiB" expires_after="2021-03-28">
+    units="MiB" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="BrowserRunningMode" -->
 
   <owner>hanxi@chromium.org</owner>
@@ -389,7 +389,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.FreelistSize.Foreground" units="KiB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
@@ -419,7 +419,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.Size.Foreground" units="KiB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
@@ -429,7 +429,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.VirtualSize.Foreground" units="KiB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
@@ -1461,7 +1461,7 @@
 </histogram>
 
 <histogram name="Memory.NativeLibrary.NotResidentOrderedCodeMemoryFootprint"
-    units="KB" expires_after="2021-03-28">
+    units="KB" expires_after="2021-05-30">
   <owner>lizeb@chromium.org</owner>
   <summary>
     The size of the native library code which was ordered, yet is not resident
diff --git a/tools/metrics/histograms/histograms_xml/navigation/histograms.xml b/tools/metrics/histograms/histograms_xml/navigation/histograms.xml
index 7231833..450278d 100644
--- a/tools/metrics/histograms/histograms_xml/navigation/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/navigation/histograms.xml
@@ -150,7 +150,7 @@
 
 <histogram
     name="BackForwardCache.Experimental.UnexpectedIPCMessagePostedToCachedFrame.MethodHash"
-    enum="MojoInterfaceName" expires_after="2021-03-28">
+    enum="MojoInterfaceName" expires_after="2021-05-30">
   <owner>hbolaria@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
@@ -168,7 +168,7 @@
 
 <histogram
     name="BackForwardCache.Experimental.UnexpectedIPCMessagePostedToCachedFrame.TimeUntilIPCReceived"
-    units="ms" expires_after="2021-03-28">
+    units="ms" expires_after="2021-05-30">
   <owner>hbolaria@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
@@ -358,6 +358,22 @@
   </summary>
 </histogram>
 
+<histogram name="BackForwardCache.Restore.DisableEvictionDelay" units="ms"
+    expires_after="2021-10-01">
+  <owner>carlscab@google.com</owner>
+  <owner>bfcache-dev@chromium.org</owner>
+  <summary>
+    Delay introduced by the IPC round trips to disable eviction in all the
+    renderers of a page stored in the back-forward cache. That is, the interval
+    of time between sending an SetPageLifecycleState IPC to each renderer and
+    receiving all the responses.
+
+    Recorded on reception of the last ACK reply. We added this histogram to
+    measure the impact of this extra round trip to the renderer when restoring a
+    page from the back-forward cache.
+  </summary>
+</histogram>
+
 <histogram name="BackForwardCache.Restore.NavigationToFirstPaint" units="ms"
     expires_after="2021-10-01">
   <owner>sreejakshetty@chromium.org</owner>
@@ -951,6 +967,9 @@
 </histogram>
 
 <histogram name="Navigation.TimeToURLJobStart" units="ms" expires_after="M85">
+  <obsolete>
+    Removed from code in M89 (Nov 2020), after expiring in M85.
+  </obsolete>
   <owner>carlosk@chromium.org</owner>
   <summary>
     Time between the start of a browser-started navigation request and the
diff --git a/tools/metrics/histograms/histograms_xml/net/histograms.xml b/tools/metrics/histograms/histograms_xml/net/histograms.xml
index ee473f8..a5fb030 100644
--- a/tools/metrics/histograms/histograms_xml/net/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/net/histograms.xml
@@ -1867,7 +1867,7 @@
 </histogram>
 
 <histogram name="Net.NetworkChangeNotifier.NewConnectionType"
-    enum="NetworkConnectionType" expires_after="2021-03-30">
+    enum="NetworkConnectionType" expires_after="2021-05-30">
   <owner>rockot@google.com</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -4845,7 +4845,7 @@
 </histogram>
 
 <histogram base="true" name="Net.TrustTokens.NetErrorForFetchFailure"
-    enum="NetErrorCodes" expires_after="2021-03-30">
+    enum="NetErrorCodes" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
 
   <owner>davidvc@chromium.org</owner>
@@ -4860,7 +4860,7 @@
 </histogram>
 
 <histogram base="true" name="Net.TrustTokens.NetErrorForTrustTokenOperation"
-    enum="NetErrorCodes" expires_after="2021-03-30">
+    enum="NetErrorCodes" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
 
   <owner>davidvc@chromium.org</owner>
@@ -4874,7 +4874,7 @@
 </histogram>
 
 <histogram base="true" name="Net.TrustTokens.OperationBeginTime" units="ms"
-    expires_after="2021-03-30">
+    expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
 
   <owner>davidvc@chromium.org</owner>
@@ -4924,7 +4924,7 @@
 </histogram>
 
 <histogram base="true" name="Net.TrustTokens.RequestHelperFactoryOutcome"
-    enum="TrustTokenRequestHelperFactoryOutcome" expires_after="2021-03-30">
+    enum="TrustTokenRequestHelperFactoryOutcome" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
 
   <owner>davidvc@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml b/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
index d5ac6c0b..f76d9ba2 100644
--- a/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
@@ -35972,7 +35972,8 @@
 
 <histogram name="Navigation.TimeToCommit" units="ms" expires_after="2018-03-30">
   <obsolete>
-    Removed March 2018 in favor of Navigation.StartToCommit variants.
+    Removed March 2018 in favor of Navigation.StartToCommit variants. Removed
+    from code in November 2020 (M89).
   </obsolete>
   <owner>carlosk@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/offline/OWNERS b/tools/metrics/histograms/histograms_xml/offline/OWNERS
new file mode 100644
index 0000000..c96d97e
--- /dev/null
+++ b/tools/metrics/histograms/histograms_xml/offline/OWNERS
@@ -0,0 +1,4 @@
+# If these reviewers are unavailable, please send CLs to
+# <chromium-metrics-reviews@google.com>. See tools/metrics/histograms/histograms_xml/OWNERS
+# for details.
+tbansal@chromium.org
\ No newline at end of file
diff --git a/tools/metrics/histograms/histograms_xml/offline/histograms.xml b/tools/metrics/histograms/histograms_xml/offline/histograms.xml
index a2bcb42..ee2b5f4e5 100644
--- a/tools/metrics/histograms/histograms_xml/offline/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/offline/histograms.xml
@@ -23,6 +23,8 @@
 
 <histogram name="OfflineIndicator.ConnectivityChanged.DeviceState.Offline"
     enum="OfflineIndicatorSurfaceState" expires_after="2021-05-09">
+  <owner>curranmax@chromium.org</owner>
+  <owner>tbansal@chromium.org</owner>
   <owner>sinansahin@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -33,7 +35,9 @@
 </histogram>
 
 <histogram name="OfflineIndicator.ConnectivityChanged.DeviceState.Online"
-    enum="OfflineIndicatorSurfaceState" expires_after="2021-01-01">
+    enum="OfflineIndicatorSurfaceState" expires_after="2021-05-09">
+  <owner>curranmax@chromium.org</owner>
+  <owner>tbansal@chromium.org</owner>
   <owner>sinansahin@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -53,8 +57,10 @@
   </summary>
 </histogram>
 
-<histogram name="OfflineIndicator.ShownDuration" units="s"
+<histogram name="OfflineIndicator.ShownDuration" units="ms"
     expires_after="2021-05-09">
+  <owner>curranmax@chromium.org</owner>
+  <owner>tbansal@chromium.org</owner>
   <owner>sinansahin@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/oobe/histograms.xml b/tools/metrics/histograms/histograms_xml/oobe/histograms.xml
index 0635609e..efbec73 100644
--- a/tools/metrics/histograms/histograms_xml/oobe/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/oobe/histograms.xml
@@ -128,7 +128,7 @@
 </histogram>
 
 <histogram name="OOBE.MarketingOptInScreen.BackendConnector"
-    enum="MarketingOptInBackendConnectorEvent" expires_after="2021-03-30">
+    enum="MarketingOptInBackendConnectorEvent" expires_after="2021-05-30">
   <owner>rrsilva@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <summary>
@@ -140,7 +140,7 @@
 </histogram>
 
 <histogram name="OOBE.MarketingOptInScreen.Event"
-    enum="MarketingOptInScreenEvent" expires_after="2021-03-30">
+    enum="MarketingOptInScreenEvent" expires_after="2021-05-30">
   <owner>rrsilva@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <summary>
@@ -150,7 +150,7 @@
 </histogram>
 
 <histogram name="OOBE.MarketingOptInScreen.GeolocationResolve"
-    enum="MarketingOptInGeolocationEvent" expires_after="2021-03-30">
+    enum="MarketingOptInGeolocationEvent" expires_after="2021-05-30">
   <owner>rrsilva@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <summary>
@@ -159,7 +159,7 @@
 </histogram>
 
 <histogram name="OOBE.MarketingOptInScreen.GeolocationResolveLength"
-    units="chars" expires_after="2021-03-30">
+    units="chars" expires_after="2021-05-30">
   <owner>rrsilva@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml
index 71964a0..e36c524 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -34,7 +34,7 @@
 </variants>
 
 <histogram name="AccountManager.AccountAdditionSource"
-    enum="AccountManagerAccountAdditionSource" expires_after="2021-03-28">
+    enum="AccountManagerAccountAdditionSource" expires_after="2021-05-30">
   <owner>sinhak@chromium.org</owner>
   <owner>anastasiian@chromium.org</owner>
   <summary>
@@ -165,7 +165,7 @@
 </histogram>
 
 <histogram name="AccountManager.NumAccounts" units="count"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>sinhak@chromium.org</owner>
   <summary>
     Tracks the number of accounts stored in Chrome OS Account Manager by a given
@@ -326,7 +326,7 @@
   </summary>
 </histogram>
 
-<histogram name="Ads.Media.Duration" units="ms" expires_after="2021-03-28">
+<histogram name="Ads.Media.Duration" units="ms" expires_after="2021-05-30">
   <owner>johnidel@chromium.org</owner>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
@@ -428,7 +428,7 @@
 </histogram>
 
 <histogram name="AnimatedImage.NumOfFramesSkipped" units="count"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>khushalsagar@chromium.org</owner>
   <summary>
     If the frame rate for the image animation can not be reached, frames in the
@@ -1682,7 +1682,7 @@
 </histogram>
 
 <histogram name="Bookmarks.OpenBookmarkType" enum="BookmarkType"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wychen@chromium.org</owner>
   <summary>
     Logs whether the bookmark entry is a user bookmark or a partner bookmark
@@ -2379,10 +2379,11 @@
   </summary>
 </histogram>
 
-<histogram name="ClientHints.PersistDuration" units="ms" expires_after="M88">
+<histogram name="ClientHints.PersistDuration" units="ms" expires_after="M90">
   <owner>yoavweiss@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
   <owner>mkwst@chromium.org</owner>
+  <owner>aarontag@chromium.org</owner>
   <summary>
     Duration for which the origin requested the client hints to be persisted.
     Collected on the renderer side.
@@ -2390,20 +2391,22 @@
 </histogram>
 
 <histogram name="ClientHints.UpdateEventCount" units="count"
-    expires_after="M88">
+    expires_after="M90">
   <owner>yoavweiss@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
   <owner>mkwst@chromium.org</owner>
+  <owner>aarontag@chromium.org</owner>
   <summary>
     Count of events when the client hints needs to be persisted to the disk by
     the browser.
   </summary>
 </histogram>
 
-<histogram name="ClientHints.UpdateSize" units="count" expires_after="M88">
+<histogram name="ClientHints.UpdateSize" units="count" expires_after="M90">
   <owner>yoavweiss@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
   <owner>mkwst@chromium.org</owner>
+  <owner>aarontag@chromium.org</owner>
   <summary>
     Count of client hints that need to be persisted to the disk. Recorded by the
     renderer.
@@ -3002,7 +3005,7 @@
 </histogram>
 
 <histogram name="ContextMenu.TimeToTakeAction.Abandoned" units="ms"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>twellington@chromium.org</owner>
   <owner>clank-app-team@google.com</owner>
   <summary>
@@ -3015,7 +3018,7 @@
 </histogram>
 
 <histogram name="ContextMenu.TimeToTakeAction.SelectedItem" units="ms"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>twellington@chromium.org</owner>
   <owner>clank-app-team@google.com</owner>
   <summary>
@@ -4385,7 +4388,7 @@
 </histogram>
 
 <histogram name="Downgrade.TakeSnapshot.Result" enum="SnapshotOperationResult"
-    expires_after="2021-03-07">
+    expires_after="2021-05-30">
   <owner>grt@chromium.org</owner>
   <owner>ydago@chromium.org</owner>
   <summary>
@@ -4534,7 +4537,7 @@
 </histogram>
 
 <histogram name="DrmUtil.CreateDisplaySnapshot.BitsPerChannel" units="bits"
-    expires_after="M89">
+    expires_after="2022-01-03">
   <owner>andrescj@chromium.org</owner>
   <owner>mcasas@chromium.org</owner>
   <owner>chromeos-gfx@google.com</owner>
@@ -4545,7 +4548,7 @@
 </histogram>
 
 <histogram name="DrmUtil.CreateDisplaySnapshot.HasEdidBlob" enum="Boolean"
-    expires_after="2021-04-18">
+    expires_after="2022-01-03">
   <owner>andrescj@chromium.org</owner>
   <owner>mcasas@chromium.org</owner>
   <owner>chromeos-gfx@google.com</owner>
@@ -4556,7 +4559,7 @@
 </histogram>
 
 <histogram name="DrmUtil.CreateDisplaySnapshot.IsHDR" enum="Boolean"
-    expires_after="M89">
+    expires_after="2022-01-03">
   <owner>andrescj@chromium.org</owner>
   <owner>mcasas@chromium.org</owner>
   <owner>chromeos-gfx@google.com</owner>
@@ -6723,7 +6726,7 @@
 </histogram>
 
 <histogram name="ImportantFile.FileRenameError" enum="PlatformFileError"
-    expires_after="2021-03-21">
+    expires_after="2021-05-30">
   <owner>grt@chromium.org</owner>
   <owner>xaerox@yandex-team.ru</owner>
   <summary>
@@ -8164,7 +8167,7 @@
 </histogram>
 
 <histogram name="Linux.WindowManager" enum="LinuxWindowManagerName"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>pkotwicz@chromium.org</owner>
   <owner>thomasanderson@chromium.org</owner>
   <summary>
@@ -8493,7 +8496,7 @@
 </histogram>
 
 <histogram name="MachineLearningService.MojoConnectionEvent"
-    enum="MachineLearningServiceMojoConnectionEvent" expires_after="2021-03-28">
+    enum="MachineLearningServiceMojoConnectionEvent" expires_after="2021-05-30">
   <owner>alanlxl@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <summary>
@@ -8709,7 +8712,7 @@
 </histogram>
 
 <histogram name="ManualFallback.VisibleSuggestions.OpenCreditCards"
-    units="Suggestions" expires_after="2021-01-15">
+    units="Suggestions" expires_after="2021-05-30">
   <owner>javierrobles@chromium.org</owner>
   <owner>gambard@chromium.org</owner>
   <summary>
@@ -8719,7 +8722,7 @@
 </histogram>
 
 <histogram name="ManualFallback.VisibleSuggestions.OpenPasswords"
-    units="Suggestions" expires_after="2021-01-15">
+    units="Suggestions" expires_after="2021-05-30">
   <owner>javierrobles@chromium.org</owner>
   <owner>gambard@chromium.org</owner>
   <summary>
@@ -9406,6 +9409,21 @@
 </histogram>
 
 <histogram
+    name="Nearby.Share.Certificates.Manager.BluetoothMacAddressSetInPrivateCertificate"
+    enum="BooleanSet" expires_after="2021-08-19">
+  <owner>nohle@chromium.org</owner>
+  <owner>better-together-dev@google.com</owner>
+  <summary>
+    Records whether or not a Bluetooth MAC address is set in the local device's
+    private certificate metadata during certificate creation. Emitted when
+    private certificates are created, which typically occurs every three days if
+    Nearby Share is enabled. This will only be emitted once if multiple
+    certificates are created at a time, for example, when all certificates are
+    created after onboarding.
+  </summary>
+</histogram>
+
+<histogram
     name="Nearby.Share.Certificates.Manager.DownloadPublicCertificatesCount"
     units="certificates" expires_after="2021-08-19">
   <owner>cclem@chromium.org</owner>
@@ -9602,6 +9620,36 @@
   </summary>
 </histogram>
 
+<histogram name="Nearby.Share.InstantMessaging.{Direction}Express.Result"
+    enum="BooleanSuccess" expires_after="2021-08-19">
+  <owner>nohle@chromium.org</owner>
+  <owner>better-together-dev@google.com</owner>
+  <summary>
+    Records whether an HTTPS call to {Direction} the Instant Messaging API
+    succeeds or fails. Emitted when the HTTPS call succeeds or fails.
+  </summary>
+  <token key="Direction">
+    <variant name="Receive" summary="receive a message from"/>
+    <variant name="Send" summary="send a message to"/>
+  </token>
+</histogram>
+
+<histogram
+    name="Nearby.Share.InstantMessaging.{Direction}Express.Result.FailureReason"
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2021-08-19">
+  <owner>nohle@chromium.org</owner>
+  <owner>better-together-dev@google.com</owner>
+  <summary>
+    Records the network error code or HTTPS response code from a failed HTTPS
+    call to {Direction} the Instant Messaging API. Emitted when the HTTPS call
+    fails.
+  </summary>
+  <token key="Direction">
+    <variant name="Receive" summary="receive a message from"/>
+    <variant name="Send" summary="send a message to"/>
+  </token>
+</histogram>
+
 <histogram name="Nearby.Share.LocalDeviceData.DeviceDataUpdater.HttpResult"
     enum="NearbyShareHttpResult" expires_after="2021-08-19">
   <owner>cclem@chromium.org</owner>
@@ -10606,7 +10654,7 @@
 </histogram>
 
 <histogram name="PDF.IsTagged" enum="BooleanIsTagged"
-    expires_after="2021-03-29">
+    expires_after="2021-05-30">
   <owner>dmazzoni@chromium.org</owner>
   <owner>thestig@chromium.org</owner>
   <summary>
@@ -10692,7 +10740,7 @@
 </histogram>
 
 <histogram name="PerformanceHints.Observer.HintForURLResult"
-    enum="PerformanceHintsObserverHintForURLResult" expires_after="2021-03-28">
+    enum="PerformanceHintsObserverHintForURLResult" expires_after="2021-05-30">
   <owner>jds@chromium.org</owner>
   <owner>src/chrome/browser/performance_hints/OWNERS</owner>
   <summary>
@@ -10715,7 +10763,7 @@
 
 <histogram base="true" name="PerformanceHints.Observer.SourceLookupStatus"
     enum="PerformanceHintsObserverSourceLookupStatus"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>jds@chromium.org</owner>
   <owner>src/chrome/browser/performance_hints/OWNERS</owner>
   <summary>
@@ -11061,7 +11109,7 @@
 </histogram>
 
 <histogram name="PrefetchedSignedExchangeCache.BodySize" units="bytes"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>horo@chromium.org</owner>
   <owner>webpackage-dev@chromium.org</owner>
   <summary>
@@ -11084,7 +11132,7 @@
 </histogram>
 
 <histogram name="PrefetchedSignedExchangeCache.Count" units="count"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>horo@chromium.org</owner>
   <owner>webpackage-dev@chromium.org</owner>
   <summary>
@@ -11426,7 +11474,7 @@
 </histogram>
 
 <histogram name="Privacy.AccessContextAudit.CookieDomainCount" units="units"
-    expires_after="M89">
+    expires_after="M93">
   <owner>msramek@chromium.org</owner>
   <owner>sauski@google.com</owner>
   <summary>
@@ -11437,7 +11485,7 @@
 </histogram>
 
 <histogram name="Privacy.AccessContextAudit.DatabaseSize" units="KiB"
-    expires_after="M89">
+    expires_after="M93">
   <owner>msramek@chromium.org</owner>
   <owner>sauski@google.com</owner>
   <summary>
@@ -11448,7 +11496,7 @@
 </histogram>
 
 <histogram name="Privacy.AccessContextAudit.RecordCount" units="units"
-    expires_after="M89">
+    expires_after="M93">
   <owner>msramek@chromium.org</owner>
   <owner>sauski@google.com</owner>
   <summary>
@@ -11459,7 +11507,7 @@
 </histogram>
 
 <histogram name="Privacy.AccessContextAudit.StorageOriginCount" units="units"
-    expires_after="M89">
+    expires_after="M93">
   <owner>msramek@chromium.org</owner>
   <owner>sauski@google.com</owner>
   <summary>
@@ -11470,7 +11518,7 @@
 </histogram>
 
 <histogram name="Privacy.AccessContextAudit.TopFrameOriginCount" units="units"
-    expires_after="M89">
+    expires_after="M93">
   <owner>msramek@chromium.org</owner>
   <owner>sauski@google.com</owner>
   <summary>
@@ -13008,7 +13056,7 @@
 </histogram>
 
 <histogram name="ScreenLocker.AuthenticationFailure" enum="UnlockType"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>antrim@chromium.org</owner>
   <owner>jessejames@chromium.org</owner>
   <owner>rsorokin@chromium.org</owner>
@@ -13029,7 +13077,7 @@
 </histogram>
 
 <histogram name="ScreenLocker.AuthenticationSuccess" enum="UnlockType"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>antrim@chromium.org</owner>
   <owner>jessejames@chromium.org</owner>
   <owner>rsorokin@chromium.org</owner>
@@ -14914,7 +14962,7 @@
 </histogram>
 
 <histogram name="TextFragmentAnchor.ElementIdFragmentFound" enum="Boolean"
-    expires_after="2021-03-07">
+    expires_after="2021-05-30">
   <owner>nburris@chromium.org</owner>
   <owner>bokan@chromium.org</owner>
   <summary>
@@ -15828,7 +15876,7 @@
 </histogram>
 
 <histogram name="Tracing.Background.FinalizingTraceSizeInKB" units="KB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>oysteine@chromium.org</owner>
   <summary>
     The size, in kilobytes, of a finalized trace ready to be uploaded.
@@ -16537,7 +16585,7 @@
 </histogram>
 
 <histogram name="VoiceInteraction.DismissedEventSource"
-    enum="VoiceInteractionEventSource" expires_after="2021-03-28">
+    enum="VoiceInteractionEventSource" expires_after="2021-05-30">
   <owner>wylieb@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
   <owner>yusufo@chromium.org</owner>
@@ -16557,7 +16605,7 @@
 </histogram>
 
 <histogram name="VoiceInteraction.FinishEventSource"
-    enum="VoiceInteractionEventSource" expires_after="2021-03-28">
+    enum="VoiceInteractionEventSource" expires_after="2021-05-30">
   <owner>wylieb@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
   <owner>yusufo@chromium.org</owner>
@@ -16609,7 +16657,7 @@
 </histogram>
 
 <histogram name="VoiceInteraction.StartEventSource"
-    enum="VoiceInteractionEventSource" expires_after="2021-03-28">
+    enum="VoiceInteractionEventSource" expires_after="2021-05-30">
   <owner>wylieb@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
   <owner>yusufo@chromium.org</owner>
@@ -16637,7 +16685,7 @@
 </histogram>
 
 <histogram name="VoiceInteraction.VoiceResultConfidenceValue" units="%"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wylieb@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
   <owner>yusufo@chromium.org</owner>
@@ -16648,7 +16696,7 @@
 </histogram>
 
 <histogram name="VoiceInteraction.VoiceSearchResult" enum="BooleanSuccess"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>wylieb@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
   <owner>yusufo@chromium.org</owner>
@@ -17155,7 +17203,7 @@
 </histogram>
 
 <histogram name="WebAuthentication.MakeCredentialResponseTransport"
-    enum="WebAuthenticationFidoTransport" expires_after="2021-03-07">
+    enum="WebAuthenticationFidoTransport" expires_after="2021-05-30">
   <owner>kenrb@chromium.org</owner>
   <owner>martinkr@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/page/histograms.xml b/tools/metrics/histograms/histograms_xml/page/histograms.xml
index 5af2de1..413c7413 100644
--- a/tools/metrics/histograms/histograms_xml/page/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/page/histograms.xml
@@ -74,7 +74,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.Ads.AdDensity.MaxPercentByArea" units="%"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>justinmron@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <summary>
@@ -87,7 +87,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.Ads.AdDensity.MaxPercentByHeight" units="%"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>justinmron@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <summary>
@@ -123,7 +123,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.Ads.AllPages.PercentNetworkBytesAds"
-    units="%" expires_after="2021-03-28">
+    units="%" expires_after="2021-05-30">
   <owner>alexmt@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <summary>
@@ -165,7 +165,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.Ads.HeavyAds.DisallowedByBlocklist"
-    enum="BooleanBlocked" expires_after="2021-03-28">
+    enum="BooleanBlocked" expires_after="2021-05-30">
   <owner>johnidel@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
@@ -215,7 +215,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.Ads.HeavyAds.UserDidReload"
-    enum="BooleanReloaded" expires_after="2021-03-28">
+    enum="BooleanReloaded" expires_after="2021-05-30">
   <owner>johnidel@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
@@ -627,7 +627,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.ThirdParty.Origins.CookieRead2" units="Count"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>jkarlin@chromium.org</owner>
   <owner>yaoxia@chromium.org</owner>
   <summary>
@@ -637,7 +637,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.ThirdParty.Origins.CookieWrite2"
-    units="Count" expires_after="2021-03-28">
+    units="Count" expires_after="2021-05-30">
   <owner>jkarlin@chromium.org</owner>
   <owner>yaoxia@chromium.org</owner>
   <summary>
@@ -844,7 +844,7 @@
 </histogram>
 
 <histogram name="PageLoad.Experimental.Bytes.Total2" units="KB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>jkarlin@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/password/histograms.xml b/tools/metrics/histograms/histograms_xml/password/histograms.xml
index 498c9ca7..f644fd8 100644
--- a/tools/metrics/histograms/histograms_xml/password/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/password/histograms.xml
@@ -127,7 +127,7 @@
 </histogram>
 
 <histogram name="PasswordGeneration.UserDecision"
-    enum="PasswordGenerationUserEvent" expires_after="2021-03-28">
+    enum="PasswordGenerationUserEvent" expires_after="2021-05-30">
   <owner>ioanap@chromium.org</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -897,7 +897,7 @@
 </histogram>
 
 <histogram name="PasswordManager.CompromisedCredentials.CountLeaked"
-    units="credentials" expires_after="2021-03-28">
+    units="credentials" expires_after="2021-05-30">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -907,7 +907,7 @@
 
 <histogram
     name="PasswordManager.CompromisedCredentials.CountLeakedAfterBulkCheck"
-    units="credentials" expires_after="2021-03-28">
+    units="credentials" expires_after="2021-05-30">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -1598,7 +1598,7 @@
 </histogram>
 
 <histogram name="PasswordManager.NonSyncPasswordHashChange"
-    enum="GaiaPasswordHashChange" expires_after="2021-03-27">
+    enum="GaiaPasswordHashChange" expires_after="2021-05-30">
   <owner>bdea@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -2085,7 +2085,7 @@
 </histogram>
 
 <histogram name="PasswordManager.SyncPasswordHashChange"
-    enum="GaiaPasswordHashChange" expires_after="2021-03-27">
+    enum="GaiaPasswordHashChange" expires_after="2021-05-30">
   <owner>bdea@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/platform/histograms.xml b/tools/metrics/histograms/histograms_xml/platform/histograms.xml
index c19faf8..1f634d0 100644
--- a/tools/metrics/histograms/histograms_xml/platform/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/platform/histograms.xml
@@ -593,7 +593,7 @@
   </summary>
 </histogram>
 
-<histogram name="Platform.Memory.ARC" units="MiB" expires_after="2021-03-28">
+<histogram name="Platform.Memory.ARC" units="MiB" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="ProcessMemoryType" -->
 
   <owner>sonnyrao@chromium.org</owner>
@@ -604,7 +604,7 @@
 </histogram>
 
 <histogram name="Platform.Memory.Browser" units="MiB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="ProcessMemoryType" -->
 
   <owner>sonnyrao@chromium.org</owner>
@@ -616,7 +616,7 @@
 </histogram>
 
 <histogram name="Platform.Memory.Daemons" units="MiB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="ProcessMemoryType" -->
 
   <owner>sonnyrao@chromium.org</owner>
@@ -637,7 +637,7 @@
 </histogram>
 
 <histogram name="Platform.Memory.Renderers" units="MiB"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="ProcessMemoryType" -->
 
   <owner>sonnyrao@chromium.org</owner>
@@ -1146,7 +1146,7 @@
 </histogram>
 
 <histogram name="Platform.TPM.DictionaryAttackCounter" units="units"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>cylai@chromium.org</owner>
   <owner>cros-hwsec-userland-eng+uma@chromium.org</owner>
   <summary>
@@ -1156,7 +1156,7 @@
 </histogram>
 
 <histogram name="Platform.TPM.DictionaryAttackResetStatus"
-    enum="CrosTPMDictionaryAttackResetStatusEnum" expires_after="2021-03-28">
+    enum="CrosTPMDictionaryAttackResetStatusEnum" expires_after="2021-05-30">
   <owner>cylai@chromium.org</owner>
   <owner>cros-hwsec-userland-eng+uma@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/power/histograms.xml b/tools/metrics/histograms/histograms_xml/power/histograms.xml
index 2cbd4a5..52aa0a67 100644
--- a/tools/metrics/histograms/histograms_xml/power/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/power/histograms.xml
@@ -357,7 +357,7 @@
 </histogram>
 
 <histogram name="Power.ExternalDisplayOpenResult"
-    enum="ExternalDisplayOpenResult" expires_after="2021-03-28">
+    enum="ExternalDisplayOpenResult" expires_after="2021-05-30">
   <owner>tbroch@chromium.org</owner>
   <summary>
     The result of attempting to open an I2C device to control an external
diff --git a/tools/metrics/histograms/histograms_xml/printing/histograms.xml b/tools/metrics/histograms/histograms_xml/printing/histograms.xml
index 23ef98e..0ebbd9b6 100644
--- a/tools/metrics/histograms/histograms_xml/printing/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/printing/histograms.xml
@@ -101,7 +101,7 @@
 </histogram>
 
 <histogram name="Printing.CUPS.HighestIppVersion" enum="IppVersion"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>skau@chromium.org</owner>
   <owner>pawliczek@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/renderer/histograms.xml b/tools/metrics/histograms/histograms_xml/renderer/histograms.xml
index 9289355..1ec4dc7e 100644
--- a/tools/metrics/histograms/histograms_xml/renderer/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/renderer/histograms.xml
@@ -135,7 +135,7 @@
 </histogram>
 
 <histogram name="Renderer.PaintPreview.Capture.MainFrameBlinkCaptureDuration"
-    units="ms" expires_after="2021-03-28">
+    units="ms" expires_after="2021-05-30">
   <owner>ckitagawa@chromium.org</owner>
   <owner>mahmoudi@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/renderer4/histograms.xml b/tools/metrics/histograms/histograms_xml/renderer4/histograms.xml
index 40632bc7..9a29901 100644
--- a/tools/metrics/histograms/histograms_xml/renderer4/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/renderer4/histograms.xml
@@ -152,7 +152,7 @@
 </histogram>
 
 <histogram base="true" name="Renderer4.ImageUploadTaskDurationUs"
-    units="microseconds" expires_after="2021-03-28">
+    units="microseconds" expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="DecodedImageType" -->
 
   <owner>sashamcintosh@chromium.org</owner>
@@ -262,7 +262,7 @@
 </histogram>
 
 <histogram name="Renderer4.ScrollingThread" enum="ScrollingThreadStatus"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
 <!-- Name completed by histogram_suffixes name="ScrollSourceDevice" -->
 
   <owner>bokan@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml b/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
index b3c4dd92..b2ad571 100644
--- a/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
@@ -68,7 +68,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.BlockingPage.ResourceType"
-    enum="ContentResourceType2" expires_after="2021-03-27">
+    enum="ContentResourceType2" expires_after="2021-05-30">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/sb_client/histograms.xml b/tools/metrics/histograms/histograms_xml/sb_client/histograms.xml
index b1e0653..9bc4483 100644
--- a/tools/metrics/histograms/histograms_xml/sb_client/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/sb_client/histograms.xml
@@ -312,7 +312,7 @@
 </histogram>
 
 <histogram name="SBClientPhishing.Classifier.Event"
-    enum="SBPhishingClassifierEvent" expires_after="2021-03-28">
+    enum="SBPhishingClassifierEvent" expires_after="2021-05-30">
   <owner>bdea@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -345,7 +345,7 @@
 </histogram>
 
 <histogram name="SBClientPhishing.ClientModelStatus"
-    enum="SBClientPhishingClientModelStatus" expires_after="2021-03-28">
+    enum="SBClientPhishingClientModelStatus" expires_after="2021-05-30">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/service/histograms.xml b/tools/metrics/histograms/histograms_xml/service/histograms.xml
index 8a03638e..cc33f269 100644
--- a/tools/metrics/histograms/histograms_xml/service/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/service/histograms.xml
@@ -1157,7 +1157,7 @@
 </histogram>
 
 <histogram name="ServiceWorkerCache.Cache.Browser.Match.RelatedFetchEvent"
-    units="ms" expires_after="2021-03-28">
+    units="ms" expires_after="2021-05-30">
   <owner>wanderview@chromium.org</owner>
   <owner>chrome-owp-storage@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/stability/histograms.xml b/tools/metrics/histograms/histograms_xml/stability/histograms.xml
index e58012b..d6f0a6bf 100644
--- a/tools/metrics/histograms/histograms_xml/stability/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/stability/histograms.xml
@@ -382,7 +382,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.BatteryCharge" units="%"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>michaeldo@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -416,7 +416,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.LowPowerModeEnabled" enum="BooleanEnabled"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>michaeldo@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -426,7 +426,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.MobileSessionAppState" enum="IOSAppState"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>eugenebut@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/tab/histograms.xml b/tools/metrics/histograms/histograms_xml/tab/histograms.xml
index 203efc4..ae67c42 100644
--- a/tools/metrics/histograms/histograms_xml/tab/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/tab/histograms.xml
@@ -151,7 +151,7 @@
   </summary>
 </histogram>
 
-<histogram name="Tab.NewTab" enum="NewTabType" expires_after="2021-05-23">
+<histogram name="Tab.NewTab" enum="NewTabType" expires_after="2021-05-30">
   <owner>tbergquist@chromium.org</owner>
   <owner>bsep@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/translate/histograms.xml b/tools/metrics/histograms/histograms_xml/translate/histograms.xml
index a9c5e98e..5d111b6 100644
--- a/tools/metrics/histograms/histograms_xml/translate/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/translate/histograms.xml
@@ -471,8 +471,8 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.PageLoad.FinalSourceLanguage" enum="LanguageCode"
-    expires_after="2021-04-04">
+<histogram name="Translate.PageLoad.FinalSourceLanguage"
+    enum="CLD3LanguageCode" expires_after="2021-04-04">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -499,8 +499,8 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.PageLoad.FinalTargetLanguage" enum="LanguageCode"
-    expires_after="2021-04-04">
+<histogram name="Translate.PageLoad.FinalTargetLanguage"
+    enum="CLD3LanguageCode" expires_after="2021-04-04">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -513,8 +513,8 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.PageLoad.InitialSourceLanguage" enum="LanguageCode"
-    expires_after="2021-04-04">
+<histogram name="Translate.PageLoad.InitialSourceLanguage"
+    enum="CLD3LanguageCode" expires_after="2021-04-04">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -541,8 +541,8 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.PageLoad.InitialTargetLanguage" enum="LanguageCode"
-    expires_after="2021-04-04">
+<histogram name="Translate.PageLoad.InitialTargetLanguage"
+    enum="CLD3LanguageCode" expires_after="2021-04-04">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/uma/histograms.xml b/tools/metrics/histograms/histograms_xml/uma/histograms.xml
index f5e28ab..7588628c 100644
--- a/tools/metrics/histograms/histograms_xml/uma/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/uma/histograms.xml
@@ -571,7 +571,7 @@
 </histogram>
 
 <histogram name="UMA.TruncatedEvents.UserAction" units="events"
-    expires_after="2021-05-23">
+    expires_after="2021-05-30">
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/v8/histograms.xml b/tools/metrics/histograms/histograms_xml/v8/histograms.xml
index da336de75..a666c16 100644
--- a/tools/metrics/histograms/histograms_xml/v8/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/v8/histograms.xml
@@ -988,7 +988,7 @@
 </histogram>
 
 <histogram name="V8.WasmCompileFunctionMicroSeconds" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -1028,7 +1028,7 @@
 </histogram>
 
 <histogram name="V8.WasmCompileModuleMicroSeconds" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -1045,7 +1045,7 @@
 </histogram>
 
 <histogram name="V8.WasmCompileModuleStreamingMicroSeconds"
-    units="microseconds" expires_after="2021-03-31">
+    units="microseconds" expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -1059,7 +1059,7 @@
 </histogram>
 
 <histogram name="V8.WasmFinishModuleStreamingMicroSeconds" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>bbudge@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
@@ -1074,7 +1074,7 @@
 </histogram>
 
 <histogram name="V8.WasmFunctionSizeBytes" units="bytes"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -1085,7 +1085,7 @@
 </histogram>
 
 <histogram name="V8.WasmFunctionsPerModule" units="functions"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -1096,7 +1096,7 @@
 </histogram>
 
 <histogram name="V8.WasmInstantiateModuleMicroSeconds" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -1180,7 +1180,7 @@
 </histogram>
 
 <histogram name="V8.WasmModuleCodeSizeTopTierMiB" units="MB"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -1213,7 +1213,7 @@
 </histogram>
 
 <histogram name="V8.WasmModuleSizeBytes" units="bytes"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>ahaas@chromium.org</owner>
@@ -1225,7 +1225,7 @@
 </histogram>
 
 <histogram name="V8.WasmModulesPerEngine" units="count"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>clemensb@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <summary>
@@ -1235,7 +1235,7 @@
 </histogram>
 
 <histogram name="V8.WasmModulesPerIsolate" units="count"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>clemensb@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <summary>
@@ -1245,7 +1245,7 @@
 </histogram>
 
 <histogram name="V8.WasmTierUpModuleMicroSeconds" units="microseconds"
-    expires_after="2021-03-31">
+    expires_after="2021-05-30">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/variations/histograms.xml b/tools/metrics/histograms/histograms_xml/variations/histograms.xml
index 3dcc2fdc..272e63b 100644
--- a/tools/metrics/histograms/histograms_xml/variations/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/variations/histograms.xml
@@ -22,7 +22,7 @@
 <histograms>
 
 <histogram name="Variations.AppSeedFreshness" units="minutes"
-    expires_after="2021-03-28">
+    expires_after="2021-05-30">
   <owner>rmcelrath@chromium.org</owner>
   <owner>ntfschr@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
diff --git a/tools/metrics/histograms/histograms_xml/web_apk/histograms.xml b/tools/metrics/histograms/histograms_xml/web_apk/histograms.xml
index 8c5bbf7..a72e061 100644
--- a/tools/metrics/histograms/histograms_xml/web_apk/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/web_apk/histograms.xml
@@ -21,6 +21,12 @@
 
 <histograms>
 
+<variants name="WebApkDistributorType">
+  <variant name=".Browser" summary="Installed by Chrome"/>
+  <variant name=".DevicePolicy" summary="Installed by device policy"/>
+  <variant name=".Other" summary="Installed by other sources"/>
+</variants>
+
 <histogram name="WebApk.Install.AvailableSpace.Fail" units="MB"
     expires_after="2021-02-01">
   <owner>hartmanng@chromium.org</owner>
@@ -166,19 +172,22 @@
   </summary>
 </histogram>
 
-<histogram name="WebApk.Session.TotalDuration2" units="ms"
-    expires_after="2021-05-16">
+<histogram name="WebApk.Session.TotalDuration2{WebApkDistributorType}"
+    units="ms" expires_after="2021-05-16">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
   </owner>
   <summary>
     The length of a WebAPK session (launch/foregrounding to backgrounding) in
-    milliseconds.
+    milliseconds. {WebApkDistributorType}
   </summary>
+  <token key="WebApkDistributorType" variants="WebApkDistributorType">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram base="true" name="WebApk.ShellApkVersion2" units="units"
+<histogram name="WebApk.ShellApkVersion2{WebApkDistributorType}" units="units"
     expires_after="2021-04-04">
   <owner>hartmanng@chromium.org</owner>
   <owner>
@@ -187,7 +196,15 @@
   <summary>
     Records WebAPK &quot;Shell APK version&quot; when the WebAPK is launched.
     The &quot;Shell APK version&quot; is documented in shell_apk_version.gni
+    {WebApkDistributorType}
   </summary>
+  <token key="WebApkDistributorType" variants="WebApkDistributorType">
+    <variant name="">
+      <obsolete>
+        Base histogram. Use suffixes of this histogram instead.
+      </obsolete>
+    </variant>
+  </token>
 </histogram>
 
 <histogram name="WebApk.Startup.Cold.NewStyle.ShellLaunchToSplashscreenVisible"
@@ -240,13 +257,22 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="WebApk.Uninstall" enum="BooleanHit"
+<histogram name="WebApk.Uninstall{WebApkDistributorType}" enum="BooleanHit"
     expires_after="2021-06-06">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
   </owner>
-  <summary>Records that a WebAPK was uninstalled.</summary>
+  <summary>
+    Records that a WebAPK was uninstalled. {WebApkDistributorType}
+  </summary>
+  <token key="WebApkDistributorType" variants="WebApkDistributorType">
+    <variant name="">
+      <obsolete>
+        Base histogram. Use suffixes of this histogram instead.
+      </obsolete>
+    </variant>
+  </token>
 </histogram>
 
 <histogram name="WebApk.Update.GooglePlayUpdateResult"
diff --git a/tools/metrics/histograms/histograms_xml/web_core/histograms.xml b/tools/metrics/histograms/histograms_xml/web_core/histograms.xml
index ad0af26..ae19ba10 100644
--- a/tools/metrics/histograms/histograms_xml/web_core/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/web_core/histograms.xml
@@ -21,6 +21,14 @@
 
 <histograms>
 
+<variants name="FindInPageRequestEndState">
+  <variant name=".Aborted"
+      summary="The request got aborted before it went through every text in
+               the document."/>
+  <variant name=".Finished"
+      summary="The request finished going through every text in the document."/>
+</variants>
+
 <histogram name="WebCore.DistillabilityUs" units="microseconds"
     expires_after="2021-04-04">
   <owner>wychen@chromium.org</owner>
@@ -58,27 +66,42 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="WebCore.FindInPage.NumberOfTasksPerRequest"
+<histogram
+    name="WebCore.FindInPage.NumberOfTasksPerRequest{FindInPageRequestEndState}"
     units="tasks" expires_after="2021-04-04">
   <owner>rakina@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <summary>
     Records the number of find-in-page tasks executed for a find-in-page
     request. Emitted when a find-in-page request is finished (it went through
-    the whole document) or when it got aborted.
+    the whole document) or when it got aborted. {FindInPageRequestEndState}
   </summary>
+  <token key="FindInPageRequestEndState" variants="FindInPageRequestEndState">
+    <variant name="">
+      <obsolete>
+        Base histogram. Use suffixes of this histogram instead.
+      </obsolete>
+    </variant>
+  </token>
 </histogram>
 
-<histogram base="true" name="WebCore.FindInPage.RequestDuration" units="ms"
-    expires_after="2021-04-04">
+<histogram name="WebCore.FindInPage.RequestDuration{FindInPageRequestEndState}"
+    units="ms" expires_after="2021-04-04">
   <owner>rakina@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <summary>
     Records how long one find-in-page request (consisting multiple tasks) took
     from the request start until the last find-in-page task for the request
     finished. Emitted when a find-in-page request is finished (it went through
-    the whole document) or when it got aborted.
+    the whole document) or when it got aborted. {FindInPageRequestEndState}
   </summary>
+  <token key="FindInPageRequestEndState" variants="FindInPageRequestEndState">
+    <variant name="">
+      <obsolete>
+        Base histogram. Use suffixes of this histogram instead.
+      </obsolete>
+    </variant>
+  </token>
 </histogram>
 
 <histogram name="WebCore.FindInPage.TaskDuration" units="ms"
@@ -91,8 +114,9 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="WebCore.FindInPage.TotalTaskDuration" units="ms"
-    expires_after="2021-04-04">
+<histogram
+    name="WebCore.FindInPage.TotalTaskDuration{FindInPageRequestEndState}"
+    units="ms" expires_after="2021-04-04">
   <owner>rakina@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <summary>
@@ -100,7 +124,15 @@
     find-in-page request. Nothe that this does not include the time spent in
     between tasks. Emitted when a find-in-page request is finished (it went
     through the whole document) or when it got aborted.
+    {FindInPageRequestEndState}
   </summary>
+  <token key="FindInPageRequestEndState" variants="FindInPageRequestEndState">
+    <variant name="">
+      <obsolete>
+        Base histogram. Use suffixes of this histogram instead.
+      </obsolete>
+    </variant>
+  </token>
 </histogram>
 
 <histogram name="WebCore.Framebust.ClickThroughPosition"
diff --git a/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml b/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
index 795b46ea..c1d103c 100644
--- a/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
@@ -21,6 +21,82 @@
 
 <histograms>
 
+<variants name="IPProtocolType">
+  <variant name="_TCP" summary=""/>
+  <variant name="_UDP" summary=""/>
+</variants>
+
+<variants name="NatType">
+  <variant name=".NoNAT" summary=""/>
+  <variant name=".NonSymNAT" summary=""/>
+  <variant name=".SymNAT" summary=""/>
+  <variant name=".UnknownNAT" summary=""/>
+</variants>
+
+<variants name="ScreenshareLayerStats">
+  <variant name=".FrameRate"
+      summary="Frames per second sent, in fps. The value is reported when a
+               stream is removed and is calculated as the total number of
+               frames in this layer, divided by the duration of the call."/>
+  <variant name=".Qp"
+      summary="Average quantizer (qp) of frames sent. The value is reported
+               when a stream is removed and is calculated, for this layer, as
+               the sum of all qp values divided the number of frames."/>
+  <variant name=".TargetBitrate"
+      summary="Average target bitrate in kbps. The value is reported when a
+               stream is removed and is calculated as the sum of all target
+               bitrates for this layer (sampled after frame has been encoded)
+               divided by the total number of frames for this layer."/>
+</variants>
+
+<variants name="WebRTCEchoCancellerEstimate">
+  <variant name=".Max" summary="The maximum over the time interval"/>
+  <variant name=".Min" summary="The minimum over the time interval"/>
+  <variant name=".Value"
+      summary="The last estimated value of the time interval"/>
+</variants>
+
+<variants name="WebRTCMediaType">
+  <variant name=".Audio" summary="Audio"/>
+  <variant name=".Data" summary="Data"/>
+  <variant name=".Video" summary="Video"/>
+</variants>
+
+<variants name="WebRTCVideoExperimentGroupId">
+  <variant name=".ExperimentGroup0" summary="">
+    <owner>ilnik@chromium.org</owner>
+    <owner>webrtc-video@google.com</owner>
+  </variant>
+  <variant name=".ExperimentGroup1" summary="">
+    <owner>ilnik@chromium.org</owner>
+    <owner>webrtc-video@google.com</owner>
+  </variant>
+  <variant name=".ExperimentGroup2" summary="">
+    <owner>ilnik@chromium.org</owner>
+    <owner>webrtc-video@google.com</owner>
+  </variant>
+  <variant name=".ExperimentGroup3" summary="">
+    <owner>ilnik@chromium.org</owner>
+    <owner>webrtc-video@google.com</owner>
+  </variant>
+  <variant name=".ExperimentGroup4" summary="">
+    <owner>ilnik@chromium.org</owner>
+    <owner>webrtc-video@google.com</owner>
+  </variant>
+  <variant name=".S0" summary="">
+    <owner>ilnik@chromium.org</owner>
+    <owner>webrtc-video@google.com</owner>
+  </variant>
+  <variant name=".S1" summary="">
+    <owner>ilnik@chromium.org</owner>
+    <owner>webrtc-video@google.com</owner>
+  </variant>
+  <variant name=".S2" summary="">
+    <owner>ilnik@chromium.org</owner>
+    <owner>webrtc-video@google.com</owner>
+  </variant>
+</variants>
+
 <histogram name="WebRTC.AecFilterHasDivergence" units="%" expires_after="M85">
   <owner>grunell@chromium.org</owner>
   <owner>minyue@chromium.org</owner>
@@ -423,17 +499,6 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Audio.EchoCanceller.Erl" units="dB (shifted)"
-    expires_after="2021-10-19">
-  <owner>gustaf@chromium.org</owner>
-  <owner>peah@chromium.org</owner>
-  <summary>
-    This histogram logs the echo return loss achieved by the WebRTC echo
-    canceller as described in ITU G.168. When the echo canceller is being used,
-    one value is logged every 10 seconds per ongoing WebRTC call.
-  </summary>
-</histogram>
-
 <histogram name="WebRTC.Audio.EchoCanceller.ErlBand0" units="dB (shifted)"
     expires_after="2020-12-01">
   <obsolete>
@@ -462,17 +527,6 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Audio.EchoCanceller.Erle" units="dB"
-    expires_after="2021-10-19">
-  <owner>gustaf@chromium.org</owner>
-  <owner>peah@chromium.org</owner>
-  <summary>
-    This histogram logs the echo return loss enhancement achieved by the WebRTC
-    echo canceller as described in ITU G.168. When the echo canceller is being
-    used, one value is logged every 10 seconds per ongoing WebRTC call.
-  </summary>
-</histogram>
-
 <histogram name="WebRTC.Audio.EchoCanceller.ErleBand0" units="dB (shifted)"
     expires_after="2020-12-01">
   <obsolete>
@@ -501,6 +555,38 @@
   </summary>
 </histogram>
 
+<histogram name="WebRTC.Audio.EchoCanceller.Erle{WebRTCEchoCancellerEstimate}"
+    units="dB" expires_after="2021-10-19">
+  <owner>gustaf@chromium.org</owner>
+  <owner>peah@chromium.org</owner>
+  <summary>
+    This histogram logs the echo return loss enhancement achieved by the WebRTC
+    echo canceller as described in ITU G.168. When the echo canceller is being
+    used, one value is logged every 10 seconds per ongoing WebRTC call.
+    {WebRTCEchoCancellerEstimate}
+  </summary>
+  <token key="WebRTCEchoCancellerEstimate"
+      variants="WebRTCEchoCancellerEstimate">
+    <variant name=""/>
+  </token>
+</histogram>
+
+<histogram name="WebRTC.Audio.EchoCanceller.Erl{WebRTCEchoCancellerEstimate}"
+    units="dB (shifted)" expires_after="2021-10-19">
+  <owner>gustaf@chromium.org</owner>
+  <owner>peah@chromium.org</owner>
+  <summary>
+    This histogram logs the echo return loss achieved by the WebRTC echo
+    canceller as described in ITU G.168. When the echo canceller is being used,
+    one value is logged every 10 seconds per ongoing WebRTC call.
+    {WebRTCEchoCancellerEstimate}
+  </summary>
+  <token key="WebRTCEchoCancellerEstimate"
+      variants="WebRTCEchoCancellerEstimate">
+    <variant name=""/>
+  </token>
+</histogram>
+
 <histogram name="WebRTC.Audio.EchoCanceller.FilterDelay" units="Blocks"
     expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
@@ -1102,14 +1188,17 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.PeerConnection.CandidatePairType"
+<histogram name="WebRTC.PeerConnection.CandidatePairType{IPProtocolType}"
     enum="IceCandidatePairTypes" expires_after="2020-04-05">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
   <summary>
     Counters of various ICE Endpoint types. These values are logged for the
-    first selected candidate pair of a PeerConnection.
+    first selected candidate pair of a PeerConnection. {IPProtocolType}
   </summary>
+  <token key="IPProtocolType" variants="IPProtocolType">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.ConnectionState"
@@ -1424,14 +1513,17 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.PeerConnection.SrtpCryptoSuite"
+<histogram name="WebRTC.PeerConnection.SrtpCryptoSuite{WebRTCMediaType}"
     enum="DTLS_SRTPCryptoSuite" expires_after="M81">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
   <summary>
     Counters on the type of SRTP crypto suites used by WebRTC. This is collected
-    whenever the transport signals the OnCompleted event.
+    whenever the transport signals the OnCompleted event. {WebRTCMediaType}
   </summary>
+  <token key="WebRTCMediaType" variants="WebRTCMediaType">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.SrtpUnprotectError" enum="SrtpErrorCode"
@@ -1445,14 +1537,17 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.PeerConnection.SslCipherSuite" enum="SSLCipherSuite"
-    expires_after="M81">
+<histogram name="WebRTC.PeerConnection.SslCipherSuite{WebRTCMediaType}"
+    enum="SSLCipherSuite" expires_after="M81">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
   <summary>
     Counters on the type of SSL cipher suites used by WebRTC. This is collected
-    whenever the transport signals the OnCompleted event.
+    whenever the transport signals the OnCompleted event. {WebRTCMediaType}
   </summary>
+  <token key="WebRTCMediaType" variants="WebRTCMediaType">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.ThermalState" enum="ThermalState"
@@ -1551,7 +1646,8 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Stun.BatchSuccessPercent" units="%" expires_after="M85">
+<histogram name="WebRTC.Stun.BatchSuccessPercent{NatType}" units="%"
+    expires_after="M85">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
   <summary>
@@ -1560,54 +1656,72 @@
     various intervals between requests. Only the first instance of renderers
     will conduct the trial and log this result. The STUN binding requests are
     grouped into multiple batches and the success rate is calculated for an
-    individual batch.
+    individual batch. {NatType}
   </summary>
+  <token key="NatType" variants="NatType">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Stun.ResponseLatency" units="ms" expires_after="M85">
+<histogram name="WebRTC.Stun.ResponseLatency{NatType}" units="ms"
+    expires_after="M85">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
   <summary>
     For clients using a shared source port per STUN binding request, average RTT
     for requests which received a response with various intervals between
     requests. Only the first instance of renderers will conduct the trial and
-    log this result.
+    log this result. {NatType}
   </summary>
+  <token key="NatType" variants="NatType">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Stun.SuccessPercent" units="%" expires_after="M85">
+<histogram name="WebRTC.Stun.SuccessPercent{NatType}" units="%"
+    expires_after="M85">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
   <summary>
     For clients using a shared source port per STUN binding request, success
     rate for requests which received a response with various intervals between
     requests. Only the first instance of renderers will conduct the trial and
-    log this result.
+    log this result. {NatType}
   </summary>
+  <token key="NatType" variants="NatType">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.SystemMaxConsecutiveBytesDelayed" units="units"
-    expires_after="M81">
+<histogram name="WebRTC.SystemMaxConsecutiveBytesDelayed{IPProtocolType}"
+    units="units" expires_after="M81">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
   <summary>
     The maximum of consecutive delayed bytes caused by EWOULDBLOCKs from system.
     This happens when system can't send any packet synchronously at that moment.
+    {IPProtocolType}
   </summary>
+  <token key="IPProtocolType" variants="IPProtocolType">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.SystemPercentPacketsDelayed" units="%"
+<histogram name="WebRTC.SystemPercentPacketsDelayed{IPProtocolType}" units="%"
     expires_after="M81">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
   <summary>
     The percentage of packets delayed due to ERR_IO_PENDING from system in a
     WebRTC socket. This happens when system can't send any packet synchronously
-    at that moment.
+    at that moment. {IPProtocolType}
   </summary>
+  <token key="IPProtocolType" variants="IPProtocolType">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.SystemSendPacketDuration" units="ms"
+<histogram name="WebRTC.SystemSendPacketDuration{IPProtocolType}" units="ms"
     expires_after="M81">
   <owner>qingsi@google.com</owner>
   <owner>jeroendb@google.com</owner>
@@ -1617,7 +1731,11 @@
     EWOULDBLOCK from system) as well as the time system takes to finish the
     asynchronous send. For UDP, it's the time from P2PSocketHostUdp::Send to
     P2PSocketHostUdp::HandleSendResult. Tcp part is to be implemented.
+    {IPProtocolType}
   </summary>
+  <token key="IPProtocolType" variants="IPProtocolType">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.UnreliableDataChannelMessageSize" units="bytes"
@@ -1764,15 +1882,19 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.Decoded.Vp8.Qp" units="qp value"
-    expires_after="never">
+<histogram name="WebRTC.Video.Decoded.Vp8.Qp{WebRTCVideoExperimentGroupId}"
+    units="qp value" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>asapersson@chromium.org</owner>
   <summary>
     The average QP (quantizer value) per frame for a received VP8 video stream.
-    Recorded when a stream is removed.
+    Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.DecodedFramesPerSecond" units="fps"
@@ -1958,27 +2080,36 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.EndToEndDelayInMs" units="ms"
-    expires_after="never">
+<histogram name="WebRTC.Video.EndToEndDelayInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>asapersson@chromium.org</owner>
   <summary>
     The average end-to-end delay per frame for a received video stream. Recorded
-    when a stream is removed.
+    when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Video.EndToEndDelayMaxInMs" units="ms"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.EndToEndDelayMaxInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The maximum end-to-end delay per frame for a received video stream. Recorded
-    when a stream is removed.
+    when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.FecBitrateReceivedInKbps" units="kbps"
@@ -2117,38 +2248,53 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.InterframeDelay95PercentileInMs" units="ms"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.InterframeDelay95PercentileInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The 95th percentile of interframe delay for a received video stream.
-    Recorded when a stream is removed.
+    Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Video.InterframeDelayInMs" units="ms"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.InterframeDelayInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The average interframe delay for a received video stream. Recorded when a
-    stream is removed.
+    stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Video.InterframeDelayMaxInMs" units="ms"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.InterframeDelayMaxInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The maximum interframe delay for a received video stream. Recorded when a
-    stream is removed.
+    stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.JitterBufferDelayInMs" units="ms"
@@ -2162,15 +2308,20 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.KeyFramesReceivedInPermille" units="permille"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.KeyFramesReceivedInPermille{WebRTCVideoExperimentGroupId}"
+    units="permille" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>asapersson@chromium.org</owner>
   <summary>
     Permille of frames that are key frames for a received video stream. Recorded
-    when a stream is removed.
+    when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.KeyFramesSentInPermille" units="permille"
@@ -2208,16 +2359,21 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.MediaBitrateReceivedInKbps" units="kbps"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.MediaBitrateReceivedInKbps{WebRTCVideoExperimentGroupId}"
+    units="kbps" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>asapersson@chromium.org</owner>
   <summary>
     The number of received media payload bits per second for a received video
     stream. Recorded when a stream is removed. The total number of bytes is
-    divided by the time the video stream exists.
+    divided by the time the video stream exists. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.MediaBitrateSentInKbps" units="kbps"
@@ -2393,15 +2549,20 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.ReceivedHeightInPixels" units="pixels"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.ReceivedHeightInPixels{WebRTCVideoExperimentGroupId}"
+    units="pixels" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>asapersson@chromium.org</owner>
   <summary>
     The average received height per frame for a received video stream. Recorded
-    when a stream is removed.
+    when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.ReceivedPacketsLostInPercent" units="%"
@@ -2415,15 +2576,20 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.ReceivedWidthInPixels" units="pixels"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.ReceivedWidthInPixels{WebRTCVideoExperimentGroupId}"
+    units="pixels" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>asapersson@chromium.org</owner>
   <summary>
     The average received width per frame for a received video stream. Recorded
-    when a stream is removed.
+    when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.ReceiveStreamLifetimeInSeconds" units="seconds"
@@ -2569,16 +2735,21 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.Decoded.Vp8.Qp" units="qp value"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.Screenshare.Decoded.Vp8.Qp{WebRTCVideoExperimentGroupId}"
+    units="qp value" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The average QP (quantizer value) per frame for a received VP8 screenshare
-    stream. Recorded when a stream is removed.
+    stream. Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.Screenshare.DroppedFrames.Capturer"
@@ -2640,28 +2811,38 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.EndToEndDelayInMs" units="ms"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.Screenshare.EndToEndDelayInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The average end-to-end delay per frame for a received screenshare stream.
-    Recorded when a stream is removed.
+    Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.EndToEndDelayMaxInMs" units="ms"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.Screenshare.EndToEndDelayMaxInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The maximum end-to-end delay per frame for a received screenshare stream.
-    Recorded when a stream is removed.
+    Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.Screenshare.FecBitrateSentInKbps" units="kbps"
@@ -2746,7 +2927,8 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"
+<histogram
+    name="WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs{WebRTCVideoExperimentGroupId}"
     units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
@@ -2754,35 +2936,50 @@
   <owner>webrtc-video@google.com</owner>
   <summary>
     The 95th percentile of interframe delay for a received screenshare stream.
-    Recorded when a stream is removed.
+    Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.InterframeDelayInMs" units="ms"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.Screenshare.InterframeDelayInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The average interframe delay for a received screenshare stream. Recorded
-    when a stream is removed.
+    when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.InterframeDelayMaxInMs" units="ms"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.Screenshare.InterframeDelayMaxInMs{WebRTCVideoExperimentGroupId}"
+    units="ms" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The maximum interframe delay for a received screenshare stream. Recorded
-    when a stream is removed.
+    when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.KeyFramesReceivedInPermille"
+<histogram
+    name="WebRTC.Video.Screenshare.KeyFramesReceivedInPermille{WebRTCVideoExperimentGroupId}"
     units="permille" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
@@ -2790,8 +2987,12 @@
   <owner>webrtc-video@google.com</owner>
   <summary>
     Permille of frames that are key frames for a received screenshare stream.
-    Recorded when a stream is removed.
+    Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.Screenshare.KeyFramesSentInPermille"
@@ -2805,24 +3006,32 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.Layer0" units="units"
-    expires_after="never">
+<histogram name="WebRTC.Video.Screenshare.Layer0{ScreenshareLayerStats}"
+    units="units" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>sprang@chromium.org</owner>
   <summary>
     Stats for the lower layer (TL0) of a screenshare stream in conference mode.
+    {ScreenshareLayerStats}
   </summary>
+  <token key="ScreenshareLayerStats" variants="ScreenshareLayerStats">
+    <variant name=""/>
+  </token>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.Layer1" units="units"
-    expires_after="never">
+<histogram name="WebRTC.Video.Screenshare.Layer1{ScreenshareLayerStats}"
+    units="units" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>sprang@chromium.org</owner>
   <summary>
     Stats for the higher layer (TL1) of a screenshare stream in conference mode.
+    {ScreenshareLayerStats}
   </summary>
+  <token key="ScreenshareLayerStats" variants="ScreenshareLayerStats">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.Screenshare.MeanFreezeDurationMs" units="ms"
@@ -2849,7 +3058,8 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.MediaBitrateReceivedInKbps"
+<histogram
+    name="WebRTC.Video.Screenshare.MediaBitrateReceivedInKbps{WebRTCVideoExperimentGroupId}"
     units="kbps" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
@@ -2859,7 +3069,12 @@
     The number of received media payload bits per second for a received
     screenshare stream. Recorded when a stream is removed. The total number of
     bytes is divided by the time the video stream exists.
+    {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.Screenshare.MediaBitrateSentInKbps" units="kbps"
@@ -2945,7 +3160,8 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.ReceivedHeightInPixels"
+<histogram
+    name="WebRTC.Video.Screenshare.ReceivedHeightInPixels{WebRTCVideoExperimentGroupId}"
     units="pixels" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
@@ -2953,8 +3169,12 @@
   <owner>webrtc-video@google.com</owner>
   <summary>
     The average received height per frame for a received screenshare stream.
-    Recorded when a stream is removed.
+    Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.Screenshare.ReceivedPacketsLostInPercent"
@@ -2969,16 +3189,21 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Video.Screenshare.ReceivedWidthInPixels" units="pixels"
-    expires_after="never">
+<histogram
+    name="WebRTC.Video.Screenshare.ReceivedWidthInPixels{WebRTCVideoExperimentGroupId}"
+    units="pixels" expires_after="never">
 <!-- expires-never: WebRTC health metric. -->
 
   <owner>ilnik@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
     The average received width per frame for a received screenshare stream.
-    Recorded when a stream is removed.
+    Recorded when a stream is removed. {WebRTCVideoExperimentGroupId}
   </summary>
+  <token key="WebRTCVideoExperimentGroupId"
+      variants="WebRTCVideoExperimentGroupId">
+    <variant name=""/>
+  </token>
 </histogram>
 
 <histogram name="WebRTC.Video.Screenshare.ReceiveStreamLifetimeInSeconds"
diff --git a/tools/metrics/histograms/histograms_xml/windows/histograms.xml b/tools/metrics/histograms/histograms_xml/windows/histograms.xml
index d3edc879..a81fefc 100644
--- a/tools/metrics/histograms/histograms_xml/windows/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/windows/histograms.xml
@@ -21,6 +21,11 @@
 
 <histograms>
 
+<variants name="FileOperations">
+  <variant name=".DeleteFile.NonRecursive" summary=""/>
+  <variant name=".DeleteFile.Recursive" summary=""/>
+</variants>
+
 <histogram name="Windows.ApplockerRunning" enum="Boolean" expires_after="M83">
   <owner>forshaw@chromium.org</owner>
   <owner>wfh@chromium.org</owner>
@@ -64,13 +69,20 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="Windows.FilesystemError" enum="WinGetLastError"
-    expires_after="M81">
+<histogram name="Windows.FilesystemError{FileOperations}"
+    enum="WinGetLastError" expires_after="M81">
   <owner>grt@chromium.org</owner>
   <summary>
     The Windows error code relating to a failed attempt to operate on a file or
-    a directory.
+    a directory. {FileOperations}
   </summary>
+  <token key="FileOperations" variants="FileOperations">
+    <variant name="">
+      <obsolete>
+        Base histogram. Use suffixes of this histogram instead.
+      </obsolete>
+    </variant>
+  </token>
 </histogram>
 
 <histogram name="Windows.GetVersionExVersion" enum="WindowsVersion"
@@ -281,12 +293,20 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="Windows.PostOperationState"
+<histogram name="Windows.PostOperationState{FileOperations}"
     enum="PostOperationState" expires_after="M81">
   <owner>grt@chromium.org</owner>
   <summary>
     The state of an item in the filesystem following an operation on it.
+    {FileOperations}
   </summary>
+  <token key="FileOperations" variants="FileOperations">
+    <variant name="">
+      <obsolete>
+        Base histogram. Use suffixes of this histogram instead.
+      </obsolete>
+    </variant>
+  </token>
 </histogram>
 
 <histogram name="Windows.ProcessorFamily" enum="ProcessorFamily"
diff --git a/tools/perf/core/minidump_unittest.py b/tools/perf/core/minidump_unittest.py
index a1f72e8..5c6979c5 100644
--- a/tools/perf/core/minidump_unittest.py
+++ b/tools/perf/core/minidump_unittest.py
@@ -48,7 +48,6 @@
   # still read-only, so skip the test in that case.
   @decorators.Disabled(
       'chromeos-local',
-      'android', # https://crbug.com/1149237
       'win7'  # https://crbug.com/1084931
   )
   def testSymbolizeMinidump(self):
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index cbc4ca5..37c42f0 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -538,7 +538,7 @@
             'pool': 'chrome.tests.pinpoint',  # Sharing Pinpoint pool
             'os': 'Android',
             'device_type': 'sunfish',
-            'device_os': 'QD4A.200102.001.A1',
+            'device_os': 'RQ1D.201205.012',
             'device_os_flavor': 'google',
         },
     },
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 91c0f67..daaf938 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "e8474594069dc7104a150ab3cf1e0545784fec5b",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/42433abb9596f1f471251070f7fd7d135c3e9df0/trace_processor_shell.exe"
+            "hash": "8cc08f8d3b63a49ae3a02d85490e3ffe14e24624",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/6d300e3738dbcfd8c6f69c5bf7006d107fce871d/trace_processor_shell.exe"
         },
         "mac": {
             "hash": "93f80fdc5944e51cabff3dd7cf60c2b5968898a0",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/42433abb9596f1f471251070f7fd7d135c3e9df0/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/a3bcd1c0e2e95d464d97dd130ff0d43fa8d8eeee/trace_processor_shell"
         },
         "linux": {
-            "hash": "1d4d4a899be58fbaf9404144b7ccadc523f2bda8",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/42433abb9596f1f471251070f7fd7d135c3e9df0/trace_processor_shell"
+            "hash": "6647a9e3bd7770a3070c3baeb43604c38e65e23f",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/6d300e3738dbcfd8c6f69c5bf7006d107fce871d/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/perf/page_sets/webrtc_cases.py b/tools/perf/page_sets/webrtc_cases.py
index bbf19e8..5dc1cbb 100644
--- a/tools/perf/page_sets/webrtc_cases.py
+++ b/tools/perf/page_sets/webrtc_cases.py
@@ -82,6 +82,7 @@
                                          repeatable=False):
       action_runner.ClickElement('input[id="%s"]' % self.video_codec)
       action_runner.ClickElement('button[id="startButton"]')
+      action_runner.WaitForElement('button[id="callButton"]:enabled')
       action_runner.ClickElement('button[id="callButton"]')
       action_runner.Wait(20)
       action_runner.ClickElement('button[id="hangupButton"]')
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 64e70c2a..327a5b9 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -801,7 +801,7 @@
       "ime/chromeos/mock_input_method_manager.h",
     ]
     deps += [
-      # Generates a header used by component_extension_ime_manager.cc
+      # Generates a header used by mock_component_extension_ime_manager_delegate.cc
       "//chromeos/ime:gencode",
       "//ui/base/ime/chromeos",
     ]
diff --git a/ui/base/ime/chromeos/BUILD.gn b/ui/base/ime/chromeos/BUILD.gn
index b08f3981..9f099bb 100644
--- a/ui/base/ime/chromeos/BUILD.gn
+++ b/ui/base/ime/chromeos/BUILD.gn
@@ -57,7 +57,6 @@
     ":ime_types",
     "//build:branding_buildflags",
     "//chromeos/constants",
-    "//chromeos/ime:gencode",
     "//chromeos/services/ime/public/mojom",
     "//chromeos/system",
     "//third_party/icu",
diff --git a/ui/base/ime/chromeos/component_extension_ime_manager.cc b/ui/base/ime/chromeos/component_extension_ime_manager.cc
index 9f7a9f7..3ba4f43 100644
--- a/ui/base/ime/chromeos/component_extension_ime_manager.cc
+++ b/ui/base/ime/chromeos/component_extension_ime_manager.cc
@@ -11,7 +11,6 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/ime/input_methods.h"
 #include "ui/base/ime/chromeos/extension_ime_util.h"
 
 namespace chromeos {
@@ -58,11 +57,6 @@
 ComponentExtensionIMEManager::ComponentExtensionIMEManager(
     std::unique_ptr<ComponentExtensionIMEManagerDelegate> delegate)
     : delegate_(std::move(delegate)) {
-  for (const auto& input_method : input_method::kInputMethods) {
-    if (input_method.is_login_keyboard)
-      login_layout_set_.insert(input_method.xkb_layout_id);
-  }
-
   // Creates internal mapping between input method id and engine components.
   std::vector<ComponentExtensionIME> ext_list = delegate_->ListIME();
   for (const auto& ext : ext_list) {
@@ -122,7 +116,7 @@
           ime.language_codes,
           // Enables extension based xkb keyboards on login screen.
           extension_ime_util::IsKeyboardLayoutExtension(input_method_id) &&
-              IsInLoginLayoutAllowlist(layouts),
+              delegate_->IsInLoginLayoutAllowlist(layouts),
           ime.options_page_url, ime.input_view_url));
     }
   }
@@ -159,13 +153,4 @@
   return true;
 }
 
-bool ComponentExtensionIMEManager::IsInLoginLayoutAllowlist(
-    const std::vector<std::string>& layouts) {
-  for (const auto& layout : layouts) {
-    if (login_layout_set_.find(layout) != login_layout_set_.end())
-      return true;
-  }
-  return false;
-}
-
 }  // namespace chromeos
diff --git a/ui/base/ime/chromeos/component_extension_ime_manager.h b/ui/base/ime/chromeos/component_extension_ime_manager.h
index b21391d9..2917459 100644
--- a/ui/base/ime/chromeos/component_extension_ime_manager.h
+++ b/ui/base/ime/chromeos/component_extension_ime_manager.h
@@ -94,8 +94,6 @@
   // It's filled by ctor and never changed during runtime.
   std::set<std::string> input_method_id_set_;
 
-  std::set<std::string> login_layout_set_;
-
   DISALLOW_COPY_AND_ASSIGN(ComponentExtensionIMEManager);
 };
 
diff --git a/ui/base/ime/chromeos/component_extension_ime_manager_delegate.h b/ui/base/ime/chromeos/component_extension_ime_manager_delegate.h
index 395be85..9e63114 100644
--- a/ui/base/ime/chromeos/component_extension_ime_manager_delegate.h
+++ b/ui/base/ime/chromeos/component_extension_ime_manager_delegate.h
@@ -30,6 +30,9 @@
                     const std::string& extension_id,
                     const std::string& manifest,
                     const base::FilePath& path) = 0;
+
+  virtual bool IsInLoginLayoutAllowlist(
+      const std::vector<std::string>& layouts) = 0;
 };
 
 }  // namespace chromeos
diff --git a/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.cc b/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.cc
index 55bc9ad..8232642 100644
--- a/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.cc
+++ b/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.cc
@@ -3,13 +3,20 @@
 // found in the LICENSE file.
 
 #include "ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h"
+#include "chromeos/ime/input_methods.h"
 #include "ui/base/ime/chromeos/component_extension_ime_manager.h"
 
 namespace chromeos {
 namespace input_method {
 
 MockComponentExtensionIMEManagerDelegate::
-    MockComponentExtensionIMEManagerDelegate() = default;
+    MockComponentExtensionIMEManagerDelegate() {
+  for (const auto& input_method : input_method::kInputMethods) {
+    if (input_method.is_login_keyboard) {
+      login_layout_set_.insert(input_method.xkb_layout_id);
+    }
+  }
+}
 
 MockComponentExtensionIMEManagerDelegate::
     ~MockComponentExtensionIMEManagerDelegate() = default;
@@ -24,5 +31,16 @@
     const std::string& extension_id,
     const std::string& manifest,
     const base::FilePath& path) {}
+
+bool MockComponentExtensionIMEManagerDelegate::IsInLoginLayoutAllowlist(
+    const std::vector<std::string>& layouts) {
+  for (const auto& layout : layouts) {
+    if (login_layout_set_.find(layout) != login_layout_set_.end()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace input_method
 }  // namespace chromeos
diff --git a/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h b/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h
index 2b6967c..757c1d6 100644
--- a/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h
+++ b/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h
@@ -24,12 +24,15 @@
             const std::string& extension_id,
             const std::string& manifest,
             const base::FilePath& path) override;
+  bool IsInLoginLayoutAllowlist(
+      const std::vector<std::string>& layouts) override;
 
   void set_ime_list(const std::vector<ComponentExtensionIME>& ime_list) {
     ime_list_ = ime_list;
   }
 
  private:
+  std::set<std::string> login_layout_set_;
   std::vector<ComponentExtensionIME> ime_list_;
 
   DISALLOW_COPY_AND_ASSIGN(MockComponentExtensionIMEManagerDelegate);
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ar.xtb b/ui/chromeos/translations/ui_chromeos_strings_ar.xtb
index a8586c1..8ca9d99e 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ar.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ar.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">‏الصينية باستخدام لوحة مفاتيح Zhuyin</translation>
 <translation id="2843806747483486897">تغيير الإجراء التلقائي...</translation>
 <translation id="2850124913210091882">النسخ الاحتياطي</translation>
+<translation id="2873951654529031587">المهملات</translation>
 <translation id="288024221176729610">التشيكية</translation>
 <translation id="2887525882758501333">‏مستند PDF</translation>
 <translation id="2888807692577297075">‏لا توجد عناصر متطابقة مع  &lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt;</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_be.xtb b/ui/chromeos/translations/ui_chromeos_strings_be.xtb
index cdc303d..4c424b3 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_be.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_be.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">Кітайская (чжуінь)</translation>
 <translation id="2843806747483486897">Змяніць стандартнае дзеянне...</translation>
 <translation id="2850124913210091882">Стварыць рэзервовую копію</translation>
+<translation id="2873951654529031587">Сметніца</translation>
 <translation id="288024221176729610">Чэшская</translation>
 <translation id="2887525882758501333">Дакумент PDF</translation>
 <translation id="2888807692577297075">Няма элементаў, якія адпавядаюць запыту &lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt;</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ca.xtb b/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
index 8f0ab5f..ae5e8bb 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
@@ -128,7 +128,7 @@
 <translation id="2377319039870049694">Canvia a la visualització de llista</translation>
 <translation id="2377590462528165447">S'han compartit <ph name="NUMBER_OF_ITEMS" /> carpetes amb Linux</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> fitxers seleccionats</translation>
-<translation id="2389832672041313158">Birmà (Birmània)</translation>
+<translation id="2389832672041313158">Birmà (Myanmar)</translation>
 <translation id="240770291734945588"><ph name="SPACE_AVAILABLE" /> disponibles</translation>
 <translation id="2425665904502185219">Mida total dels fitxers</translation>
 <translation id="2428749644083375155">S'estan copiant <ph name="NUMBER_OF_ITEMS" /> elements a la carpeta <ph name="FOLDER_NAME" /></translation>
@@ -153,7 +153,7 @@
 <translation id="2638942478653899953">No s'ha pogut accedir a Google Drive. <ph name="BEGIN_LINK" />Tanqueu la sessió<ph name="END_LINK" /> i torneu-la a iniciar.</translation>
 <translation id="2649120831653069427">Peix arc iris</translation>
 <translation id="2661146741306740526">16 x 9</translation>
-<translation id="2663066752008346276">Birmà (Birmània) amb teclat myansan</translation>
+<translation id="2663066752008346276">Birmà (Myanmar) amb teclat myansan</translation>
 <translation id="2664412712123763093">Ubicació del fitxer</translation>
 <translation id="2672394958563893062">S'ha produït un error. Feu clic per reiniciar des del principi.</translation>
 <translation id="2676946222714718093">En reproducció</translation>
@@ -299,7 +299,7 @@
 <translation id="4325128273762811722">Eslovè</translation>
 <translation id="4326192123064055915">Cafè</translation>
 <translation id="4336032328163998280">L'operació de còpia ha fallat. <ph name="ERROR_MESSAGE" /></translation>
-<translation id="4348495354623233847">Kurd central amb teclat basat en l'àrab</translation>
+<translation id="4348495354623233847">Kurd sorani amb teclat basat en l'àrab</translation>
 <translation id="4363958938297989186">Rus amb teclat fonètic</translation>
 <translation id="4364327530094270451">Meló</translation>
 <translation id="4372884569765913867">1 x 1</translation>
@@ -423,7 +423,7 @@
 <translation id="5358764674931277">Fotogrames per segon</translation>
 <translation id="5368191757080475556">Comparteix la carpeta amb Linux</translation>
 <translation id="5402367795255837559">Braille</translation>
-<translation id="541890217011173530">Kurd central amb teclat basat en l'anglès</translation>
+<translation id="541890217011173530">Kurd sorani amb teclat basat en l'anglès</translation>
 <translation id="5428105026674456456">Espanyol</translation>
 <translation id="5438282218546237410">No hi ha cap resultat per a <ph name="SEARCH_TERM" />.</translation>
 <translation id="5449551289610225147">La contrasenya no és vàlida</translation>
@@ -771,7 +771,7 @@
 <translation id="9154418932169119429">Aquesta imatge no està disponible sense connexió.</translation>
 <translation id="9172592259078059678">Gujarati (transliteració)</translation>
 <translation id="9173120999827300720">Anglès (EUA) amb teclat internacional</translation>
-<translation id="9189836632794948435">kazakh</translation>
+<translation id="9189836632794948435">Kazakh</translation>
 <translation id="9213073329713032541">La instal·lació s'ha iniciat.</translation>
 <translation id="9219103736887031265">Imatges</translation>
 <translation id="9219908252191632183">Paisatge lunar</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fi.xtb b/ui/chromeos/translations/ui_chromeos_strings_fi.xtb
index e01e2a3..3b15c6f 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fi.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fi.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">kiina (zhuyin)</translation>
 <translation id="2843806747483486897">Muuta oletusta...</translation>
 <translation id="2850124913210091882">Varmuuskopiointi</translation>
+<translation id="2873951654529031587">Roskakori</translation>
 <translation id="288024221176729610">tšekki</translation>
 <translation id="2887525882758501333">PDF-asiakirja</translation>
 <translation id="2888807692577297075">Haulla &lt;b&gt;<ph name="SEARCH_STRING" />&lt;/b&gt; ei löytynyt kohteita</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fr-CA.xtb b/ui/chromeos/translations/ui_chromeos_strings_fr-CA.xtb
index 8d12a945..744c43cf 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fr-CA.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fr-CA.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">Chinois (Zhuyin)</translation>
 <translation id="2843806747483486897">Changer l'action par défaut…</translation>
 <translation id="2850124913210091882">Sauvegarder</translation>
+<translation id="2873951654529031587">Corbeille</translation>
 <translation id="288024221176729610">Tchèque</translation>
 <translation id="2887525882758501333">Document PDF</translation>
 <translation id="2888807692577297075">Aucun élément ne correspond à votre recherche sur &lt;b&gt;« <ph name="SEARCH_STRING" /> »&lt;/b&gt;</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fr.xtb b/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
index d268e34..0e7b6c5 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
@@ -299,7 +299,7 @@
 <translation id="4325128273762811722">Slovène</translation>
 <translation id="4326192123064055915">Café</translation>
 <translation id="4336032328163998280">Échec de l'opération de copie. <ph name="ERROR_MESSAGE" /></translation>
-<translation id="4348495354623233847">Kurde sorani (avec clavier arabe)</translation>
+<translation id="4348495354623233847">Kurde sorani (avec clavier basé sur l'arabe)</translation>
 <translation id="4363958938297989186">Russe avec clavier phonétique</translation>
 <translation id="4364327530094270451">Melon</translation>
 <translation id="4372884569765913867">1 x 1</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_gl.xtb b/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
index c85bd314..66b972a 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">Chinés (zhuyin)</translation>
 <translation id="2843806747483486897">Cambiar acción predeterminada...</translation>
 <translation id="2850124913210091882">Copia de seguranza</translation>
+<translation id="2873951654529031587">Papeleira</translation>
 <translation id="288024221176729610">Checo</translation>
 <translation id="2887525882758501333">Documento PDF</translation>
 <translation id="2888807692577297075">Non coincide ningún elemento con &lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt;</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_gu.xtb b/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
index 05e1a79..90a10b3 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
@@ -9,6 +9,8 @@
 <translation id="1062407476771304334">બદલો</translation>
 <translation id="1119069657431255176">Bzip2 સંકુચિત તાર આર્કાઇવ</translation>
 <translation id="1120073797882051782">હંગુલ રોમાજા</translation>
+<translation id="112387589102719461">અંગ્રેજી (યુએસ), પ્રોગ્રામર Dvorak કીબોર્ડ સાથે</translation>
+<translation id="1134697384939541955">અંગ્રેજી (યુએસ), વધારાની કી ધરાવતા કીબોર્ડ સાથે</translation>
 <translation id="1148097584170732637"><ph name="FILE_COUNT" /> મળી.
     <ph name="LINE_BREAK1" />
     સ્થાનિક સ્ટોરેજમાં પર્યાપ્ત જગ્યા ઉપલબ્ધ નથી. વધારાના <ph name="FILE_SIZE" />ની જરૂર છે.
@@ -23,6 +25,7 @@
 <translation id="1178581264944972037">થોભો</translation>
 <translation id="1190144681599273207">આ ફાઇલને આનયન કરવું લગભગ <ph name="FILE_SIZE" /> મોબાઇલ ડેટાનો ઉપયોગ કરશે.</translation>
 <translation id="1201402288615127009">આગલું</translation>
+<translation id="1210831758834677569">લાઓ</translation>
 <translation id="1243314992276662751">અપલોડ કરો</translation>
 <translation id="1249250836236328755">શૈલી</translation>
 <translation id="1293556467332435079">Files</translation>
@@ -36,34 +39,46 @@
 <translation id="1378727793141957596">Google ડ્રાઇવ પર આપનું સ્વાગત છે!</translation>
 <translation id="1383876407941801731">શોધો</translation>
 <translation id="1395262318152388157">સ્લાઇડર શોધો</translation>
+<translation id="1404323374378969387">નૉર્વેજીયન</translation>
 <translation id="1430915738399379752">પ્રિન્ટ</translation>
 <translation id="1435838927755162558">Parallels ડેસ્કટૉપ સાથે ફોલ્ડર શેર કરો</translation>
 <translation id="1439494416798956626"><ph name="FOLDER_NAME" />માં ખસેડ્યું.</translation>
 <translation id="1464724975715666883">1 ભૂલ.</translation>
 <translation id="1467432559032391204">ડાબું</translation>
+<translation id="1471718551822868769">સ્લોવાક</translation>
 <translation id="1474339897586437869">"<ph name="FILENAME" />" ને અપલોડ કરવામાં આવી ન હતી. તમારી Google ડ્રાઇવમાં પૂરતી ખાલી જગ્યા નથી.</translation>
+<translation id="1482884275703521657">ફિનિશ</translation>
 <translation id="148466539719134488">સ્વીસ</translation>
 <translation id="1497522201463361063">"<ph name="FILE_NAME" />" નું નામ બદલવામાં અક્ષમ. <ph name="ERROR_MESSAGE" /></translation>
+<translation id="1499943022354839699">અંગ્રેજી (યુએસ), Dvorak કીબોર્ડ સાથે</translation>
 <translation id="1538729222189715449">Linux ફાઇલો ખોલી રહ્યાં છીએ...</translation>
 <translation id="1547964879613821194">કેનેડિયન અંગ્રેજી</translation>
 <translation id="1556189134700913550">બધા પર લાગુ કરો</translation>
 <translation id="1561842594491319104">Chrome ડિવાઇસ</translation>
 <translation id="1572585716423026576">વૉલપેપર તરીકે સેટ કરો</translation>
+<translation id="1576937952766665062">બંગાળી (લિપ્યંતર)</translation>
 <translation id="1589128298353575783"><ph name="NUMBER_OF_PB" /> PB</translation>
 <translation id="1620510694547887537">કૅમેરો</translation>
+<translation id="162175252992296058">પોર્ટુગીઝ, યુએસ આંતરરાષ્ટ્રીય કીબોર્ડ સાથે</translation>
+<translation id="1641780993263690097">ચાઇનીઝ પિનયિન</translation>
 <translation id="1646019627374511909"><ph name="NUMBER_OF_ITEMS" /> ફાઇલ ઑફલાઇન ઉપલબ્ધ કરાવી રહ્યાં છીએ</translation>
 <translation id="164969095109328410">Chrome ઉપકરણ</translation>
 <translation id="1665611772925418501">ફાઇલ સંશોધિત કરી શકાઈ નથી.</translation>
 <translation id="1673103856845176271">સુરક્ષા કારણોસર ફાઇલ ઍક્સેસ કરી શકાઈ નથી.</translation>
 <translation id="169515659049020177">Shift</translation>
 <translation id="1722487484194605434"><ph name="NUMBER_OF_ITEMS" /> આઇટમને ઝિપ કરી રહ્યું છે...</translation>
+<translation id="1729953886957086472">જર્મન (જર્મની)</translation>
+<translation id="1730235522912993863">ચાઇનીઝ (કેન્જી)</translation>
 <translation id="1731889557567069540"><ph name="NUMBER_OF_ITEMS" /> આઇટમ કૉપિ કરી.</translation>
 <translation id="174173592514158117">બધા Play ફોલ્ડરો બતાવો</translation>
+<translation id="1742316578210444689">હીબ્રુ લિપ્યંતર</translation>
+<translation id="1747761757048858544">ડચ (નેધરલૅન્ડ)</translation>
 <translation id="174937106936716857">કુલ ફાઇલની સંખ્યા</translation>
 <translation id="1775381402323441512">વીડિયોની માહિતી</translation>
 <translation id="180035236176489073">આ ફાઇલો ઍક્સેસ કરવા માટે તમારું ઑનલાઇન હોું જરૂરી છે.</translation>
 <translation id="1807938677607439181">બધી ફાઇલો</translation>
 <translation id="1810764548349082891">કોઈ પ્રીવ્યૂ ઉપલબ્ધ નથી</translation>
+<translation id="1812302367230252929">એમ્હારિક લિપ્યંતર</translation>
 <translation id="1815861158988915678"><ph name="BEGIN_BOLD" />ચેતવણી:<ph name="END_BOLD" />  આ ફાઇલો અસ્થાયી છે અને બની શકે કે ડિસ્ક સ્થાન ખાલી કરવા માટે ઑટોમૅટિક રીતે કાઢી નાખવામાં આવે.  <ph name="BEGIN_LINK" />વધુ જાણો<ph name="END_LINK" /></translation>
 <translation id="1829129547161959350">પેન્ગ્વિન</translation>
 <translation id="183183971458492120">માહિતી લોડ કરી રહ્યું છે...</translation>
@@ -72,6 +87,7 @@
 <translation id="1847880352285315359">સાચવ્યો</translation>
 <translation id="1853795129690976061">આ ફોલ્ડર Linux સાથે શેર થાય છે</translation>
 <translation id="1864756863218646478">ફાઇલ શોધી શકાઈ નથી.</translation>
+<translation id="1920670151694390848">મલયાલમ લિપ્યંતર</translation>
 <translation id="1924372192547904021"><ph name="DRIVE_NAME" />ને ફોર્મેટ કરી</translation>
 <translation id="1931134289871235022">સ્લોવૅક</translation>
 <translation id="1933345018156373194">ખસેડવું નિષ્ફળ થયું, અનપેક્ષિત ભૂલ: <ph name="ERROR_MESSAGE" /></translation>
@@ -82,16 +98,22 @@
 <translation id="1995337122023280937">ફાઇલના સ્થાન પર જાઓ</translation>
 <translation id="2001796770603320721">ડ્રાઇવમાં મેનેજ કરો</translation>
 <translation id="2009067268969781306">ડ્રાઇવને ફોર્મેટ કરવાથી તેના પર સ્ટોર કરેલો બધો ડેટા ડિલીટ થઈ જશે. આ છેલ્લા ફેરફારને રદ કરી શકાતો નથી.</translation>
+<translation id="2025955442973426285">ટિગ્રિન્યા</translation>
 <translation id="2028997212275086731">RAR આર્કાઇવ</translation>
+<translation id="2037845485764049925">રશિયન</translation>
 <translation id="2046702855113914483">રામેન - જાપાનના એક પ્રકારના નૂડલ</translation>
 <translation id="2070909990982335904">ડૉટથી પ્રારંભ થતા નામો સિસ્ટમ માટે આરક્ષિત છે. કૃપા કરી બીજું નામ પસંદ કરો.</translation>
 <translation id="2079545284768500474">છેલ્લો ફેરફાર રદ કરો</translation>
 <translation id="2084108471225856927">ઉપકરણ સેટિંગ</translation>
 <translation id="2085470240340828803">"<ph name="FILENAME" />" નામની ફાઇલ પહેલાંથી અસ્તિત્વમાં છે. તમે શું કરવા માંગો છો?</translation>
 <translation id="2121825465123208577">આકાર બદલો</translation>
+<translation id="2125607626296734455">ખમેર</translation>
+<translation id="2142680004883808240">રશિયન, ફોનેટિક YaZHert કીબોર્ડ સાથે</translation>
 <translation id="2163152940313951844">અમાન્ય અક્ષર: <ph name="CHARACTER_NAME" /></translation>
+<translation id="2184934335987813305">પોર્ટુગીઝ, યુએસ આંતરરાષ્ટ્રીય PC કીબોર્ડ સાથે</translation>
 <translation id="2198315389084035571">સરળીકૃત ચાઇનીઝ</translation>
 <translation id="2208158072373999562">ઝિપ આર્કાઈવ</translation>
+<translation id="22085916256174561">કોરિયન</translation>
 <translation id="2208919847696382164">Linux વડે ઇન્સ્ટૉલ કરો</translation>
 <translation id="2225536596944493418">શું તમે ખરેખર <ph name="NUMBER_OF_ITEMS" /> આઇટમને ડિલીટ કરવા માંગો છો?</translation>
 <translation id="2230062665678605299">ફોલ્ડર "<ph name="FOLDER_NAME" />" બનાવવામાં અક્ષમ. <ph name="ERROR_MESSAGE" /></translation>
@@ -101,10 +123,12 @@
 <translation id="2303301624314357662"><ph name="FILE_NAME" /> ફાઇલ ખુલી રહી છે.</translation>
 <translation id="2305020378527873881"><ph name="VOLUME_NAME" /> બહાર કાઢવામાં આવ્યું છે.</translation>
 <translation id="2325650632570794183">આ ફાઇલ પ્રકાર સમર્થિત નથી. આ પ્રકારની ફાઇલ ખોલી શકે તે એપ્લિકેશનને શોધવા માટે કૃપા કરીને Chrome વેબ દુકાનની મુલાકાત લો.</translation>
+<translation id="2326539130272988168">બલ્ગેરિયન</translation>
 <translation id="2352947182261340447">સ્થાનિક સ્ટોરેજમાં પર્યાપ્ત જગ્યા ઉપલબ્ધ નથી.</translation>
 <translation id="2377319039870049694">સૂચિ દૃશ્ય પર સ્વિચ કરો</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> ફોલ્ડર Linux સાથે શેર કર્યા</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ફાઇલો પસંદ કરી</translation>
+<translation id="2389832672041313158">બર્મીઝ/મ્યાનમાર</translation>
 <translation id="240770291734945588"><ph name="SPACE_AVAILABLE" /> ઉપલબ્ધ</translation>
 <translation id="2425665904502185219">કુલ ફાઇલ કદ</translation>
 <translation id="2428749644083375155"><ph name="NUMBER_OF_ITEMS" /> આઇટમની <ph name="FOLDER_NAME" />માં કૉપિ કરી રહ્યાં છીએ</translation>
@@ -112,6 +136,7 @@
 <translation id="2453576648990281505">ફાઇલ પહેલાથી જ અસ્તિત્વમાં છે</translation>
 <translation id="2464079411014186876">આઈસ્ક્રીમ</translation>
 <translation id="2468402215065996499">ટેમાગોચી</translation>
+<translation id="2500392669976258912">ગુજરાતી ફોનેટિક</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> આઇટમ કાઢી નાખી</translation>
 <translation id="2541377937973966830">આ ફોલ્ડરનું કન્ટેન્ટ ફક્ત વાંચી શકાય છે. કેટલીક પ્રવૃત્તિઓને સપોર્ટ આપવામાં આવતો નથી.</translation>
@@ -121,20 +146,26 @@
 <translation id="2562685439590298522">Docs</translation>
 <translation id="2563185590376525700">દેડકો</translation>
 <translation id="2572501073504669105">તમારી પાસે ઇન્ટરનેટ કનેક્શન ન હોય, ત્યારે તમે ફાઇલોને ઍક્સેસ માટે ઑફલાઇન ઉપલબ્ધ કરી શકો છો.</translation>
+<translation id="2578394532502990878">તમિળ ફોનેટિક</translation>
+<translation id="2579959351793446050">ઉડિયા</translation>
 <translation id="2614589611416690597"><ph name="VIDEO_TYPE" /> વીડિયો</translation>
 <translation id="2620090360073999360">આ સમયે Google ડ્રાઇવ પર જઈ શકાતું નથી.</translation>
 <translation id="2638942478653899953">Google ડ્રાઇવ પર પહોંચી શકાયું નથી. કૃપા કરીને <ph name="BEGIN_LINK" />લૉગ આઉટ કરો<ph name="END_LINK" /> અને પાછા લૉગ ઇન કરો.</translation>
 <translation id="2649120831653069427">રેન્બોફીશ</translation>
 <translation id="2661146741306740526">16x9</translation>
+<translation id="2663066752008346276">બર્મીઝ/મ્યાનમાર, Myansan કીબોર્ડ સાથે</translation>
 <translation id="2664412712123763093">ફાઇલનું સ્થાન</translation>
 <translation id="2672394958563893062">એક ભૂલ આવી. શરૂઆતથી પુન: પ્રારંભ કરોને ક્લિક કરો.</translation>
 <translation id="2676946222714718093">આ પર ચલાવી રહ્યાં છે</translation>
 <translation id="2718540689505416944">Linux વડે ઍપ ઇન્સ્ટૉલ કરો</translation>
+<translation id="2724954091494693138">ટર્કિશ, F-કીબોર્ડ સાથે</translation>
+<translation id="2732839045120506979">વિયેતનામીઝ VNI</translation>
 <translation id="2735623501230989521">Parallels ડેસ્કટૉપને <ph name="FOLDER_NAME" /> ફોલ્ડરમાંની ફાઇલોને ઍક્સેસ કરવાની પરવાનગી આપો</translation>
 <translation id="2771816809568414714">ચીઝ</translation>
 <translation id="2781645665747935084">બેલ્જિયન</translation>
 <translation id="2782104745158847185">Linux ઍપ્લિકેશન ઇન્સ્ટૉલ કરવામાં ભૂલ</translation>
 <translation id="2787047795752739979">મૂળ પર ઓવરરાઇટ કરો</translation>
+<translation id="2830077785865012357">ચાઇનીઝ ઝુયિન</translation>
 <translation id="2843806747483486897">ડિફૉલ્ટ બદલો...</translation>
 <translation id="2850124913210091882">બૅકઅપ લો</translation>
 <translation id="288024221176729610">ચેક</translation>
@@ -143,6 +174,7 @@
 <translation id="2894654529758326923">માહિતી</translation>
 <translation id="2902312830803030883">વધુ ક્રિયાઓ</translation>
 <translation id="2902734494705624966">યુએસ વિસ્તૃત</translation>
+<translation id="290843123675549676">મરાઠી</translation>
 <translation id="2923240520113693977">એસ્ટોનિયન</translation>
 <translation id="2925966894897775835">Sheets</translation>
 <translation id="2938685643439809023">મોંગોલિયન</translation>
@@ -152,9 +184,11 @@
 <translation id="2951236788251446349">જેલીફીશ</translation>
 <translation id="2984337792991268709">આજે <ph name="TODAY_DAYTIME" /></translation>
 <translation id="2994669386200004489"><ph name="FILE_NAME" />નો બૅકઅપ લઈ શક્યા નથી</translation>
+<translation id="299638574917407533">ફ્રેન્ચ (કેનેડા)</translation>
 <translation id="3003633581067744647">થંબનેલ દૃશ્ય પર સ્વિચ કરો</translation>
 <translation id="3007214526293698309">ગુણોત્તર ઠીક કરો</translation>
 <translation id="303198083543495566">સ્થાન માહિતી</translation>
+<translation id="3047197340186497470">ચાઇનીઝ ડાયી</translation>
 <translation id="3057861065630527966">તમારા ફોટો અને વિડિઓઝનો બેકઅપ લો</translation>
 <translation id="3067790092342515856">Windows ફાઇલો</translation>
 <translation id="3078461028045006476"><ph name="EXTENSION_NAME" /> સાથે શેર કરો</translation>
@@ -164,6 +198,7 @@
 <translation id="3188257591659621405">મારી ફાઇલો</translation>
 <translation id="3197563288998582412">યુકે ડ્વોરેક</translation>
 <translation id="3202131003361292969">પથ</translation>
+<translation id="3205852408225871810">પોર્ટુગીઝ (બ્રાઝિલ)</translation>
 <translation id="3224239078034945833">કેનેડિયન બહુભાષીય</translation>
 <translation id="3236289833370040187">માલિકીને <ph name="DESTINATION_DOMAIN" />માં સ્થાનાંતરિત કરવામાં આવશે.</translation>
 <translation id="3241720467332021590">આઇરિશ</translation>
@@ -171,28 +206,35 @@
 <translation id="3248185426436836442">બાકી</translation>
 <translation id="3252266817569339921">ફ્રેન્ચ</translation>
 <translation id="3254434849914415189"><ph name="FILE_TYPE" /> ફાઇલો માટે ડિફૉલ્ટ ઍપ્લિકેશન પસંદ કરો:</translation>
+<translation id="3255159654094949700">અરબી</translation>
 <translation id="3264582393905923483">સંદર્ભ</translation>
 <translation id="3272909651715601089">"<ph name="PATH" />" ખોલી શક્યા નથી</translation>
 <translation id="3280431534455935878">તૈયારી કરી રહ્યાં છીએ</translation>
 <translation id="3280987981688031357">વિનાઇલ રેકોર્ડ</translation>
 <translation id="3296763833017966289">જ્યોર્જિઅન</translation>
+<translation id="3307875152560779385">યુક્રેનિયન</translation>
 <translation id="3326821416087822643"><ph name="FILE_NAME" /> ને ઝિપ કરી રહ્યું છે...</translation>
 <translation id="3335337277364016868">રેકોર્ડ કર્યાનું વર્ષ</translation>
 <translation id="3353984535370177728">અપલોડ કરવા માટે એક ફોલ્ડર પસંદ કરો</translation>
 <translation id="3356580349448036450">પૂર્ણ</translation>
+<translation id="3382143449143186018">નેપાળી, ઇનસ્ક્રિપ્ટ કીબોર્ડ સાથે</translation>
+<translation id="3408236822532681288">જર્મન (જર્મની), નીઓ 2 કીબોર્ડ સાથે</translation>
 <translation id="3414856743105198592">દૂર કરવા યોગ્ય મીડિયાને ફોર્મેટ કરવાથી તમામ ડેટા ભૂંસાઈ જાય છે. શું તમે ચાલુ રાખવા ઈચ્છો છો?</translation>
 <translation id="3437801641691368414">બનાવ્યાનો સમય</translation>
+<translation id="3455931012307786678">એસ્ટોનિયન</translation>
 <translation id="3466147780910026086">તમારા મીડિયા ઉપકરણને સ્કેન કરી રહ્યું છે...</translation>
 <translation id="3468522857997926824"><ph name="BEGIN_LINK" />Google ડ્રાઇવ<ph name="END_LINK" /> પર <ph name="FILE_COUNT" /> ફોટાનો બેક અપ લેવાયો</translation>
 <translation id="3470502288861289375">કૉપિ કરી રહ્યું છે...</translation>
 <translation id="3473378059788601120"><ph name="FOLDER_NAME" />માં કૉપિ કર્યા.</translation>
 <translation id="3475447146579922140">Google સ્પ્રેડશીટ</translation>
+<translation id="3486821258960016770">મૉંગોલિયન</translation>
 <translation id="3495304270784461826"><ph name="COUNT" /> ભૂલો.</translation>
 <translation id="3522708245912499433">પોર્ટુગીઝ</translation>
 <translation id="3524311639100184459">ચેતવણી: આ ફાઇલો અસ્થાયી છે અને બની શકે કે ડિસ્ક પર સ્પેસ ખાલી કરવા માટે તેમને ઑટોમૅટિક રીતે ડિલીટ કરવામાં આવે  <ph name="BEGIN_LINK" />વધુ જાણો<ph name="END_LINK" /></translation>
 <translation id="3527085408025491307">ફોલ્ડર</translation>
 <translation id="3549797760399244642">drive.google.com પર જાઓ...</translation>
 <translation id="3553048479571901246"><ph name="APP_NAME" /> વડે ફાઇલો ખોલવા માટે, પહેલા તેમને Windowsના ફાઇલ ફોલ્ડરમાં કૉપિ કરો.</translation>
+<translation id="3556731189587832921">અંગ્રેજી (યુએસ), આંતરરાષ્ટ્રીય PC કીબોર્ડ સાથે</translation>
 <translation id="357479282490346887">લિથુનિયન</translation>
 <translation id="3603385196401704894">કેનેડિયન ફ્રેંચ</translation>
 <translation id="3606220979431771195">ટર્કિશ-F</translation>
@@ -206,6 +248,7 @@
 <translation id="3645531960514756307">ફોલ્ડરને અનપિન કરો</translation>
 <translation id="3685122418104378273">મોબાઇલ ડેટાનો ઉપયોગ કરી રહ્યાં હોય ત્યારે, Google ડ્રાઇવ સિંક ડિફોલ્ટ રૂપે બંધ છે.</translation>
 <translation id="3689865792480713551"><ph name="ACTIVITY_DESCRIPTION" />ને રદ કરો.</translation>
+<translation id="3691184985318546178">સિંહાલા</translation>
 <translation id="3726463242007121105">આ ઉપકરણ ખોલી શકાતું નથી કારણ કે તેની ફાઇલસિસ્ટમને સપોર્ટ નથી.</translation>
 <translation id="3741243925913727067">Google ડ્રાઇવ પર તમારા મીડિયા ડિવાઇસના ફોટા અને વીડિયોનો બૅકઅપ લો.</translation>
 <translation id="3749289110408117711">ફાઇલનું નામ</translation>
@@ -225,17 +268,25 @@
 <translation id="3855472144336161447">જર્મન નીઓ 2</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> સાથે પૅક કરો</translation>
 <translation id="3866249974567520381">વર્ણન</translation>
+<translation id="3899991606604168269">ફ્રેન્ચ (કેનેડા), બહુભાષીય કીબોર્ડ સાથે</translation>
 <translation id="3924145049010392604">Meta</translation>
 <translation id="3930521966936686665">આના પર ચલાવો</translation>
 <translation id="3943857333388298514">પેસ્ટ કરો</translation>
+<translation id="3952872973865944257">તેલુગુ ફોનેટિક</translation>
 <translation id="3958548648197196644">કિવી</translation>
 <translation id="3966388904776714213">ઑડિયો પ્લેયર</translation>
+<translation id="3973925058222872294">અંગ્રેજી (યુકે)</translation>
+<translation id="3975895378829046965">બંગાળી ફોનેટિક</translation>
 <translation id="4002066346123236978">શીર્ષક</translation>
+<translation id="4017788180641807848">અંગ્રેજી (યુએસ), વર્કમેન કીબોર્ડ સાથે</translation>
+<translation id="4092890906744441904">આઇરિશ</translation>
 <translation id="4124935795427217608">યુનિકોર્ન - એક કાલ્પનિક પાંખવાળો ઘોડો</translation>
 <translation id="4158739975813877944">પ્લે લિસ્ટ ખોલો</translation>
 <translation id="4159731583141908892"><ph name="FILE_NAME" /> ખસેડી.</translation>
 <translation id="4193154014135846272">Google દસ્તાવેજ</translation>
 <translation id="4197674956721858839">ઝિપ પસંદગી</translation>
+<translation id="4202378258276439759">સ્પેનિશ (લેટિન અમેરિકા)</translation>
+<translation id="4202977638116331303">જ્યોર્જિયન</translation>
 <translation id="421017592316736757">આ ફાઇલ એક્સેસ કરવા તમારું ઑનલાઇન હોું જરૂરી છે.</translation>
 <translation id="4212740939091998969">"<ph name="FOLDER_NAME" />" નામનું ફોલ્ડર પહેલાંથી અસ્તિત્વમાં છે. કૃપા કરીને કોઈ અલગ નામ પસંદ કરો.</translation>
 <translation id="4215448920900139318"><ph name="FILE_COUNT" />નો બૅકઅપ લઈ રહ્યાં છીએ</translation>
@@ -243,14 +294,20 @@
 <translation id="4290535918735525311">Linux વડે શેર કરેલું 1 ફોલ્ડર</translation>
 <translation id="4299729908419173967">બ્રાઝિલિયન</translation>
 <translation id="4309915981827077375">સામાન્ય માહિતી</translation>
+<translation id="432252891123397018">રોમાનિયન, માનક કીબોર્ડ સાથે</translation>
+<translation id="4325128273762811722">સ્લોવેનિયન</translation>
 <translation id="4326192123064055915">કૉફી</translation>
 <translation id="4336032328163998280">કૉપિ ઑપરેશન નિષ્ફળ થયું. <ph name="ERROR_MESSAGE" /></translation>
+<translation id="4348495354623233847">સોરાની કુર્દિશ, અરબી-આધારિત કીબોર્ડ સાથે</translation>
+<translation id="4363958938297989186">રશિયન, ફોનેટિક કીબોર્ડ સાથે</translation>
 <translation id="4364327530094270451">ટેટી</translation>
 <translation id="4372884569765913867">1x1</translation>
 <translation id="4394214039309501350">બાહ્ય લિંક</translation>
 <translation id="4425149324548788773">મારી ડ્રાઇવ</translation>
 <translation id="4470564870223067757">હંગુલ 2 સેટ</translation>
+<translation id="4477002475007461989">રોમાનિયન</translation>
 <translation id="4477219268485577442">બલ્ગેરિયન ધ્વન્યાત્મક</translation>
+<translation id="4509667233588080747">અંગ્રેજી (યુએસ), વર્કમેન આંતરરાષ્ટ્રીય કીબોર્ડ સાથે</translation>
 <translation id="4522570452068850558">વિગતો</translation>
 <translation id="4527800702232535228">Parallels Desktop સાથે આ ફોલ્ડર શેર કરવામાં આવ્યું છે</translation>
 <translation id="4552678318981539154">વધુ સ્ટોરેજ ખરીદો</translation>
@@ -262,12 +319,15 @@
 <translation id="4594543368593301662"><ph name="SEARCH_TERM" /> માટે પરિણામો બતાવી રહ્યાં છીએ.</translation>
 <translation id="4603392156942865207"><ph name="FILE_NAME" />ની <ph name="FOLDER_NAME" />માં કૉપિ કરી રહ્યાં છીએ</translation>
 <translation id="4631887759990505102">કલાકાર</translation>
+<translation id="4646813851450205600">ચેક, Qwerty કીબોર્ડ સાથે</translation>
 <translation id="4656293982926141856">આ કમ્પ્યુટર</translation>
 <translation id="4669606053856530811">'<ph name="SOURCE_NAME" />'ના સભ્યો ઍક્સેસ ગુમાવશે સિવાય કે આ આઇટમને તેમની સાથે શેર કરવામાં ન આવી હોય.</translation>
 <translation id="4690246192099372265">સ્વીડિશ</translation>
 <translation id="4693155481716051732">સુશી - માછલીની એક જાપાની વાનગી</translation>
 <translation id="4694604912444486114">વાનર</translation>
+<translation id="469612310041132144">ચાઇનીઝ ક્વિક</translation>
 <translation id="4697043402264950621">ફાઇલ સૂચિને <ph name="COLUMN_NAME" /> દ્વારા ચઢતા ક્રમમાં સૉર્ટ કરેલી છે.</translation>
+<translation id="4706042980341760088">તમિળ, ટાઇપરાઇટર કીબોર્ડ સાથે</translation>
 <translation id="4711094779914110278">ટર્કીશ</translation>
 <translation id="4712283082407695269">"<ph name="PATH" />" ખોલી રહ્યાં છીએ</translation>
 <translation id="4713544552769165154">આ ફાઇલની રચના Macintosh સૉફ્ટવેરનો ઉપયોગ કરી રહેલ કમ્પ્યુટર માટે કરી છે. આ Chrome OS ચલાવે છે તેવા તમારા ડિવાઇસ સાથે સુસંગત નથી. કૃપા કરીને અનુકૂળ અવેજી ઍપ્લિકેશન માટે <ph name="BEGIN_LINK" />Chrome વેબ સ્ટોર<ph name="END_LINK" /> પર શોધ કરો.<ph name="BEGIN_LINK_HELP" />વધુ જાણો<ph name="END_LINK_HELP" /></translation>
@@ -278,6 +338,7 @@
 <translation id="4737050008115666127">લેન્ડિંગ</translation>
 <translation id="4747271164117300400">મેસેડોનિયન</translation>
 <translation id="4759238208242260848">ડાઉનલોડ્સ</translation>
+<translation id="4779041693283480986">પોર્ટુગીઝ (પોર્ટુગલ)</translation>
 <translation id="4779136857077979611">ઓનિગિરી - ભાતની એક જાપાની વાનગી</translation>
 <translation id="4784330909746505604">PowerPoint પ્રસ્તુતિ</translation>
 <translation id="4788401404269709922"><ph name="NUMBER_OF_KB" /> KB</translation>
@@ -285,6 +346,7 @@
 <translation id="4801956050125744859">બંનેને રાખો</translation>
 <translation id="4804827417948292437">એવોકેડો</translation>
 <translation id="4823651846660089135">ઉપકરણ ફક્ત વાંચવા માટે છે</translation>
+<translation id="4826849268470072925">તમિળ ITRANS</translation>
 <translation id="4839847978919684242"><ph name="SELCTED_FILES_COUNT" /> આઇટમ્સ પસંદ કરી</translation>
 <translation id="4843566743023903107">Chromebases</translation>
 <translation id="4850886885716139402">જુઓ</translation>
@@ -303,6 +365,7 @@
 <translation id="4969785127455456148">આલ્બમ</translation>
 <translation id="4973523518332075481"><ph name="MAX_LENGTH" /> કે તેથી ઓછા અક્ષરોનું હોય તેવા નામનો ઉપયોગ કરો</translation>
 <translation id="4973970068702235170">ઝિપ કરવાનું નિષ્ફળ, અનપેક્ષિત ભૂલ: <ph name="ERROR_MESSAGE" /></translation>
+<translation id="4984616446166309645">જાપાનીઝ</translation>
 <translation id="4988205478593450158">શું તમે ખરેખર "<ph name="FILE_NAME" />"ને ડિલીટ કરવા માંગો છો?</translation>
 <translation id="498902553138568924">લાલ પતંગિયું</translation>
 <translation id="4992066212339426712">અનમ્યૂટ કરો</translation>
@@ -312,12 +375,15 @@
 <translation id="5024856940085636730">ઑપરેશનમાં અપેક્ષિત કરતાં વધુ સમય લાગી રહ્યો છે. શું તમે તેને નિરસ્ત કરવા માગો છો?</translation>
 <translation id="5036159836254554629">Parallels ડેસ્કટૉપ સાથે શેર કરવાને મેનેજ કરો</translation>
 <translation id="5038625366300922036">વધુ જુઓ...</translation>
+<translation id="5044852990838351217">આર્મેનિયન</translation>
+<translation id="5059127710849015030">નેપાળી લિપ્યંતર</translation>
 <translation id="5061708541166515394">કોન્ટ્રાસ્ટ</translation>
 <translation id="5068919226082848014">પિઝા</translation>
 <translation id="5081517858322016911"><ph name="TOTAL_FILE_SIZE" /> ફાઇલો ડિલીટ કરવામાં આવશે</translation>
 <translation id="508423945471810158"><ph name="NUMBER_OF_ITEMS" /> આઇટમને <ph name="FOLDER_NAME" />માં ખસેડી રહ્યાં છીએ</translation>
 <translation id="509429900233858213">કોઈ ભૂલ આવી છે.</translation>
 <translation id="5098629044894065541">હીબ્રુ</translation>
+<translation id="5110329002213341433">અંગ્રેજી (કેનેડા)</translation>
 <translation id="5123433949759960244">બાસ્કેટબૉલ</translation>
 <translation id="5129662217315786329">પોલીશ</translation>
 <translation id="5144820558584035333">હંગુલ 3 સેટ (390)</translation>
@@ -332,6 +398,7 @@
 <translation id="5170477580121653719">Google ડ્રાઇવ સ્થાન બાકી: <ph name="SPACE_AVAILABLE" />.</translation>
 <translation id="5177526793333269655">થંબનેલ દૃશ્ય</translation>
 <translation id="5194713942430106590">કૉલમને ચઢતા ક્રમમાં સૉર્ટ કરવા માટે ક્લિક કરો.</translation>
+<translation id="5211614973734216083">ફૅરોઇઝ</translation>
 <translation id="5218183485292899140">સ્વિસ ફ્રેંચ</translation>
 <translation id="5234764350956374838">કાઢી નાખો</translation>
 <translation id="5253070652067921974">આના દ્વારા બનાવેલ</translation>
@@ -355,10 +422,12 @@
 <translation id="5358764674931277">ફ્રેમ રેટ</translation>
 <translation id="5368191757080475556">Linux વડે ફોલ્ડર શેર કરો</translation>
 <translation id="5402367795255837559">બ્રેઇલ</translation>
+<translation id="541890217011173530">સોરાની કુર્દિશ, અંગ્રેજી-આધારિત કીબોર્ડ સાથે</translation>
 <translation id="5428105026674456456">સ્પેનિશ</translation>
 <translation id="5438282218546237410"><ph name="SEARCH_TERM" /> માટે કોઈ પરિણામ નથી.</translation>
 <translation id="5449551289610225147">અમાન્ય પાસવર્ડ</translation>
 <translation id="5469868506864199649">ઇટાલિયન</translation>
+<translation id="5489067830765222292">લૅતવિયન</translation>
 <translation id="5494920125229734069">બધા પસંદ કરો</translation>
 <translation id="5500122897333236901">આઇસલેન્ડિક</translation>
 <translation id="5508696409934741614">બિંદુઓ</translation>
@@ -366,8 +435,11 @@
 <translation id="5524517123096967210">ફાઇલ વાંચી શકાઈ નથી.</translation>
 <translation id="5533102081734025921"><ph name="IMAGE_TYPE" /> છબી</translation>
 <translation id="5534520101572674276">કદની ગણના કરી રહ્યું છે</translation>
+<translation id="554153475311314364">ગ્રીક લિપ્યંતર</translation>
 <translation id="5583640892426849032">Backspace</translation>
+<translation id="5602622065581044566">બલ્ગેરિયન, ફોનેટિક કીબોર્ડ સાથે</translation>
 <translation id="5605830556594064952">યુએસ ડ્વોરેક</translation>
+<translation id="5625294776298156701">તમિળ, તમિળ99 કીબોર્ડ સાથે</translation>
 <translation id="5649768706273821470">સાંભળો</translation>
 <translation id="5678784840044122290">Linux ઍપ્લિકેશન તમારા ટર્મિનલમાં ઉપલબ્ધ થશે અને તમારા લૉન્ચરમાં આઇકન પણ બતાવી શકે છે.</translation>
 <translation id="5686799162999241776"><ph name="BEGIN_BOLD" />આર્કાઇવ અથવા વર્ચ્યુઅલ ડિસ્ક પરથી ડિસ્કનેક્ટ કરી શકતાં નથી<ph name="END_BOLD" />
@@ -375,13 +447,17 @@
    આર્કાઇવ અથવા વર્ચ્યુઅલ ડિસ્ક પરની બધી ફાઇલો બંધ કરો, પછી ફરી પ્રયાસ કરો.</translation>
 <translation id="5691596662111998220">ઊફ્ફ, <ph name="FILE_NAME" /> હવે અસ્તિત્વમાં નથી.</translation>
 <translation id="5700087501958648444">ઑડિઓ માહિતી</translation>
+<translation id="5724172041621205163">થાઇ, Pattachote કીબોર્ડ સાથે</translation>
 <translation id="5731409020711461763">1 નવો ફોટો</translation>
 <translation id="5752453871435543420">Chrome OS ક્લાઉડ બેકઅપ</translation>
 <translation id="5756666464756035725">હંગેરિયન QWERTY</translation>
+<translation id="5763377084591234761">જર્મન (સ્વિટ્ઝર્લૅન્ડ)</translation>
+<translation id="5775750595919327203">ઉર્દુ</translation>
 <translation id="5776325638577448643">કાઢી નાખો અને ફોર્મેટ કરો</translation>
 <translation id="57838592816432529">અવાજ બંધ કરો</translation>
 <translation id="5788127256798019331">Play ફાઇલો</translation>
 <translation id="5790193330357274855">કઝાખ</translation>
+<translation id="5804245609861364054">કન્નડ લિપ્યંતર</translation>
 <translation id="5817397429773072584">પરંપરાગત ચાઇનીઝ</translation>
 <translation id="5818003990515275822">કોરિયન</translation>
 <translation id="5819442873484330149">હંગુલ 3 સેટ (ફાઇનલ)</translation>
@@ -394,6 +470,7 @@
 <translation id="5911887972742538906">તમારી Linux ઍપ્લિકેશનના ઇન્સ્ટૉલેશન દરમિયાન ભૂલ આવી.</translation>
 <translation id="5912396950572065471">ફોર્મેટ</translation>
 <translation id="5913638992615760742">કૉપિ ઑપરેશન નિષ્ફળ થયું, અનપેક્ષિત ભૂલ: <ph name="ERROR_MESSAGE" /></translation>
+<translation id="5926082595146149752">ડચ (નેધરલૅન્ડ), યુએસ આંતરરાષ્ટ્રીય PC કીબોર્ડ સાથે</translation>
 <translation id="5932901536148835538">Chromebit</translation>
 <translation id="5955954492236143329"><ph name="NUMBER_OF_ITEMS" /> આઇટમ</translation>
 <translation id="5957366693331451795">Chromeboxes</translation>
@@ -404,20 +481,27 @@
 <translation id="604001903249547235">મેઘ બેકઅપ</translation>
 <translation id="6040143037577758943">બંધ કરો</translation>
 <translation id="6074825444536523002">Google ફોર્મ</translation>
+<translation id="6079871810119356840">હંગેરિયન, Qwerty કીબોર્ડ સાથે</translation>
 <translation id="6096979789310008754">શોધ ટેક્સ્ટ સાફ કરી, બધી ફાઇલો અને ફોલ્ડરો બતાવવામાં આવી રહ્યાં છે.</translation>
 <translation id="610101264611565198"><ph name="FILE_NAME" />ને <ph name="FOLDER_NAME" />માં ખસેડાય છે</translation>
 <translation id="6129953537138746214">જગ્યા</translation>
 <translation id="6133173853026656527"><ph name="FILE_NAME" /> ખસેડાઈ રહી છે...</translation>
+<translation id="613750717151263950">જાપાનીઝ, યુએસ કીબોર્ડ સાથે</translation>
 <translation id="6146563240635539929">વીડિયો</translation>
 <translation id="6150853954427645995">આ ફાઇલને ઑફલાઇન ઉપયોગ માટે સાચવવા, પાછા ઓનલાઇન થાઓ, ફાઇલને રાઇટ-ક્લિક કરો અને <ph name="OFFLINE_CHECKBOX_NAME" /> વિકલ્પ પસંદ કરો.</translation>
 <translation id="6164412158936057769">પતંગિયાઓ</translation>
 <translation id="6170470584681422115">સેન્ડવિચ</translation>
+<translation id="6187719147498869044">હંગેરિયન</translation>
 <translation id="6189412234224385711"><ph name="EXTENSION_NAME" /> સાથે ખોલો</translation>
 <translation id="6199801702437275229">સ્થાન માહિતી માટે રાહ જોઈ રહ્યું છે...</translation>
 <translation id="6205710420833115353">કેટલાક ઑપરેશન્સમાં અપેક્ષિત કરતાં વધુ સમય લાગી રહ્યો છે. શું તમે તેમને નિરસ્ત કરવા માગો છો?</translation>
+<translation id="6220423280121890987">પંજાબી</translation>
+<translation id="6224240818060029162">ડેનિશ</translation>
 <translation id="6224253798271602650"><ph name="DRIVE_NAME" />ને ફોર્મેટ કરો</translation>
 <translation id="6227235786875481728">આ ફાઇલ ચલાવી શકાઈ નથી.</translation>
+<translation id="6241349547798190358">ડચ (બેલ્જિયમ)</translation>
 <translation id="6248400709929739064">સબટાઇટલ ચાલુ કરો</translation>
+<translation id="6269630227984243955">મલય</translation>
 <translation id="6287852322318138013">આ ફાઇલ ખોલવા માટે એક ઍપ્લિકેશન પસંદ કરો</translation>
 <translation id="6339145975392024142">US આંતરરાષ્ટ્રીય (PC)</translation>
 <translation id="6346310558342052870">ઍક્સેસ પ્રતિબંધિત</translation>
@@ -428,6 +512,7 @@
 <translation id="6395575651121294044"><ph name="NUMBER_OF_FILES" /> આઇટમ</translation>
 <translation id="6398765197997659313">પૂર્ણ સ્ક્રીનથી બહાર નીકળો</translation>
 <translation id="642282551015776456">આ નામનો ઉપયોગ ફોલ્ડર નામની કોઈ ફાઇલ તરીકે થઈ શકશે નહીં</translation>
+<translation id="6423031066725912715">વિયેતનામીઝ, TCVN કીબોર્ડ સાથે</translation>
 <translation id="6485131920355264772">સ્થાન માહિતી પુનર્પ્રાપ્ત કરવામાં નિષ્ફળ</translation>
 <translation id="6509122719576673235">નોર્વેજીયન</translation>
 <translation id="6527303717912515753">શેર કરો</translation>
@@ -444,19 +529,23 @@
 <translation id="6643016212128521049">સાફ કરો</translation>
 <translation id="6650726141019353908">ગુલાબી પતંગિયું</translation>
 <translation id="6657585470893396449">પાસવર્ડ</translation>
+<translation id="6673674183150363784">ફ્રેન્ચ (ફ્રાન્સ), Bépo કીબોર્ડ સાથે</translation>
 <translation id="6710213216561001401">પાછલી</translation>
 <translation id="6718273304615422081">ઝિપ કરી રહ્યાં છે...</translation>
 <translation id="6751256176799620176">1 ફોલ્ડર પસંદ કર્યું</translation>
 <translation id="6790428901817661496">ચલાવો</translation>
 <translation id="6795884519221689054">પાંડા</translation>
 <translation id="6806699711453372963">Linux શેરિંગ મેનેજ કરો</translation>
+<translation id="6806796368146926706">આલ્ફાન્યૂમેરિક, જાપાનીઝ કીબોર્ડ સાથે</translation>
 <translation id="6808193438228982088">શિયાળ</translation>
 <translation id="6820687829547641339">Gzip સંકુચિત તાર આર્કાઇવ</translation>
 <translation id="6823166707458800069">આ ફોલ્ડરમાં સાચવેલી તમામ ફાઇલોનું ઑટોમૅટિક રીતે ઑનલાઇન બૅકઅપ લેવાય છે.</translation>
 <translation id="6825883775269213504">રશિયન</translation>
 <translation id="6827236167376090743">આ વીડિયો સમીસાંજ સુધી ચાલુ રહેશે.</translation>
 <translation id="6847101934483209767"><ph name="ENTRY_NAME" /> પસંદગીમાંથી કાઢી નાખ્યું.</translation>
+<translation id="6861394552169064235">ફારસી</translation>
 <translation id="6862635236584086457">આ ફોલ્ડરમાં સાચવેલી તમામ ફાઇલોનું ઑટોમૅટિક રીતે ઑનલાઇન બૅકઅપ લેવાય છે</translation>
+<translation id="6864328437977279120">સંસ્કૃત</translation>
 <translation id="6876155724392614295">બાઇક</translation>
 <translation id="6878261347041253038">દેવનાગરી કીબોર્ડ (ધ્વન્યાત્મક)</translation>
 <translation id="6885780034956018177">ગોકળગાય</translation>
@@ -470,20 +559,28 @@
     <ph name="LINE_BREAK1" />
     <ph name="FILE_COUNT" /> મળી</translation>
 <translation id="6935521024859866267">ઊલટું</translation>
+<translation id="6949408524333579394">સર્બિયન લિપ્યંતર</translation>
 <translation id="696203921837389374">મોબાઇલ ડેટા પર સિંક કરવાનું ચાલુ કરો</translation>
 <translation id="6965382102122355670">બરાબર, સમજાઇ ગયું</translation>
 <translation id="6970230597523682626">બલ્ગેરિયન</translation>
 <translation id="6973630695168034713">ફોલ્ડર્સ</translation>
 <translation id="6978611942794658017">આ ફાઇલ Windows સોફ્ટવેરનો ઉપયોગ કરતા PC માટે ડિઝાઇન કરવામાં આવી છે. આ તમારું ડિવાઇસ જે Chrome OS પર ચાલે છે તેની સાથે સુસંગત નથી. કૃપા કરીને યોગ્ય અવેજી ઍપ્લિકેશન માટે Chrome વેબ સ્ટોરમાં શોધો.</translation>
 <translation id="6979158407327259162">Google Drive</translation>
+<translation id="6989942356279143254">સ્વીડિશ</translation>
 <translation id="6990081529015358884">તમારી પાસે સ્થાન નથી</translation>
 <translation id="6998711733709403587"><ph name="SELCTED_FOLDERS_COUNT" /> ફોલ્ડર્સ પસંદ કર્યા</translation>
 <translation id="7012943028104619157"><ph name="ROOT_TITLE" /> (<ph name="ROOT_SUMMARY" />)</translation>
 <translation id="7014174261166285193">ઇન્સ્ટોલેશન નિષ્ફળ થયું.</translation>
+<translation id="7031639531908619281">ટર્કિશ</translation>
+<translation id="7037472120706603960">તમિળ (લિપ્યંતર)</translation>
 <translation id="7040138676081995583">આની સાથે ખોલો...</translation>
+<translation id="7075931588889865715">થાઇ, TIS 820-2531 કીબોર્ડ સાથે</translation>
+<translation id="7086590977277044826">તમિળ, ઇનસ્ક્રિપ્ટ કીબોર્ડ સાથે</translation>
 <translation id="7100897339030255923"><ph name="COUNT" /> આઇટમ્સ પસંદ કરી</translation>
+<translation id="7103992300314999525">મેસિડોનિયન</translation>
 <translation id="7106346894903675391">વધુ સ્ટોરેજ ખરીદો...</translation>
 <translation id="7126604456862387217">'&lt;b&gt;<ph name="SEARCH_STRING" />&lt;/b&gt;' - &lt;em&gt;ડ્રાઇવમાં શોધો&lt;/em&gt;</translation>
+<translation id="7135561821015524160">કન્નડ ફોનેટિક</translation>
 <translation id="714034171374937760">Chromebase</translation>
 <translation id="7180611975245234373">રિફ્રેશ કરો</translation>
 <translation id="7189874332498648577"><ph name="NUMBER_OF_GB" /> GB</translation>
@@ -492,33 +589,42 @@
 <translation id="7248671827512403053">ઍપ્લિકેશન</translation>
 <translation id="7268659760406822741">ઉપલબ્ધ સેવાઓ</translation>
 <translation id="7283041136720745563">તમારો Google ડ્રાઇવ ક્વોટા પૂરતો મોટો નથી.</translation>
+<translation id="7294063083760278948">તેલુગુ લિપ્યંતર</translation>
 <translation id="7295662345261934369">બીજા સાથે શેર કરો</translation>
+<translation id="7309413087278791451">જર્મન (બેલ્જિયમ)</translation>
 <translation id="7339898014177206373">નવી વિંડો</translation>
+<translation id="7343393116438664539">વિયેતનામીઝ ટેલેક્સ</translation>
 <translation id="7359359531237882347"><ph name="NUMBER_OF_ITEMS" /> આઇટમ કૉપિ કરી રહ્યું છે...</translation>
 <translation id="7375951387215729722">ફાઇલ સૂચિને <ph name="COLUMN_NAME" /> દ્વારા ઉતરતા ક્રમમાં સૉર્ટ કરેલી છે.</translation>
+<translation id="7408870451288633753">ચેક</translation>
 <translation id="7417453074306512035">ઇથિઓપિક કીબોર્ડ</translation>
 <translation id="7417705661718309329">Google નકશો</translation>
 <translation id="7460898608667578234">યુક્રેનિયન</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> મળ્યા
     <ph name="LINE_BREAK1" />
     <ph name="BEGIN_LINK" />Google ડ્રાઇવ<ph name="END_LINK" /> પર બૅકઅપ માટે તૈયાર</translation>
+<translation id="7495372004724182530">મલયાલમ ફોનેટિક</translation>
 <translation id="7505167922889582512">છુપાવેલી ફાઇલો દર્શાવો</translation>
 <translation id="7508545000531937079">સ્લાઇડશો</translation>
 <translation id="751507702149411736">બેલારુશિયન</translation>
+<translation id="7532029025027028521">ફારસી લિપ્યંતર</translation>
 <translation id="7544830582642184299">Linux ઍપને તમારી Google Driveમાંની ફાઇલોને ઍક્સેસ કરવાની પરવાનગી આપો. ફેરફારો તમારા બીજા ડિવાઇસ સાથે સિંક થશે.</translation>
 <translation id="7544853251252956727">શફલ કરો</translation>
+<translation id="7547780573915868306">લિથુએનિયન</translation>
 <translation id="7547811415869834682">ડચ</translation>
 <translation id="7551643184018910560">શેલ્ફ પર પિન કરો</translation>
 <translation id="7553492409867692754">Linux ઍપને <ph name="FOLDER_NAME" /> ફોલ્ડરમાંની ફાઇલોને ઍક્સેસ કરવાની પરવાનગીઓ આપો</translation>
 <translation id="7576032389798113292">6x4</translation>
 <translation id="7589661784326793847">ક્ષણભર રોકાવ</translation>
 <translation id="7592775719802218421"><ph name="FILE_NAME" />ને ઑફલાઇન ઉપલબ્ધ કરાવી રહ્યાં છીએ</translation>
+<translation id="7600126690270271294">સર્બિયન</translation>
 <translation id="7603724359189955920">ગ્રીડ</translation>
 <translation id="7627790789328695202">ઉફ્ફ, <ph name="FILE_NAME" /> પહેલાંથી અસ્તિત્વમાં છે. તેનું નામ બદલો અને ફરી પ્રયાસ કરો.</translation>
 <translation id="7628656427739290098"><ph name="PERCENT" />% પૂર્ણ.</translation>
 <translation id="7649070708921625228">સહાય</translation>
 <translation id="7654209398114106148"><ph name="NUMBER_OF_ITEMS" /> આઇટમ ખસેડી રહ્યું છે...</translation>
 <translation id="7658239707568436148">રદ કરો</translation>
+<translation id="7663224033570512922">હિન્દી</translation>
 <translation id="7693909743393669729">ડ્રાઇવને ફૉર્મેટ કરવાથી તેના પર સ્ટોર કરેલો બધો ડેટા ભૂંસાઈ જશે અને કદાચ દેખાતા ન હોય તેવા વિભાગો સહિત હાલના બધા વિભાગો કાઢી નખાશે. આ ક્રિયા રદ કરી શકાતી નથી.</translation>
 <translation id="7695430100978772476"><ph name="DRIVE_NAME" />ને ફોર્મેટ કરી શક્યાં નથી</translation>
 <translation id="770015031906360009">ગ્રીક</translation>
@@ -527,6 +633,7 @@
 <translation id="7724603315864178912">કાપો</translation>
 <translation id="7730494089396812859">મેઘ બેકઅપ વિગતો દર્શાવો</translation>
 <translation id="7748626145866214022">ક્રિયા બાર પર વધુ વિકલ્પો ઉપલબ્ધ છે. ક્રિયા બાર પર ફોકસ કરવા માટે Alt + A દબાવો.</translation>
+<translation id="7760449188139285140">ચાઇનીઝ વુબી</translation>
 <translation id="7765158879357617694">સ્થાન</translation>
 <translation id="7774365994322694683">પક્ષી</translation>
 <translation id="7788080748068240085">"<ph name="FILE_NAME" />"ને ઓફલાઇન સાચવવા માટે તમારે વધુ<ph name="TOTAL_FILE_SIZE" /> સ્થાન ખાલી કરવું જરૂરી છે:<ph name="MARKUP_1" /><ph name="MARKUP_2" />તમને હવે ઓફલાઇન ઍક્સેસ કરવાની જરૂર ન હોય એવી ફાઇલોને અનપિન કરો<ph name="MARKUP_3" /><ph name="MARKUP_4" />તમારા ડાઉનલોડ ફોલ્ડરમાંથી ફાઇલો ડિલીટ કરો<ph name="MARKUP_5" /></translation>
@@ -534,6 +641,8 @@
 <translation id="7799329977874311193">HTML દસ્તાવેજ</translation>
 <translation id="7801354353640549019">Chromebooks</translation>
 <translation id="7805768142964895445">સ્થિતિ</translation>
+<translation id="7806708061868529807">હીબ્રુ</translation>
+<translation id="78104721049218340">થાઇ, Kedmanee કીબોર્ડ સાથે</translation>
 <translation id="7821462174190887129"><ph name="FILE_COUNT" /> મળી.
     <ph name="LINE_BREAK1" />
     તમારો Google ડ્રાઇવ ક્વોટા પૂરતો મોટો નથી. વધારાની <ph name="FILE_SIZE" /> જરૂર છે.
@@ -544,7 +653,9 @@
 <translation id="7846076177841592234">પસંદગી રદ કરો</translation>
 <translation id="7853966320808728790">ફ્રેંચ BÉPO</translation>
 <translation id="7864662577698025113">નવી સેવા ઉમેરો</translation>
+<translation id="7868774406711971383">પોલિશ</translation>
 <translation id="7873831373602885875"><ph name="FOLDER_NAME" /> પર સાચવી શકતા નથી. બધા ફેરફારો <ph name="DOWNLOADS_FOLDER" /> ડાઉનલોડ ફોલ્ડરમાં સાચવવામાં આવશે.</translation>
+<translation id="7874321682039004450">ફિલિપિનો</translation>
 <translation id="7881969471599061635">ઉપશીર્ષકો બંધ કરો</translation>
 <translation id="78946041517601018">શેર કરેલી ડ્રાઇવ</translation>
 <translation id="7908793776359722643">વિભાગને ફૉર્મેટ કરવાથી તેમાં સ્ટોર કરેલો બધો ડેટા કાઢી નાખવામાં આવશે. આ ક્રિયા રદ કરી શકાતી નથી.</translation>
@@ -553,6 +664,8 @@
 <translation id="7943385054491506837">યુએસ કોલમેક</translation>
 <translation id="7953739707111622108">આ ઉપકરણ ખોલી શકાતું નથી કારણ કે તેની ફાઇલસિસ્ટમ ઓળખાઈ ન હતી.</translation>
 <translation id="7969525169268594403">સ્લોવેનિયન</translation>
+<translation id="7972920761225148017">ફ્રેન્ચ (સ્વિટ્ઝર્લૅન્ડ)</translation>
+<translation id="7980421588063892270">અંગ્રેજી (યુએસ), Colemak કીબોર્ડ સાથે</translation>
 <translation id="7982283708762922719">ઊંચાઈ</translation>
 <translation id="8008366997883261463">કૂતરો</translation>
 <translation id="8028993641010258682">કદ</translation>
@@ -565,18 +678,21 @@
 <translation id="8079530767338315840">પુનરાવર્તન કરો</translation>
 <translation id="8106045200081704138">મારી સાથે શેર કરેલા</translation>
 <translation id="8116072619078571545">બરફનું પાણી</translation>
+<translation id="8128733386027980860">અંગ્રેજી (યુકે), Dvorak કીબોર્ડ સાથે</translation>
 <translation id="8137331602592933310">"<ph name="FILENAME" />" તમારી સાથે શેર કરવામાં આવી છે. તમે એને કાઢી શકતા નથી કારણ કે તમે તેના માલિક નથી.</translation>
 <translation id="8151638057146502721">ગોઠવો</translation>
 <translation id="8153607920959057464">આ ફાઇલ પ્રદર્શિત કરી શકાઈ નથી.</translation>
 <translation id="8154842056504218462">બધી એન્ટ્રી પસંદ કરેલી છે.</translation>
 <translation id="8157684860301034423">ઍપ માહિતી ફરી મેળવવામાં નિષ્ફળ થયાં.</translation>
 <translation id="8157939133946352716">7x5</translation>
+<translation id="8175731104491895765">ફ્રેન્ચ (બેલ્જિયમ)</translation>
 <translation id="8179976553408161302">Enter</translation>
 <translation id="8193175696669055101">ઉપકરણ મૉડેલ</translation>
 <translation id="8208580316430297579">આર્ટવર્ક</translation>
 <translation id="8223479393428528563">ઑફલાઇન વપરાશ માટે આ ફાઇલો સાચવવા, પાછા ઓનલાઇન થાઓ, ફાઇલો પર જમણી ક્લિક કરો અને <ph name="OFFLINE_CHECKBOX_NAME" /> વિકલ્પ પસંદ કરો.</translation>
 <translation id="8249296373107784235">છોડો</translation>
 <translation id="8261506727792406068">ડિલીટ કરો</translation>
+<translation id="8261561378965667560">ચાઇનીઝ અરે</translation>
 <translation id="8269755669432358899">ફાઇલોના પ્રતિસાદની પૅનલ નાની કરો</translation>
 <translation id="8280151743281770066">આર્મેનિયન ધ્વન્યાત્મક</translation>
 <translation id="8294431847097064396">સ્રોત</translation>
@@ -585,43 +701,59 @@
 <translation id="8312871300878166382">ફોલ્ડરમાં પેસ્ટ કરો</translation>
 <translation id="8329978297633540474">સાદી ટેક્સ્ટ</translation>
 <translation id="8335587457941836791">શેલ્ફમાંથી અનપિન કરો</translation>
+<translation id="8335837413233998004">બેલારુશિયન</translation>
 <translation id="8336153091935557858">ગઈ કાલે <ph name="YESTERDAY_DAYTIME" /></translation>
 <translation id="8342318071240498787">સમાન નામની ફાઇલ અથવા ડિરેક્ટરી પહેલાથી જ અસ્તિત્વમાં છે.</translation>
+<translation id="8372852072747894550">ગ્રીક</translation>
 <translation id="8382450452152102026"><ph name="FOLDER_NAME" />માં</translation>
 <translation id="8395901698320285466">પરિમાણો</translation>
 <translation id="8437209419043462667">અમેરિકા</translation>
 <translation id="8456681095658380701">અમાન્ય નામ</translation>
+<translation id="8463494891489624050">વિયેતનામીઝ VIQR</translation>
 <translation id="8466234950814670489">તાર આર્કાઇવ</translation>
 <translation id="8475647382427415476">Google ડ્રાઇવ "<ph name="FILENAME" />" ને અત્યારે જ સમન્વયિત કરવા અસમર્થ હતી. Google ડ્રાઇવ પછી ફરીથી પ્રયાસ કરશે.</translation>
 <translation id="8477649328507734757">સ્પિન</translation>
 <translation id="8487700953926739672">ઑફલાઇન ઉપલબ્ધ</translation>
 <translation id="8521441079177373948">યુકે</translation>
 <translation id="8525306231823319788">પૂર્ણ સ્ક્રીન</translation>
+<translation id="853494022971700746">ફ્રેન્ચ (ફ્રાન્સ)</translation>
+<translation id="8545476925160229291">અંગ્રેજી (યુએસ)</translation>
+<translation id="8549186985808798022">ઇટાલિયન</translation>
 <translation id="8551494947769799688">લાતવિયન</translation>
+<translation id="8560515948038859357">કેન્ટોનીઝ</translation>
 <translation id="8561206103590473338">હાથી</translation>
 <translation id="8569764466147087991">ખોલવા માટે એક ફાઇલ પસંદ કરો</translation>
+<translation id="8577897833047451336">ક્રોએશિયન</translation>
+<translation id="8578308463707544055">ઇન્ડોનેશિયન</translation>
 <translation id="8579285237314169903"><ph name="NUMBER_OF_FILES" /> આઇટમ્સ સમન્વયિત કરી રહ્યાં છે...</translation>
 <translation id="8600173386174225982">ફાઇલ સૂચિને થંબનેલ દૃશ્યમાં બદલી છે.</translation>
 <translation id="8601932370724196034">Crostini છબી ફાઇલ</translation>
+<translation id="8609695766746872526">આઇસલેન્ડિક</translation>
 <translation id="8669949407341943408">ખસેડી રહ્યું છે...</translation>
 <translation id="8698464937041809063">Google રેખાંકન</translation>
+<translation id="8713112442029511308">માલ્ટીઝ</translation>
 <translation id="8714406895390098252">સાયકલ</translation>
 <translation id="8719721339511222681"><ph name="ENTRY_NAME" /> પસંદ કર્યું</translation>
 <translation id="872537912056138402">ક્રોએશિયન</translation>
 <translation id="8775404590947523323">તમારા ફેરફારો ઑટોમૅટિક રીતે સચવાયા છે.<ph name="BREAKS" />મૂળ છબીની કૉપિ રાખવા માટે, "મૂળ પર ઓવરરાઇટ કરો" ને  અનચેક કરો</translation>
 <translation id="8808686172382650546">બિલાડી</translation>
 <translation id="8810671769985673465">ઝિપ કરવાનું નિષ્ફળ, આઇટમ અસ્તિત્વમાં છે: "<ph name="FILE_NAME" />"</translation>
+<translation id="8813284582615685103">સ્પેનિશ (સ્પેન)</translation>
 <translation id="8834164572807951958">'<ph name="DESTINATION_NAME" />'ના સભ્યો આ આઇટમની કૉપિનો ઍક્સેસ મેળવશે.</translation>
+<translation id="8857149712089373752">નેપાળી, ફોનેટિક કીબોર્ડ સાથે</translation>
 <translation id="8860454412039442620">Excel સ્પ્રેડશીટ</translation>
+<translation id="8866284467018526531">અરબી લિપ્યંતર</translation>
 <translation id="8900820606136623064">હંગેરિયન</translation>
 <translation id="8919081441417203123">ડેનિશ</translation>
 <translation id="8965697826696209160">પર્યાપ્ત સ્થાન નથી.</translation>
+<translation id="8997962250644902079">ચાઇનીઝ (પરંપરાગત) પિનયિન</translation>
 <translation id="9017798300203431059">રશિયન ધ્વન્યાત્મક</translation>
 <translation id="9034924485347205037">Linux ફાઇલો</translation>
 <translation id="9035012421917565900">આઇટમને પાછી '<ph name="DESTINATION_NAME" />'માં ખસેડી શકાતી નથી, તેથી તમે આ ક્રિયાનો છેલ્લો ફેરફાર રદ કરી શકશો નહીંં.</translation>
 <translation id="9038620279323455325">"<ph name="FILE_NAME" />" નામની ફાઇલ પહેલાંથી અસ્તિત્વમાં છે. કૃપા કરીને કોઈ અલગ નામ પસંદ કરો.</translation>
 <translation id="9064939804718829769">સ્થાનાંતરિત કરી રહ્યાં છે...</translation>
 <translation id="9065203028668620118">ફેરફાર કરો</translation>
+<translation id="908378762078012445">રશિયન, ફોનેટિક AATSEEL કીબોર્ડ સાથે</translation>
 <translation id="9099674669267916096">પેજની સંખ્યા</translation>
 <translation id="9110990317705400362">અમે સતત તમારા બ્રાઉઝિંગને વધુ સલામત બનાવવાની રીતો શોધી રહ્યાં છીએ. પૂર્વમાં, કોઈપણ વેબસાઇટ તમને તમારા બ્રાઉઝરમાં એક્સ્ટેન્શન ઉમેરવા માટે સંકેત આપી શકતી હતી. Google Chrome ના નવીનતમ સંસ્કરણોમાં, તમે એક્સ્ટેન્શન્સ પૃષ્ઠ દ્વારા આ એક્સ્ટેન્શન્સને ઉમેરીને તમે તેમને ઇન્સ્ટોલ કરવા માગો છો તે, તમારે Chrome ને સ્પષ્ટપણે કહેવું આવશ્યક છે. <ph name="BEGIN_LINK" />વધુ જાણો<ph name="END_LINK" /></translation>
 <translation id="9111102763498581341">અનલોક કરો</translation>
@@ -631,8 +763,12 @@
 <translation id="9131598836763251128">એક અથવા વધુ ફાઇલ પસંદ કરો</translation>
 <translation id="9133055936679483811">ઝિપ કરવાનું નિષ્ફળ: <ph name="ERROR_MESSAGE" /></translation>
 <translation id="9134524245363717059">આ ફાઇલની રચના Macintosh સૉફ્ટવેરનો ઉપયોગ કરી રહેલા કમ્પ્યુટર માટે કરી છે. આ Chrome OS ચલાવે છે તેવા તમારા ડિવાઇસ સાથે સુસંગત નથી. કૃપા કરીને અનુકૂળ અવેજી ઍપ્લિકેશન માટે Chrome વેબ સ્ટોર પર શોધ કરો.</translation>
+<translation id="9144340019284012223">કૅટલેન</translation>
 <translation id="9148058034647219655">બહાર નીકળો</translation>
 <translation id="9154418932169119429">આ છબી ઑફલાઇન ઉપલબ્ધ નથી.</translation>
+<translation id="9172592259078059678">ગુજરાતી લિપ્યંતર</translation>
+<translation id="9173120999827300720">અંગ્રેજી (યુએસ), આંતરરાષ્ટ્રીય કીબોર્ડ સાથે</translation>
+<translation id="9189836632794948435">કઝાક</translation>
 <translation id="9213073329713032541">ઇન્સ્ટૉલેશન સફળતાપૂર્વક શરૂ થયું.</translation>
 <translation id="9219103736887031265">Images</translation>
 <translation id="9219908252191632183">ચંદ્ર</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_hu.xtb b/ui/chromeos/translations/ui_chromeos_strings_hu.xtb
index b4a0f4d1..8212020 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_hu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_hu.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">kínai zujin</translation>
 <translation id="2843806747483486897">Alapértelmezés módosítása...</translation>
 <translation id="2850124913210091882">Biztonsági mentés</translation>
+<translation id="2873951654529031587">Kuka</translation>
 <translation id="288024221176729610">cseh</translation>
 <translation id="2887525882758501333">PDF-dokumentum</translation>
 <translation id="2888807692577297075">Nincs &lt;b&gt;„<ph name="SEARCH_STRING" />”&lt;/b&gt; keresésnek megfelelő elem</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_km.xtb b/ui/chromeos/translations/ui_chromeos_strings_km.xtb
index cbb25354..a2e3f11 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_km.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_km.xtb
@@ -100,7 +100,7 @@
 <translation id="2009067268969781306">ការសម្អាត​ឧបករណ៍ផ្ទុក USB នឹងលុបទិន្នន័យ​ទាំងអស់​ដែលបានរក្សាទុក​នៅលើវា។ សកម្មភាព​នេះ​មិន​អាច​​ត្រឡប់វិញ​បានទេ។</translation>
 <translation id="2025955442973426285">ភាសាទីរិនយា</translation>
 <translation id="2028997212275086731">ឯកសារបណ្ណាសារ RAR</translation>
-<translation id="2037845485764049925">ភាសា​រុស្សី</translation>
+<translation id="2037845485764049925">ភាសា​រុស្ស៊ី</translation>
 <translation id="2046702855113914483">មីរ៉ាមេន</translation>
 <translation id="2070909990982335904">ឈ្មោះដែលចាប់ផ្តើមជាមួយសញ្ញាចុចត្រូវបានរក្សាទុកសម្រាប់ប្រព័ន្ធ។ សូមជ្រើសរើសឈ្មោះដ៏ទៃទៀត។</translation>
 <translation id="2079545284768500474">ត្រឡប់វិញ</translation>
@@ -123,7 +123,7 @@
 <translation id="2303301624314357662">កំពុងបើក​ឯកសារ <ph name="FILE_NAME" /> ។</translation>
 <translation id="2305020378527873881"><ph name="VOLUME_NAME" /> ត្រូវបាន​ដកចេញ។</translation>
 <translation id="2325650632570794183">ប្រភេទឯកសារនេះមិនត្រូវបានគាំទ្រទេ។ សូមទៅកាន់ Chrome Web Store ដើម្បិស្វែងរកកម្មវិធីដែលអាចបើកប្រភេទឯកសារនេះបាន។</translation>
-<translation id="2326539130272988168">ភាសា​ប៊ុលហ្គារី</translation>
+<translation id="2326539130272988168">ភាសា​ប៊ុលហ្ការី</translation>
 <translation id="2352947182261340447">មិនមាន​ទំហំផ្ទុក​ទំនេរ​គ្រប់គ្រាន់​នៅក្នុង​ទំហំផ្ទុក​មូលដ្ឋានទេ។</translation>
 <translation id="2377319039870049694">ប្ដូរ​ទៅ​ទិដ្ឋភាពជាបញ្ជី</translation>
 <translation id="2377590462528165447">ថត <ph name="NUMBER_OF_ITEMS" /> ដែលបាន​ចែករំលែកជាមួយ Linux</translation>
@@ -499,7 +499,7 @@
 <translation id="6224240818060029162">ភាសា​ដាណឺម៉ាក</translation>
 <translation id="6224253798271602650">សម្អាត <ph name="DRIVE_NAME" /></translation>
 <translation id="6227235786875481728">ឯកសារនោះមិនអាចលេងបានទេ។</translation>
-<translation id="6241349547798190358">ភាសា​ហូឡង់ (បែលហ្សិក)</translation>
+<translation id="6241349547798190358">ភាសា​ហូឡង់ (បែលហ្ស៊ិក)</translation>
 <translation id="6248400709929739064">បើកដំណើរការចំណងជើងរង</translation>
 <translation id="6269630227984243955">ភាសា​ម៉ាឡេ</translation>
 <translation id="6287852322318138013">ជ្រើសរើសកម្មវិធីដើម្បីបើកឯកសារនេះ</translation>
@@ -657,7 +657,7 @@
 <translation id="7864662577698025113">បញ្ចូល​សេវាកម្មថ្មី</translation>
 <translation id="7868774406711971383">ភាសា​ប៉ូឡូញ</translation>
 <translation id="7873831373602885875">មិនអាច​រក្សាទុកទៅ <ph name="FOLDER_NAME" /> បានទេ។ ការកែសម្រួល​ទាំងអស់​នឹងត្រូវរក្សាទុកទៅក្នុង <ph name="DOWNLOADS_FOLDER" /> នៅក្នុងថត​ទាញយក។</translation>
-<translation id="7874321682039004450">ភាសា​ហ្វីលីពីន</translation>
+<translation id="7874321682039004450">ភាសា​ហ្វ៊ីលីពីន</translation>
 <translation id="7881969471599061635">បិទដំណើរការចំណងជើងរង</translation>
 <translation id="78946041517601018">ថាស​ដែលបាន​ចែករំលែក</translation>
 <translation id="7908793776359722643">ការសម្អាតផ្នែកណាមួយនឹងលុបទិន្នន័យទាំងអស់ ដែលបានរក្សាទុកនៅក្នុងនោះ។ សកម្មភាព​នេះ​មិន​អាច​​ត្រឡប់វិញ​បានទេ។</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_kn.xtb b/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
index cb9290c..dad8915 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
@@ -164,6 +164,7 @@
 <translation id="2830077785865012357">ಚೈನೀಸ್ ಜುಯೆನ್</translation>
 <translation id="2843806747483486897">ಡಿಫಾಲ್ಟ್‌ ಅನ್ನು ಬದಲಾಯಿಸಿ...</translation>
 <translation id="2850124913210091882">ಬ್ಯಾಕಪ್‌ ಮಾಡು</translation>
+<translation id="2873951654529031587">ಅನುಪಯುಕ್ತ</translation>
 <translation id="288024221176729610">ಜೆಕ್</translation>
 <translation id="2887525882758501333">PDF  ಡಾಕ್ಯುಮೆಂಟ್</translation>
 <translation id="2888807692577297075">&lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt; ಗೆ ಯಾವ ಐಟಂಗಳೂ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ko.xtb b/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
index d7b5f577..a7dd97b 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">중국어(주음부호)</translation>
 <translation id="2843806747483486897">기본값 변경...</translation>
 <translation id="2850124913210091882">백업</translation>
+<translation id="2873951654529031587">휴지통</translation>
 <translation id="288024221176729610">체코어</translation>
 <translation id="2887525882758501333">PDF 문서</translation>
 <translation id="2888807692577297075">&lt;b&gt;'<ph name="SEARCH_STRING" />'&lt;/b&gt;와(과) 일치하는 항목 없음</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_or.xtb b/ui/chromeos/translations/ui_chromeos_strings_or.xtb
index d826a0f..e7ccb35 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_or.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_or.xtb
@@ -9,6 +9,8 @@
 <translation id="1062407476771304334">ପ୍ରତିସ୍ଥାପନ କରନ୍ତୁ</translation>
 <translation id="1119069657431255176">Bzip2 ସଙ୍କୁଚିତ ଟାର୍ ଆରକାଇଭ୍</translation>
 <translation id="1120073797882051782">ହଂଗୁଲ୍ ରୋମାଜା</translation>
+<translation id="112387589102719461">ପ୍ରୋଗାମର୍ ଡିଭୋରାକ୍ କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (US)</translation>
+<translation id="1134697384939541955">ବିସ୍ତାରିତ କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (US)</translation>
 <translation id="1148097584170732637"><ph name="FILE_COUNT" />ଟି ମିଳିଛି।
     <ph name="LINE_BREAK1" />
     ସ୍ଥାନୀୟ ଷ୍ଟୋରେଜ୍‌ରେ ପର୍ଯ୍ୟାପ୍ତ ଖାଲି ସ୍ଥାନ ଉପଲବ୍ଧ ନାହିଁ। ଅତିରିକ୍ତ <ph name="FILE_SIZE" /> ଆବଶ୍ୟକ ଅଟେ।
@@ -23,6 +25,7 @@
 <translation id="1178581264944972037">ବିରତି</translation>
 <translation id="1190144681599273207">ଏହି ଫାଇଲ୍ ଆଣିବା ପାଇଁ ଆନୁମାନିକ <ph name="FILE_SIZE" /> ମୋବାଇଲ୍ ଡାଟା ବ୍ୟବହାର ହେବ।</translation>
 <translation id="1201402288615127009">ପରବର୍ତ୍ତୀ</translation>
+<translation id="1210831758834677569">ଲାଓ</translation>
 <translation id="1243314992276662751">ଅପ୍‌ଲୋଡ୍ କରନ୍ତୁ</translation>
 <translation id="1249250836236328755">ଶୈଳୀ</translation>
 <translation id="1293556467332435079">Files</translation>
@@ -36,34 +39,46 @@
 <translation id="1378727793141957596">Google Driveକୁ ସ୍ୱାଗତ!</translation>
 <translation id="1383876407941801731">Search</translation>
 <translation id="1395262318152388157">ସୀକ୍ ସ୍ଲାଇଡର୍‍</translation>
+<translation id="1404323374378969387">ନରୱେଜୀୟ</translation>
 <translation id="1430915738399379752">ପ୍ରିଣ୍ଟ କରନ୍ତୁ</translation>
 <translation id="1435838927755162558">Parallels Desktop ସହ ଫୋଲ୍ଡର ସେୟାର୍ କରନ୍ତୁ</translation>
 <translation id="1439494416798956626"><ph name="FOLDER_NAME" />କୁ ନିଆଗଲା।</translation>
 <translation id="1464724975715666883">1ଟି ତ୍ରୁଟି।</translation>
 <translation id="1467432559032391204">ବାମ</translation>
+<translation id="1471718551822868769">ସ୍ଲୋଭାକ୍</translation>
 <translation id="1474339897586437869">"<ph name="FILENAME" />" ଅପ୍‌ଲୋଡ୍‍ କରାଯାଇନଥିଲା। ଆପଣଙ୍କର Google Driveରେ ଯଥେଷ୍ଟ ମୁକ୍ତ ସ୍ଥାନ ନାହିଁ।</translation>
+<translation id="1482884275703521657">ଫିନିଶ୍</translation>
 <translation id="148466539719134488">ସ୍ଵିସ୍</translation>
 <translation id="1497522201463361063">"<ph name="FILE_NAME" />" ରିନେମ୍‌ କରିବାକୁ ଅକ୍ଷମ। <ph name="ERROR_MESSAGE" /></translation>
+<translation id="1499943022354839699">ଡିଭୋରାକ୍ କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (US)</translation>
 <translation id="1538729222189715449">Linux ଫାଇଲ୍‌ଗୁଡ଼ିକ ଖୋଲୁଛି...</translation>
 <translation id="1547964879613821194">କାନାଡିଆନ୍ ଇଂରାଜୀ</translation>
 <translation id="1556189134700913550">ସମସ୍ତ ପାଇଁ ଲାଗୁ ହେବ</translation>
 <translation id="1561842594491319104">Chrome ଡିଭାଇସଗୁଡ଼ିକ</translation>
 <translation id="1572585716423026576">ୱାଲ୍‌‌ପେପର୍‌ ଭାବରେ ସେଟ୍‍ କରନ୍ତୁ</translation>
+<translation id="1576937952766665062">ବଙ୍ଗଳା ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="1589128298353575783"><ph name="NUMBER_OF_PB" /> PB</translation>
 <translation id="1620510694547887537">କ୍ୟାମେରା</translation>
+<translation id="162175252992296058">US ଆନ୍ତର୍ଜାତୀୟ କୀବୋର୍ଡ ସହ ପର୍ତ୍ତୁଗୀଜ୍</translation>
+<translation id="1641780993263690097">ଚାଇନିଜ୍ ପିନୟିନ୍</translation>
 <translation id="1646019627374511909"><ph name="NUMBER_OF_ITEMS" />ଟି ଫାଇଲକୁ ଅଫଲାଇନରେ ଉପଲବ୍ଧ କରାଯାଉଛି</translation>
 <translation id="164969095109328410">Chrome ଡିଭାଇସ୍</translation>
 <translation id="1665611772925418501">ଫାଇଲ୍‌ଟି ସଂଶୋଧିତ ହୋଇପାରିଲା ନାହିଁ।</translation>
 <translation id="1673103856845176271">ସୁରକ୍ଷା କାରଣରୁ ଏହି ଫାଇଲ୍‍କୁ ଆକ୍ସେସ୍ କରାଯାଇପାରିଲା ନାହିଁ।</translation>
 <translation id="169515659049020177">Shift</translation>
 <translation id="1722487484194605434"><ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍ ଜିପ୍ ହେଉଛି...</translation>
+<translation id="1729953886957086472">ଜର୍ମାନ (ଜର୍ମାନୀ)</translation>
+<translation id="1730235522912993863">ଚାଇନିଜ୍ କାଙ୍ଗଜି</translation>
 <translation id="1731889557567069540"><ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍ କପି ହୋଇଛି।</translation>
 <translation id="174173592514158117">ସମସ୍ତ Play ଫୋଲ୍ଡର୍ ଦେଖାନ୍ତୁ</translation>
+<translation id="1742316578210444689">ହିବ୍ରୁ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
+<translation id="1747761757048858544">ଡଚ୍ (ନେଦରଲ୍ୟାଣ୍ଡ)</translation>
 <translation id="174937106936716857">ସମୁଦାୟ ଫାଇଲ୍ ସଂଖ୍ୟା</translation>
 <translation id="1775381402323441512">ଭିଡିଓର ସୂଚନା</translation>
 <translation id="180035236176489073">ଏହି ଫାଇଲ୍‌ଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବା ପାଇଁ ଆପଣଙ୍କୁ ନିଶ୍ଚିତ ରୂପେ ଅନ୍‍ଲାଇନ୍ ରହିବାକୁ ହେବ।</translation>
 <translation id="1807938677607439181">ସମସ୍ତ ଫାଇଲ୍</translation>
 <translation id="1810764548349082891">କୌଣସି ପୂର୍ବାବଲୋକନ ଉପଲବ୍ଧ ନାହିଁ</translation>
+<translation id="1812302367230252929">ଆମହାରିକ୍ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="1815861158988915678"><ph name="BEGIN_BOLD" />ସତର୍କତା:<ph name="END_BOLD" />  ଏହି ଫାଇଲ୍‌ଗୁଡ଼ିକ ଅସ୍ଥାୟୀ ଅଟେ ଏବଂ ଡିସ୍କ‌ରେ ଜାଗା ଖାଲି କରିବା ପାଇଁ ହୁଏତ ସ୍ୱଚାଳିତ ରୂପେ ଡିଲିଟ୍ କରାଯାଇଥାଇପାରେ।  <ph name="BEGIN_LINK" />ଅଧିକ ଜାଣନ୍ତୁ<ph name="END_LINK" /></translation>
 <translation id="1829129547161959350">ପେଙ୍ଗୁଇନ୍‍</translation>
 <translation id="183183971458492120">ସୂଚନା ଲୋଡ୍ ହେଉଛି..</translation>
@@ -72,6 +87,7 @@
 <translation id="1847880352285315359">ସେଭ୍‍ ହୋ‍ଇଗଲା</translation>
 <translation id="1853795129690976061">ଏହି ଫୋଲ୍ଡରକୁ Linux ସହିତ ସେୟାର୍ କରାଯାଇଛି</translation>
 <translation id="1864756863218646478">ଏହି ଫାଇଲ୍ ମିଳିଲା ନାହଁ।</translation>
+<translation id="1920670151694390848">ମାଲାୟଲମ୍ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="1924372192547904021"><ph name="DRIVE_NAME" /> ଫର୍ମାଟ୍ କରାଯାଇଛି</translation>
 <translation id="1931134289871235022">ସ୍ଲୋଭାକ୍</translation>
 <translation id="1933345018156373194">ଘୁଞ୍ଚାଇବା କାର୍ଯ୍ୟ ବିଫଳ ହେଲା, ଅପ୍ରତ୍ୟାଶିତ ତ୍ରୁଟି: <ph name="ERROR_MESSAGE" /></translation>
@@ -82,16 +98,23 @@
 <translation id="1995337122023280937">ଫାଇଲ୍ ଲୋକେସନକୁ ଯାଆନ୍ତୁ</translation>
 <translation id="2001796770603320721">Driveରେ ପରିଚାଳନା କରନ୍ତୁ</translation>
 <translation id="2009067268969781306">କୌଣସି ଡ୍ରାଇଭ୍‍କୁ ଡିଲିଟ୍ କରିବା ଦ୍ୱାରା ଏଥିରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହୋଇଯିବ। ଏହି କାର୍ଯ୍ୟକୁ ପୂର୍ବବତ୍ କରାଯାଇପାରିବ ନାହିଁ।</translation>
+<translation id="2025955442973426285">ଟାଇଗ୍ରିନ୍ୟା</translation>
 <translation id="2028997212275086731">ରାର୍‌ ଆର୍କାଇଭ୍‌</translation>
+<translation id="2037845485764049925">ଋଷୀୟ</translation>
 <translation id="2046702855113914483">ରାମେନ୍</translation>
 <translation id="2070909990982335904">ଡଟ୍ ସହିତ ଆରମ୍ଭ ହେଉଥିବା ନାମଗୁଡ଼ିକ ସିଷ୍ଟମ୍ ପାଇଁ ସଂରକ୍ଷିତ ଅଛି। ଦୟାକରି ଅନ୍ୟ ଏକ ନାମ ଚୟନ କରନ୍ତୁ।</translation>
 <translation id="2079545284768500474">ପୂର୍ବବତ୍</translation>
 <translation id="2084108471225856927">ଡିଭାଇସ୍ ସେଟିଂସ୍</translation>
 <translation id="2085470240340828803">"<ph name="FILENAME" />" ନାମକ ଗୋଟିଏ ଫାଇଲ୍ ପୂର୍ବରୁ ବିଦ୍ୟମାନ ଅଛି। ଆପଣ କ’ଣ କରିବାକୁ ଚାହାନ୍ତି?</translation>
 <translation id="2121825465123208577">ଆକାର ବଦଳାନ୍ତୁ</translation>
+<translation id="2125607626296734455">ଖମେର୍</translation>
+<translation id="2142680004883808240">ଫୋନେଟିକ୍ YaZHert କୀବୋର୍ଡ ସହ ଋଷୀୟ</translation>
 <translation id="2163152940313951844">ଅବୈଧ ବର୍ଣ୍ଣ: <ph name="CHARACTER_NAME" /></translation>
+<translation id="2184934335987813305">US ଆନ୍ତର୍ଜାତୀୟ PC କୀବୋର୍ଡ ସହ ପର୍ତ୍ତୁଗୀଜ୍</translation>
 <translation id="2198315389084035571">ସରଳୀକୃତ ଚାଇନିଜ୍</translation>
 <translation id="2208158072373999562">Zip ଆର୍କାଇଭ୍‍</translation>
+<translation id="22085916256174561">କୋରୀୟ</translation>
+<translation id="2208919847696382164">Linux ସହିତ ଇନଷ୍ଟଲ୍ କରନ୍ତୁ</translation>
 <translation id="2225536596944493418">ଆପଣ କ'ଣ ନିଶ୍ଚିତ ରୂପେ <ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍ ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି?</translation>
 <translation id="2230062665678605299">ଫୋଲ୍ଡର୍‌ ତିଆରି କରିବାରେ ଅକ୍ଷମ "<ph name="FOLDER_NAME" />". <ph name="ERROR_MESSAGE" /></translation>
 <translation id="2275059641601412272">ମୁଭ୍ କରାଯାଇଛି।</translation>
@@ -100,10 +123,12 @@
 <translation id="2303301624314357662"><ph name="FILE_NAME" />ଫାଇଲ୍ ଖୋଲୁଛି।</translation>
 <translation id="2305020378527873881"><ph name="VOLUME_NAME" /> ବାହାର କରାଯାଇଛି</translation>
 <translation id="2325650632570794183">ଏହି ଫାଇଲ୍ ପ୍ରକାର ସମର୍ଥିତ ନୁହେଁ। ଏହି ପ୍ରକାରର ଫାଇଲ୍ ଖୋଲିବା ପାଇଁ ଗୋଟିଏ ଆପ୍ ଖୋଜିବାକୁ ଦୟାକରି Chrome ୱେବ୍ ଷ୍ଟୋର୍‌କୁ ଯାଆନ୍ତୁ।</translation>
+<translation id="2326539130272988168">ବୁଲଗେରିଆନ୍</translation>
 <translation id="2352947182261340447">ସ୍ଥାନୀୟ ଷ୍ଟୋରେଜ୍‌ରେ ପର୍ଯ୍ୟାପ୍ତ ଖାଲି ସ୍ଥାନ ଉପଲବ୍ଧ ନାହିଁ।</translation>
 <translation id="2377319039870049694">ଲିଷ୍ଟ ଭ୍ୟୁକୁ ସ୍ୱିଚ୍ କରନ୍ତୁ</translation>
 <translation id="2377590462528165447">Linux ସହ <ph name="NUMBER_OF_ITEMS" />ଟି ଫୋଲ୍ଡର୍‌ ସେୟାର୍‌ କରାଯାଇଛି</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" />ଟି ଫାଇଲ୍ ଚୟନ କରାଯାଇଛି</translation>
+<translation id="2389832672041313158">ବର୍ମିଜ୍/ମିଆଁମାର୍</translation>
 <translation id="240770291734945588"><ph name="SPACE_AVAILABLE" /> ଉପଲବ୍ଧ</translation>
 <translation id="2425665904502185219">ମୋଟ ଫାଇଲ୍‍ର ଆକାର</translation>
 <translation id="2428749644083375155"><ph name="FOLDER_NAME" />ରେ <ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍ କପି କରାଯାଉଛି</translation>
@@ -111,6 +136,7 @@
 <translation id="2453576648990281505">ପୂର୍ବରୁ ଏହି ଫାଇଲ୍‌ଟି ଅଛି</translation>
 <translation id="2464079411014186876">ଆଇସ୍‍କ୍ରିମ୍</translation>
 <translation id="2468402215065996499">ଟାମାଗୋଚୀ</translation>
+<translation id="2500392669976258912">ଗୁଜୁରାଟୀ ଫୋନେଟିକ୍</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍‌ ଡିଲିଟ୍‍ ହୋ‍ଇଛି</translation>
 <translation id="2541377937973966830">ଏହି ଫୋଲ୍ଡରରେ ଥିବା ବିଷୟବସ୍ତୁଗୁଡ଼ିକ କେବଳ-ପଢ଼ିବା ପାଇଁ ଅଟେ। କିଛି କାର୍ଯ୍ୟକଳାପ ସମର୍ଥିତ ନୁହେଁ।</translation>
@@ -120,19 +146,26 @@
 <translation id="2562685439590298522">Docs</translation>
 <translation id="2563185590376525700">ବେଙ୍ଗ</translation>
 <translation id="2572501073504669105">ଯେତେବେଳେ ଆପଣଙ୍କ ପାଖରେ ଇଣ୍ଟରନେଟ୍ ସଂଯୋଗ ନଥାଏ, ସେତେବେଳେ ଆପଣ ଫାଇଲଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବା ପାଇଁ ଅଫଲାଇନରେ ଉପଲବ୍ଧ କରିପାରିବେ।</translation>
+<translation id="2578394532502990878">ତାମିଲ ଫୋନେଟିକ୍</translation>
+<translation id="2579959351793446050">ଓଡ଼ିଆ</translation>
 <translation id="2614589611416690597"><ph name="VIDEO_TYPE" /> ଭିଡିଓ</translation>
 <translation id="2620090360073999360">ଏହି ସମୟରେ Google Driveରେ ପହଞ୍ଚି ହେବ ନାହିଁ।</translation>
 <translation id="2638942478653899953">Google Drive ପର୍ଯ୍ୟନ୍ତ ପହଞ୍ଚିହେଲା ନାହିଁ। ଦୟାକରି <ph name="BEGIN_LINK" />ଲଗ୍‌ ଆଉଟ୍‍<ph name="END_LINK" /> ଏବଂ ଫେରି ଲଗ୍‍ ଇନ୍‍ କରନ୍ତୁ।</translation>
 <translation id="2649120831653069427">ରେନ୍‌ବୋଫିସ୍</translation>
 <translation id="2661146741306740526">16x9</translation>
+<translation id="2663066752008346276">ମିଆଁସାନ୍ କୀବୋର୍ଡ ସହ ବର୍ମିଜ୍/ମିଆଁମାର୍</translation>
 <translation id="2664412712123763093">ଫାଇଲ୍ ଲୋକେସନ୍</translation>
 <translation id="2672394958563893062">ଏକ ତ୍ରୁଟି ଦେଖାଦେଲା। ଆରମ୍ଭରୁ ପୁଣିଥରେ ଚଲାଇବାକୁ କ୍ଲିକ୍ କରନ୍ତୁ।</translation>
 <translation id="2676946222714718093">ଏଥିରେ ଚାଲୁଛି</translation>
+<translation id="2718540689505416944">Linux ମାଧ୍ୟମରେ ଆପକୁ ଇନଷ୍ଟଲ୍ କରନ୍ତୁ</translation>
+<translation id="2724954091494693138">ତୁର୍କିଶ୍ F-କୀବୋର୍ଡ</translation>
+<translation id="2732839045120506979">ଭିଏତନାମିଜ୍ VNI</translation>
 <translation id="2735623501230989521">Parallels Desktopକୁ <ph name="FOLDER_NAME" /> ଫୋଲ୍ଡରରେ ଥିବା ଫାଇଲଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ</translation>
 <translation id="2771816809568414714">ଚିଜ୍</translation>
 <translation id="2781645665747935084">ବେଲ୍‍ଜିଆନ୍</translation>
 <translation id="2782104745158847185">Linux ଆପ୍ଲିକେସନ୍ ଇନ୍‌ଷ୍ଟଲ୍‌ କରିବାରେ ତ୍ରୁଟି</translation>
 <translation id="2787047795752739979">ମୂଳଲେଖାକୁ ଓଭର୍‍ରାଇଟ୍ କରନ୍ତୁ</translation>
+<translation id="2830077785865012357">ଚାଇନିଜ୍ ଝୁୟିନ୍</translation>
 <translation id="2843806747483486897">ଡିଫଲ୍ଟ ପରିବର୍ତ୍ତନ କରନ୍ତୁ...</translation>
 <translation id="2850124913210091882">ବ୍ୟାକ୍‌ଅପ୍‌ ନିଅନ୍ତୁ</translation>
 <translation id="2873951654529031587">ଟ୍ରାସ୍</translation>
@@ -142,6 +175,7 @@
 <translation id="2894654529758326923">ସୂଚନା</translation>
 <translation id="2902312830803030883">ଅଧିକ କାର୍ଯ୍ୟ</translation>
 <translation id="2902734494705624966">US ସମ୍ପ୍ରସାରିତ କୀବୋର୍ଡ</translation>
+<translation id="290843123675549676">ମରାଠୀ</translation>
 <translation id="2923240520113693977">ଏଷ୍ଟୋନିଆନ୍</translation>
 <translation id="2925966894897775835">Sheets</translation>
 <translation id="2938685643439809023">ମଙ୍ଗୋଲିଆ</translation>
@@ -151,9 +185,11 @@
 <translation id="2951236788251446349">ଜେଲିଫିସ୍</translation>
 <translation id="2984337792991268709">ଆଜି <ph name="TODAY_DAYTIME" /></translation>
 <translation id="2994669386200004489"><ph name="FILE_NAME" />ର ବ୍ୟାକ୍‍ଅପ୍ ନିଆଯାଇପାରିଲା ନାହିଁ</translation>
+<translation id="299638574917407533">ଫରାସୀ (କାନାଡ଼ା)</translation>
 <translation id="3003633581067744647">ଥମ୍ବନେଲ୍ ଭ୍ୟୁକୁ ସ୍ବିଚ୍ କରନ୍ତୁ</translation>
 <translation id="3007214526293698309">ଅନୁପାତର ସମାଧାନ କରନ୍ତୁ</translation>
 <translation id="303198083543495566">ଭୌଗଳିକ</translation>
+<translation id="3047197340186497470">ଚାଇନିଜ୍ ଡାୟି</translation>
 <translation id="3057861065630527966">ଆପଣଙ୍କର ଫଟୋ ଓ ଭିଡିଓଗୁଡ଼ିକର ବ୍ୟାକ୍‌ଅପ୍ ନିଅନ୍ତୁ</translation>
 <translation id="3067790092342515856">Windows ଫାଇଲଗୁଡ଼ିକ</translation>
 <translation id="3078461028045006476"><ph name="EXTENSION_NAME" /> ସହ ସେୟାର୍ କରନ୍ତୁ</translation>
@@ -163,6 +199,7 @@
 <translation id="3188257591659621405">ମୋ ଫାଇଲ୍‌ଗୁଡ଼ିକ</translation>
 <translation id="3197563288998582412">US ଡିଭୋରାକ୍</translation>
 <translation id="3202131003361292969">ପାଥ୍</translation>
+<translation id="3205852408225871810">ପର୍ତ୍ତୁଗୀଜ୍ (ବ୍ରାଜିଲ୍)</translation>
 <translation id="3224239078034945833">କାନାଡିଆନ୍ ବହୁଭାଷୀ</translation>
 <translation id="3236289833370040187"><ph name="DESTINATION_DOMAIN" />କୁ ମାଲିକାନା ସ୍ଥାନାନ୍ତର ହେବ।</translation>
 <translation id="3241720467332021590">ଇରିସ୍</translation>
@@ -170,28 +207,35 @@
 <translation id="3248185426436836442">ବାକି ଅଛି</translation>
 <translation id="3252266817569339921">ଫ୍ରେଞ୍ଚ</translation>
 <translation id="3254434849914415189"><ph name="FILE_TYPE" /> ଫାଇଲ୍‍ଗୁଡ଼ିକ ପାଇଁ ଡିଫଲ୍ଟ ଆପ୍‍ ବାଛନ୍ତୁ:</translation>
+<translation id="3255159654094949700">ଆରବିକ୍</translation>
 <translation id="3264582393905923483">ପ୍ରସଙ୍ଗ</translation>
 <translation id="3272909651715601089">"<ph name="PATH" />" ଖୋଲାଯାଇପାରିଲା ନାହିଁ</translation>
 <translation id="3280431534455935878">ପ୍ରସ୍ତୁତ ହେଉଛି</translation>
 <translation id="3280987981688031357">Vinyl ରେକର୍ଡ</translation>
 <translation id="3296763833017966289">ଜର୍ଜିଆନ୍</translation>
+<translation id="3307875152560779385">ୟୁକ୍ରେନିଆନ୍</translation>
 <translation id="3326821416087822643"><ph name="FILE_NAME" />କୁ ଜିପ୍ କରୁଛି...</translation>
 <translation id="3335337277364016868">ରେକର୍ଡ କରାଯାଇଥିବା ବର୍ଷ</translation>
 <translation id="3353984535370177728">ଅପ୍‌ଲୋଡ୍‍ କରିବାକୁ ଏକ ଫୋଲ୍ଡର୍‌ ଚୟନ କରନ୍ତୁ</translation>
 <translation id="3356580349448036450">ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି</translation>
+<translation id="3382143449143186018">InScript କୀବୋର୍ଡ ସହ ନେପାଳୀ</translation>
+<translation id="3408236822532681288">ନିଓ 2 କୀବୋର୍ଡ ସହ ଜର୍ମାନ (ଜର୍ମାନୀ)</translation>
 <translation id="3414856743105198592">ବାହାର କରାଯାଇପାରୁଥିବା ମେଡ଼ିଆକୁ ଫର୍ମାଟ୍ କଲେ ଏହା ସମସ୍ତ ଡାଟା ଲିଭାଇଦେବ। ଆପଣ ଜାରି ରଖିବା ଚାହାନ୍ତି କି?</translation>
 <translation id="3437801641691368414">ତିଆରି ହୋ‌ଇଥିବାର ସମୟ</translation>
+<translation id="3455931012307786678">ଇସ୍ତୋନିଆନ୍</translation>
 <translation id="3466147780910026086">ଆପଣଙ୍କର ମେଡିଆ ଡିଭାଇସ୍ ସ୍କାନ୍ ହେଉଛି...</translation>
 <translation id="3468522857997926824"><ph name="FILE_COUNT" />ଟି ଫଟୋକୁ <ph name="BEGIN_LINK" />Google Drive<ph name="END_LINK" />ରେ ବ୍ୟାକ୍‌ଅପ୍‌ ନିଆଯାଇଛି</translation>
 <translation id="3470502288861289375">କପି କରାଯାଉଛି…</translation>
 <translation id="3473378059788601120"><ph name="FOLDER_NAME" />କୁ କପି କରାଯାଇଛି।</translation>
 <translation id="3475447146579922140">Google ସ୍ପ୍ରେଡ୍‌ସିଟ୍</translation>
+<translation id="3486821258960016770">ମଙ୍ଗୋଲିଆନ୍</translation>
 <translation id="3495304270784461826"><ph name="COUNT" />ଟି ତ୍ରୁଟି।</translation>
 <translation id="3522708245912499433">ପର୍ତ୍ତୁଗୀଜ୍</translation>
 <translation id="3524311639100184459">ସାବଧାନ: ଏହି ଫାଇଲଗୁଡ଼ିକ ଅସ୍ଥାୟୀ ଅଟେ ଏବଂ ଡିସ୍କରେ ଜାଗା ଖାଲି କରିବା ପାଇଁ ଏଗୁଡ଼ିକ ସ୍ୱଚାଳିତ ଭାବେ ଡିଲିଟ୍ ହୋଇଯାଇପାରେ।  <ph name="BEGIN_LINK" />ଅଧିକ ଜାଣନ୍ତୁ<ph name="END_LINK" /></translation>
 <translation id="3527085408025491307">ଫୋଲ୍ଡର୍</translation>
 <translation id="3549797760399244642">drive.google.comକୁ ଯାଆନ୍ତୁ …</translation>
 <translation id="3553048479571901246"><ph name="APP_NAME" /> ମାଧ୍ୟମରେ ଫାଇଲଗୁଡ଼ିକ ଖୋଲିବାକୁ, ପ୍ରଥମେ ସେଗୁଡ଼ିକୁ Windows ଫାଇଲ୍ ଫୋଲ୍ଡରରେ କପି କରନ୍ତୁ।</translation>
+<translation id="3556731189587832921">ଆନ୍ତର୍ଜାତୀୟ PC କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (US)</translation>
 <translation id="357479282490346887">ଲିଥୁଆନିଆନ୍</translation>
 <translation id="3603385196401704894">କାନାଡିଆନ୍ ଫ୍ରେଞ୍ଚ୍</translation>
 <translation id="3606220979431771195">ତୁର୍କୀସ୍-F</translation>
@@ -205,6 +249,7 @@
 <translation id="3645531960514756307">ଫୋଲ୍ଡର୍ ଅନ୍‌ପିନ୍ କରନ୍ତୁ</translation>
 <translation id="3685122418104378273">ମୋବାଇଲ୍ ଡାଟା ବ୍ୟବହାର କରିବା ସମୟରେ Google ଡ୍ରାଇଭ୍ ସିଙ୍କ ଡିଫଲ୍ଟ ରୂପେ ଅକ୍ଷମ କରାଯାଇଛି।</translation>
 <translation id="3689865792480713551"><ph name="ACTIVITY_DESCRIPTION" /> ବାତିଲ୍ କରନ୍ତୁ।</translation>
+<translation id="3691184985318546178">ସିଂହଳ</translation>
 <translation id="3726463242007121105">ଏହି ଡିଭାଇସ୍‌ ଖୋଲାଯାଇପାରିବ ନାହିଁ କାରଣ ଏହାର ଫାଇଲ୍‌ସିଷ୍ଟମ୍‌ ସମର୍ଥିତ ନୁହେଁ।</translation>
 <translation id="3741243925913727067">Google ଡ୍ରାଇଭ୍‌ରେ ଆପଣଙ୍କର ମିଡିଆ ଡିଭାଇସ୍‍ର ଫଟୋ ଓ ଭିଡିଓର ବ୍ୟାକ୍ ଅପ୍ ନିଅନ୍ତୁ।</translation>
 <translation id="3749289110408117711">ଫାଇଲ୍ ନାମ</translation>
@@ -224,17 +269,25 @@
 <translation id="3855472144336161447">ଜର୍ମନ୍ ନିଓ 2</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> ମାଧ୍ୟମରେ ପ୍ୟାକ୍ କରନ୍ତୁ</translation>
 <translation id="3866249974567520381">ବିବରଣୀ</translation>
+<translation id="3899991606604168269">ବହୁଭାଷୀ କୀବୋର୍ଡ ସହ ଫରାସୀ (କାନାଡ଼ା)</translation>
 <translation id="3924145049010392604">ମେଟା</translation>
 <translation id="3930521966936686665">ଚାଲୁ କରନ୍ତୁ</translation>
 <translation id="3943857333388298514">ପେଷ୍ଟ କରନ୍ତୁ</translation>
+<translation id="3952872973865944257">ତେଲୁଗୁ ଫୋନେଟିକ୍</translation>
 <translation id="3958548648197196644">କିୱି</translation>
 <translation id="3966388904776714213">ଅଡିଓ ପ୍ଲେୟାର୍</translation>
+<translation id="3973925058222872294">ଇଂରାଜୀ (UK)</translation>
+<translation id="3975895378829046965">ବଙ୍ଗଳା ଫୋନେଟିକ୍</translation>
 <translation id="4002066346123236978">ଆଖ୍ୟା</translation>
+<translation id="4017788180641807848">ୱାର୍କମ୍ୟାନ୍ କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (US)</translation>
+<translation id="4092890906744441904">ଆଇରିଶ୍</translation>
 <translation id="4124935795427217608">ୟୁନିକର୍ନ</translation>
 <translation id="4158739975813877944">ପ୍ଲେ ତାଲିକା ଖୋଲନ୍ତୁ</translation>
 <translation id="4159731583141908892"><ph name="FILE_NAME" /> ମୁଭ୍ କରାଯାଇଛି।</translation>
 <translation id="4193154014135846272">Google ଡକ୍ୟୁମେଣ୍ଟ</translation>
 <translation id="4197674956721858839">Zip ଚୟନ</translation>
+<translation id="4202378258276439759">ସ୍ପେନୀୟ (ଲାଟିନ୍ ଆମେରିକା)</translation>
+<translation id="4202977638116331303">ଜର୍ଜିଆନ୍</translation>
 <translation id="421017592316736757">ଏହି ଫାଇଲ୍‌କୁ ଆକ୍ସେସ୍‌ କରିବାକୁ ଆପଣଙ୍କୁ ଅନ୍‌ଲାଇନ୍‌ ରହିବା ଆବଶ୍ୟକ।</translation>
 <translation id="4212740939091998969">"<ph name="FOLDER_NAME" />" ନାମରେ ଫୋଲ୍ଡର୍‌ ପୂର୍ବରୁ ବିଦ୍ୟମାନ ଅଛି। ଦୟାକରି ଗୋଟିଏ ଅଲଗା ନାମ ବାଛନ୍ତୁ।</translation>
 <translation id="4215448920900139318"><ph name="FILE_COUNT" />ଟି ବ୍ୟାକ୍‍ଅପ୍ ନିଆଯାଉଛି</translation>
@@ -242,14 +295,20 @@
 <translation id="4290535918735525311">Linux ସହ 1ଟି ଫୋଲ୍ଡର୍ ସେୟାର୍ କରାଯାଇଛି</translation>
 <translation id="4299729908419173967">ବ୍ରାଜିଲିଆନ୍</translation>
 <translation id="4309915981827077375">ସାଧାରଣ ସୂଚନା</translation>
+<translation id="432252891123397018">ଷ୍ଟାଣ୍ଡାର୍ଡ କୀବୋର୍ଡ ସହ ରୋମାନିଆନ୍</translation>
+<translation id="4325128273762811722">ସ୍ଲୋଭେନିଆନ୍</translation>
 <translation id="4326192123064055915">କଫି</translation>
 <translation id="4336032328163998280">କପି କରିବା କାର୍ଯ୍ୟ ବିଫଳ ହେଲା।<ph name="ERROR_MESSAGE" /></translation>
+<translation id="4348495354623233847">ସୋରାନୀ କୁର୍ଦ୍ଦିଶ୍ ଆରବିକ୍-ଆଧାରିତ କୀବୋର୍ଡ</translation>
+<translation id="4363958938297989186">ଫୋନେଟିକ୍ କୀବୋର୍ଡ ସହ ଋଷୀୟ</translation>
 <translation id="4364327530094270451">ମେଲୋନ୍</translation>
 <translation id="4372884569765913867">1x1</translation>
 <translation id="4394214039309501350">ଏକ୍ସଟର୍ନଲ୍ ଲିଙ୍କ୍</translation>
 <translation id="4425149324548788773">ମୋ ଡ୍ରାଇଭ୍</translation>
 <translation id="4470564870223067757">ହଂଗୁଲ୍ 2 ସେଟ୍</translation>
+<translation id="4477002475007461989">ରୋମାନିଆନ୍</translation>
 <translation id="4477219268485577442">ବୁଲ୍‍‍ଗେରିଆନ୍ ଫୋନେଟିକ୍</translation>
+<translation id="4509667233588080747">ୱାର୍କମ୍ୟାନ୍ ଆନ୍ତର୍ଜାତୀୟ କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (US)</translation>
 <translation id="4522570452068850558">ବିବରଣୀ</translation>
 <translation id="4527800702232535228">Parallels Desktop ସହିତ ଏହି ଫୋଲ୍ଡରକୁ ସେୟାର୍ କରାଯାଇଛି</translation>
 <translation id="4552678318981539154">ଅଧିକ ଷ୍ଟୋରେଜ୍ କିଣନ୍ତୁ</translation>
@@ -261,12 +320,15 @@
 <translation id="4594543368593301662"><ph name="SEARCH_TERM" /> ପାଇଁ ଫଳାଫଳ ଦେଖାଉଛି।</translation>
 <translation id="4603392156942865207"><ph name="FOLDER_NAME" />କୁ <ph name="FILE_NAME" /> କପି କରାଯାଉଛି</translation>
 <translation id="4631887759990505102">କଳାକାର</translation>
+<translation id="4646813851450205600">Qwerty କୀବୋର୍ଡ ସହ ଚେକ୍</translation>
 <translation id="4656293982926141856">ଏହି କମ୍ପ୍ୟୁଟର୍</translation>
 <translation id="4669606053856530811"><ph name="SOURCE_NAME" />ର ସଦସ୍ୟମାନେ ସେପର୍ଯ୍ୟନ୍ତ ଆକ୍ସେସ୍ ହରାଇବେ ଯେପର୍ଯ୍ୟନ୍ତ ଏହି ଆଇଟମ୍‍ଗୁଡ଼ିକୁ ସେମାନଙ୍କ ସହିତ ସେୟାର୍‌ କରାଯାଇ ନାହିଁ।</translation>
 <translation id="4690246192099372265">ସ୍ୱିଡିଶ୍</translation>
 <translation id="4693155481716051732">ସୁଶି</translation>
 <translation id="4694604912444486114">ମାଙ୍କଡ଼</translation>
+<translation id="469612310041132144">ଚାଇନିଜ୍ କ୍ୱିକ୍</translation>
 <translation id="4697043402264950621"><ph name="COLUMN_NAME" /> ଦ୍ୱାରା ଫାଇଲ୍‌ର ତାଲିକା ସାନରୁ ବଡ଼ କ୍ରମରେ ସଜାଯାଇଛି।</translation>
+<translation id="4706042980341760088">ଟାଇପରାଇଟର୍ କୀବୋର୍ଡ ସହ ତାମିଲ</translation>
 <translation id="4711094779914110278">ତୁର୍କିସ୍</translation>
 <translation id="4712283082407695269">"<ph name="PATH" />" ଖୋଲାଯାଉଛି</translation>
 <translation id="4713544552769165154">ମେସିନ୍‍ଟୋସ୍ ସଫ୍ଟୱେର୍ ବ୍ୟବହାର କରି ଗୋଟିଏ କମ୍ପ୍ୟୁଟର୍ ପାଇଁ ଏହି ଫାଇଲ୍‍କୁ ତିଆରି କରାଯାଇଛି। Chrome OS ଚାଲୁଥିବା ଆପଣଙ୍କର ଡିଭାଇସ୍‌ରେ ଏହା ସୁସଙ୍ଗତ ନୁହେଁ। ଆପ୍‍ର ଗୋଟିଏ ଉପଯୁକ୍ତ ବିକଳ୍ପ ପାଇଁ ଦୟାକରି <ph name="BEGIN_LINK" />Chrome ୱେବ୍ ଷ୍ଟୋର୍<ph name="END_LINK" /> ସର୍ଚ୍ଚ କରନ୍ତୁ। <ph name="BEGIN_LINK_HELP" />ଅଧିକ ଜାଣନ୍ତୁ<ph name="END_LINK_HELP" /></translation>
@@ -277,6 +339,7 @@
 <translation id="4737050008115666127">ଲ୍ୟାଣ୍ଡିଙ୍ଗ୍‌</translation>
 <translation id="4747271164117300400">ମାସିଡୋନିୟ</translation>
 <translation id="4759238208242260848">ଡାଉନଲୋଡସମୂହ</translation>
+<translation id="4779041693283480986">ପର୍ତ୍ତୁଗୀଜ୍ (ପର୍ତ୍ତୁଗାଲ୍)</translation>
 <translation id="4779136857077979611">ଓନିଗିରି</translation>
 <translation id="4784330909746505604">PowerPoint ଉପସ୍ଥାପନା</translation>
 <translation id="4788401404269709922"><ph name="NUMBER_OF_KB" /> KB</translation>
@@ -284,6 +347,7 @@
 <translation id="4801956050125744859">ଉଭୟ ରଖନ୍ତୁ</translation>
 <translation id="4804827417948292437">ଆଭୋକାଡୋ</translation>
 <translation id="4823651846660089135">ଡିଭାଇସ୍‌ କେବଳ ପଢ଼ିବା ପାଇଁ ଅଟେ</translation>
+<translation id="4826849268470072925">ତାମିଲ ITRANS</translation>
 <translation id="4839847978919684242"><ph name="SELCTED_FILES_COUNT" />ଟି ଆଇଟମ୍ ଚୟନ କରାଯାଇଛି</translation>
 <translation id="4843566743023903107">Chromebases</translation>
 <translation id="4850886885716139402">ଦେଖନ୍ତୁ</translation>
@@ -302,6 +366,7 @@
 <translation id="4969785127455456148">ଆଲ୍‌ବମ୍</translation>
 <translation id="4973523518332075481"><ph name="MAX_LENGTH" /> କିମ୍ବା ତା’ଠାରୁ କମ୍‌ ଅକ୍ଷରର ନାମ ବ୍ୟବହାର କରନ୍ତୁ</translation>
 <translation id="4973970068702235170">ଜିପ୍ କରିବା ବିଫଳ ହେଲା, ଅପ୍ରତ୍ୟାଶିତ ତ୍ରୁଟି: <ph name="ERROR_MESSAGE" /></translation>
+<translation id="4984616446166309645">ଜାପାନିଜ</translation>
 <translation id="4988205478593450158">ଆପଣ "<ph name="FILE_NAME" />"କୁ ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଥିବା ସୁନିଶ୍ଚିତ କି?</translation>
 <translation id="498902553138568924">ଲାଲ୍ ପ୍ରଜାପତି</translation>
 <translation id="4992066212339426712">ଅନମ୍ୟୁଟ୍ କରନ୍ତୁ</translation>
@@ -311,12 +376,15 @@
 <translation id="5024856940085636730">ଗୋଟିଏ କାର୍ଯ୍ୟ ଆଶା କରାଯାଉଥିବା ସମୟରୁ ଅଧିକ ସମୟ ନେଉଛି। ଆପଣ ଏହାକୁ ବନ୍ଦ କରିବାକୁ ଚାହାଁନ୍ତି କି?</translation>
 <translation id="5036159836254554629">Parallels Desktop ସେୟାରିଂ ପରିଚାଳନା କରନ୍ତୁ</translation>
 <translation id="5038625366300922036">ଅଧିକ ଦେଖନ୍ତୁ...</translation>
+<translation id="5044852990838351217">ଆର୍ମେନିଆନ୍</translation>
+<translation id="5059127710849015030">ନେପାଳୀ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="5061708541166515394">କଣ୍ଟ୍ରାଷ୍ଟ</translation>
 <translation id="5068919226082848014">ପିଜା</translation>
 <translation id="5081517858322016911"><ph name="TOTAL_FILE_SIZE" />ଟି ଫାଇଲ୍ ଡିଲିଟ୍ କରାଯିବ</translation>
 <translation id="508423945471810158"><ph name="FOLDER_NAME" />କୁ <ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍ ମୁଭ୍ କରାଯାଉଛି</translation>
 <translation id="509429900233858213">ଏକ ତ୍ରୁଟି ଦେଖାଦେଲା।</translation>
 <translation id="5098629044894065541">ହେବ୍ର୍ୟୁ</translation>
+<translation id="5110329002213341433">ଇଂରାଜୀ (କାନାଡ଼ା)</translation>
 <translation id="5123433949759960244">ବାସ୍କେଟବଲ୍</translation>
 <translation id="5129662217315786329">ପୋଲିସ୍</translation>
 <translation id="5144820558584035333">ହଂଗୁଲ୍ 3 ସେଟ୍ (390)</translation>
@@ -331,6 +399,7 @@
 <translation id="5170477580121653719">Google ଡ୍ରାଇଭ୍ ଅବଶିଷ୍ଟ ସ୍ଥାନ: <ph name="SPACE_AVAILABLE" />।</translation>
 <translation id="5177526793333269655">ଥମ୍ଵନେଲ୍ ଦର୍ଶନ</translation>
 <translation id="5194713942430106590">କଲମ୍‍କୁ ସାନରୁ ବଡ଼ କ୍ରମରେ ସଜାଇବା ପାଇଁ କ୍ଲିକ୍ କରନ୍ତୁ।</translation>
+<translation id="5211614973734216083">ଫାରୋସି</translation>
 <translation id="5218183485292899140">ସୁଇସ୍ ଫ୍ରେଞ୍ଚ</translation>
 <translation id="5234764350956374838">ଖାରଜ କରନ୍ତୁ</translation>
 <translation id="5253070652067921974">ଏହାଙ୍କ ଦ୍ୱାରା ତିଆରି କରାଯାଇଛି</translation>
@@ -348,10 +417,12 @@
 <translation id="5358764674931277">ଫ୍ରେମ୍ ହାର</translation>
 <translation id="5368191757080475556">Linux ସହ ଫୋଲ୍ଡର୍ ସେୟାର୍ କରନ୍ତୁ</translation>
 <translation id="5402367795255837559">ବ୍ରେଲ୍ଲୀ</translation>
+<translation id="541890217011173530">ସୋରାନୀ କୁର୍ଦ୍ଦିଶ୍ ଇଂରାଜୀ-ଆଧାରିତ କୀବୋର୍ଡ</translation>
 <translation id="5428105026674456456">ସ୍ପାନିଶ୍</translation>
 <translation id="5438282218546237410"><ph name="SEARCH_TERM" /> ପାଇଁ କୌଣସି ଫଳାଫଳ ନାହିଁ।</translation>
 <translation id="5449551289610225147">ଅବୈଧ ପାସ୍‌ୱର୍ଡ</translation>
 <translation id="5469868506864199649">ଇଟାଲିୟାନ୍</translation>
+<translation id="5489067830765222292">ଲାତଭିଆନ୍</translation>
 <translation id="5494920125229734069">ସମସ୍ତ ଚୟନ କରନ୍ତୁ</translation>
 <translation id="5500122897333236901">ଆଇସ୍ଲେଣ୍ଡିକ୍</translation>
 <translation id="5508696409934741614">ଡଟ୍</translation>
@@ -359,8 +430,11 @@
 <translation id="5524517123096967210">ଫାଇଲ୍‌କୁ ପଢ଼ାଯାଇପାରିଲା ନାହିଁ।</translation>
 <translation id="5533102081734025921"><ph name="IMAGE_TYPE" /> ଛବି</translation>
 <translation id="5534520101572674276">ଆକାର ଗଣନା କରାଯାଉଛି</translation>
+<translation id="554153475311314364">ଗ୍ରୀକ୍ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="5583640892426849032">ପଶ୍ଚାତ୍</translation>
+<translation id="5602622065581044566">ଫୋନେଟିକ୍ କୀବୋର୍ଡ ସହ ବୁଲଗେରିଆନ୍</translation>
 <translation id="5605830556594064952">US ଡିଭୋରାକ୍</translation>
+<translation id="5625294776298156701">ତାମିଲ99 କୀବୋର୍ଡ ସହ ତାମିଲ</translation>
 <translation id="5649768706273821470">ଶୁଣନ୍ତୁ</translation>
 <translation id="5678784840044122290">Linux ଆପ୍ଲିକେସନ୍‌ଟି ଆପଣଙ୍କର ଟର୍ମିନାଲ୍ ଭିତରେ ଉପଲବ୍ଧ ହେବ ଏବଂ ଆପଣଙ୍କର ଲଞ୍ଚର୍‌ରେ ହୁଏତ ଏକ ଆଇକନ୍ ମଧ୍ୟ ଦେଖାଇବ।</translation>
 <translation id="5686799162999241776"><ph name="BEGIN_BOLD" />ଏକ ଆର୍କାଇଭ୍‍ କିମ୍ବା ଭର୍ଚୁଆଲ୍‌ ଡିକ୍ସରୁ ବିଚ୍ଛିନ୍ନ କରାଯାଇପାରିବ ନାହିଁ<ph name="END_BOLD" />
@@ -368,13 +442,17 @@
 ଆର୍କାଇଭ୍‍ କିମ୍ବା ଭର୍ଚୁଆଲ୍‌ ଡିକ୍ସରେ ଥିବା ସମସ୍ତ ଫାଇଲ୍‌ ବନ୍ଦ କରନ୍ତୁ, ଏହାପରେ ପୁଣି ଚେଷ୍ଟାକରି ଦେଖନ୍ତୁ।</translation>
 <translation id="5691596662111998220">ଓହୋଃ, <ph name="FILE_NAME" /> ଏବେ ଆଉ ନାହିଁ।</translation>
 <translation id="5700087501958648444">ଅଡିଓ ସୂଚନା</translation>
+<translation id="5724172041621205163">ପାଟ୍ଟାଚୋଟେ କୀବୋର୍ଡ ସହ ଥାଇ</translation>
 <translation id="5731409020711461763">1 ନୂଆ ଫଟୋ</translation>
 <translation id="5752453871435543420">Chrome OS କ୍ଲାଉଡ୍‌ ବ୍ୟାକ୍‌ଅପ୍‌</translation>
 <translation id="5756666464756035725">ହଙ୍ଗେରିଆନ୍ QWERTY</translation>
+<translation id="5763377084591234761">ଜର୍ମାନ (ସ୍ୱିଜରଲ୍ୟାଣ୍ଡ)</translation>
+<translation id="5775750595919327203">ଉର୍ଦ୍ଦୁ</translation>
 <translation id="5776325638577448643">ଲିଭାଇ ଦିଅନ୍ତୁ ଏବଂ ଫର୍ମାଟ୍ କରନ୍ତୁ</translation>
 <translation id="57838592816432529">ମ୍ୟୁଟ୍‌</translation>
 <translation id="5788127256798019331">Play ଫାଇଲ୍ସ</translation>
 <translation id="5790193330357274855">କାଜାଖ୍</translation>
+<translation id="5804245609861364054">କନ୍ନଡ଼ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="5817397429773072584">ପାରମ୍ପାରିକ ଚାଇନିଜ୍</translation>
 <translation id="5818003990515275822">କୋରିୟ</translation>
 <translation id="5819442873484330149">ହଂଗୁଲ୍ 3 ସେଟ୍ (ଅନ୍ତିମ)</translation>
@@ -387,6 +465,7 @@
 <translation id="5911887972742538906">ଆପଣଙ୍କର Linux ଆପ୍ଲିକେସନ୍ ଇନ୍‌ଷ୍ଟଲେସନ୍‌ ସମୟରେ ଏକ ତ୍ରୁଟି ଦେଖାଦେଲା।</translation>
 <translation id="5912396950572065471">ଫର୍ମାଟ୍</translation>
 <translation id="5913638992615760742">କପି କାର୍ଯ୍ୟ ବିଫଳ ହେଲା, ଅପ୍ରତ୍ୟାଶିତ ତ୍ରୁଟି: <ph name="ERROR_MESSAGE" /></translation>
+<translation id="5926082595146149752">US ଆନ୍ତର୍ଜାତୀୟ PC କୀବୋର୍ଡ ସହ ଡଚ୍ (ନେଦରଲ୍ୟାଣ୍ଡ)</translation>
 <translation id="5932901536148835538">Chromebit</translation>
 <translation id="5955954492236143329"><ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍</translation>
 <translation id="5957366693331451795">Chromeboxes</translation>
@@ -397,20 +476,27 @@
 <translation id="604001903249547235">କ୍ଲାଉଡ୍ ବ୍ୟାକ୍‌ଅପ୍‌</translation>
 <translation id="6040143037577758943">ବନ୍ଦ</translation>
 <translation id="6074825444536523002">Google ଫର୍ମ</translation>
+<translation id="6079871810119356840">Qwerty କୀବୋର୍ଡ ସହ ହଙ୍ଗେରୀୟ</translation>
 <translation id="6096979789310008754">ସନ୍ଧାନ ଟେକ୍ସଟ୍ ଖାଲି ହୋଇଛି, ସମସ୍ତ ଫାଇଲ୍ ଏବଂ ଫୋଲ୍ଡର୍ ଦେଖାଉଛି।</translation>
 <translation id="610101264611565198"><ph name="FOLDER_NAME" />କୁ <ph name="FILE_NAME" /> ମୁଭ୍ କରାଯାଉଛି</translation>
 <translation id="6129953537138746214">ସ୍ପେସ୍</translation>
 <translation id="6133173853026656527"><ph name="FILE_NAME" /> ଘୁଞ୍ଚୁଛି...</translation>
+<translation id="613750717151263950">US କୀବୋର୍ଡ ସହ ଜାପାନିଜ</translation>
 <translation id="6146563240635539929">ଭିଡିଓଗୁଡ଼ିକ</translation>
 <translation id="6150853954427645995">ଅଫ୍‌ଲାଇନ୍‌ ବ୍ୟବହାର ପାଇଁ ଏହି ଫାଇଲ୍‌ ସେଭ୍‌ କରିବାକୁ, ଅନ୍‌ଲାଇନ୍‌କୁ ଫେରନ୍ତୁ, ଫାଇଲ୍‌ରେ ରାଇଟ୍‍-କ୍ଲିକ୍‌ କରନ୍ତୁ ଏବଂ <ph name="OFFLINE_CHECKBOX_NAME" />ର ବିକଳ୍ପ ଚୟନ କରନ୍ତୁ।</translation>
 <translation id="6164412158936057769">ବଟର୍‌ଫ୍ଲାଇସ୍</translation>
 <translation id="6170470584681422115">ସାଣ୍ଡୱିଚ୍</translation>
+<translation id="6187719147498869044">ହଙ୍ଗେରୀୟ</translation>
 <translation id="6189412234224385711"><ph name="EXTENSION_NAME" /> ମାଧ୍ୟମରେ ଖୋଲନ୍ତୁ</translation>
 <translation id="6199801702437275229">ସ୍ଥାନ ସୂଚନା ପାଇଁ ଅପେକ୍ଷାରତ...</translation>
 <translation id="6205710420833115353">କିଛି କାର୍ଯ୍ୟ ପ୍ରଣାଳୀ ଆଶା କରାଯାଉଥିବା ସମୟରୁ ଅଧିକ ସମୟ ନେଇଥାଏ। ଆପଣ ସେଗୁଡ଼ିକୁ ବନ୍ଦ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି?</translation>
+<translation id="6220423280121890987">ପଞ୍ଜାବୀ</translation>
+<translation id="6224240818060029162">ଡେନିସ୍</translation>
 <translation id="6224253798271602650"><ph name="DRIVE_NAME" /> ଫର୍ମାଟ୍ କରନ୍ତୁ</translation>
 <translation id="6227235786875481728">ଏହି ଫାଇଲ୍ ଚଲାଯାଇପାରିଲା ନାହିଁ।</translation>
+<translation id="6241349547798190358">ଡଚ୍ (ବେଲଜିୟମ୍)</translation>
 <translation id="6248400709929739064">ଉପଶୀର୍ଷକ ସକ୍ଷମ କରନ୍ତୁ</translation>
+<translation id="6269630227984243955">ମଲୟ</translation>
 <translation id="6287852322318138013">ଏହି ଫାଇଲ୍ ଖୋଲିବା ପାଇଁ ଗୋଟିଏ ଆପ୍ ଚୟନ କରନ୍ତୁ</translation>
 <translation id="6339145975392024142">US ଆନ୍ତର୍ଜାତିକ (PC)</translation>
 <translation id="6346310558342052870">ଆକ୍ସେସ୍‍କୁ ପ୍ରତିବନ୍ଧିତ କରାଯାଇଛି</translation>
@@ -421,6 +507,7 @@
 <translation id="6395575651121294044"><ph name="NUMBER_OF_FILES" />ଟି ଆଇଟମ୍</translation>
 <translation id="6398765197997659313">ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍‌ରୁ ପ୍ରସ୍ଥାନ କରନ୍ତୁ</translation>
 <translation id="642282551015776456">ଏହି ନାମ କୌଣସି ଫାଇଲ୍‍ କିମ୍ବା ଫୋଲ୍ଡର୍‌ର ନାମ ଭାବେ ବ୍ୟବହାର କରାଯାଇନପାରେ</translation>
+<translation id="6423031066725912715">TCVN କୀବୋର୍ଡ ସହ ଭିଏତନାମିଜ୍</translation>
 <translation id="6485131920355264772">ଯାଗା ସମ୍ବନ୍ଧିତ ତଥ୍ୟ ପୁନରୁଦ୍ଧାର କରିବାରେ ବିଫଳ ହେଲା</translation>
 <translation id="6509122719576673235">ନରୱେଜିଆନ୍</translation>
 <translation id="6527303717912515753">ସେୟାର୍ କରନ୍ତୁ</translation>
@@ -437,19 +524,23 @@
 <translation id="6643016212128521049">ଖାଲି କରନ୍ତୁ</translation>
 <translation id="6650726141019353908">ଗୋଲାପି ପ୍ରଜାପତି</translation>
 <translation id="6657585470893396449">ପାସ୍‌ୱର୍ଡ</translation>
+<translation id="6673674183150363784">Bépo କୀବୋର୍ଡ ସହ ଫରାସୀ (ଫ୍ରାନ୍ସ)</translation>
 <translation id="6710213216561001401">ପୂର୍ବବର୍ତ୍ତୀ</translation>
 <translation id="6718273304615422081">ଜିପ୍ ହେଉଛି...</translation>
 <translation id="6751256176799620176">1ଟି ଫୋଲ୍ଡର୍ ଚୟନ କରାଯାଇଛି</translation>
 <translation id="6790428901817661496">ଚଲାନ୍ତୁ</translation>
 <translation id="6795884519221689054">ପାଣ୍ଡା</translation>
 <translation id="6806699711453372963">Linux ସେୟାରିଂ ପରିଚାଳନା କରନ୍ତୁ</translation>
+<translation id="6806796368146926706">ଆଲ୍ଫାନ୍ୟୁମେରିକ୍, ଜାପାନିଜ କୀବୋର୍ଡ ସହିତ</translation>
 <translation id="6808193438228982088">ଶିଆଳ</translation>
 <translation id="6820687829547641339">Gzip ଟାର୍ ଆର୍କାଇଭ୍‌କୁ ଛୋଟ କରିଦେଇଛି</translation>
 <translation id="6823166707458800069">ଏହି ଫୋଲ୍ଡରରେ ସେଭ୍ କରାଯାଇଥିବା ସମସ୍ତ ଫାଇଲର ସ୍ୱଚାଳିତରୂପେ ଅନଲାଇନରେ ବ୍ୟାକଅପ୍ ନିଆଯାଏ।</translation>
 <translation id="6825883775269213504">ଋଷିଆନ୍</translation>
 <translation id="6827236167376090743">ଏହି ଭିଡିଓଟି ଦୀର୍ଘ ସମୟ ପର୍ଯ୍ୟନ୍ତ ବାରମ୍ବାର ଚାଲୁଥିବ।</translation>
 <translation id="6847101934483209767">ଚୟନରୁ <ph name="ENTRY_NAME" /> କାଢ଼ି ଦିଆଯାଇଛି।</translation>
+<translation id="6861394552169064235">ପାର୍ସି</translation>
 <translation id="6862635236584086457">ଏହି ଫୋଲ୍ଡର୍‌ରେ ସେଭ୍ ହୋଇଥିବା ସମସ୍ତ ଫାଇଲ୍‌ଗୁଡ଼ିକ ସ୍ୱଚାଳିତରୂପେ ଅନ୍‌ଲାଇନ୍‌ରେ ବ୍ୟାକ୍‌ଅପ୍ ନିଆଯାଏ</translation>
+<translation id="6864328437977279120">ସଂସ୍କୃତ</translation>
 <translation id="6876155724392614295">ବାଇକ୍</translation>
 <translation id="6878261347041253038">ଦେବନାଗରୀ କୀବୋର୍ଡ (ଫୋନେଟିକ୍)</translation>
 <translation id="6885780034956018177">ଗେଣ୍ଡା</translation>
@@ -463,20 +554,28 @@
     <ph name="LINE_BREAK1" />
     <ph name="FILE_COUNT" />ଟି ମିଳିଲା</translation>
 <translation id="6935521024859866267">ଓଲଟା</translation>
+<translation id="6949408524333579394">ସର୍ବିଆନ୍ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="696203921837389374">ମୋବାଇଲ୍ ଡାଟା ଜରିଆରେ ସିଙ୍କ୍ ପ୍ରକ୍ରିୟା ସକ୍ଷମ କରନ୍ତୁ</translation>
 <translation id="6965382102122355670">ଓକେ ବଟନ୍</translation>
 <translation id="6970230597523682626">ବୁଲଗେରୀୟ</translation>
 <translation id="6973630695168034713">ଫୋଲ୍ଡର୍‌ଗୁଡ଼ିକ</translation>
 <translation id="6978611942794658017">Windows ସଫ୍ଟୱେର୍ ବ୍ୟବହାର କରୁଥିବା PC ପାଇଁ ଏହି ଫାଇଲ୍ ଡିଜାଇନ୍ କରାଯାଇଛି। Chrome OS ଚାଲୁଥିବା ଆପଣଙ୍କର ଡିଭାଇସ୍‌ରେ ଏହା ସୁସଙ୍ଗତ ନୁହେଁ। ଆପ୍‍ର ଗୋଟିଏ ଉପଯୁକ୍ତ ବିକଳ୍ପ ପାଇଁ ଦୟାକରି Chrome ୱେବ୍ ଷ୍ଟୋର୍‌ରେ ସନ୍ଧାନ କରନ୍ତୁ।</translation>
 <translation id="6979158407327259162">Google Drive</translation>
+<translation id="6989942356279143254">ସ୍ୱେଡିସ</translation>
 <translation id="6990081529015358884">ଆପଣଙ୍କ ପାଖରେ ଥିବା ଜାଗା ସରିଯାଇଛି</translation>
 <translation id="6998711733709403587"><ph name="SELCTED_FOLDERS_COUNT" />ଫୋଲ୍ଡର୍‌ଗୁଡ଼ିକ ବଛାଯାଇଛି</translation>
 <translation id="7012943028104619157"><ph name="ROOT_TITLE" /> (<ph name="ROOT_SUMMARY" />)</translation>
 <translation id="7014174261166285193">ଇନ୍‍ଷ୍ଟଲ୍ କରିହେଲା ନାହିଁ</translation>
+<translation id="7031639531908619281">ତୁର୍କିଶ୍</translation>
+<translation id="7037472120706603960">ତାମିଲ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="7040138676081995583">ଏହା ମାଧ୍ୟମରେ ଖୋଲନ୍ତୁ...</translation>
+<translation id="7075931588889865715">TIS 820-2531 କୀବୋର୍ଡ ସହ ଥାଇ</translation>
+<translation id="7086590977277044826">InScript କୀବୋର୍ଡ ସହ ତାମିଲ</translation>
 <translation id="7100897339030255923"><ph name="COUNT" />ଟି ଆଇଟମ୍ ଚୟନ କରାଯାଇଛି</translation>
+<translation id="7103992300314999525">ମାସିଡୋନିଆନ୍</translation>
 <translation id="7106346894903675391">ଅଧିକ ଷ୍ଟୋରେଜ୍ କିଣନ୍ତୁ...</translation>
 <translation id="7126604456862387217">'&lt;b&gt;<ph name="SEARCH_STRING" />&lt;/b&gt;' - &lt;em&gt;ଡ୍ରାଇଭ୍‍‍ରେ ଖୋଜନ୍ତୁ&lt;/em&gt;</translation>
+<translation id="7135561821015524160">କନ୍ନଡ଼ ଫୋନେଟିକ୍</translation>
 <translation id="714034171374937760">Chromebase</translation>
 <translation id="7180611975245234373">ରିଫ୍ରେଶ୍</translation>
 <translation id="7189874332498648577"><ph name="NUMBER_OF_GB" /> GB</translation>
@@ -485,33 +584,42 @@
 <translation id="7248671827512403053">ଆପ୍ଲିକେସନ୍</translation>
 <translation id="7268659760406822741">ଉପଲବ୍ଧ ଥିବା ସେବାଗୁଡ଼ିକ</translation>
 <translation id="7283041136720745563">Google ଡ୍ରାଇଭ୍‌ରେ ଆପଣଙ୍କ ପାଇଁ ସଂରକ୍ଷିତ ଥିବା ସ୍ଥିରୀକୃତ ଅଂଶ ପର୍ଯ୍ୟାପ୍ତ ନୁହେଁ।</translation>
+<translation id="7294063083760278948">ତେଲୁଗୁ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="7295662345261934369">ଅନ୍ୟମାନଙ୍କ ସହ ସେୟାର୍ କରନ୍ତୁ</translation>
+<translation id="7309413087278791451">ଜର୍ମାନ (ବେଲଜିୟମ୍)</translation>
 <translation id="7339898014177206373">ନୂଆ ୱିଣ୍ଡୋ</translation>
+<translation id="7343393116438664539">ଭିଏତନାମିଜ୍ ଟେଲେକ୍ସ</translation>
 <translation id="7359359531237882347"><ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍‌ କପି ହେଉଛି...</translation>
 <translation id="7375951387215729722"><ph name="COLUMN_NAME" /> ଦ୍ୱାରା ଫାଇଲ୍‌ର ତାଲିକା ବଡ଼ରୁ ସାନ କ୍ରମରେ ସଜାଯାଇଛି।</translation>
+<translation id="7408870451288633753">ଚେକ୍</translation>
 <translation id="7417453074306512035">ଇଥିଓପିକ୍ କୀବୋର୍ଡ</translation>
 <translation id="7417705661718309329">Google ମ୍ୟାପ୍‌</translation>
 <translation id="7460898608667578234">ୟୁକ୍ରାନିଆନ୍</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" />ଟି ମିଳିଛି
     <ph name="LINE_BREAK1" />
     <ph name="BEGIN_LINK" />Google ଡ୍ରାଇଭ୍‍<ph name="END_LINK" />ରେ ବ୍ୟାକ୍‌ଅପ୍‌ ପାଇଁ ପ୍ରସ୍ତୁତ</translation>
+<translation id="7495372004724182530">ମାଲାୟଲମ୍ ଫୋନେଟିକ୍</translation>
 <translation id="7505167922889582512">ଲୁଚିଥିବା ଫାଇଲ୍ ଦେଖାନ୍ତୁ</translation>
 <translation id="7508545000531937079">ସ୍ଲାଇଡ୍ ଶୋ</translation>
 <translation id="751507702149411736">ବେଲାରଷୀୟ</translation>
+<translation id="7532029025027028521">ପାର୍ସି ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="7544830582642184299">ଆପଣଙ୍କର Google Driveରେ ଥିବା ଫାଇଲଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବାକୁ Linux ଆପ୍ସକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ପରିବର୍ତ୍ତନଗୁଡ଼ିକ ଆପଣଙ୍କ ଅନ୍ୟ ଡିଭାଇସଗୁଡ଼ିକ ସହିତ ସିଙ୍କ୍ ହୋଇଯିବ।</translation>
 <translation id="7544853251252956727">ଅଦଳବଦଳ</translation>
+<translation id="7547780573915868306">ଲିଥୁନିଆନ୍</translation>
 <translation id="7547811415869834682">ଡଚ୍</translation>
 <translation id="7551643184018910560">ସେଲ୍ଫରେ ପିନ୍‌ କରନ୍ତୁ</translation>
 <translation id="7553492409867692754">Linux ଆପ୍ସକୁ <ph name="FOLDER_NAME" /> ଫୋଲ୍ଡରରେ ଥିବା ଫାଇଲଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ</translation>
 <translation id="7576032389798113292">6x4</translation>
 <translation id="7589661784326793847">ଗୋଟିଏ ସେକେଣ୍ଡ ଅପେକ୍ଷା କରନ୍ତୁ</translation>
 <translation id="7592775719802218421"><ph name="FILE_NAME" />କୁ ଅଫଲାଇନରେ ଉପଲବ୍ଧ କରାଯାଉଛି</translation>
+<translation id="7600126690270271294">ସର୍ବିଆନ୍</translation>
 <translation id="7603724359189955920">ଗ୍ରିଡ୍ସ</translation>
 <translation id="7627790789328695202">ଓହୋଃ, <ph name="FILE_NAME" /> ପୂର୍ବରୁ ଅଛି। ଏହାକୁ ରିନେମ୍ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="7628656427739290098"><ph name="PERCENT" />% ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି।</translation>
 <translation id="7649070708921625228">ସହାୟତା</translation>
 <translation id="7654209398114106148"><ph name="NUMBER_OF_ITEMS" /> ଟି ଆଇଟମ୍ ଘୁଞ୍ଚାଯାଉଛି ...</translation>
 <translation id="7658239707568436148">ବାତିଲ୍</translation>
+<translation id="7663224033570512922">ହିନ୍ଦୀ</translation>
 <translation id="7693909743393669729">ଏକ ଡ୍ରାଇଭକୁ ଫର୍ମାଟ୍ କରିବା ଦ୍ୱାରା ସେଥିରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ସମସ୍ତ ଡାଟା ଲିଭିଯିବ ଏବଂ ଦୃଶ୍ୟମାନ ହେଉନଥିବା ପାର୍ଟିସନଗୁଡ଼ିକ ସମେତ, ପୂର୍ବରୁ ଥିବା ସମସ୍ତ ପାର୍ଟିସନକୁ କାଢ଼ି ଦିଆଯିବ। ଏହି କାର୍ଯ୍ୟକୁ ପୂର୍ବବତ୍ କରାଯାଇପାରିବ ନାହିଁ।</translation>
 <translation id="7695430100978772476"><ph name="DRIVE_NAME" /> ଫର୍ମାଟ୍ କରାଯାଇପାରିଲା ନାହିଁ</translation>
 <translation id="770015031906360009">ଗ୍ରୀକ୍</translation>
@@ -520,6 +628,7 @@
 <translation id="7724603315864178912">Cut</translation>
 <translation id="7730494089396812859">କ୍ଲାଉଡ୍‌ ବ୍ୟାକ୍‍ଅପ୍‌ ବିବରଣୀ ଦେଖାନ୍ତୁ</translation>
 <translation id="7748626145866214022">ଆକ୍ସନ୍‌ ବାର୍‌ରେ ଅଧିକ ବିକଳ୍ପ ଉପଲବ୍ଧ ଅଛି ଆକ୍ସନ ବାର୍‌କୁ ଫୋକସ୍‌ କରିବାକୁ Alt + A ଦବାନ୍ତୁ।</translation>
+<translation id="7760449188139285140">ଚାଇନିଜ୍ ୟୁବି</translation>
 <translation id="7765158879357617694">ନିଅନ୍ତୁ</translation>
 <translation id="7774365994322694683">Bird</translation>
 <translation id="7788080748068240085">"<ph name="FILE_NAME" />"କୁ ଅଫ୍‍ଲାଇନ୍‍‍ରେ ସେଭ୍ କରିବା ପାଇଁ ଆପଣଙ୍କୁ ନିଶ୍ଚିତ ରୂପେ ଅତିରିକ୍ତ <ph name="TOTAL_FILE_SIZE" />ର ସ୍ଥାନ ଖାଲି କରିବାକୁ ହେବ:<ph name="MARKUP_1" />
@@ -529,6 +638,8 @@
 <translation id="7799329977874311193">HTML ଡକ୍ୟୁମେଣ୍ଟ</translation>
 <translation id="7801354353640549019">Chromebooks</translation>
 <translation id="7805768142964895445">ସ୍ଥିତି</translation>
+<translation id="7806708061868529807">ହିବ୍ରୁ</translation>
+<translation id="78104721049218340">କେଡମାନୀ କୀବୋର୍ଡ ସହ ଥାଇ</translation>
 <translation id="7821462174190887129"><ph name="FILE_COUNT" />ଟି ମିଳିଛି।
     <ph name="LINE_BREAK1" />
    Google ଡ୍ରାଇଭ୍‌ ଆପଣଙ୍କ ପାଇଁ ସଂରକ୍ଷିତ ଥିବା ସ୍ଥିରୀକୃତ ଅଂଶ ପର୍ଯ୍ୟାପ୍ତ ନୁହେଁ। ଅତିରିକ୍ତ <ph name="FILE_SIZE" /> ଆବଶ୍ୟକ ଅଟେ।
@@ -539,7 +650,9 @@
 <translation id="7846076177841592234">ଚୟନିତ ଆଇଟମ୍ ବାତିଲ୍ କରନ୍ତୁ</translation>
 <translation id="7853966320808728790">ଫ୍ରେଞ୍ଚ BÉPO</translation>
 <translation id="7864662577698025113">ନୂଆ ସେବା ଯୋଗ କରନ୍ତୁ</translation>
+<translation id="7868774406711971383">ପୋଲିଶ୍</translation>
 <translation id="7873831373602885875"><ph name="FOLDER_NAME" />ରେ ସେଭ୍ କରିପାରିବ ନାହିଁ। ସମସ୍ତ ଏଡ଼ିଟ୍‌ ଡାଉନ୍‌ଲୋଡ୍‌ ଫୋଲ୍ଡର୍‌ର <ph name="DOWNLOADS_FOLDER" />ରେ ସେଭ୍‌ କରାଯିବ।</translation>
+<translation id="7874321682039004450">ଫିଲିପିନୋ</translation>
 <translation id="7881969471599061635">ଉପଶୀର୍ଷକ ଅକ୍ଷମ କରନ୍ତୁ</translation>
 <translation id="78946041517601018">ସେୟାର୍ ହୋଇଥିବା ଡ୍ରାଇଭ୍‌ଗୁଡ଼ିକ</translation>
 <translation id="7908793776359722643">ଏକ ପାର୍ଟିସନକୁ ଫର୍ମାଟ୍ କରିବା ଦ୍ୱାରା ଏଥିରେ ଷ୍ଟୋର୍ କରାଯାଇଥିବା ସମସ୍ତ ଡାଟା ଲିଭିଯିବ। ଏହି କାର୍ଯ୍ୟକୁ ପୂର୍ବବତ୍ କରାଯାଇପାରିବ ନାହିଁ।</translation>
@@ -548,6 +661,8 @@
 <translation id="7943385054491506837">US କୋଲ୍‌ମାର୍କ</translation>
 <translation id="7953739707111622108">ଏହି ଡିଭାଇସ୍‌ ଖୋଲାଯାଇପାରିବ ନାହିଁ କାରଣ ଏହାର ଫାଇଲ୍‌ସିଷ୍ଟମ୍‌କୁ ଚିହ୍ନଟ କରାଯାଇପାରିନଥିଲା।</translation>
 <translation id="7969525169268594403">ସ୍ଲୋଭେନିଆନ୍</translation>
+<translation id="7972920761225148017">ଫରାସୀ (ସ୍ୱିଜରଲ୍ୟାଣ୍ଡ)</translation>
+<translation id="7980421588063892270">କୋଲମାକ୍ କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (US)</translation>
 <translation id="7982283708762922719">ଉଚ୍ଚତା</translation>
 <translation id="8008366997883261463">ଶ୍ୱାନ</translation>
 <translation id="8028993641010258682">ଆକାର</translation>
@@ -560,18 +675,21 @@
 <translation id="8079530767338315840">ପୁନର୍ବାର କରନ୍ତୁ</translation>
 <translation id="8106045200081704138">ମୋ ସହିତ ସେୟାର୍‌ କରାଯାଇଛି</translation>
 <translation id="8116072619078571545">ଥଣ୍ଡା ପାଣି</translation>
+<translation id="8128733386027980860">ଡିଭୋରାକ୍ କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (UK)</translation>
 <translation id="8137331602592933310">"<ph name="FILENAME" />" ଆପଣଙ୍କ ସହ ସେୟାର୍ ହୋଇଛି। ଆପଣଙ୍କ ପାଖରେ ଏହା ନଥିବାରୁ ଆପଣ ଏହାକୁ ଡିଲିଟ୍ କରିପାରିବେ ନାହିଁ।</translation>
 <translation id="8151638057146502721">କନ୍‍ଫିଗର୍ କରନ୍ତୁ</translation>
 <translation id="8153607920959057464">ଏହି ଫାଇଲ୍‌ ପ୍ରଦର୍ଶିତ କରାଯାଇପାରିଲା ନାହିଁ।</translation>
 <translation id="8154842056504218462">ସବୁ ବଛାଯାଇଛି।</translation>
 <translation id="8157684860301034423">ଆପ୍ ସୂଚନାଗୁଡ଼ିକୁ ପୁନରୁଦ୍ଧାର କରିହେଲାନାହିଁ।</translation>
 <translation id="8157939133946352716">7x5</translation>
+<translation id="8175731104491895765">ଫରାସୀ (ବେଲଜିୟମ୍)</translation>
 <translation id="8179976553408161302">ପ୍ରବେଶ</translation>
 <translation id="8193175696669055101">ଡିଭାଇସ୍‍ର ମଡେଲ୍</translation>
 <translation id="8208580316430297579">କଳାକୃତି</translation>
 <translation id="8223479393428528563">ଅଫ୍‍ଲାଇନ୍‍‍ରେ ବ୍ୟବହାର କରିବା ପାଇଁ ଏହି ଫାଇଲ୍‍ଗୁଡ଼ିକୁ ସେଭ୍ କରିବାକୁ, ଅନ୍‍ଲାଇନ୍‍‍ରେ ଫେରି ଆସନ୍ତୁ, ଫାଇଲ୍‍ଗୁଡ଼ିକ ଉପରେ ଡାହାଣ-କ୍ଲିକ୍ କରନ୍ତୁ ଏବଂ <ph name="OFFLINE_CHECKBOX_NAME" /> ବିକଳ୍ପ ଚୟନ କରନ୍ତୁ।</translation>
 <translation id="8249296373107784235">ବନ୍ଦ କରନ୍ତୁ</translation>
 <translation id="8261506727792406068">ବିଲୋପ</translation>
+<translation id="8261561378965667560">ଚାଇନିଜ୍ ଆରେ</translation>
 <translation id="8269755669432358899">ଫାଇଲ୍ ମତାମତ ପ୍ୟାନେଲ୍‍ଗୁଡ଼ିକୁ ସଙ୍କୁଚିତ କରନ୍ତୁ</translation>
 <translation id="8280151743281770066">ଆରମେନିଆନ୍ ଫୋନେଟିକ୍</translation>
 <translation id="8294431847097064396">ଉତ୍ସ</translation>
@@ -580,43 +698,59 @@
 <translation id="8312871300878166382">ଫୋଲ୍ଡର୍‌ରେ ପେଷ୍ଟ କରନ୍ତୁ</translation>
 <translation id="8329978297633540474">କେବଳ ଟେକ୍ସଟ୍</translation>
 <translation id="8335587457941836791">ସେଲ୍ଫରୁ ଅନପିନ୍ କରନ୍ତୁ</translation>
+<translation id="8335837413233998004">ବେଲାରୁସିଆନ୍</translation>
 <translation id="8336153091935557858">ଗତକାଲି <ph name="YESTERDAY_DAYTIME" /></translation>
 <translation id="8342318071240498787">ସମାନ ନାମ ଥିବା ଗୋଟିଏ ଫାଇଲ୍ କିମ୍ବା ଡିରେକ୍ଟୋରୀ ପୂର୍ବରୁ ବିଦ୍ୟମାନ ଅଛି।</translation>
+<translation id="8372852072747894550">ଗ୍ରୀକ୍</translation>
 <translation id="8382450452152102026"><ph name="FOLDER_NAME" /> କୁ</translation>
 <translation id="8395901698320285466">ପରିମେୟ ପରିସର</translation>
 <translation id="8437209419043462667">US</translation>
 <translation id="8456681095658380701">ଅବୈଧ ନାମ</translation>
+<translation id="8463494891489624050">ଭିଏତନାମିଜ୍ VIQR</translation>
 <translation id="8466234950814670489">ଟାର୍ ଆରକାଇଭ୍</translation>
 <translation id="8475647382427415476">Google ଡ୍ରାଇଭ୍ ଏହିକ୍ଷଣି "<ph name="FILENAME" />"କୁ ସିଙ୍କ କରିପାରିଲା ନାହିଁ। Google ଡ୍ରାଇଭ୍ ପୁଣି ପରେ ଚେଷ୍ଟା କରିବ।</translation>
 <translation id="8477649328507734757">ସ୍ପିନ୍‌</translation>
 <translation id="8487700953926739672">ଅଫ୍‍ଲାଇନ୍‌ରେ ଉପଲବ୍ଧ</translation>
 <translation id="8521441079177373948">UK</translation>
 <translation id="8525306231823319788">ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍‌</translation>
+<translation id="853494022971700746">ଫରାସୀ (ଫ୍ରାନ୍ସ)</translation>
+<translation id="8545476925160229291">ଇଂରାଜୀ (US)</translation>
+<translation id="8549186985808798022">ଇଟାଲୀୟ</translation>
 <translation id="8551494947769799688">ଲାଟଭିଆନ୍</translation>
+<translation id="8560515948038859357">କାଣ୍ଟୋନିଜ୍</translation>
 <translation id="8561206103590473338">ହାତୀ</translation>
 <translation id="8569764466147087991">ଖୋଲିବାକୁ ଏକ ଫାଇଲ୍‌ ଚୟନ କରନ୍ତୁ</translation>
+<translation id="8577897833047451336">କ୍ରୋଏସୀୟ</translation>
+<translation id="8578308463707544055">ଇନ୍ଦୋନେସୀୟ</translation>
 <translation id="8579285237314169903"><ph name="NUMBER_OF_FILES" />ଟି ଆଇଟମ୍‌ ସିଙ୍କ୍‌ ହେଉଛି...</translation>
 <translation id="8600173386174225982">ଫାଇଲ୍‌ ତାଲିକାକୁ ଥମ୍ବନେଲ୍ ଭ୍ୟୁରେ ପରିବର୍ତ୍ତନ କରାଯାଇଛି।</translation>
 <translation id="8601932370724196034">Crostini ଛବି ଫାଇଲ୍</translation>
+<translation id="8609695766746872526">ଆଇସଲାଣ୍ଡିକ୍</translation>
 <translation id="8669949407341943408">ଘୁଞ୍ଚୁଛି …</translation>
 <translation id="8698464937041809063">Google ଡ୍ରଇଂ</translation>
+<translation id="8713112442029511308">ମାଲଟିଜ୍</translation>
 <translation id="8714406895390098252">ସାଇକେଲ୍</translation>
 <translation id="8719721339511222681"><ph name="ENTRY_NAME" /> ବଛାଯାଇଛି।</translation>
 <translation id="872537912056138402">କ୍ରୋଏସିଆନ୍</translation>
 <translation id="8775404590947523323">ଆପଣ କରିଥିବା ଏଡିଟ୍‌ଗୁଡ଼ିକ ସ୍ୱଚାଳିତ ଭାବେ ସେଭ୍‌ କରାଯାଇଛି।<ph name="BREAKS" />ମୂଳ ଛବିର କପି ରଖିବାକୁ, "ଓଭର୍‌ରାଇଟ୍‍ ଓରିଜିନାଲ୍‌"କୁ ଅନ୍‌ଚେକ୍‌ କରନ୍ତୁ</translation>
 <translation id="8808686172382650546">କ୍ୟାଟ୍‌</translation>
 <translation id="8810671769985673465">ଜିପ୍ ହେବା ବିଫଳ ହେଲା, ଆଇଟମ୍ ବିଦ୍ୟମାନ ଅଛି: "<ph name="FILE_NAME" />"</translation>
+<translation id="8813284582615685103">ସ୍ପେନୀୟ (ସ୍ପେନ୍)</translation>
 <translation id="8834164572807951958">'<ph name="DESTINATION_NAME" />'ର ସଦସ୍ୟମାନେ ଏହି ଆଇଟମ୍‍ଗୁଡ଼ିକର କପିକୁ ଆକ୍ସେସ୍ ପାଇପାରିବେ।</translation>
+<translation id="8857149712089373752">ଫୋନେଟିକ୍ କୀବୋର୍ଡ ସହ ନେପାଳୀ</translation>
 <translation id="8860454412039442620">Excel ସ୍ପ୍ରେଡ୍‍ସିଟ୍</translation>
+<translation id="8866284467018526531">ଆରବିକ୍ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
 <translation id="8900820606136623064">ହଙ୍ଗେରୀଆନ୍</translation>
 <translation id="8919081441417203123">ଡାନିଶ୍</translation>
 <translation id="8965697826696209160">ଯଥେଷ୍ଟ ସ୍ଥାନ ଉପଲବ୍ଧ ନାହିଁ।</translation>
+<translation id="8997962250644902079">ଚାଇନିଜ୍ (ପାରମ୍ପାରିକ) ପିନୟିନ୍</translation>
 <translation id="9017798300203431059">ରସିଆନ୍ (ଫୋନେଟିକ୍)</translation>
 <translation id="9034924485347205037">Linux ଫାଇଲ୍‍ଗୁଡ଼ିକ</translation>
 <translation id="9035012421917565900">ଆଇଟମ୍‌କୁ <ph name="DESTINATION_NAME" />'କୁ ଫେରାଇ ନିଆଯାଇପାରିଲା ନାହିଁ, ତେଣୁ ଏହି କାର୍ଯ୍ୟକୁ ଆପଣ ପୂର୍ବବତ୍‍ କରିପାରିବେ ନାହିଁ।</translation>
 <translation id="9038620279323455325">"<ph name="FILE_NAME" />" ଫାଇଲ୍ ନାମ ପୂର୍ବରୁ ବିଦ୍ୟମାନ ଅଛି। ଏକ ଭିନ୍ନ ନାମ ବ୍ୟବହାର କରନ୍ତୁ।</translation>
 <translation id="9064939804718829769">ସ୍ଥାନାନ୍ତର ହେଉଛି…</translation>
 <translation id="9065203028668620118">ସମ୍ପାଦନ</translation>
+<translation id="908378762078012445">ଫୋନେଟିକ୍ AATSEEL କୀବୋର୍ଡ ସହ ଋଷୀୟ</translation>
 <translation id="9099674669267916096">ପୃଷ୍ଠା ସଂଖ୍ୟା</translation>
 <translation id="9110990317705400362">ଆପଣଙ୍କର ବ୍ରାଉଜର୍‌କୁ ସୁରକ୍ଷିତ କରିବାକୁ ଆମେ ନିରିବିଚ୍ଛିନ୍ନ ଭାବରେ ଉପାୟ ଖୋଜୁଛୁ। ପୂର୍ବରୁ, ଯେକୌଣସି ୱେବ୍‌ସାଇଟ୍‍ ଆପଣଙ୍କର ବ୍ରାଉଜର୍‌ରେ ଗୋଟିଏ ଏକ୍ସଟେନ୍‌ସନ୍‌ ଯୋଗ କରିବାକୁ ଆପଣଙ୍କୁ ସଙ୍କେତ ଦେଇଥିଲା। Google Chromeର ନବୀନତମ ସଂସ୍କରଣରେ, ଆପଣଙ୍କୁ ଏକ୍ସଟେନ୍‍ସନ୍‍ ପୃଷ୍ଠା ମାଧ୍ୟମରେ ଏହି ଏକ୍ସଟେନ୍‍ସନ୍‌କୁ ଯୋଗ କରି Chromeକୁ ସ୍ପଷ୍ଟ ଭାବରେ କହିବାକୁ ପଡ଼ିବ ଯେ ଆପଣ ଏହି ଏକ୍ସଟେନ୍‌ସନ୍‌‍ଗୁଡ଼ିକୁ ଇନ୍‍ଷ୍ଟଲ୍‍ କରିବାକୁ ଚାହୁଁଛନ୍ତି। <ph name="BEGIN_LINK" />ଅଧିକ ଜାଣନ୍ତୁ<ph name="END_LINK" /></translation>
 <translation id="9111102763498581341">ଅନ୍‌ଲକ୍ କରନ୍ତୁ</translation>
@@ -626,8 +760,12 @@
 <translation id="9131598836763251128">ଏକ କିମ୍ବା ଏକାଧିକ ଫାଇଲ୍‌ ଚିହ୍ନଟ କରନ୍ତୁ</translation>
 <translation id="9133055936679483811">ଜିପ୍ କରିବା ବିଫଳ ହୋଇଛି। <ph name="ERROR_MESSAGE" /></translation>
 <translation id="9134524245363717059">ଏହି ଫାଇଲ୍ Macintosh ସଫ୍ଟୱେର୍ ବ୍ୟବହାର କରି ଏକ କମ୍ପ୍ୟୁଟର୍ ପାଇଁ ଡିଜାଇନ୍ କରାଯାଇଛି। Chrome OS ଚାଲୁଥିବା ଆପଣଙ୍କର ଡିଭାଇସ୍‌ରେ ଏହା .ସୁସଙ୍ଗତ ନୁହେଁ। ଦୟାକରି ଗୋଟିଏ ଉପଯୁକ୍ତ ପ୍ରତିସ୍ଥାପନ ଆପ୍ Chrome ୱେବ୍ ଷ୍ଟୋର୍‌ରେ ସନ୍ଧାନ କରନ୍ତୁ।</translation>
+<translation id="9144340019284012223">କାଟାଲାନ୍</translation>
 <translation id="9148058034647219655">ପ୍ରସ୍ଥାନ କରନ୍ତୁ</translation>
 <translation id="9154418932169119429">ଏହି ଛବି ଅଫ୍‍ଲାଇନ୍‍‍ରେ ଉପଲବ୍ଧ ନାହିଁ।</translation>
+<translation id="9172592259078059678">ଗୁଜୁରାଟୀ ଟ୍ରାନ୍ସଲିଟ୍ରେସନ୍</translation>
+<translation id="9173120999827300720">ଆନ୍ତର୍ଜାତୀୟ କୀବୋର୍ଡ ସହ ଇଂରାଜୀ (US)</translation>
+<translation id="9189836632794948435">କାଜାଖ୍</translation>
 <translation id="9213073329713032541">ସଫଳତାପୂର୍ବକ ଇନ୍‌ଷ୍ଟଲେସନ୍ ଆରମ୍ଭ ହେଲା।</translation>
 <translation id="9219103736887031265">Images</translation>
 <translation id="9219908252191632183">ଲୁନାର୍</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_pa.xtb b/ui/chromeos/translations/ui_chromeos_strings_pa.xtb
index 5059a912..36cf6c9 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_pa.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_pa.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">ਚੀਨੀ ਜ਼ੂਯਿਨ</translation>
 <translation id="2843806747483486897">ਪੂਰਵ-ਨਿਰਧਾਰਤ ਬਦਲੋ...</translation>
 <translation id="2850124913210091882">ਬੈਕਅੱਪ ਲਓ</translation>
+<translation id="2873951654529031587">ਰੱਦੀ</translation>
 <translation id="288024221176729610">Czech</translation>
 <translation id="2887525882758501333">PDF ਦਸਤਾਵੇਜ਼</translation>
 <translation id="2888807692577297075">ਕੋਈ ਆਈਟਮਾਂ ਮੇਲ ਨਹੀਂ ਖਾਂਦੀਆਂ &lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt;</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sk.xtb b/ui/chromeos/translations/ui_chromeos_strings_sk.xtb
index 7bef0c94e..1cfb1fd 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sk.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sk.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">Čínska klávesnica Ču-jin</translation>
 <translation id="2843806747483486897">Zmeniť predvolenú akciu...</translation>
 <translation id="2850124913210091882">Zálohovať</translation>
+<translation id="2873951654529031587">Kôš</translation>
 <translation id="288024221176729610">Čeština</translation>
 <translation id="2887525882758501333">Dokument PDF</translation>
 <translation id="2888807692577297075">Dopytu  &lt;b&gt;„<ph name="SEARCH_STRING" />“&lt;/b&gt; nezodpovedajú žiadne položky</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sq.xtb b/ui/chromeos/translations/ui_chromeos_strings_sq.xtb
index 5f65963..4edab678 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sq.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sq.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">Kinezisht Zhuyin</translation>
 <translation id="2843806747483486897">Ndrysho parazgjedhjen...</translation>
 <translation id="2850124913210091882">Rezervimi</translation>
+<translation id="2873951654529031587">Koshi</translation>
 <translation id="288024221176729610">Çekisht</translation>
 <translation id="2887525882758501333">Dokument PDF</translation>
 <translation id="2888807692577297075">Asnjë artikull nuk përputhet me &lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt;</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sv.xtb b/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
index 80e7df4..c50b308 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">kinesiska (zhuyin)</translation>
 <translation id="2843806747483486897">Ändra standard ...</translation>
 <translation id="2850124913210091882">Säkerhetskopiera</translation>
+<translation id="2873951654529031587">Papperskorgen</translation>
 <translation id="288024221176729610">tjeckiska</translation>
 <translation id="2887525882758501333">PDF-dokument</translation>
 <translation id="2888807692577297075">Inga objekt matchar &lt;b&gt;<ph name="SEARCH_STRING" />&lt;/b&gt;</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sw.xtb b/ui/chromeos/translations/ui_chromeos_strings_sw.xtb
index 8c7294a6..105b753 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sw.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sw.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">Zhuyin ya Kichina</translation>
 <translation id="2843806747483486897">Badilisha chaguomsingi...</translation>
 <translation id="2850124913210091882">Hifadhi nakala</translation>
+<translation id="2873951654529031587">Tupio</translation>
 <translation id="288024221176729610">Kicheki</translation>
 <translation id="2887525882758501333">Hati ya PDF</translation>
 <translation id="2888807692577297075">Hakuna vipengee vinavyolingana &lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt;</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_tr.xtb b/ui/chromeos/translations/ui_chromeos_strings_tr.xtb
index c2768230..d310006f 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_tr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_tr.xtb
@@ -168,6 +168,7 @@
 <translation id="2830077785865012357">Çince Zhuyin</translation>
 <translation id="2843806747483486897">Varsayılanı değiştir...</translation>
 <translation id="2850124913210091882">Yedekle</translation>
+<translation id="2873951654529031587">Çöp Kutusu</translation>
 <translation id="288024221176729610">Çek dili</translation>
 <translation id="2887525882758501333">PDF dokümanı</translation>
 <translation id="2888807692577297075">&lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt; ile eşleşen öğe yok</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_uk.xtb b/ui/chromeos/translations/ui_chromeos_strings_uk.xtb
index ea901bb..9fba4f0 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_uk.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_uk.xtb
@@ -128,7 +128,7 @@
 <translation id="2377319039870049694">Список</translation>
 <translation id="2377590462528165447">Linux має доступ до стількох папок: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2378075407703503998">Вибрано файлів: <ph name="SELCTED_FILE_COUNT" /></translation>
-<translation id="2389832672041313158">Бірманська (М'янма)</translation>
+<translation id="2389832672041313158">Бірманська/м'янмська</translation>
 <translation id="240770291734945588">Доступно <ph name="SPACE_AVAILABLE" /></translation>
 <translation id="2425665904502185219">Загальний розмір файлу</translation>
 <translation id="2428749644083375155">Копіювання елементів (<ph name="NUMBER_OF_ITEMS" />) у папку "<ph name="FOLDER_NAME" />"</translation>
@@ -153,7 +153,7 @@
 <translation id="2638942478653899953">Диск Google недоступний. <ph name="BEGIN_LINK" />Вийдіть<ph name="END_LINK" /> і ввійдіть знову.</translation>
 <translation id="2649120831653069427">Золота рибка</translation>
 <translation id="2661146741306740526">16x9</translation>
-<translation id="2663066752008346276">Бірманська (М'янма), розкладка м'янсан</translation>
+<translation id="2663066752008346276">Бірманська/м'янмська, розкладка м'янсан</translation>
 <translation id="2664412712123763093">Місце розташування файлу</translation>
 <translation id="2672394958563893062">Сталася помилка. Натисніть, щоб знову запустити з початку.</translation>
 <translation id="2676946222714718093">Відтворюється на пристрої</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ur.xtb b/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
index f7c89015..c09ea0e 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
@@ -137,6 +137,7 @@
 <translation id="2787047795752739979">اصل کو اوور رائٹ کریں</translation>
 <translation id="2843806747483486897">ڈیفالٹ کو تبدیل کریں…</translation>
 <translation id="2850124913210091882">بیک اپ لیں</translation>
+<translation id="2873951654529031587">کوڑے دان</translation>
 <translation id="288024221176729610">چيک</translation>
 <translation id="2887525882758501333">‏PDF دستاویز</translation>
 <translation id="2888807692577297075">‏کوئی آئٹم &lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt; سے مماثل نہیں ہے</translation>
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 20134239..5f5eecd 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -1299,7 +1299,7 @@
   cc_layer_->RequestCopyOfOutput(std::move(request));
 }
 
-gfx::Rect Layer::PaintableRegion() {
+gfx::Rect Layer::PaintableRegion() const {
   return gfx::Rect(size());
 }
 
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index 62d5959a6..f2a863d 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -440,7 +440,7 @@
   void SetScrollOffset(const gfx::ScrollOffset& offset);
 
   // ContentLayerClient implementation.
-  gfx::Rect PaintableRegion() override;
+  gfx::Rect PaintableRegion() const override;
   scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() override;
   bool FillsBoundsCompletely() const override;
 
diff --git a/ui/display/manager/configure_displays_task.cc b/ui/display/manager/configure_displays_task.cc
index c9561cb..7c3dd61 100644
--- a/ui/display/manager/configure_displays_task.cc
+++ b/ui/display/manager/configure_displays_task.cc
@@ -93,6 +93,71 @@
                  });
 }
 
+void UpdateResolutionAndRefreshRateUma(const DisplayConfigureRequest& request) {
+  const bool internal =
+      request.display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
+
+  base::UmaHistogramExactLinear(
+      internal ? "ConfigureDisplays.Internal.Modeset.Resolution"
+               : "ConfigureDisplays.External.Modeset.Resolution",
+      ComputeDisplayResolutionEnum(request.mode),
+      base::size(kDisplayResolutionSamples) *
+              base::size(kDisplayResolutionSamples) +
+          2);
+
+  base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
+      internal ? "ConfigureDisplays.Internal.Modeset.RefreshRate"
+               : "ConfigureDisplays.External.Modeset.RefreshRate",
+      1, 240, 18, base::HistogramBase::kUmaTargetedHistogramFlag);
+  histogram->Add(request.mode ? std::round(request.mode->refresh_rate()) : 0);
+}
+
+void UpdateAttemptSucceededUma(DisplaySnapshot* display, bool display_success) {
+  const bool internal = display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
+  base::UmaHistogramBoolean(
+      internal ? "ConfigureDisplays.Internal.Modeset.AttemptSucceeded"
+               : "ConfigureDisplays.External.Modeset.AttemptSucceeded",
+      display_success);
+}
+
+void UpdateFinalStatusUma(const std::vector<DisplayConfigureRequest>& requests,
+                          bool config_success) {
+  int mst_external_displays = 0;
+  size_t total_external_displays = requests.size();
+  for (auto& request : requests) {
+    // Is this display SST (single-stream vs. MST multi-stream).
+    bool sst_display = request.display->base_connector_id() &&
+                       request.display->path_topology().empty();
+    if (!sst_display)
+      mst_external_displays++;
+
+    bool internal = request.display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
+    if (internal)
+      total_external_displays--;
+
+    base::UmaHistogramBoolean(
+        internal ? "ConfigureDisplays.Internal.Modeset.FinalStatus"
+                 : "ConfigureDisplays.External.Modeset.FinalStatus",
+        config_success);
+  }
+
+  base::UmaHistogramExactLinear(
+      "ConfigureDisplays.Modeset.TotalExternalDisplaysCount",
+      base::checked_cast<int>(total_external_displays), kMaxDisplaysCount);
+
+  base::UmaHistogramExactLinear(
+      "ConfigureDisplays.Modeset.MstExternalDisplaysCount",
+      mst_external_displays, kMaxDisplaysCount);
+
+  if (total_external_displays > 0) {
+    const int mst_displays_percentage =
+        100.0 * mst_external_displays / total_external_displays;
+    UMA_HISTOGRAM_PERCENTAGE(
+        "ConfigureDisplays.Modeset.MstExternalDisplaysPercentage",
+        mst_displays_percentage);
+  }
+}
+
 }  // namespace
 
 DisplayConfigureRequest::DisplayConfigureRequest(DisplaySnapshot* display,
@@ -123,20 +188,7 @@
     config_requests.emplace_back(request.display->display_id(), request.origin,
                                  request.mode);
 
-    const bool internal =
-        request.display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
-    base::UmaHistogramExactLinear(
-        internal ? "ConfigureDisplays.Internal.Modeset.Resolution"
-                 : "ConfigureDisplays.External.Modeset.Resolution",
-        ComputeDisplayResolutionEnum(request.mode),
-        base::size(kDisplayResolutionSamples) *
-                base::size(kDisplayResolutionSamples) +
-            2);
-    base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
-        internal ? "ConfigureDisplays.Internal.Modeset.RefreshRate"
-                 : "ConfigureDisplays.External.Modeset.RefreshRate",
-        1, 240, 18, base::HistogramBase::kUmaTargetedHistogramFlag);
-    histogram->Add(request.mode ? std::round(request.mode->refresh_rate()) : 0);
+    UpdateResolutionAndRefreshRateUma(request);
   }
 
   delegate_->Configure(config_requests,
@@ -170,12 +222,7 @@
             << " origin=" << request->origin.ToString()
             << " mode=" << (request->mode ? request->mode->ToString() : "null");
 
-    bool internal =
-        request->display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
-    base::UmaHistogramBoolean(
-        internal ? "ConfigureDisplays.Internal.Modeset.AttemptSucceeded"
-                 : "ConfigureDisplays.External.Modeset.AttemptSucceeded",
-        display_success);
+    UpdateAttemptSucceededUma(request->display, display_success);
   }
 
   // Update displays upon success or prep |requests_| for reconfiguration.
@@ -210,40 +257,7 @@
   }
 
   // Update the final state.
-  int mst_external_displays = 0;
-  size_t total_external_displays = requests_.size();
-  for (auto& request : requests_) {
-    // Is this display SST (single-stream vs. MST multi-stream).
-    bool sst_display = request.display->base_connector_id() &&
-                       request.display->path_topology().empty();
-    if (!sst_display)
-      mst_external_displays++;
-
-    bool internal = request.display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
-    if (internal)
-      total_external_displays--;
-
-    base::UmaHistogramBoolean(
-        internal ? "ConfigureDisplays.Internal.Modeset.FinalStatus"
-                 : "ConfigureDisplays.External.Modeset.FinalStatus",
-        config_success);
-  }
-
-  base::UmaHistogramExactLinear(
-      "ConfigureDisplays.Modeset.TotalExternalDisplaysCount",
-      base::checked_cast<int>(total_external_displays), kMaxDisplaysCount);
-
-  base::UmaHistogramExactLinear(
-      "ConfigureDisplays.Modeset.MstExternalDisplaysCount",
-      mst_external_displays, kMaxDisplaysCount);
-
-  if (total_external_displays > 0) {
-    const int mst_displays_percentage =
-        100.0 * mst_external_displays / total_external_displays;
-    UMA_HISTOGRAM_PERCENTAGE(
-        "ConfigureDisplays.Modeset.MstExternalDisplaysPercentage",
-        mst_displays_percentage);
-  }
+  UpdateFinalStatusUma(requests_, config_success);
 
   if (!config_success)
     task_status_ = ERROR;
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index aa3feff..43c4d6c 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -760,6 +760,7 @@
       "geometry/quad_unittest.cc",
       "geometry/quaternion_unittest.cc",
       "geometry/rect_unittest.cc",
+      "geometry/resize_utils_unittest.cc",
       "geometry/rounded_corners_f_unittest.cc",
       "geometry/scroll_offset_unittest.cc",
       "geometry/size_unittest.cc",
diff --git a/ui/gfx/geometry/BUILD.gn b/ui/gfx/geometry/BUILD.gn
index f4e4a7d..3f83f70 100644
--- a/ui/gfx/geometry/BUILD.gn
+++ b/ui/gfx/geometry/BUILD.gn
@@ -41,6 +41,8 @@
     "rect_conversions.h",
     "rect_f.cc",
     "rect_f.h",
+    "resize_utils.cc",
+    "resize_utils.h",
     "rounded_corners_f.cc",
     "rounded_corners_f.h",
     "scroll_offset.cc",
diff --git a/ui/views/window/window_resize_utils.cc b/ui/gfx/geometry/resize_utils.cc
similarity index 68%
rename from ui/views/window/window_resize_utils.cc
rename to ui/gfx/geometry/resize_utils.cc
index 5578e3ac..cde1838 100644
--- a/ui/views/window/window_resize_utils.cc
+++ b/ui/gfx/geometry/resize_utils.cc
@@ -1,8 +1,8 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/views/window/window_resize_utils.h"
+#include "ui/gfx/geometry/resize_utils.h"
 
 #include <algorithm>
 
@@ -10,12 +10,11 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
-namespace views {
+namespace gfx {
 
-// static
-void WindowResizeUtils::SizeMinMaxToAspectRatio(float aspect_ratio,
-                                                gfx::Size* min_window_size,
-                                                gfx::Size* max_window_size) {
+void SizeMinMaxToAspectRatio(float aspect_ratio,
+                             Size* min_window_size,
+                             Size* max_window_size) {
   DCHECK_GT(aspect_ratio, 0.0f);
 
   // Calculate the height using the min-width and aspect ratio.
@@ -42,21 +41,20 @@
   DCHECK_GE(max_window_size->height(), min_window_size->height());
 }
 
-// static
-void WindowResizeUtils::SizeRectToAspectRatio(HitTest param,
-                                              float aspect_ratio,
-                                              const gfx::Size& min_window_size,
-                                              const gfx::Size& max_window_size,
-                                              gfx::Rect* rect) {
+void SizeRectToAspectRatio(ResizeEdge resize_edge,
+                           float aspect_ratio,
+                           const Size& min_window_size,
+                           const Size& max_window_size,
+                           Rect* rect) {
   DCHECK_GT(aspect_ratio, 0.0f);
   DCHECK_GE(max_window_size.width(), min_window_size.width());
   DCHECK_GE(max_window_size.height(), min_window_size.height());
 
   float rect_width = 0.0;
   float rect_height = 0.0;
-  if (param == HitTest::kLeft || param == HitTest::kRight ||
-      param == HitTest::kTopLeft ||
-      param == HitTest::kBottomLeft) { /* horizontal axis to pivot */
+  if (resize_edge == ResizeEdge::kLeft || resize_edge == ResizeEdge::kRight ||
+      resize_edge == ResizeEdge::kTopLeft ||
+      resize_edge == ResizeEdge::kBottomLeft) { /* horizontal axis to pivot */
     rect_width = std::min(max_window_size.width(),
                           std::max(rect->width(), min_window_size.width()));
     rect_height = rect_width / aspect_ratio;
@@ -72,30 +70,30 @@
   int right = rect->right();
   int bottom = rect->bottom();
 
-  switch (param) {
-    case HitTest::kRight:
-    case HitTest::kBottom:
+  switch (resize_edge) {
+    case ResizeEdge::kRight:
+    case ResizeEdge::kBottom:
       right = rect_width + left;
       bottom = top + rect_height;
       break;
-    case HitTest::kTop:
+    case ResizeEdge::kTop:
       right = rect_width + left;
       top = bottom - rect_height;
       break;
-    case HitTest::kLeft:
-    case HitTest::kTopLeft:
+    case ResizeEdge::kLeft:
+    case ResizeEdge::kTopLeft:
       left = right - rect_width;
       top = bottom - rect_height;
       break;
-    case HitTest::kTopRight:
+    case ResizeEdge::kTopRight:
       right = left + rect_width;
       top = bottom - rect_height;
       break;
-    case HitTest::kBottomLeft:
+    case ResizeEdge::kBottomLeft:
       left = right - rect_width;
       bottom = top + rect_height;
       break;
-    case HitTest::kBottomRight:
+    case ResizeEdge::kBottomRight:
       right = left + rect_width;
       bottom = top + rect_height;
       break;
@@ -104,4 +102,4 @@
   rect->SetByBounds(left, top, right, bottom);
 }
 
-}  // namespace views
+}  // namespace gfx
diff --git a/ui/gfx/geometry/resize_utils.h b/ui/gfx/geometry/resize_utils.h
new file mode 100644
index 0000000..44d697a
--- /dev/null
+++ b/ui/gfx/geometry/resize_utils.h
@@ -0,0 +1,47 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_GEOMETRY_RESIZE_UTILS_H_
+#define UI_GFX_GEOMETRY_RESIZE_UTILS_H_
+
+#include "ui/gfx/geometry/geometry_export.h"
+
+namespace gfx {
+
+class Rect;
+class Size;
+
+enum class ResizeEdge {
+  kBottom,
+  kBottomLeft,
+  kBottomRight,
+  kLeft,
+  kRight,
+  kTop,
+  kTopLeft,
+  kTopRight
+};
+
+// Force the min and max window sizes to adhere to the aspect ratio.
+// |aspect_ratio| must be valid and is found using width / height.
+void GEOMETRY_EXPORT SizeMinMaxToAspectRatio(float aspect_ratio,
+                                             Size* min_window_size,
+                                             Size* max_window_size);
+
+// Updates |rect| to adhere to the |aspect_ratio| of the window, if it has
+// been set. |resize_edge| refers to the edge of the window being sized.
+// |min_window_size| and |max_window_size| are expected to adhere to the
+// given aspect ratio.
+// |aspect_ratio| must be valid and is found using width / height.
+// TODO(apacible): |max_window_size| is expected to be non-empty. Handle
+// unconstrained max sizes and sizing when windows are maximized.
+void GEOMETRY_EXPORT SizeRectToAspectRatio(ResizeEdge resize_edge,
+                                           float aspect_ratio,
+                                           const Size& min_window_size,
+                                           const Size& max_window_size,
+                                           Rect* rect);
+
+}  // namespace gfx
+
+#endif  // UI_GFX_GEOMETRY_RESIZE_UTILS_H_
diff --git a/ui/gfx/geometry/resize_utils_unittest.cc b/ui/gfx/geometry/resize_utils_unittest.cc
new file mode 100644
index 0000000..6f669f8
--- /dev/null
+++ b/ui/gfx/geometry/resize_utils_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/geometry/resize_utils.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace gfx {
+namespace {
+
+// Aspect ratio is defined by width / height.
+constexpr float kAspectRatioSquare = 1.0f;
+constexpr float kAspectRatioHorizontal = 2.0f;
+constexpr float kAspectRatioVertical = 0.5f;
+
+const Size kMinSizeSquare = Size(10, 10);
+const Size kMaxSizeSquare = Size(50, 50);
+
+const Size kMinSizeHorizontal = Size(20, 10);
+const Size kMaxSizeHorizontal = Size(50, 25);
+
+const Size kMinSizeVertical = Size(10, 20);
+const Size kMaxSizeVertical = Size(25, 50);
+
+}  // namespace
+
+// Tests resizing of window with a 1:1 aspect ratio. This test also tests the
+// 'pivot points' when resizing, i.e. the opposite side or corner of the
+// window.
+TEST(WindowResizeUtilsTest, SizeToSquareAspectRatio) {
+  // Size from the top of the window.
+  // |window_rect| within the bounds of kMinSizeSquare and kMaxSizeSquare.
+  Rect window_rect(100, 100, 15, 15);
+  SizeRectToAspectRatio(ResizeEdge::kTop, kAspectRatioSquare, kMinSizeSquare,
+                        kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect, Rect(100, 100, 15, 15));
+
+  // Size from the bottom right corner of the window.
+  // |window_rect| smaller than kMinSizeSquare.
+  window_rect.SetRect(100, 100, 5, 5);
+  SizeRectToAspectRatio(ResizeEdge::kBottomRight, kAspectRatioSquare,
+                        kMinSizeSquare, kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect,
+            Rect(100, 100, kMinSizeSquare.width(), kMinSizeSquare.height()));
+
+  // Size from the top of the window.
+  // |window_rect| larger than kMaxSizeSquare.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kTop, kAspectRatioSquare, kMinSizeSquare,
+                        kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect,
+            Rect(100, 150, kMaxSizeSquare.width(), kMaxSizeSquare.height()));
+
+  // Size from the bottom of the window.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kBottom, kAspectRatioSquare, kMinSizeSquare,
+                        kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect,
+            Rect(100, 100, kMaxSizeSquare.width(), kMaxSizeSquare.height()));
+
+  // Size from the left of the window.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kLeft, kAspectRatioSquare, kMinSizeSquare,
+                        kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect,
+            Rect(150, 150, kMaxSizeSquare.width(), kMaxSizeSquare.height()));
+
+  // Size from the right of the window.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kRight, kAspectRatioSquare, kMinSizeSquare,
+                        kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect,
+            Rect(100, 100, kMaxSizeSquare.width(), kMaxSizeSquare.height()));
+
+  // Size from the top left corner of the window.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kTopLeft, kAspectRatioSquare,
+                        kMinSizeSquare, kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect,
+            Rect(150, 150, kMaxSizeSquare.width(), kMaxSizeSquare.height()));
+
+  // Size from the top right corner of the window.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kTopRight, kAspectRatioSquare,
+                        kMinSizeSquare, kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect,
+            Rect(100, 150, kMaxSizeSquare.width(), kMaxSizeSquare.height()));
+
+  // Size from the bottom left corner of the window.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kBottomLeft, kAspectRatioSquare,
+                        kMinSizeSquare, kMaxSizeSquare, &window_rect);
+  EXPECT_EQ(window_rect,
+            Rect(150, 100, kMaxSizeSquare.width(), kMaxSizeSquare.height()));
+}
+
+// Tests the aspect ratio of the Rect adheres to the horizontal aspect
+// ratio.
+TEST(WindowResizeUtilsTest, SizeToHorizontalAspectRatio) {
+  // |window_rect| within bounds of kMinSizeHorizontal and kMaxSizeHorizontal.
+  Rect window_rect(100, 100, 20, 10);
+  SizeRectToAspectRatio(ResizeEdge::kTop, kAspectRatioHorizontal,
+                        kMinSizeHorizontal, kMaxSizeHorizontal, &window_rect);
+  EXPECT_EQ(window_rect, Rect(100, 100, 20, 10));
+
+  // |window_rect| smaller than kMinSizeHorizontal.
+  window_rect.SetRect(100, 100, 5, 5);
+  SizeRectToAspectRatio(ResizeEdge::kBottomRight, kAspectRatioHorizontal,
+                        kMinSizeHorizontal, kMaxSizeHorizontal, &window_rect);
+  EXPECT_EQ(window_rect, Rect(100, 100, kMinSizeHorizontal.width(),
+                              kMinSizeHorizontal.height()));
+
+  // |window_rect| greater than kMaxSizeHorizontal.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kTop, kAspectRatioHorizontal,
+                        kMinSizeHorizontal, kMaxSizeHorizontal, &window_rect);
+  EXPECT_EQ(window_rect, Rect(100, 175, kMaxSizeHorizontal.width(),
+                              kMaxSizeHorizontal.height()));
+}
+
+// Tests the aspect ratio of the Rect adheres to the vertical aspect ratio.
+TEST(WindowResizeUtilsTest, SizeToVerticalAspectRatio) {
+  // |window_rect| within bounds of kMinSizeVertical and kMaxSizeVertical.
+  Rect window_rect(100, 100, 10, 20);
+  SizeRectToAspectRatio(ResizeEdge::kBottomRight, kAspectRatioVertical,
+                        kMinSizeVertical, kMaxSizeVertical, &window_rect);
+  EXPECT_EQ(window_rect, Rect(100, 100, 10, 20));
+
+  // |window_rect| smaller than kMinSizeVertical.
+  window_rect.SetRect(100, 100, 5, 5);
+  SizeRectToAspectRatio(ResizeEdge::kBottomRight, kAspectRatioVertical,
+                        kMinSizeVertical, kMaxSizeVertical, &window_rect);
+  EXPECT_EQ(window_rect, Rect(100, 100, kMinSizeVertical.width(),
+                              kMinSizeVertical.height()));
+
+  // |window_rect| greater than kMaxSizeVertical.
+  window_rect.SetRect(100, 100, 100, 100);
+  SizeRectToAspectRatio(ResizeEdge::kBottomRight, kAspectRatioVertical,
+                        kMinSizeVertical, kMaxSizeVertical, &window_rect);
+  EXPECT_EQ(window_rect, Rect(100, 100, kMaxSizeVertical.width(),
+                              kMaxSizeVertical.height()));
+}
+
+}  // namespace gfx
diff --git a/ui/ozone/platform/wayland/host/wayland_surface.h b/ui/ozone/platform/wayland/host/wayland_surface.h
index 15fc91a5..55ed7727 100644
--- a/ui/ozone/platform/wayland/host/wayland_surface.h
+++ b/ui/ozone/platform/wayland/host/wayland_surface.h
@@ -75,8 +75,9 @@
 
   // Sets the region that is opaque on this surface in physical pixels. This is
   // expected to be called whenever the region that the surface span changes or
-  // the opacity changes.
-  void SetOpaqueRegion(const gfx::Rect& bounds_px);
+  // the opacity changes. |region_px| is specified surface-local, in physical
+  // pixels.
+  void SetOpaqueRegion(const gfx::Rect& region_px);
 
   // Set the source rectangle of the associated wl_surface.
   // See:
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc
index aeb12a5f..618d1b4d 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -15,6 +15,7 @@
 #include "ui/events/ozone/events_ozone.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/size.h"
 #include "ui/ozone/common/features.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
@@ -148,7 +149,7 @@
     return;
   bounds_px_ = bounds_px;
 
-  root_surface_->SetOpaqueRegion(bounds_px);
+  root_surface_->SetOpaqueRegion(gfx::Rect(bounds_px_.size()));
   delegate_->OnBoundsChanged(bounds_px_);
 }
 
@@ -403,7 +404,7 @@
 
   // Will do nothing for menus because they have got their scale above.
   UpdateBufferScale(false);
-  root_surface_->SetOpaqueRegion(bounds_px_);
+  root_surface_->SetOpaqueRegion(gfx::Rect(bounds_px_.size()));
 
   return true;
 }
diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
index 25ab1911..07e8515 100644
--- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -1593,6 +1593,7 @@
   Sync();
 
   VerifyAndClearExpectations();
+  EXPECT_EQ(mock_surface->opaque_region(), new_bounds);
 
   new_bounds.set_size(gfx::Size(1000, 534));
   SendConfigureEvent(xdg_surface_, new_bounds.width(), new_bounds.height(), 2,
@@ -1604,6 +1605,7 @@
   Sync();
 
   VerifyAndClearExpectations();
+  EXPECT_EQ(mock_surface->opaque_region(), new_bounds);
 }
 
 TEST_P(WaylandWindowTest, OnCloseRequest) {
@@ -1647,6 +1649,8 @@
 
   EXPECT_EQ(test_subsurface->position(), subsurface_bounds.origin());
   EXPECT_FALSE(test_subsurface->sync());
+  EXPECT_EQ(mock_surface_subsurface->opaque_region(),
+            gfx::Rect(subsurface_bounds.size()));
 
   auto* parent_resource =
       server_
@@ -1876,6 +1880,8 @@
   auto new_origin = subsurface_bounds.origin() -
                     menu_window_bounds.origin().OffsetFromOrigin();
   EXPECT_EQ(test_subsurface->position(), new_origin);
+  EXPECT_EQ(mock_surface_subsurface->opaque_region(),
+            gfx::Rect(subsurface_bounds.size()));
 
   menu_window->SetPointerFocus(false);
 }
diff --git a/ui/ozone/platform/wayland/test/mock_surface.cc b/ui/ozone/platform/wayland/test/mock_surface.cc
index d7ec1ec..f2039e5 100644
--- a/ui/ozone/platform/wayland/test/mock_surface.cc
+++ b/ui/ozone/platform/wayland/test/mock_surface.cc
@@ -4,6 +4,8 @@
 
 #include "ui/ozone/platform/wayland/test/mock_surface.h"
 
+#include "ui/ozone/platform/wayland/test/test_region.h"
+
 namespace wl {
 
 namespace {
@@ -20,7 +22,7 @@
 void SetOpaqueRegion(wl_client* client,
                      wl_resource* resource,
                      wl_resource* region) {
-  GetUserDataAs<MockSurface>(resource)->SetOpaqueRegion(region);
+  GetUserDataAs<MockSurface>(resource)->SetOpaqueRegionImpl(region);
 }
 
 void SetInputRegion(wl_client* client,
@@ -100,6 +102,15 @@
   return GetUserDataAs<MockSurface>(resource);
 }
 
+void MockSurface::SetOpaqueRegionImpl(wl_resource* region) {
+  auto bounds = GetUserDataAs<TestRegion>(region)->getBounds();
+  opaque_region_ =
+      gfx::Rect(bounds.fLeft, bounds.fTop, bounds.fRight - bounds.fLeft,
+                bounds.fBottom - bounds.fTop);
+
+  SetOpaqueRegion(region);
+}
+
 void MockSurface::AttachNewBuffer(wl_resource* buffer_resource,
                                   int32_t x,
                                   int32_t y) {
diff --git a/ui/ozone/platform/wayland/test/mock_surface.h b/ui/ozone/platform/wayland/test/mock_surface.h
index 5c4e5cf..0901319 100644
--- a/ui/ozone/platform/wayland/test/mock_surface.h
+++ b/ui/ozone/platform/wayland/test/mock_surface.h
@@ -56,6 +56,8 @@
   void set_viewport(TestViewport* viewport) { viewport_ = viewport; }
   TestViewport* viewport() { return viewport_; }
 
+  gfx::Rect opaque_region() const { return opaque_region_; }
+
   void set_frame_callback(wl_resource* callback_resource) {
     DCHECK(!frame_callback_);
     frame_callback_ = callback_resource;
@@ -66,6 +68,7 @@
 
   bool has_role() const { return !!xdg_surface_ || !!sub_surface_; }
 
+  void SetOpaqueRegionImpl(wl_resource* region);
   void AttachNewBuffer(wl_resource* buffer_resource, int32_t x, int32_t y);
   void DestroyPrevAttachedBuffer();
   void ReleaseBuffer(wl_resource* buffer);
@@ -75,6 +78,7 @@
   MockXdgSurface* xdg_surface_ = nullptr;
   TestSubSurface* sub_surface_ = nullptr;
   TestViewport* viewport_ = nullptr;
+  gfx::Rect opaque_region_ = {-1, -1, 0, 0};
 
   wl_resource* frame_callback_ = nullptr;
 
diff --git a/ui/strings/translations/ui_strings_or.xtb b/ui/strings/translations/ui_strings_or.xtb
index 97720b6e..e906097c 100644
--- a/ui/strings/translations/ui_strings_or.xtb
+++ b/ui/strings/translations/ui_strings_or.xtb
@@ -94,6 +94,7 @@
 <translation id="3306688585798492231">ବିଲ୍ଟ-ଇନ୍ ଡିସପ୍ଲେ</translation>
 <translation id="335581015389089642">ସ୍ପୀଚ୍‌</translation>
 <translation id="3389286852084373014">ଟେକ୍ସଟ୍ ବହୁତ ଲମ୍ବା ଅଟେ</translation>
+<translation id="3406306243914553062">HTML ବିଷୟବସ୍ତୁ</translation>
 <translation id="348799646910989694">ସେଲ୍ପ ସ୍ୱଚାଳିତ ରୂପେ ଲୁଚାଯାଇଛି</translation>
 <translation id="3554637740840164787"><ph name="ITEM_TITLE" /> ପିନ୍ କରାଯାଇଥିଲା</translation>
 <translation id="3600566671520689681">{DAYS,plural, =1{1 ଦିନ ବାକି ଅଛି}other{# ଦିନ ବାକି ଅଛି}}</translation>
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 8e0f7d3..3529a77 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -274,7 +274,6 @@
     "window/native_frame_view.h",
     "window/non_client_view.h",
     "window/window_button_order_provider.h",
-    "window/window_resize_utils.h",
     "window/window_resources.h",
     "window/window_shape.h",
     "word_lookup_client.h",
@@ -460,7 +459,6 @@
     "window/native_frame_view.cc",
     "window/non_client_view.cc",
     "window/window_button_order_provider.cc",
-    "window/window_resize_utils.cc",
     "window/window_shape.cc",
   ]
 
@@ -1153,7 +1151,6 @@
     "window/frame_caption_button_unittest.cc",
     "window/hit_test_utils_unittest.cc",
     "window/non_client_view_unittest.cc",
-    "window/window_resize_utils_unittest.cc",
   ]
 
   configs += [ "//build/config:precompiled_headers" ]
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm
index 41ef0a06..7a9ea8e 100644
--- a/ui/views/widget/native_widget_mac_unittest.mm
+++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -18,6 +18,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
 #import "components/remote_cocoa/app_shim/bridged_content_view.h"
 #import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
 #import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
@@ -1244,7 +1245,13 @@
 }
 
 // Tests behavior of window-modal dialogs, displayed as sheets.
-TEST_F(NativeWidgetMacTest, WindowModalSheet) {
+#if defined(ARCH_CPU_ARM64)
+// Bulk-disabled as part of arm64 bot stabilization: https://crbug.com/1154345
+#define MAYBE_WindowModalSheet DISABLED_WindowModalSheet
+#else
+#define MAYBE_WindowModalSheet WindowModalSheet
+#endif
+TEST_F(NativeWidgetMacTest, MAYBE_WindowModalSheet) {
   NSWindow* native_parent = MakeClosableTitledNativeParent();
 
   Widget* sheet_widget = views::DialogDelegate::CreateDialogWidget(
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 5e202ca..46f2701 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -55,6 +55,7 @@
 #include "ui/events/win/system_event_state_lookup.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/resize_utils.h"
 #include "ui/gfx/icon_util.h"
 #include "ui/gfx/path_win.h"
 #include "ui/gfx/win/hwnd_util.h"
@@ -255,28 +256,28 @@
          hittest == HTBOTTOMLEFT || hittest == HTBOTTOMRIGHT;
 }
 
-// Convert |param| to the HitTest used in WindowResizeUtils.
-HitTest GetWindowResizeHitTest(UINT param) {
+// Convert |param| to the gfx::ResizeEdge used in gfx::SizeRectToAspectRatio().
+gfx::ResizeEdge GetWindowResizeEdge(UINT param) {
   switch (param) {
     case WMSZ_BOTTOM:
-      return HitTest::kBottom;
+      return gfx::ResizeEdge::kBottom;
     case WMSZ_TOP:
-      return HitTest::kTop;
+      return gfx::ResizeEdge::kTop;
     case WMSZ_LEFT:
-      return HitTest::kLeft;
+      return gfx::ResizeEdge::kLeft;
     case WMSZ_RIGHT:
-      return HitTest::kRight;
+      return gfx::ResizeEdge::kRight;
     case WMSZ_TOPLEFT:
-      return HitTest::kTopLeft;
+      return gfx::ResizeEdge::kTopLeft;
     case WMSZ_TOPRIGHT:
-      return HitTest::kTopRight;
+      return gfx::ResizeEdge::kTopRight;
     case WMSZ_BOTTOMLEFT:
-      return HitTest::kBottomLeft;
+      return gfx::ResizeEdge::kBottomLeft;
     case WMSZ_BOTTOMRIGHT:
-      return HitTest::kBottomRight;
+      return gfx::ResizeEdge::kBottomRight;
     default:
       NOTREACHED();
-      return HitTest::kBottomRight;
+      return gfx::ResizeEdge::kBottomRight;
   }
 }
 
@@ -3540,13 +3541,12 @@
   gfx::Size min_window_size;
   gfx::Size max_window_size;
   delegate_->GetMinMaxSize(&min_window_size, &max_window_size);
-  WindowResizeUtils::SizeMinMaxToAspectRatio(
-      aspect_ratio_.value(), &min_window_size, &max_window_size);
+  gfx::SizeMinMaxToAspectRatio(aspect_ratio_.value(), &min_window_size,
+                               &max_window_size);
   min_window_size = delegate_->DIPToScreenSize(min_window_size);
   max_window_size = delegate_->DIPToScreenSize(max_window_size);
-  WindowResizeUtils::SizeRectToAspectRatio(
-      GetWindowResizeHitTest(param), aspect_ratio_.value(), min_window_size,
-      max_window_size, window_rect);
+  gfx::SizeRectToAspectRatio(GetWindowResizeEdge(param), aspect_ratio_.value(),
+                             min_window_size, max_window_size, window_rect);
 }
 
 POINT HWNDMessageHandler::GetCursorPos() const {
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h
index 5e5845b..2f5eefa 100644
--- a/ui/views/win/hwnd_message_handler.h
+++ b/ui/views/win/hwnd_message_handler.h
@@ -36,7 +36,6 @@
 #include "ui/views/views_export.h"
 #include "ui/views/win/pen_event_processor.h"
 #include "ui/views/win/scoped_enable_unadjusted_mouse_events_win.h"
-#include "ui/views/window/window_resize_utils.h"
 
 namespace gfx {
 class ImageSkia;
diff --git a/ui/views/window/window_resize_utils.h b/ui/views/window/window_resize_utils.h
deleted file mode 100644
index 77d3b162..0000000
--- a/ui/views/window/window_resize_utils.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WINDOW_WINDOW_RESIZE_UTILS_H_
-#define UI_VIEWS_WINDOW_WINDOW_RESIZE_UTILS_H_
-
-#include "base/macros.h"
-#include "ui/views/views_export.h"
-
-namespace gfx {
-class Size;
-class Rect;
-}  // namespace gfx
-
-namespace views {
-
-enum class HitTest {
-  kBottom,
-  kBottomLeft,
-  kBottomRight,
-  kLeft,
-  kRight,
-  kTop,
-  kTopLeft,
-  kTopRight
-};
-
-class VIEWS_EXPORT WindowResizeUtils {
- public:
-  // Force the min and max window sizes to adhere to the aspect ratio.
-  // |aspect_ratio| must be valid and is found using width / height.
-  static void SizeMinMaxToAspectRatio(float aspect_ratio,
-                                      gfx::Size* min_window_size,
-                                      gfx::Size* max_window_size);
-
-  // Updates |rect| to adhere to the |aspect_ratio| of the window, if it has
-  // been set. |param| refers to the edge of the window being sized.
-  // |min_window_size| and |max_window_size| are expected to adhere to the
-  // given aspect ratio.
-  // |aspect_ratio| must be valid and is found using width / height.
-  // TODO(apacible): |max_window_size| is expected to be non-empty. Handle
-  // unconstrained max sizes and sizing when windows are maximized.
-  static void SizeRectToAspectRatio(HitTest param,
-                                    float aspect_ratio,
-                                    const gfx::Size& min_window_size,
-                                    const gfx::Size& max_window_size,
-                                    gfx::Rect* rect);
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(WindowResizeUtils);
-};
-
-}  // namespace views
-
-#endif  // UI_VIEWS_WINDOW_WINDOW_RESIZE_UTILS_H_
diff --git a/ui/views/window/window_resize_utils_unittest.cc b/ui/views/window/window_resize_utils_unittest.cc
deleted file mode 100644
index 4b5ba7f8..0000000
--- a/ui/views/window/window_resize_utils_unittest.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/window/window_resize_utils.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace views {
-
-namespace {
-// Aspect ratio is defined by width / height.
-constexpr float kAspectRatioSquare = 1.0f;
-constexpr float kAspectRatioHorizontal = 2.0f;
-constexpr float kAspectRatioVertical = 0.5f;
-
-const gfx::Size kMinSizeSquare = gfx::Size(10, 10);
-const gfx::Size kMaxSizeSquare = gfx::Size(50, 50);
-
-const gfx::Size kMinSizeHorizontal = gfx::Size(20, 10);
-const gfx::Size kMaxSizeHorizontal = gfx::Size(50, 25);
-
-const gfx::Size kMinSizeVertical = gfx::Size(10, 20);
-const gfx::Size kMaxSizeVertical = gfx::Size(25, 50);
-}  // namespace
-
-// Tests resizing of window with a 1:1 aspect ratio. This test also tests the
-// 'pivot points' when resizing, i.e. the opposite side or corner of the
-// window.
-TEST(WindowResizeUtilsTest, SizeToSquareAspectRatio) {
-  // Size from the top of the window.
-  // |window_rect| within the bounds of kMinSizeSquare and kMaxSizeSquare.
-  gfx::Rect window_rect(100, 100, 15, 15);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kTop, kAspectRatioSquare,
-                                           kMinSizeSquare, kMaxSizeSquare,
-                                           &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, 15, 15));
-
-  // Size from the bottom right corner of the window.
-  // |window_rect| smaller than kMinSizeSquare.
-  window_rect.SetRect(100, 100, 5, 5);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kBottomRight,
-                                           kAspectRatioSquare, kMinSizeSquare,
-                                           kMaxSizeSquare, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, kMinSizeSquare.width(),
-                                   kMinSizeSquare.height()));
-
-  // Size from the top of the window.
-  // |window_rect| larger than kMaxSizeSquare.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kTop, kAspectRatioSquare,
-                                           kMinSizeSquare, kMaxSizeSquare,
-                                           &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 150, kMaxSizeSquare.width(),
-                                   kMaxSizeSquare.height()));
-
-  // Size from the bottom of the window.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kBottom, kAspectRatioSquare,
-                                           kMinSizeSquare, kMaxSizeSquare,
-                                           &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, kMaxSizeSquare.width(),
-                                   kMaxSizeSquare.height()));
-
-  // Size from the left of the window.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kLeft, kAspectRatioSquare,
-                                           kMinSizeSquare, kMaxSizeSquare,
-                                           &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(150, 150, kMaxSizeSquare.width(),
-                                   kMaxSizeSquare.height()));
-
-  // Size from the right of the window.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kRight, kAspectRatioSquare,
-                                           kMinSizeSquare, kMaxSizeSquare,
-                                           &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, kMaxSizeSquare.width(),
-                                   kMaxSizeSquare.height()));
-
-  // Size from the top left corner of the window.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kTopLeft,
-                                           kAspectRatioSquare, kMinSizeSquare,
-                                           kMaxSizeSquare, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(150, 150, kMaxSizeSquare.width(),
-                                   kMaxSizeSquare.height()));
-
-  // Size from the top right corner of the window.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kTopRight,
-                                           kAspectRatioSquare, kMinSizeSquare,
-                                           kMaxSizeSquare, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 150, kMaxSizeSquare.width(),
-                                   kMaxSizeSquare.height()));
-
-  // Size from the bottom left corner of the window.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(HitTest::kBottomLeft,
-                                           kAspectRatioSquare, kMinSizeSquare,
-                                           kMaxSizeSquare, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(150, 100, kMaxSizeSquare.width(),
-                                   kMaxSizeSquare.height()));
-}
-
-// Tests the aspect ratio of the gfx::Rect adheres to the horizontal aspect
-// ratio.
-TEST(WindowResizeUtilsTest, SizeToHorizontalAspectRatio) {
-  // |window_rect| within bounds of kMinSizeHorizontal and kMaxSizeHorizontal.
-  gfx::Rect window_rect(100, 100, 20, 10);
-  WindowResizeUtils::SizeRectToAspectRatio(
-      HitTest::kTop, kAspectRatioHorizontal, kMinSizeHorizontal,
-      kMaxSizeHorizontal, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, 20, 10));
-
-  // |window_rect| smaller than kMinSizeHorizontal.
-  window_rect.SetRect(100, 100, 5, 5);
-  WindowResizeUtils::SizeRectToAspectRatio(
-      HitTest::kBottomRight, kAspectRatioHorizontal, kMinSizeHorizontal,
-      kMaxSizeHorizontal, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, kMinSizeHorizontal.width(),
-                                   kMinSizeHorizontal.height()));
-
-  // |window_rect| greater than kMaxSizeHorizontal.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(
-      HitTest::kTop, kAspectRatioHorizontal, kMinSizeHorizontal,
-      kMaxSizeHorizontal, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 175, kMaxSizeHorizontal.width(),
-                                   kMaxSizeHorizontal.height()));
-}
-
-// Tests the aspect ratio of the gfx::Rect adheres to the vertical aspect ratio.
-TEST(WindowResizeUtilsTest, SizeToVerticalAspectRatio) {
-  // |window_rect| within bounds of kMinSizeVertical and kMaxSizeVertical.
-  gfx::Rect window_rect(100, 100, 10, 20);
-  WindowResizeUtils::SizeRectToAspectRatio(
-      HitTest::kBottomRight, kAspectRatioVertical, kMinSizeVertical,
-      kMaxSizeVertical, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, 10, 20));
-
-  // |window_rect| smaller than kMinSizeVertical.
-  window_rect.SetRect(100, 100, 5, 5);
-  WindowResizeUtils::SizeRectToAspectRatio(
-      HitTest::kBottomRight, kAspectRatioVertical, kMinSizeVertical,
-      kMaxSizeVertical, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, kMinSizeVertical.width(),
-                                   kMinSizeVertical.height()));
-
-  // |window_rect| greater than kMaxSizeVertical.
-  window_rect.SetRect(100, 100, 100, 100);
-  WindowResizeUtils::SizeRectToAspectRatio(
-      HitTest::kBottomRight, kAspectRatioVertical, kMinSizeVertical,
-      kMaxSizeVertical, &window_rect);
-  EXPECT_EQ(window_rect, gfx::Rect(100, 100, kMaxSizeVertical.width(),
-                                   kMaxSizeVertical.height()));
-}
-
-}  // namespace views
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn
index ee2a9666..caec6ea3 100644
--- a/ui/webui/resources/cr_components/BUILD.gn
+++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -98,6 +98,7 @@
       "chromeos/cellular_setup/base_page.m.js",
       "chromeos/cellular_setup/button_bar.m.js",
       "chromeos/cellular_setup/cellular_setup_delegate.m.js",
+      "chromeos/cellular_setup/cellular_setup_icons.m.js",
       "chromeos/cellular_setup/cellular_setup.m.js",
       "chromeos/cellular_setup/cellular_types.m.js",
       "chromeos/cellular_setup/esim_flow_ui.m.js",
@@ -205,6 +206,7 @@
       "chromeos/cellular_setup/button_bar.js",
       "chromeos/cellular_setup/cellular_setup_delegate.html",
       "chromeos/cellular_setup/cellular_setup_delegate.js",
+      "chromeos/cellular_setup/cellular_setup_icons.html",
       "chromeos/cellular_setup/cellular_setup.html",
       "chromeos/cellular_setup/cellular_setup.js",
       "chromeos/cellular_setup/cellular_types.html",
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
index b328eed..4b14ea0 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
@@ -366,6 +366,7 @@
     ":activation_code_page_module",
     ":base_page_module",
     ":button_bar_module",
+    ":cellular_setup_icons_module",
     ":cellular_setup_module",
     ":esim_flow_ui_module",
     ":final_page_module",
@@ -475,6 +476,12 @@
   auto_imports = cr_components_chromeos_auto_imports
 }
 
+polymer_modulizer("cellular_setup_icons") {
+  js_file = "cellular_setup_icons.m.js"
+  html_file = "cellular_setup_icons.html"
+  html_type = "iron-iconset"
+}
+
 js_modulizer("modulize") {
   input_files = [
     "cellular_types.js",
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
index 416b4fe..f292ff16 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
@@ -1,9 +1,11 @@
 <link rel="import" href="../../../html/polymer.html">
 
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="../../../html/i18n_behavior.html">
 <link rel="import" href="../../../cr_elements/cr_input/cr_input.html">
 <link rel="import" href="base_page.html">
 <link rel="import" href="cellular_setup_delegate.html">
+<link rel="import" href="cellular_setup_icons.html">
 
 <dom-module id="activation-code-page">
   <template>
@@ -47,15 +49,11 @@
       }
 
       .button-image {
-        height: 20px;
         margin-inline-end: 8px;
-        width: 20px;
       }
 
       .scan-finish-image {
-        height: 20px;
         position: absolute;
-        width: 20px;
        }
 
       .scan-finish-message {
@@ -67,7 +65,12 @@
         cursor: default;
       }
 
+      #startScanningContainer {
+        --iron-icon-fill-color: #1A73E8;
+      }
+
       #scanSuccessContainer {
+        --iron-icon-fill-color: #1E8E3E;
         margin-bottom: 8px;
       }
 
@@ -77,6 +80,7 @@
       }
 
       #scanFailureContainer {
+        --iron-icon-fill-color: #D93025;
         margin-bottom: 4px;
       }
 
@@ -101,8 +105,9 @@
         z-index: 2;
       }
 
-      #switchCameraButton img {
+      #switchCameraButton iron-icon {
         filter: brightness(2.1);
+        --iron-icon-fill-color: #5F6368;
       }
     </style>
     <base-page>
@@ -115,9 +120,7 @@
               on-click="onSwitchCameraButtonPressed_"
               hidden$="[[isUiElementHidden_(UiElement.SWITCH_CAMERA, state_, hasMultipleCameras_)]]"
               disabled="[[isUiElementDisabled_(UiElement.SWITCH_CAMERA, state_)]]">
-            <img class="button-image"
-                src="activation_code_page_switch_camera.svg"
-                aria-hidden="true">
+            <iron-icon class="button-image" icon="cellular-setup:switch-camera"></iron-icon>
             [[i18n('switchCamera')]]
           </cr-button>
           <video id="video"
@@ -129,9 +132,7 @@
                 id="startScanningButton"
                 on-click="startScanning_"
                 aria-describedby="scanQrCodeDescription">
-              <img class="button-image"
-                  src="activation_code_page_camera.svg"
-                  aria-hidden="true">
+              <iron-icon class="button-image" icon="cellular-setup:camera"></iron-icon>
               [[i18n('useCamera')]]
             </cr-button>
           </div>
@@ -140,16 +141,14 @@
             <div>
               <div id="scanSuccessContainer"
                   hidden$="[[isUiElementHidden_(UiElement.SCAN_SUCCESS, state_)]]">
-                <img class="scan-finish-image"
-                    src="activation_code_page_checked.svg">
+                <iron-icon class="scan-finish-image" icon="cellular-setup:checked"></iron-icon>
                 <span class="label scan-finish-message" id="scanSuccessMessage">
                   [[i18n('scanQRCodeSuccess')]]
                 </span>
               </div>
               <div id="scanFailureContainer"
                   hidden$="[[isUiElementHidden_(UiElement.SCAN_FAILURE, state_)]]">
-                <img class="scan-finish-image"
-                    src="activation_code_page_error.svg">
+                <iron-icon class="scan-finish-image" icon="cellular-setup:error"></iron-icon>
                 <span class="label scan-finish-message" id="scanFailureMessage">
                   [[i18n('scanQrCodeInvalid')]]
                 </span>
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_camera.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_camera.svg
deleted file mode 100644
index 9e8e0fe77..0000000
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_camera.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="a" maskUnits="userSpaceOnUse" x="1" y="2" width="18" height="16"><path fill-rule="evenodd" clip-rule="evenodd" d="M16.667 4.167h-2.642L12.5 2.5h-5L5.975 4.167H3.334c-.917 0-1.667.75-1.667 1.666v10c0 .917.75 1.667 1.667 1.667h13.333c.917 0 1.667-.75 1.667-1.667v-10c0-.916-.75-1.666-1.667-1.666zm0 11.666H3.334v-10h13.333v10zm-10-5A3.332 3.332 0 1 1 10 14.166a3.332 3.332 0 0 1-3.333-3.333z" fill="#fff"/></mask><g mask="url(#a)"><path fill="#1A73E8" d="M0 0h20v20H0z"/></g></svg>
\ No newline at end of file
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_checked.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_checked.svg
deleted file mode 100644
index adf445fe..0000000
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_checked.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.707 7.293a1 1 0 0 0-1.414 0L9 10.586 7.707 9.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414z" fill="#1E8E3E"/><path fill-rule="evenodd" clip-rule="evenodd" d="M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-2a6 6 0 1 0 0-12 6 6 0 0 0 0 12z" fill="#1E8E3E"/></svg>
\ No newline at end of file
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_error.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_error.svg
deleted file mode 100644
index 64ff5ab1..0000000
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_error.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M9 10h2V6H9v4zm1-8c-4.416 0-8 3.584-8 8s3.584 8 8 8 8-3.584 8-8-3.584-8-8-8zm0 14c-3.308 0-6-2.693-6-6 0-3.308 2.692-6 6-6 3.307 0 6 2.692 6 6 0 3.307-2.693 6-6 6zm-1-2h2v-2H9v2z" fill="#D93025"/></svg>
\ No newline at end of file
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_switch_camera.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_switch_camera.svg
deleted file mode 100644
index ba6127d..0000000
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page_switch_camera.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 9V7H4.802A5.996 5.996 0 0 1 10 4a6 6 0 0 1 5.917 5h2.021c-.491-3.945-3.853-7-7.93-7a7.992 7.992 0 0 0-6.009 2.712L4 3H2v6h5zm5.938 2v2h2.198a5.996 5.996 0 0 1-5.198 3 6 6 0 0 1-5.917-5H2c.492 3.945 3.853 7 7.93 7a7.992 7.992 0 0 0 6.009-2.712V17h2v-6h-5zM10 12a2 2 0 1 0 0-4 2 2 0 0 0 0 4z" fill="#5F6368"/></svg>
\ No newline at end of file
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html
new file mode 100644
index 0000000..e751d548
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html
@@ -0,0 +1,16 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
+
+<!-- These icons were converted from source .svg files. -->
+
+<iron-iconset-svg name="cellular-setup" size="20">
+  <svg>
+    <defs>
+        <g id="camera" viewBox="0 0 20 20"><mask id="a" maskUnits="userSpaceOnUse" x="1" y="2" width="18" height="16"><path fill-rule="evenodd" clip-rule="evenodd" d="M16.667 4.167h-2.642L12.5 2.5h-5L5.975 4.167H3.334c-.917 0-1.667.75-1.667 1.666v10c0 .917.75 1.667 1.667 1.667h13.333c.917 0 1.667-.75 1.667-1.667v-10c0-.916-.75-1.666-1.667-1.666zm0 11.666H3.334v-10h13.333v10zm-10-5A3.332 3.332 0 1 1 10 14.166a3.332 3.332 0 0 1-3.333-3.333z" fill="#fff"></mask><g mask="url(#a)"><path d="M0 0h20v20H0z"></g></g>
+        <g id="checked" viewBox="0 0 20 20"><path d="M13.707 7.293a1 1 0 0 0-1.414 0L9 10.586 7.707 9.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414z"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-2a6 6 0 1 0 0-12 6 6 0 0 0 0 12z"></path></g>
+        <g id="error" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M9 10h2V6H9v4zm1-8c-4.416 0-8 3.584-8 8s3.584 8 8 8 8-3.584 8-8-3.584-8-8-8zm0 14c-3.308 0-6-2.693-6-6 0-3.308 2.692-6 6-6 3.307 0 6 2.692 6 6 0 3.307-2.693 6-6 6zm-1-2h2v-2H9v2z"></g>
+        <g id="switch-camera" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 9V7H4.802A5.996 5.996 0 0 1 10 4a6 6 0 0 1 5.917 5h2.021c-.491-3.945-3.853-7-7.93-7a7.992 7.992 0 0 0-6.009 2.712L4 3H2v6h5zm5.938 2v2h2.198a5.996 5.996 0 0 1-5.198 3 6 6 0 0 1-5.917-5H2c.492 3.945 3.853 7 7.93 7a7.992 7.992 0 0 0 6.009-2.712V17h2v-6h-5zM10 12a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></g>
+    </defs>
+  </svg>
+</iron-iconset-svg>
\ No newline at end of file
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/profile_discovery_list_item.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/profile_discovery_list_item.html
index 2ddf925c..8c421d4e 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/profile_discovery_list_item.html
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/profile_discovery_list_item.html
@@ -3,6 +3,8 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="cellular_setup_icons.html">
 
 <dom-module id="profile-discovery-list-item">
   <template>
@@ -23,13 +25,9 @@
       }
 
       #checkmark {
-        -webkit-mask: url(activation_code_page_checked.svg) no-repeat center;
-        background-color: var(--google-blue-600);
-        height: 20px;
+        --iron-icon-fill-color: var(--google-blue-600);
         margin-inline-end: 8px;
-        mask: url(activation_code_page_checked.svg) no-repeat center;
         padding-inline-end: var(--cr-section-padding);
-        width: 20px;
       }
     </style>
     <div class="two-line no-padding" selectable>
@@ -47,8 +45,11 @@
             </div>
           </div>
         </div>
-        <span id="checkmark" hidden$="[[!selected]]"
+        <iron-icon id="checkmark"
+            icon="cellular-setup:checked"
+            hidden$="[[!selected]]"
             tabindex="-1">
+        </iron-icon>
       </div>
     </div>
   </template>
diff --git a/ui/webui/resources/cr_components/cr_components_images.grdp b/ui/webui/resources/cr_components/cr_components_images.grdp
index 63b3c65..fd33a2e 100644
--- a/ui/webui/resources/cr_components/cr_components_images.grdp
+++ b/ui/webui/resources/cr_components/cr_components_images.grdp
@@ -27,22 +27,6 @@
              compress="gzip" />
 
     <!-- CellularSetup Images -->
-    <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_ACTIVATION_CODE_PAGE_CAMERA_SVG"
-             file="cr_components/chromeos/cellular_setup/activation_code_page_camera.svg"
-             type="BINDATA"
-             compress="gzip" />
-    <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_ACTIVATION_CODE_PAGE_CHECKED_SVG"
-             file="cr_components/chromeos/cellular_setup/activation_code_page_checked.svg"
-             type="BINDATA"
-             compress="gzip" />
-    <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_ACTIVATION_CODE_PAGE_SWITCH_CAMERA_SVG"
-             file="cr_components/chromeos/cellular_setup/activation_code_page_switch_camera.svg"
-             type="BINDATA"
-             compress="gzip" />
-    <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_ACTIVATION_CODE_PAGE_ERROR_SVG"
-             file="cr_components/chromeos/cellular_setup/activation_code_page_error.svg"
-             type="BINDATA"
-             compress="gzip" />
     <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_ERROR_1X_PNG"
              file="cr_components/chromeos/cellular_setup/error_1x.png"
              type="BINDATA"
diff --git a/weblayer/browser/background_sync/background_sync_browsertest.cc b/weblayer/browser/background_sync/background_sync_browsertest.cc
index 6c90b5d..3816bdd 100644
--- a/weblayer/browser/background_sync/background_sync_browsertest.cc
+++ b/weblayer/browser/background_sync/background_sync_browsertest.cc
@@ -104,7 +104,9 @@
 }
 
 #if defined(OS_ANDROID)
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, BackgroundSyncNotDisabled) {
+// TODO(crbug.com/1154332): Fix flaky test.
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
+                       DISABLED_BackgroundSyncNotDisabled) {
   auto* controller = BackgroundSyncControllerFactory::GetForBrowserContext(
       GetBrowserContext());
   ASSERT_TRUE(controller);
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/payments/WebLayerPaymentRequestService.java b/weblayer/browser/java/org/chromium/weblayer_private/payments/WebLayerPaymentRequestService.java
index 4e01adbd..ccc846a 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/payments/WebLayerPaymentRequestService.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/payments/WebLayerPaymentRequestService.java
@@ -129,7 +129,7 @@
     // Implements BrowserPaymentRequest:
     @Override
     @Nullable
-    public String triggerPaymentAppUiSkipIfApplicable(boolean isUserGestureShow) {
+    public String onShowCalledAndAppsQueriedAndDetailsFinalized(boolean isUserGestureShow) {
         assert !mAvailableApps.isEmpty()
             : "triggerPaymentAppUiSkipIfApplicable() should be called only when there is any "
                 + "available app.";
diff --git a/weblayer/test/browsertests_main.cc b/weblayer/test/browsertests_main.cc
index eba1221..f066bdd 100644
--- a/weblayer/test/browsertests_main.cc
+++ b/weblayer/test/browsertests_main.cc
@@ -4,18 +4,29 @@
 
 #include "base/command_line.h"
 #include "base/test/launcher/test_launcher.h"
+#include "build/build_config.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/network_service_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "weblayer/test/test_launcher_delegate_impl.h"
 #include "weblayer/utility/content_utility_client_impl.h"
 
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#endif  // defined(OS_WIN)
+
 int main(int argc, char** argv) {
   base::CommandLine::Init(argc, argv);
   size_t parallel_jobs = base::NumParallelJobs(/*cores_per_job=*/1);
   if (parallel_jobs == 0U)
     return 1;
 
+#if defined(OS_WIN)
+  // Load and pin user32.dll to avoid having to load it once tests start while
+  // on the main thread loop where blocking calls are disallowed.
+  base::win::PinUser32();
+#endif  // OS_WIN
+
   // Set up a working test environment for the network service in case it's
   // used. Only create this object in the utility process, so that its members
   // don't interfere with other test objects in the browser process.