diff --git a/DEPS b/DEPS
index b6687daf..6fe8ee0 100644
--- a/DEPS
+++ b/DEPS
@@ -209,11 +209,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e14d72500fc74a2de02571759898c71ca03957fe',
+  'skia_revision': 'd276cdfdeebd68ef7f458b53edc1083a9a4d2f1d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '64478f20cfc01191c2173ac646f73e599c9f3f69',
+  'v8_revision': '53d8ce6eaaa65772b7074bd390b1fcd29208f387',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -221,7 +221,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '81401be2a035471e394cd2014ba90791c1102cf0',
+  'angle_revision': 'fdba40fe44688078e9f9e7c9d6e9e4cc26eea553',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -288,7 +288,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '9646971c47066c84b2fa6254a94838bdfe786bc6',
+  'devtools_frontend_revision': '3167ffee9b376e6152a8ae8c4c2b509fb873a003',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -328,7 +328,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'faea7f78414e21abe84cc072409f358d02a47ee6',
+  'dawn_revision': 'c59d0f60140b6dd597dfe42bce982aa286b0e4bc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -570,7 +570,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'e2f4fd39ee036bef0411b59b35080642b4a23483',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '14a603f05a4c1d368559ea4fdb34ff90112c4946',
       'condition': 'checkout_ios',
   },
 
@@ -727,7 +727,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'DkjJyAndtE7UV7h5rNQdFWztxKvMiWIhS0cXGk4pS-UC',
+          'version': 'IoB78nVutc7u1QVob6zeGRS6YrTtEaNyYCFV4iBH3bcC',
       },
     ],
     'condition': 'checkout_android',
@@ -994,7 +994,7 @@
     Var('chromium_git') + '/external/github.com/google/farmhash.git' + '@' + '816a4ae622e964763ca0862d9dbd19324a1eaf45',
 
   'src/third_party/ffmpeg':
-    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '4fb42ae52e7327469281d612784dd9d0e066d5ed',
+    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '280d5fd0df8b4284ad040bd29deb3241bd6dfc4a',
 
   'src/third_party/flac':
     Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596',
@@ -1335,7 +1335,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '1b78913ea7b1a4c3a3447f6b183e4be62a01e7e3',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '31ac7832bfcaabb8389a8d04a321d459917da176',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1413,7 +1413,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': '3LqGeo5KWUbxoMWPc5T6Gs_Iql4roUq5CBjDHf82hwQC'
+              'version': 'dXMWT4elldlEXvj4YHtc9u0W4YEfTP-KZbIKpA75-7MC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1621,7 +1621,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5bc06e467a66812bbe8e87ad7dd6cded028f631f',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ab55d4d7ba937fd778b2d5605845acaf8ed2bec2',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc
index e1a56eb..3d2f8be 100644
--- a/ash/accelerators/accelerator_controller_impl.cc
+++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -1806,6 +1806,10 @@
 // AcceleratorControllerImpl, private:
 
 void AcceleratorControllerImpl::Init() {
+  // Use positional lookup by default if the feature is enabled.
+  accelerators_.set_use_positional_lookup(
+      ::features::IsImprovedKeyboardShortcutsEnabled());
+
   for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) {
     actions_allowed_at_login_screen_.insert(
         kActionsAllowedAtLoginOrLockScreen[i]);
diff --git a/ash/capture_mode/capture_mode_test_api.cc b/ash/capture_mode/capture_mode_test_api.cc
index 6f93d111..fa0f30fc 100644
--- a/ash/capture_mode/capture_mode_test_api.cc
+++ b/ash/capture_mode/capture_mode_test_api.cc
@@ -73,6 +73,16 @@
   controller_->recording_service_remote_.FlushForTesting();
 }
 
+void CaptureModeTestApi::ResetRecordingServiceRemote() {
+  DCHECK(controller_->is_recording_in_progress());
+  controller_->recording_service_remote_.reset();
+}
+
+void CaptureModeTestApi::ResetRecordingServiceClientReceiver() {
+  DCHECK(controller_->is_recording_in_progress());
+  controller_->recording_service_client_receiver_.reset();
+}
+
 void CaptureModeTestApi::SetType(bool for_video) {
   controller_->SetType(for_video ? CaptureModeType::kVideo
                                  : CaptureModeType::kImage);
diff --git a/ash/metrics/task_switch_metrics_recorder.cc b/ash/metrics/task_switch_metrics_recorder.cc
index 6de9684a..24bbfa82 100644
--- a/ash/metrics/task_switch_metrics_recorder.cc
+++ b/ash/metrics/task_switch_metrics_recorder.cc
@@ -26,7 +26,7 @@
     "Ash.WindowCycleController.TimeBetweenTaskSwitches";
 
 const char kOverviewModeHistogramName[] =
-    "Ash.WindowSelector.TimeBetweenActiveWindowChanges";
+    "Ash.Overview.TimeBetweenActiveWindowChanges";
 
 // Returns the histogram name for the given |task_switch_source|.
 const char* GetHistogramName(TaskSwitchSource task_switch_source) {
diff --git a/ash/metrics/task_switch_metrics_recorder_unittest.cc b/ash/metrics/task_switch_metrics_recorder_unittest.cc
index ca93552..2839617 100644
--- a/ash/metrics/task_switch_metrics_recorder_unittest.cc
+++ b/ash/metrics/task_switch_metrics_recorder_unittest.cc
@@ -115,11 +115,11 @@
 }
 
 // Verifies that the TaskSwitchSource::OVERVIEW_MODE source adds data
-// to the Ash.WindowSelector.TimeBetweenActiveWindowChanges histogram.
+// to the Ash.Overview.TimeBetweenActiveWindowChanges histogram.
 TEST_F(TaskSwitchMetricsRecorderTest,
        VerifyTaskSwitchesFromOverviewModeAreRecorded) {
   const std::string kHistogramName =
-      "Ash.WindowSelector.TimeBetweenActiveWindowChanges";
+      "Ash.Overview.TimeBetweenActiveWindowChanges";
 
   OnTaskSwitch(TaskSwitchSource::OVERVIEW_MODE);
   OnTaskSwitch(TaskSwitchSource::OVERVIEW_MODE);
diff --git a/ash/public/cpp/capture_mode_test_api.h b/ash/public/cpp/capture_mode_test_api.h
index 0b93668..c989c16 100644
--- a/ash/public/cpp/capture_mode_test_api.h
+++ b/ash/public/cpp/capture_mode_test_api.h
@@ -62,6 +62,11 @@
   // recording is in progress.
   void FlushRecordingServiceForTesting();
 
+  // APIs to reset both the recording service remote, and its client receiver in
+  // order to test that these events are correctly handled.
+  void ResetRecordingServiceRemote();
+  void ResetRecordingServiceClientReceiver();
+
  private:
   // Sets the capture mode type to a video capture if |for_video| is true, or
   // image capture otherwise.
diff --git a/ash/services/recording/recording_encoder_muxer.cc b/ash/services/recording/recording_encoder_muxer.cc
index a0d2d04..12514e2a 100644
--- a/ash/services/recording/recording_encoder_muxer.cc
+++ b/ash/services/recording/recording_encoder_muxer.cc
@@ -46,8 +46,8 @@
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
     const media::VideoEncoder::Options& video_encoder_options,
     const media::AudioParameters* audio_input_params,
-    media::WebmMuxer::WriteDataCB muxer_output_callback,
-    FailureCallback on_failure_callback) {
+    OnMuxerOutputCallback muxer_output_callback,
+    OnFailureCallback on_failure_callback) {
   return base::SequenceBound<RecordingEncoderMuxer>(
       std::move(blocking_task_runner), video_encoder_options,
       audio_input_params, std::move(muxer_output_callback),
@@ -138,12 +138,14 @@
 RecordingEncoderMuxer::RecordingEncoderMuxer(
     const media::VideoEncoder::Options& video_encoder_options,
     const media::AudioParameters* audio_input_params,
-    media::WebmMuxer::WriteDataCB muxer_output_callback,
-    FailureCallback on_failure_callback)
-    : webm_muxer_(media::kCodecOpus,
+    OnMuxerOutputCallback muxer_output_callback,
+    OnFailureCallback on_failure_callback)
+    : on_muxer_output_callback_(std::move(muxer_output_callback)),
+      webm_muxer_(media::kCodecOpus,
                   /*has_video_=*/true,
                   /*has_audio_=*/!!audio_input_params,
-                  muxer_output_callback),
+                  base::BindRepeating(&RecordingEncoderMuxer::OnMuxerWrite,
+                                      base::Unretained(this))),
       on_failure_callback_(std::move(on_failure_callback)) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -278,6 +280,17 @@
                              encoded_audio.timestamp);
 }
 
+void RecordingEncoderMuxer::OnMuxerWrite(base::StringPiece data) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!on_muxer_output_callback_.is_null());
+
+  // Note that |on_muxer_output_callback_| might be bound to a different
+  // sequence than the one used here. Therefore, we can't just pass in the
+  // StringPiece |data|, since by the time this callback is invoked on the
+  // target sequence, the |webm_muxer_| may have already clobbered it.
+  on_muxer_output_callback_.Run(std::string(data));
+}
+
 void RecordingEncoderMuxer::OnAudioEncoderFlushed(base::OnceClosure on_done,
                                                   media::Status status) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/ash/services/recording/recording_encoder_muxer.h b/ash/services/recording/recording_encoder_muxer.h
index 0f88e53..bcdb9dc1 100644
--- a/ash/services/recording/recording_encoder_muxer.h
+++ b/ash/services/recording/recording_encoder_muxer.h
@@ -38,9 +38,19 @@
 // Defines a callback type to notify the user of RecordingEncoderMuxer of a
 // failure while encoding audio or video frames.
 // TODO(afakhry): It's possible we don't need |type| or |for_video|.
-using FailureCallback =
+using OnFailureCallback =
     base::OnceCallback<void(FailureType type, bool for_video)>;
 
+// Defines a callback type to push the output of the muxer to the user of
+// RecordingEncoderMuxer. Note that this differs from the type of the
+// |WebmMuxer|'s write callback (|media::WebmMuxer::WriteDataCB|) in that the
+// below callback uses |std::string| to provide the output rather than
+// |base::StringPiece|. This enables the user to bind the callback to a
+// different sequence than the one used by the muxer, since a |StringPiece| does
+// not own its buffer and by the time the callback is invoked on another
+// sequence, the muxer might have already clobbered the underlying buffer.
+using OnMuxerOutputCallback = base::RepeatingCallback<void(std::string)>;
+
 // Encapsulates encoding and muxing audio and video frame. An instance of this
 // object can only be interacted with via a |base::SequenceBound| wrapper, which
 // guarantees all encoding and muxing operations as well as destruction of the
@@ -61,18 +71,22 @@
   // initialize the video and audio encoders respectively.
   // If |audio_input_params| is nullptr, then the service is not recording
   // audio, and the muxer will be initialized accordingly.
-  // |muxer_output_callback| will be called on the same sequence of
-  // |blocking_task_runner| to provide the muxer output chunks ready to be sent
-  // to the recording service client.
-  // |on_failure_callback| will be called on the same sequence of
-  // |blocking_task_runner| to inform the owner of this object, after which
-  // all subsequent calls to EncodeVideo() and EncodeAudio() will be ignored.
+  // |muxer_output_callback| will be called to provide the muxer output chunks
+  // ready to be sent to the recording service client.
+  // |on_failure_callback| will be called to inform the owner of this object of
+  // a failure, after which all subsequent calls to EncodeVideo() and
+  // EncodeAudio() will be ignored.
+  //
+  // By default, both |muxer_output_callback| and |on_failure_callback| will be
+  // called on the same sequence of |blocking_task_runner| (unless the caller
+  // binds the given callbacks to a different sequence by means of
+  // base::BindPostTask()).
   static base::SequenceBound<RecordingEncoderMuxer> Create(
       scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
       const media::VideoEncoder::Options& video_encoder_options,
       const media::AudioParameters* audio_input_params,
-      media::WebmMuxer::WriteDataCB muxer_output_callback,
-      FailureCallback on_failure_callback);
+      OnMuxerOutputCallback muxer_output_callback,
+      OnFailureCallback on_failure_callback);
 
   bool did_failure_occur() const {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -97,9 +111,11 @@
   // Audio and video encoders as well as the WebmMuxer may buffer several frames
   // before they're processed. It is important to flush all those buffers before
   // releasing this object so as not to drop the final portion of the recording.
-  // |on_done| will be called on the same sequence of |blocking_task_runner|
-  // when all remaining buffered frames have been processed and sent to
-  // |muxer_output_callback|.
+  // |on_done| will be called when all remaining buffered frames have been
+  // processed and sent to |muxer_output_callback|.
+  // By default, |on_done| will be called on the same sequence of
+  // |blocking_task_runner| unless the caller binds it to another sequence by
+  // means of base::BindPostTask().
   void FlushAndFinalize(base::OnceClosure on_done);
 
  private:
@@ -117,8 +133,8 @@
   RecordingEncoderMuxer(
       const media::VideoEncoder::Options& video_encoder_options,
       const media::AudioParameters* audio_input_params,
-      media::WebmMuxer::WriteDataCB muxer_output_callback,
-      FailureCallback on_failure_callback);
+      OnMuxerOutputCallback muxer_output_callback,
+      OnFailureCallback on_failure_callback);
   ~RecordingEncoderMuxer();
 
   // Creates and initializes the audio encoder.
@@ -157,6 +173,9 @@
       media::EncodedAudioBuffer encoded_audio,
       base::Optional<media::AudioEncoder::CodecDescription> codec_description);
 
+  // Called by the |webm_muxer_| to deliver a muxer output chunk |data|.
+  void OnMuxerWrite(base::StringPiece data);
+
   // Called when the audio encoder flushes all its buffered frames, at which
   // point we can flush the video encoder. |on_done| will be passed to
   // OnVideoEncoderFlushed()
@@ -176,12 +195,23 @@
   // the value of |for_video|.
   void NotifyFailure(FailureType type, bool for_video);
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   std::unique_ptr<media::VpxVideoEncoder> video_encoder_
       GUARDED_BY_CONTEXT(sequence_checker_);
 
   std::unique_ptr<media::AudioOpusEncoder> audio_encoder_
       GUARDED_BY_CONTEXT(sequence_checker_);
 
+  // A callback to deliver the muxer output to the client of this class. By
+  // default, it is invoked on the same sequence of this class, unless the
+  // client binds it to a different sequence (by means of |base::BindPostTask|)
+  // before giving it to us.
+  // Note that it has to be declared before |webm_muxer_| because the latter
+  // depends on it, so |webm_muxer_| should be destroyed first.
+  OnMuxerOutputCallback on_muxer_output_callback_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
   media::WebmMuxer webm_muxer_ GUARDED_BY_CONTEXT(sequence_checker_);
 
   // Holds video frames that were received before the video encoder is
@@ -210,7 +240,7 @@
   // A callback triggered when a failure happens during encoding. Once
   // triggered, this callback is null, and therefore indicates that a failure
   // occurred (See did_failure_occur() above).
-  FailureCallback on_failure_callback_ GUARDED_BY_CONTEXT(sequence_checker_);
+  OnFailureCallback on_failure_callback_ GUARDED_BY_CONTEXT(sequence_checker_);
 
   // True once video encoder is initialized successfully.
   bool is_video_encoder_initialized_ GUARDED_BY_CONTEXT(sequence_checker_) =
@@ -220,8 +250,6 @@
   bool is_audio_encoder_initialized_ GUARDED_BY_CONTEXT(sequence_checker_) =
       false;
 
-  SEQUENCE_CHECKER(sequence_checker_);
-
   base::WeakPtrFactory<RecordingEncoderMuxer> weak_ptr_factory_
       GUARDED_BY_CONTEXT(sequence_checker_){this};
 };
diff --git a/ash/services/recording/recording_service.cc b/ash/services/recording/recording_service.cc
index 495f29dd..b98dd9b 100644
--- a/ash/services/recording/recording_service.cc
+++ b/ash/services/recording/recording_service.cc
@@ -4,6 +4,8 @@
 
 #include "ash/services/recording/recording_service.h"
 
+#include <cstdlib>
+
 #include "ash/services/recording/recording_encoder_muxer.h"
 #include "ash/services/recording/recording_service_constants.h"
 #include "ash/services/recording/video_capture_params.h"
@@ -108,6 +110,16 @@
       scaled_size);
 }
 
+// Called when the channel to the client of the recording service gets
+// disconnected. At that point, there's nothing useful to do here, and instead
+// of wasting resources encoding/muxing remaining frames, and flushing the
+// buffers, we terminate the recording service process immediately.
+void TerminateServiceImmediately() {
+  LOG(ERROR)
+      << "The recording service client was disconnected. Exiting immediately.";
+  std::exit(EXIT_FAILURE);
+}
+
 }  // namespace
 
 RecordingService::RecordingService(
@@ -122,10 +134,31 @@
           // reasons.
           {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {
-  DETACH_FROM_SEQUENCE(encoding_sequence_checker_);
 }
 
-RecordingService::~RecordingService() = default;
+RecordingService::~RecordingService() {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
+
+  if (!current_video_capture_params_)
+    return;
+
+  // If the service gets destructed while recording in progress, the client must
+  // be still connected (since otherwise the service process would have been
+  // immediately terminated). We attempt to flush whatever we have right now
+  // before exiting.
+  DCHECK(client_remote_.is_bound());
+  DCHECK(client_remote_.is_connected());
+  StopRecording();
+  video_capturer_remote_.reset();
+  consumer_receiver_.reset();
+  if (number_of_buffered_chunks_)
+    FlushBufferedChunks();
+  SignalRecordingEndedToClient(/*success=*/false);
+
+  // Note that we don't need to call FlushAndFinalize() on the |encoder_muxer_|,
+  // since it will be done asynchronously on the |encoding_task_runner_|, and by
+  // then this |RecordingService| instance will have been already gone.
+}
 
 void RecordingService::RecordFullscreen(
     mojo::PendingRemote<mojom::RecordingServiceClient> client,
@@ -324,15 +357,15 @@
   // chance to encode and flush the remaining frames (See
   // media::AudioInputDevice::Stop(), and
   // media::AudioInputDevice::AudioThreadCallback::Process() for details). It is
-  // safer that we own our AudioBuses that are keep alive until encoded and
+  // safer that we own our AudioBuses that are kept alive until encoded and
   // flushed.
   auto audio_data =
       media::AudioBus::Create(audio_source->channels(), audio_source->frames());
   audio_source->CopyTo(audio_data.get());
   main_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&RecordingService::OnAudioCaptured, base::Unretained(this),
-                     std::move(audio_data), audio_capture_time));
+      FROM_HERE, base::BindOnce(&RecordingService::OnAudioCaptured,
+                                weak_ptr_factory_.GetWeakPtr(),
+                                std::move(audio_data), audio_capture_time));
 }
 
 void RecordingService::OnCaptureError(const std::string& message) {
@@ -355,6 +388,8 @@
 
   client_remote_.reset();
   client_remote_.Bind(std::move(client));
+  client_remote_.set_disconnect_handler(
+      base::BindOnce(&TerminateServiceImmediately));
 
   current_video_capture_params_ = std::move(capture_params);
   const bool should_record_audio = audio_stream_factory.is_valid();
@@ -363,10 +398,8 @@
       encoding_task_runner_,
       CreateVideoEncoderOptions(current_video_capture_params_->GetVideoSize()),
       should_record_audio ? &audio_parameters_ : nullptr,
-      base::BindRepeating(&RecordingService::OnMuxerWrite,
-                          base::Unretained(this)),
-      base::BindOnce(&RecordingService::OnEncodingFailure,
-                     base::Unretained(this)));
+      BindRepeatingToMainThread(&RecordingService::OnMuxerOutput),
+      BindOnceToMainThread(&RecordingService::OnEncodingFailure));
 
   ConnectAndStartVideoCapturer(std::move(video_capturer));
 
@@ -400,8 +433,8 @@
   consumer_receiver_.reset();
 
   encoder_muxer_.AsyncCall(&RecordingEncoderMuxer::FlushAndFinalize)
-      .WithArgs(base::BindOnce(&RecordingService::OnEncoderMuxerFlushed,
-                               weak_ptr_factory_.GetWeakPtr(), success));
+      .WithArgs(BindOnceToMainThread(&RecordingService::OnEncoderMuxerFlushed,
+                                     success));
 }
 
 void RecordingService::ConnectAndStartVideoCapturer(
@@ -449,11 +482,9 @@
 }
 
 void RecordingService::OnEncodingFailure(FailureType type, bool for_video) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(encoding_sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
 
-  main_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&RecordingService::OnRecordingFailure,
-                                base::Unretained(this)));
+  OnRecordingFailure();
 }
 
 void RecordingService::OnRecordingFailure() {
@@ -469,16 +500,14 @@
 }
 
 void RecordingService::OnEncoderMuxerFlushed(bool success) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(encoding_sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
 
   // If flushing the encoders and muxers resulted in some chunks being cached
   // here, we flush them to the client now.
   if (number_of_buffered_chunks_)
     FlushBufferedChunks();
 
-  main_task_runner_->PostNonNestableTask(
-      FROM_HERE, base::BindOnce(&RecordingService::SignalRecordingEndedToClient,
-                                base::Unretained(this), success));
+  SignalRecordingEndedToClient(success);
 }
 
 void RecordingService::SignalMuxerOutputToClient(std::string muxer_output) {
@@ -495,24 +524,21 @@
   client_remote_->OnRecordingEnded(success, video_thumbnail_);
 }
 
-void RecordingService::OnMuxerWrite(base::StringPiece data) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(encoding_sequence_checker_);
+void RecordingService::OnMuxerOutput(std::string data) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
 
   ++number_of_buffered_chunks_;
-  muxed_chunks_buffer_.append(data.begin(), data.end());
+  muxed_chunks_buffer_.append(data);
 
   if (number_of_buffered_chunks_ >= kMaxBufferedChunks)
     FlushBufferedChunks();
 }
 
 void RecordingService::FlushBufferedChunks() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(encoding_sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
   DCHECK(number_of_buffered_chunks_);
 
-  main_task_runner_->PostNonNestableTask(
-      FROM_HERE,
-      base::BindOnce(&RecordingService::SignalMuxerOutputToClient,
-                     base::Unretained(this), std::move(muxed_chunks_buffer_)));
+  SignalMuxerOutputToClient(std::move(muxed_chunks_buffer_));
   number_of_buffered_chunks_ = 0;
 }
 
diff --git a/ash/services/recording/recording_service.h b/ash/services/recording/recording_service.h
index fa6ad2a2..b550dd4 100644
--- a/ash/services/recording/recording_service.h
+++ b/ash/services/recording/recording_service.h
@@ -7,10 +7,13 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "ash/services/recording/public/mojom/recording_service.mojom.h"
 #include "ash/services/recording/recording_encoder_muxer.h"
 #include "ash/services/recording/video_capture_params.h"
+#include "base/bind_post_task.h"
+#include "base/callback_forward.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
@@ -128,10 +131,11 @@
   void OnAudioCaptured(std::unique_ptr<media::AudioBus> audio_bus,
                        base::TimeTicks audio_capture_time);
 
-  // This is called by |encoder_muxer_| on the same sequence of the
-  // |encoding_task_runner_| when a failure of |type| occurs during audio or
-  // video encoding depending on |for_video|. This ends the ongoing recording
-  // and signals to the client that a failure occurred.
+  // This is called by |encoder_muxer_| on the main thread (since we bound it as
+  // a callback to be invoked on the main thread. See BindOnceToMainThread()),
+  // when a failure of |type| occurs during audio or video encoding depending on
+  // |for_video|. This ends the ongoing recording and signals to the client that
+  // a failure occurred.
   void OnEncodingFailure(FailureType type, bool for_video);
 
   // Called back on the main thread to terminate the recording immediately as a
@@ -140,7 +144,8 @@
 
   // At the end of recording we ask the |encoder_muxer_| to flush and process
   // any buffered frames. When this completes this function is called on the
-  // same sequence of |encoding_task_runner_|. |success| indicates whether we're
+  // main thread (since it's bound as a callback to be invoked on the main
+  // thread. See BindOnceToMainThread()). |success| indicates whether we're
   // flushing due to normal recording termination, or due to a failure.
   void OnEncoderMuxerFlushed(bool success);
 
@@ -152,15 +157,44 @@
   // chunks will be sent to the client after this.
   void SignalRecordingEndedToClient(bool success);
 
-  // Called on the same sequence of the |encoding_task_runner_| by
-  // |encoder_muxer_| to deliver a muxer output chunk |data|.
-  void OnMuxerWrite(base::StringPiece data);
+  // Bound as a callback to be repeatedly invoked on the |main_task_runner_|.
+  // It is called by |encoder_muxer_| to deliver a muxer output chunk |data|.
+  void OnMuxerOutput(std::string data);
 
-  // Called on the same sequence of the |encoding_task_runner_| to flush the
-  // chunks buffered in |muxed_chunks_buffer_| by sending them to the client and
-  // reset the |number_of_buffered_chunks_| back to 0.
+  // Called on the main thread to flush the chunks buffered in
+  // |muxed_chunks_buffer_| by sending them to the client and reset the
+  // |number_of_buffered_chunks_| back to 0.
   void FlushBufferedChunks();
 
+  // By default, the |encoder_muxer_| will invoke any callback we provide it
+  // with to notify us of certain events (such as muxer output, or flush done)
+  // on the |encoding_task_runner_|'s sequence. But since these callbacks are
+  // invoked asynchronously from other threads, they may get invoked after this
+  // RecordingService instance had been destroyed. Therefore, we need to bind
+  // these callbacks to weak ptrs, to prevent them from invoking after this
+  // object's destruction. However, this won't work, since weak ptrs cannot be
+  // invalidated except on the sequence on which they were invoked on. Hence, we
+  // must make sure these callbacks are invoked on the main thread.
+  //
+  // The below are two convenience methods to bind once and repeating callbacks
+  // to weak ptrs that would only be invoked on the main thread.
+  template <typename Functor, typename... Args>
+  auto BindOnceToMainThread(Functor&& functor, Args&&... args) {
+    return base::BindPostTask(main_task_runner_,
+                              base::BindOnce(std::forward<Functor>(functor),
+                                             weak_ptr_factory_.GetWeakPtr(),
+                                             std::forward<Args>(args)...));
+  }
+  template <typename Functor, typename... Args>
+  auto BindRepeatingToMainThread(Functor&& functor, Args&&... args) {
+    return base::BindPostTask(
+        main_task_runner_, base::BindRepeating(std::forward<Functor>(functor),
+                                               weak_ptr_factory_.GetWeakPtr(),
+                                               std::forward<Args>(args)...));
+  }
+
+  THREAD_CHECKER(main_thread_checker_);
+
   // The audio parameters that will be used when recording audio.
   const media::AudioParameters audio_parameters_;
 
@@ -216,16 +250,11 @@
       GUARDED_BY_CONTEXT(main_thread_checker_);
 
   // To avoid doing a ton of IPC calls to the client for each muxed chunk
-  // received from |encoder_muxer_| in OnMuxerWrite(), we buffer those chunks
+  // received from |encoder_muxer_| in OnMuxerOutput(), we buffer those chunks
   // here up to |kMaxBufferedChunks| before we send them to the client over IPC
   // in SignalMuxerOutputToClient().
-  std::string muxed_chunks_buffer_
-      GUARDED_BY_CONTEXT(encoding_sequence_checker_);
-  int number_of_buffered_chunks_
-      GUARDED_BY_CONTEXT(encoding_sequence_checker_) = 0;
-
-  THREAD_CHECKER(main_thread_checker_);
-  SEQUENCE_CHECKER(encoding_sequence_checker_);
+  std::string muxed_chunks_buffer_ GUARDED_BY_CONTEXT(main_thread_checker_);
+  int number_of_buffered_chunks_ GUARDED_BY_CONTEXT(main_thread_checker_) = 0;
 
   base::WeakPtrFactory<RecordingService> weak_ptr_factory_{this};
 };
diff --git a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
index 4df740ce..60d1d1b4 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
+++ b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -15,7 +15,9 @@
 #include "base/no_destructor.h"
 #include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
+#include "ui/base/accelerators/accelerator.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/chromeos/events/keyboard_layout_util.h"
 #include "ui/events/devices/device_data_manager.h"
 #include "ui/events/event_constants.h"
@@ -101,6 +103,40 @@
   return l10n_util::GetStringUTF16(msg_id);
 }
 
+// Dead keys work by combining two consecutive keystrokes together. The first
+// keystroke does not produce an output character, it acts as a one-shot
+// modifier for a subsequent keystroke. So for example on a German keyboard,
+// pressing the acute ´ dead key, then pressing the letter e will produce é.
+// The first character is called the combining character and does not produce
+// an output glyph. This table maps the combining character to a string
+// containing the non-combining equivalent that can be displayed.
+std::u16string GetStringForDeadKey(ui::DomKey dom_key) {
+  DCHECK(dom_key.IsDeadKey());
+  int32_t ch = dom_key.ToDeadKeyCombiningCharacter();
+  switch (ch) {
+    // Combining grave.
+    case 0x300:
+      return u"`";
+    // Combining acute.
+    case 0x301:
+      return u"´";
+    // Combining circumflex.
+    case 0x302:
+      return u"^";
+    // Combining tilde.
+    case 0x303:
+      return u"~";
+    // Combining diaeresis.
+    case 0x308:
+      return u"¨";
+    default:
+      break;
+  }
+
+  LOG(WARNING) << "No mapping for dead key shortcut " << ch;
+  return base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
+}
+
 }  // namespace
 
 std::u16string GetStringForCategory(ShortcutCategory category) {
@@ -139,9 +175,38 @@
 
   ui::DomKey dom_key;
   ui::KeyboardCode key_code_to_compare = ui::VKEY_UNKNOWN;
+  const ui::KeyboardLayoutEngine* layout_engine =
+      ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine();
+
+  // The input |key_code| is the |KeyboardCode| aka VKEY of the shortcut in
+  // the US layout which is registered from the shortcut table. |key_code|
+  // is first mapped to the |DomCode| this key is on in the US layout. If
+  // the key is not positional, this processing is skipped and it is handled
+  // normally in the loop below. For the positional keys, the |DomCode| is
+  // then mapped to the |DomKey| in the current layout which represents the
+  // glyph/character that appears on the key (and usually when typed).
+  if (::features::IsImprovedKeyboardShortcutsEnabled()) {
+    ui::DomCode dom_code =
+        ui::KeycodeConverter::MapUSPositionalShortcutKeyToDomCode(key_code);
+    if (dom_code != ui::DomCode::NONE) {
+      if (layout_engine->Lookup(dom_code, /*flags=*/ui::EF_NONE, &dom_key,
+                                &key_code_to_compare)) {
+        if (dom_key.IsDeadKey()) {
+          return GetStringForDeadKey(dom_key);
+        }
+        if (!dom_key.IsValid()) {
+          return std::u16string();
+        }
+        return base::UTF8ToUTF16(
+            ui::KeycodeConverter::DomKeyToKeyString(dom_key));
+      }
+      return std::u16string();
+    }
+  }
+
   for (const auto& dom_code : ui::dom_codes) {
-    if (!ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()->Lookup(
-            dom_code, /*flags=*/ui::EF_NONE, &dom_key, &key_code_to_compare)) {
+    if (!layout_engine->Lookup(dom_code, /*flags=*/ui::EF_NONE, &dom_key,
+                               &key_code_to_compare)) {
       continue;
     }
     if (key_code_to_compare != key_code || !dom_key.IsValid() ||
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc
index a987814..39594a1 100644
--- a/ash/wm/overview/overview_controller.cc
+++ b/ash/wm/overview/overview_controller.cc
@@ -447,7 +447,7 @@
       OnStartingAnimationComplete(/*canceled=*/false);
 
     if (!last_overview_session_time_.is_null()) {
-      UMA_HISTOGRAM_LONG_TIMES("Ash.WindowSelector.TimeBetweenUse",
+      UMA_HISTOGRAM_LONG_TIMES("Ash.Overview.TimeBetweenUse",
                                base::Time::Now() - last_overview_session_time_);
     }
   }
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc
index 731bc22d..1f1e702 100644
--- a/ash/wm/overview/overview_session.cc
+++ b/ash/wm/overview/overview_session.cc
@@ -230,7 +230,7 @@
   overview_focus_widget_->SetContentsView(
       std::make_unique<OverviewFocusButton>());
 
-  UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_);
+  UMA_HISTOGRAM_COUNTS_100("Ash.Overview.Items", num_items_);
 
   SplitViewController::Get(Shell::GetPrimaryRootWindow())->AddObserver(this);
 
@@ -294,9 +294,9 @@
     overview_grid->Shutdown();
 
   DCHECK(num_items_ >= remaining_items);
-  UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems",
+  UMA_HISTOGRAM_COUNTS_100("Ash.Overview.OverviewClosedItems",
                            num_items_ - remaining_items);
-  UMA_HISTOGRAM_MEDIUM_TIMES("Ash.WindowSelector.TimeInOverview",
+  UMA_HISTOGRAM_MEDIUM_TIMES("Ash.Overview.TimeInOverview",
                              base::Time::Now() - overview_start_time_);
 
   grid_list_.clear();
@@ -360,7 +360,7 @@
     const auto it = std::find(window_list.begin(), window_list.end(), window);
     if (it != window_list.end()) {
       // Record 1-based index so that selecting a top MRU window will record 1.
-      UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.SelectionDepth",
+      UMA_HISTOGRAM_COUNTS_100("Ash.Overview.SelectionDepth",
                                1 + it - window_list.begin());
     }
   }
@@ -833,9 +833,8 @@
 }
 
 void OverviewSession::OnHighlightedItemActivated(OverviewItem* item) {
-  UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses",
-                           num_key_presses_);
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.WindowSelector.KeyPressesOverItemsRatio",
+  UMA_HISTOGRAM_COUNTS_100("Ash.Overview.ArrowKeyPresses", num_key_presses_);
+  UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.Overview.KeyPressesOverItemsRatio",
                               (num_key_presses_ * 100) / num_items_, 1, 300,
                               30);
   base::RecordAction(
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc
index f1ddf8a6..81a3829 100644
--- a/ash/wm/workspace/workspace_window_resizer.cc
+++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -117,7 +117,7 @@
 
 // Dwell time before snap to maximize. The countdown starts when window dragged
 // into snap region.
-constexpr base::TimeDelta kDwellTime = base::TimeDelta::FromMilliseconds(800);
+constexpr base::TimeDelta kDwellTime = base::TimeDelta::FromMilliseconds(400);
 // The min amount of vertical movement needed for to trigger a snap to
 // maximize.
 constexpr int kSnapTriggerVerticalMoveThreshold = 64;
diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc
index b2e8ae3..d79db90 100644
--- a/base/debug/debugger_posix.cc
+++ b/base/debug/debugger_posix.cc
@@ -239,12 +239,12 @@
 #elif defined(OS_FUCHSIA)
 
 bool BeingDebugged() {
-  zx_info_process_t info = {};
+  zx_info_process_v2_t info = {};
   // Ignore failures. The 0-initialization above will result in "false" for
   // error cases.
-  zx_object_get_info(zx_process_self(), ZX_INFO_PROCESS, &info, sizeof(info),
+  zx_object_get_info(zx_process_self(), ZX_INFO_PROCESS_V2, &info, sizeof(info),
                      nullptr, nullptr);
-  return info.debugger_attached;
+  return (info.flags & ZX_INFO_PROCESS_FLAG_DEBUGGER_ATTACHED) != 0;
 }
 
 void VerifyDebugger() {}
diff --git a/base/memory/platform_shared_memory_region.cc b/base/memory/platform_shared_memory_region.cc
index 964844a..9060cc76a 100644
--- a/base/memory/platform_shared_memory_region.cc
+++ b/base/memory/platform_shared_memory_region.cc
@@ -70,6 +70,7 @@
   bool success = MapAtInternal(offset, size, memory, mapped_size);
   if (success) {
     DCHECK(IsAligned(*memory, kMapMinimumAlignment));
+    DCHECK_GE(*mapped_size, size);
   } else {
     SharedMemorySecurityPolicy::ReleaseReservationForMapping(size);
   }
diff --git a/base/memory/platform_shared_memory_region.h b/base/memory/platform_shared_memory_region.h
index 9b67c0e9..44d28e6 100644
--- a/base/memory/platform_shared_memory_region.h
+++ b/base/memory/platform_shared_memory_region.h
@@ -251,6 +251,9 @@
              void** memory,
              size_t* mapped_size) const;
 
+  // Unmaps a region previously mapped by |MapAt()|.
+  static bool Unmap(void* memory, size_t mapped_size);
+
   const UnguessableToken& GetGUID() const { return guid_; }
 
   size_t GetSize() const { return size_; }
diff --git a/base/memory/platform_shared_memory_region_android.cc b/base/memory/platform_shared_memory_region_android.cc
index f9b08b3..1f9b4b1 100644
--- a/base/memory/platform_shared_memory_region_android.cc
+++ b/base/memory/platform_shared_memory_region_android.cc
@@ -138,6 +138,16 @@
 }
 
 // static
+bool PlatformSharedMemoryRegion::Unmap(void* memory, size_t mapped_size) {
+  if (munmap(memory, mapped_size) < 0) {
+    DPLOG(ERROR) << "munmap";
+    return false;
+  }
+
+  return true;
+}
+
+// static
 PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode,
                                                               size_t size) {
   if (size == 0) {
diff --git a/base/memory/platform_shared_memory_region_fuchsia.cc b/base/memory/platform_shared_memory_region_fuchsia.cc
index 1f91ee81..4ddf9c7 100644
--- a/base/memory/platform_shared_memory_region_fuchsia.cc
+++ b/base/memory/platform_shared_memory_region_fuchsia.cc
@@ -110,7 +110,23 @@
   }
 
   *memory = reinterpret_cast<void*>(addr);
+
+  // NOTE: The mapping operation is guaranteed to fail above if the VMO is not
+  // large enough to map `size` bytes, so this is a safe assumption.
   *mapped_size = size;
+
+  return true;
+}
+
+// static
+bool PlatformSharedMemoryRegion::Unmap(void* memory, size_t mapped_size) {
+  uintptr_t addr = reinterpret_cast<uintptr_t>(memory);
+  zx_status_t status = zx::vmar::root_self()->unmap(addr, mapped_size);
+  if (status != ZX_OK) {
+    ZX_DLOG(ERROR, status) << "zx_vmar_unmap";
+    return false;
+  }
+
   return true;
 }
 
diff --git a/base/memory/platform_shared_memory_region_mac.cc b/base/memory/platform_shared_memory_region_mac.cc
index e3754f88..0a1e1e3d 100644
--- a/base/memory/platform_shared_memory_region_mac.cc
+++ b/base/memory/platform_shared_memory_region_mac.cc
@@ -150,11 +150,22 @@
     return false;
   }
 
+  // NOTE: The mach_vm_map call above will fail if `offset + size` falls outside
+  // the bounds of the memory object, so this is a safe assumption.
   *mapped_size = size;
   return true;
 }
 
 // static
+bool PlatformSharedMemoryRegion::Unmap(void* memory, size_t mapped_size) {
+  kern_return_t kr = mach_vm_deallocate(
+      mach_task_self(), reinterpret_cast<mach_vm_address_t>(memory),
+      mapped_size);
+  MACH_DLOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_vm_deallocate";
+  return kr == KERN_SUCCESS;
+}
+
+// static
 PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode,
                                                               size_t size) {
   if (size == 0) {
diff --git a/base/memory/platform_shared_memory_region_posix.cc b/base/memory/platform_shared_memory_region_posix.cc
index f62a7d6a..86793d5 100644
--- a/base/memory/platform_shared_memory_region_posix.cc
+++ b/base/memory/platform_shared_memory_region_posix.cc
@@ -6,11 +6,13 @@
 
 #include <fcntl.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
 
 #include "base/files/file.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 
@@ -187,6 +189,35 @@
                                                size_t size,
                                                void** memory,
                                                size_t* mapped_size) const {
+  // Validate the underlying file's size first. OSes like Linux will still allow
+  // mmap() to succeed even if the requested offset + size exceeds the file's
+  // size. In such cases we find ourselves with an apparent region of
+  // `mapped_size` bytes that -- while legally addressable -- is only partially
+  // mapped to physical memory. Attempts by application code to then address the
+  // physically unmapped portion will assert a SIGBUS.
+  //
+  // This check ensures that we only succeed if the file was of sufficient size
+  // at call time, which in turn ensures that we only indicate success when the
+  // full range of `mapped_size` bytes would be safely addressable without
+  // incurring any faults. This matches the expectations upheld by other
+  // platform implementations.
+  //
+  // Note that the NaCl fstat() implementation for shared memory FDs has a bug
+  // which causes it to copy uninitialized memory from out of the sandbox. Since
+  // the NaCl runtime is deprecated now, we simply avoid doing the check there.
+#if !defined(OS_NACL)
+  struct stat status;
+  int result = fstat(handle_.fd.get(), &status);
+  if (result != 0) {
+    DPLOG(ERROR) << "fstat failed on shared memory object " << handle_.fd.get();
+    return false;
+  }
+  if (status.st_size <
+      base::ClampAdd(base::saturated_cast<off_t>(size), offset)) {
+    return false;
+  }
+#endif
+
   bool write_allowed = mode_ != Mode::kReadOnly;
   *memory = mmap(nullptr, size, PROT_READ | (write_allowed ? PROT_WRITE : 0),
                  MAP_SHARED, handle_.fd.get(), offset);
@@ -202,6 +233,16 @@
 }
 
 // static
+bool PlatformSharedMemoryRegion::Unmap(void* memory, size_t mapped_size) {
+  if (munmap(memory, mapped_size) < 0) {
+    DPLOG(ERROR) << "munmap";
+    return false;
+  }
+
+  return true;
+}
+
+// static
 PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode,
                                                               size_t size
 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/base/memory/platform_shared_memory_region_unittest.cc b/base/memory/platform_shared_memory_region_unittest.cc
index 842fde9..15d2ef9 100644
--- a/base/memory/platform_shared_memory_region_unittest.cc
+++ b/base/memory/platform_shared_memory_region_unittest.cc
@@ -340,6 +340,15 @@
   EXPECT_FALSE(check(region2, Mode::kReadOnly));
 }
 
+// Tests that attempts to map beyond the bounds of the underlying shared memory
+// object will fail.
+TEST_F(PlatformSharedMemoryRegionTest, OversizedMappingFails) {
+  auto region = PlatformSharedMemoryRegion::CreateUnsafe(kRegionSize);
+  void* memory;
+  size_t mapped_size;
+  EXPECT_FALSE(region.MapAt(0, kRegionSize * 2, &memory, &mapped_size));
+}
+
 // Tests that it's impossible to create read-only platform shared memory region.
 TEST_F(PlatformSharedMemoryRegionTest, CreateReadOnlyRegionDeathTest) {
 #ifdef OFFICIAL_BUILD
diff --git a/base/memory/platform_shared_memory_region_win.cc b/base/memory/platform_shared_memory_region_win.cc
index 21a1f2a..cfd1abb 100644
--- a/base/memory/platform_shared_memory_region_win.cc
+++ b/base/memory/platform_shared_memory_region_win.cc
@@ -213,6 +213,23 @@
   }
 
   *mapped_size = GetMemorySectionSize(*memory);
+  if (*mapped_size < size) {
+    // Mapping may succeed even if the actual shared memory object is smaller
+    // than `size` bytes. Make sure we still fail in that case.
+    Unmap(*memory, *mapped_size);
+    return false;
+  }
+
+  return true;
+}
+
+// static
+bool PlatformSharedMemoryRegion::Unmap(void* memory, size_t mapped_size) {
+  if (!UnmapViewOfFile(memory)) {
+    DPLOG(ERROR) << "UnmapViewOfFile";
+    return false;
+  }
+
   return true;
 }
 
diff --git a/base/memory/shared_memory_mapping.cc b/base/memory/shared_memory_mapping.cc
index a8c2cdf..171dee60 100644
--- a/base/memory/shared_memory_mapping.cc
+++ b/base/memory/shared_memory_mapping.cc
@@ -7,28 +7,10 @@
 #include <utility>
 
 #include "base/logging.h"
+#include "base/memory/platform_shared_memory_region.h"
 #include "base/memory/shared_memory_security_policy.h"
 #include "base/memory/shared_memory_tracker.h"
 #include "base/unguessable_token.h"
-#include "build/build_config.h"
-
-#if defined(OS_POSIX)
-#include <sys/mman.h>
-#endif
-
-#if defined(OS_WIN)
-#include <aclapi.h>
-#endif
-
-#if defined(OS_MAC)
-#include <mach/mach_vm.h>
-#include "base/mac/mach_logging.h"
-#endif
-
-#if defined(OS_FUCHSIA)
-#include <lib/zx/vmar.h>
-#include "base/fuchsia/fuchsia_logging.h"
-#endif
 
 namespace base {
 
@@ -68,23 +50,7 @@
 
   SharedMemorySecurityPolicy::ReleaseReservationForMapping(size_);
   SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this);
-#if defined(OS_WIN)
-  if (!UnmapViewOfFile(memory_))
-    DPLOG(ERROR) << "UnmapViewOfFile";
-#elif defined(OS_FUCHSIA)
-  uintptr_t addr = reinterpret_cast<uintptr_t>(memory_);
-  zx_status_t status = zx::vmar::root_self()->unmap(addr, mapped_size_);
-  if (status != ZX_OK)
-    ZX_DLOG(ERROR, status) << "zx_vmar_unmap";
-#elif defined(OS_MAC)
-  kern_return_t kr = mach_vm_deallocate(
-      mach_task_self(), reinterpret_cast<mach_vm_address_t>(memory_),
-      mapped_size_);
-  MACH_DLOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_vm_deallocate";
-#else
-  if (munmap(memory_, mapped_size_) < 0)
-    DPLOG(ERROR) << "munmap";
-#endif
+  subtle::PlatformSharedMemoryRegion::Unmap(memory_, mapped_size_);
 }
 
 ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping() = default;
diff --git a/base/message_loop/message_pump_fuchsia.cc b/base/message_loop/message_pump_fuchsia.cc
index 5e08189..beb3f76 100644
--- a/base/message_loop/message_pump_fuchsia.cc
+++ b/base/message_loop/message_pump_fuchsia.cc
@@ -121,17 +121,20 @@
   // case, we don't want to call both the CanWrite and CanRead callback,
   // when the caller asked for only, for example, readable callbacks. So,
   // mask with the events that we actually wanted to know about.
-  events &= desired_events_;
-  DCHECK_NE(0u, events);
+  //
+  // Note that errors are always included.
+  const uint32_t desired_events = desired_events_ | FDIO_EVT_ERROR;
+  const uint32_t filtered_events = events & desired_events;
+  DCHECK_NE(filtered_events, 0u) << events << " & " << desired_events;
 
   // Each |watcher_| callback we invoke may stop or delete |this|. The pump has
   // set |was_stopped_| to point to a safe location on the calling stack, so we
   // can use that to detect being stopped mid-callback and avoid doing further
   // work that would touch |this|.
   bool* was_stopped = was_stopped_;
-  if (events & FDIO_EVT_WRITABLE)
+  if (filtered_events & FDIO_EVT_WRITABLE)
     watcher_->OnFileCanWriteWithoutBlocking(fd_);
-  if (!*was_stopped && (events & FDIO_EVT_READABLE))
+  if (!*was_stopped && (filtered_events & FDIO_EVT_READABLE))
     watcher_->OnFileCanReadWithoutBlocking(fd_);
 
   // Don't add additional work here without checking |*was_stopped_| again.
diff --git a/base/process/kill_fuchsia.cc b/base/process/kill_fuchsia.cc
index 12920d0..5468399 100644
--- a/base/process/kill_fuchsia.cc
+++ b/base/process/kill_fuchsia.cc
@@ -16,20 +16,20 @@
 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
   DCHECK(exit_code);
 
-  zx_info_process_t process_info;
+  zx_info_process_v2_t process_info;
   zx_status_t status =
-      zx_object_get_info(handle, ZX_INFO_PROCESS, &process_info,
+      zx_object_get_info(handle, ZX_INFO_PROCESS_V2, &process_info,
                          sizeof(process_info), nullptr, nullptr);
   if (status != ZX_OK) {
     DLOG(ERROR) << "unable to get termination status for " << handle;
     *exit_code = 0;
     return TERMINATION_STATUS_NORMAL_TERMINATION;
   }
-  if (!process_info.started) {
+  if ((process_info.flags & ZX_INFO_PROCESS_FLAG_STARTED) == 0) {
     *exit_code = 0;
     return TERMINATION_STATUS_LAUNCH_FAILED;
   }
-  if (!process_info.exited) {
+  if ((process_info.flags & ZX_INFO_PROCESS_FLAG_EXITED) == 0) {
     *exit_code = 0;
     return TERMINATION_STATUS_STILL_RUNNING;
   }
diff --git a/base/process/process_fuchsia.cc b/base/process/process_fuchsia.cc
index ae080ffa..8ee22bb 100644
--- a/base/process/process_fuchsia.cc
+++ b/base/process/process_fuchsia.cc
@@ -243,8 +243,8 @@
     return false;
   }
 
-  zx_info_process_t proc_info;
-  status = zx_object_get_info(process_.get(), ZX_INFO_PROCESS, &proc_info,
+  zx_info_process_v2_t proc_info;
+  status = zx_object_get_info(process_.get(), ZX_INFO_PROCESS_V2, &proc_info,
                               sizeof(proc_info), nullptr, nullptr);
   if (status != ZX_OK) {
     ZX_DLOG(ERROR, status) << "zx_object_get_info";
diff --git a/base/test/power_monitor_test_base.cc b/base/test/power_monitor_test_base.cc
index dc078246..9dcc964d 100644
--- a/base/test/power_monitor_test_base.cc
+++ b/base/test/power_monitor_test_base.cc
@@ -12,6 +12,78 @@
 namespace base {
 namespace test {
 
+class PowerMonitorTestSource : public PowerMonitorSource {
+ public:
+  PowerMonitorTestSource() = default;
+  ~PowerMonitorTestSource() override = default;
+
+  // Retrieve current states.
+  PowerThermalObserver::DeviceThermalState GetCurrentThermalState() override;
+  bool IsOnBatteryPower() override;
+
+  // Sends asynchronous notifications to registered observers.
+  void Suspend();
+  void Resume();
+  void SetOnBatteryPower(bool on_battery_power);
+
+  // Sends asynchronous notifications to registered observers and ensures they
+  // are executed (i.e. RunUntilIdle()).
+  void GeneratePowerStateEvent(bool on_battery_power);
+  void GenerateSuspendEvent();
+  void GenerateResumeEvent();
+  void GenerateThermalThrottlingEvent(
+      PowerThermalObserver::DeviceThermalState new_thermal_state);
+
+ protected:
+  bool test_on_battery_power_ = false;
+  PowerThermalObserver::DeviceThermalState current_thermal_state_ =
+      PowerThermalObserver::DeviceThermalState::kUnknown;
+};
+
+PowerThermalObserver::DeviceThermalState
+PowerMonitorTestSource::GetCurrentThermalState() {
+  return current_thermal_state_;
+}
+
+void PowerMonitorTestSource::Suspend() {
+  ProcessPowerEvent(SUSPEND_EVENT);
+}
+
+void PowerMonitorTestSource::Resume() {
+  ProcessPowerEvent(RESUME_EVENT);
+}
+
+void PowerMonitorTestSource::SetOnBatteryPower(bool on_battery_power) {
+  test_on_battery_power_ = on_battery_power;
+  ProcessPowerEvent(POWER_STATE_EVENT);
+}
+
+void PowerMonitorTestSource::GeneratePowerStateEvent(bool on_battery_power) {
+  SetOnBatteryPower(on_battery_power);
+  RunLoop().RunUntilIdle();
+}
+
+void PowerMonitorTestSource::GenerateSuspendEvent() {
+  Suspend();
+  RunLoop().RunUntilIdle();
+}
+
+void PowerMonitorTestSource::GenerateResumeEvent() {
+  Resume();
+  RunLoop().RunUntilIdle();
+}
+
+bool PowerMonitorTestSource::IsOnBatteryPower() {
+  return test_on_battery_power_;
+}
+
+void PowerMonitorTestSource::GenerateThermalThrottlingEvent(
+    PowerThermalObserver::DeviceThermalState new_thermal_state) {
+  ProcessThermalEvent(new_thermal_state);
+  current_thermal_state_ = new_thermal_state;
+  RunLoop().RunUntilIdle();
+}
+
 ScopedPowerMonitorTestSource::ScopedPowerMonitorTestSource() {
   auto power_monitor_test_source = std::make_unique<PowerMonitorTestSource>();
   power_monitor_test_source_ = power_monitor_test_source.get();
@@ -63,53 +135,6 @@
 
 }  // namespace test
 
-PowerMonitorTestSource::PowerMonitorTestSource() = default;
-PowerMonitorTestSource::~PowerMonitorTestSource() = default;
-
-PowerThermalObserver::DeviceThermalState
-PowerMonitorTestSource::GetCurrentThermalState() {
-  return current_thermal_state_;
-}
-
-void PowerMonitorTestSource::Suspend() {
-  ProcessPowerEvent(SUSPEND_EVENT);
-}
-
-void PowerMonitorTestSource::Resume() {
-  ProcessPowerEvent(RESUME_EVENT);
-}
-
-void PowerMonitorTestSource::SetOnBatteryPower(bool on_battery_power) {
-  test_on_battery_power_ = on_battery_power;
-  ProcessPowerEvent(POWER_STATE_EVENT);
-}
-
-void PowerMonitorTestSource::GeneratePowerStateEvent(bool on_battery_power) {
-  SetOnBatteryPower(on_battery_power);
-  RunLoop().RunUntilIdle();
-}
-
-void PowerMonitorTestSource::GenerateSuspendEvent() {
-  Suspend();
-  RunLoop().RunUntilIdle();
-}
-
-void PowerMonitorTestSource::GenerateResumeEvent() {
-  Resume();
-  RunLoop().RunUntilIdle();
-}
-
-bool PowerMonitorTestSource::IsOnBatteryPower() {
-  return test_on_battery_power_;
-}
-
-void PowerMonitorTestSource::GenerateThermalThrottlingEvent(
-    PowerThermalObserver::DeviceThermalState new_thermal_state) {
-  ProcessThermalEvent(new_thermal_state);
-  current_thermal_state_ = new_thermal_state;
-  RunLoop().RunUntilIdle();
-}
-
 PowerMonitorTestObserver::PowerMonitorTestObserver() = default;
 PowerMonitorTestObserver::~PowerMonitorTestObserver() = default;
 
diff --git a/base/test/power_monitor_test_base.h b/base/test/power_monitor_test_base.h
index a6dd91cb..64bff6c8 100644
--- a/base/test/power_monitor_test_base.h
+++ b/base/test/power_monitor_test_base.h
@@ -10,12 +10,12 @@
 
 namespace base {
 
+namespace test {
+
 // Use PowerMonitorTestSource via ScopedPowerMonitorTestSource wrapper when you
 // need to simulate power events (suspend and resume).
 class PowerMonitorTestSource;
 
-namespace test {
-
 // ScopedPowerMonitorTestSource initializes the PowerMonitor with a Mock
 // PowerMonitorSource. Mock power notifications can be simulated through this
 // helper class.
@@ -56,36 +56,7 @@
 
 }  // namespace test
 
-// TODO(crbug/1188692): Move `PowerMonitorTestSource` and
-// `PowerMonitorTestObserver` into `test` namespace.
-class PowerMonitorTestSource : public PowerMonitorSource {
- public:
-  PowerMonitorTestSource();
-  ~PowerMonitorTestSource() override;
-
-  // Retrieve current states.
-  PowerThermalObserver::DeviceThermalState GetCurrentThermalState() override;
-  bool IsOnBatteryPower() override;
-
-  // Sends asynchronous notifications to registered observers.
-  void Suspend();
-  void Resume();
-  void SetOnBatteryPower(bool on_battery_power);
-
-  // Sends asynchronous notifications to registered observers and ensures they
-  // are executed (i.e. RunUntilIdle()).
-  void GeneratePowerStateEvent(bool on_battery_power);
-  void GenerateSuspendEvent();
-  void GenerateResumeEvent();
-  void GenerateThermalThrottlingEvent(
-      PowerThermalObserver::DeviceThermalState new_thermal_state);
-
- protected:
-  bool test_on_battery_power_ = false;
-  PowerThermalObserver::DeviceThermalState current_thermal_state_ =
-      PowerThermalObserver::DeviceThermalState::kUnknown;
-};
-
+// TODO(crbug/1188692): Move `PowerMonitorTestObserver` into `test` namespace.
 class PowerMonitorTestObserver : public PowerSuspendObserver,
                                  public PowerThermalObserver,
                                  public PowerStateObserver {
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 37467f4..c9decbb 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -934,9 +934,9 @@
 
   @contextlib.contextmanager
   def _ArchiveLogcat(self, device, test_name):
-    stream_name = 'logcat_%s_%s_%s' % (test_name.replace(
-        '#', '.'), time.strftime('%Y%m%dT%H%M%S-UTC',
-                                 time.gmtime()), device.serial)
+    stream_name = 'logcat_%s_shard%s_%s_%s' % (
+        test_name.replace('#', '.'), self._test_instance.external_shard_index,
+        time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial)
 
     logcat_file = None
     logmon = None
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 93706a6..7c33eac 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -3948,14 +3948,16 @@
       final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk"
 
       if (!defined(use_default_launcher) || use_default_launcher) {
-        deps += [ "//testing/android/native_test:native_test_java" ]
+        deps += [
+          "//base:base_java",
+          "//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
+          "//testing/android/native_test:native_test_java",
+        ]
       }
       shared_libraries = [ invoker.shared_library ]
       deps += [
         ":${target_name}__secondary_abi_shared_library_list",
         ":${target_name}__shared_library_list",
-        "//base:base_java",
-        "//testing/android/reporter:reporter_java",
       ]
     }
   }
diff --git a/build/config/chromeos/rules.gni b/build/config/chromeos/rules.gni
index eff89c7a..bb913e8 100644
--- a/build/config/chromeos/rules.gni
+++ b/build/config/chromeos/rules.gni
@@ -107,7 +107,9 @@
 #       results tracking and displaying (eg: flakiness dashboard).
 #   generated_script: Path to place the generated script.
 #   deploy_chrome: If true, deploys a locally built chrome located in the root
-#       build dir to the VM after launching it.
+#       build dir to the VM or DUT after launching it.
+#   deploy_lacros: If true, deploys a locally built Lacros located in the root
+#       build dir to the VM or DUT after launching it.
 #   runtime_deps_file: Path to file listing runtime deps for the test. If set,
 #       all files listed will be copied to the VM before testing.
 #   override_board: "cros_board" variable was used to decide both the toolchain
@@ -124,6 +126,7 @@
                          [
                            "override_board",
                            "deploy_chrome",
+                           "deploy_lacros",
                            "generated_script",
                            "runtime_deps_file",
                            "tast_attr_expr",
@@ -137,6 +140,14 @@
     cros_board = override_board
   }
 
+  if (!defined(deploy_chrome)) {
+    deploy_chrome = false
+  }
+
+  if (!defined(deploy_lacros)) {
+    deploy_lacros = false
+  }
+
   cros_is_vm = false
   is_tast = defined(tast_attr_expr) || defined(tast_tests)
   if (is_chromeos_device && cros_sdk_version != "") {
@@ -157,9 +168,8 @@
       }
     }
 
-    if (!defined(deploy_chrome)) {
-      deploy_chrome = false
-    }
+    assert(!(deploy_chrome && deploy_lacros),
+           "deploy_chrome and deploy_lacros are exclusive.")
 
     if (is_tast || cros_is_vm || deploy_chrome) {
       _symlink_targets = []
@@ -265,7 +275,7 @@
       args += [ "--deploy-chrome" ]
     }
 
-    if (is_chromeos_lacros) {
+    if (deploy_lacros) {
       args += [ "--deploy-lacros" ]
     }
 
@@ -414,6 +424,7 @@
 
   generate_runner_script(target_name) {
     testonly = true
+    deploy_lacros = true
     generated_script = "$root_build_dir/bin/run_${target_name}"
     runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps"
 
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index ae94f612..a1f44c8 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-3.20210412.1.1
+3.20210412.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index ae94f612..14cea9a 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-3.20210412.1.1
+3.20210412.3.1
diff --git a/cc/raster/OWNERS b/cc/raster/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/cc/raster/OWNERS
+++ /dev/null
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 8f56341..5afe0850 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -563,16 +563,12 @@
 
 void SingleThreadProxy::NotifyThroughputTrackerResults(
     CustomTrackerResults results) {
-  DCHECK(task_runner_provider_->IsImplThread());
-  // This method is called from ImplThread side so post a task to
-  // MainThread. This is necessary because the throughput tracker callbacks are
-  // supposed to be executed on MainThread side, which may invok compositor's
-  // method that expected to be executed on MainThread.
-  task_runner_provider_->MainThreadTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &SingleThreadProxy::NotifyThroughputTrackerResultsOnMainThread,
-          weak_factory_.GetWeakPtr(), std::move(results)));
+  // This method is called from ImplThread side to report after being requested,
+  // or from the MainThread when releasing FrameSequenceTrackers during
+  // destruction. Regardless, `layer_tree_host_` should be accessed from
+  // MainThread side.
+  DebugScopedSetMainThread main(task_runner_provider_);
+  layer_tree_host_->NotifyThroughputTrackerResults(std::move(results));
 }
 
 bool SingleThreadProxy::IsInSynchronousComposite() const {
@@ -1015,9 +1011,4 @@
   layer_tree_host_->DidReceiveCompositorFrameAck();
 }
 
-void SingleThreadProxy::NotifyThroughputTrackerResultsOnMainThread(
-    CustomTrackerResults results) {
-  layer_tree_host_->NotifyThroughputTrackerResults(std::move(results));
-}
-
 }  // namespace cc
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 246df680..c5d23a9 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -180,7 +180,6 @@
   void IssueImageDecodeFinishedCallbacks();
 
   void DidReceiveCompositorFrameAck();
-  void NotifyThroughputTrackerResultsOnMainThread(CustomTrackerResults results);
 
   // Accessed on main thread only.
   LayerTreeHost* layer_tree_host_;
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 7390a29..514559b 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1181,7 +1181,6 @@
   "java/src/org/chromium/chrome/browser/share/LensUtils.java",
   "java/src/org/chromium/chrome/browser/share/OptionalShareTargetsManager.java",
   "java/src/org/chromium/chrome/browser/share/ShareButtonController.java",
-  "java/src/org/chromium/chrome/browser/share/ShareDelegate.java",
   "java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java",
   "java/src/org/chromium/chrome/browser/share/ShareDelegateSupplier.java",
   "java/src/org/chromium/chrome/browser/share/ShareHelper.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
index c158395..f134a88 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -22,7 +22,7 @@
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.chrome.browser.share.ChromeShareExtras;
 import org.chromium.chrome.browser.share.ShareDelegate;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabCreationState;
 import org.chromium.chrome.browser.tab.TabLaunchType;
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
index 0c13072..3f6aa8b 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
@@ -42,7 +42,7 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.share.ChromeShareExtras;
 import org.chromium.chrome.browser.share.ShareDelegate;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.suggestions.NavigationRecorder;
 import org.chromium.chrome.browser.suggestions.SuggestionsConfig;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java
index 940e468..0d012b5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java
@@ -23,7 +23,7 @@
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.share.ChromeShareExtras;
 import org.chromium.chrome.browser.share.ShareDelegate;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabUtils;
 import org.chromium.chrome.browser.tab.TabWebContentsObserver;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
index a3c8141..9cc3a70 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
@@ -50,27 +50,6 @@
   "DigitalGoodsFactoryImpl\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
-  "OverlayPanel\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
-  "OverlayPanelBase\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
-  "OverlayPanelContent\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
-  "BarOverlapTapSuppression\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
-  "ContextualSearchManagementDelegate\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
-  "ContextualSearchManager\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
-  "ContextualSearchSelectionController\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
   "ContextualSearchTabHelper\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index 79c961ce..d4e16bc3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -1991,8 +1991,13 @@
         mActivityTabProvider.setLayoutManager(layoutManager);
 
         if (mContextualSearchManager != null) {
-            mContextualSearchManager.initialize(
-                    contentContainer, layoutManager, mRootUiCoordinator.getBottomSheetController());
+            mContextualSearchManager.initialize(contentContainer, layoutManager,
+                    mRootUiCoordinator.getBottomSheetController(), getCompositorViewHolder(),
+                    getControlContainerHeightResource() == NO_CONTROL_CONTAINER
+                            ? 0
+                            : getResources().getDimensionPixelSize(
+                                    getControlContainerHeightResource()),
+                    getToolbarManager(), getActivityType());
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
index b29c508b..a0fc1aa35 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
@@ -13,13 +13,15 @@
 import android.view.ViewGroup;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.cc.input.BrowserControlsState;
-import org.chromium.chrome.browser.app.ChromeActivity;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.PanelPriority;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
@@ -31,12 +33,14 @@
 import org.chromium.chrome.browser.layouts.components.VirtualView;
 import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer;
 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabBrowserControlsConstraintsHelper;
 import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.ScrollDirection;
 import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.SwipeHandler;
 import org.chromium.content_public.browser.SelectionPopupController;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.LocalizationUtils;
+import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.resources.ResourceManager;
 
 import java.lang.annotation.Retention;
@@ -115,8 +119,25 @@
     /** The observer that reacts to scene-change events. */
     private final SceneChangeObserver mSceneChangeObserver;
 
+    /** Used to measure the browser controls. */
+    private final BrowserControlsStateProvider mBrowserControlsStateProvider;
+
+    /** The {@link WindowAndroid} for the current activity.  */
+    private final WindowAndroid mWindowAndroid;
+
+    /**
+     * The {@link CompositorViewHolder}, used as an anchor view. Also injected into other classes.
+     */
+    private final ViewGroup mCompositorViewHolder;
+
+    /** Supplies the current activity {@link Tab}. */
+    private final Supplier<Tab> mCurrentTabSupplier;
+
+    /** OverlayPanel manager handle for notifications of opening and closing. */
+    protected final OverlayPanelManager mPanelManager;
+
     /** The activity this panel is in. */
-    protected ChromeActivity mActivity;
+    protected Activity mActivity;
 
     /** The initial height of the Overlay Panel. */
     private float mInitialPanelHeight;
@@ -136,9 +157,6 @@
     /** Container for content the panel will show. */
     private OverlayPanelContent mContent;
 
-    /** OverlayPanel manager handle for notifications of opening and closing. */
-    protected OverlayPanelManager mPanelManager;
-
     /** If the base page text controls have been cleared. */
     private boolean mDidClearTextControls;
 
@@ -163,12 +181,23 @@
      * @param context The current Android {@link Context}.
      * @param layoutManager A {@link LayoutManagerImpl} for observing changes in the active layout.
      * @param panelManager The {@link OverlayPanelManager} responsible for showing panels.
+     * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for measuring
+     *         controls.
+     * @param windowAndroid The {@link WindowAndroid} for the current activity.
+     * @param compositorViewHolder The {@link CompositorViewHolder}
      */
-    public OverlayPanel(
-            Context context, LayoutManagerImpl layoutManager, OverlayPanelManager panelManager) {
-        super(context, layoutManager);
+    public OverlayPanel(@NonNull Context context, @NonNull LayoutManagerImpl layoutManager,
+            @NonNull OverlayPanelManager panelManager,
+            @NonNull BrowserControlsStateProvider browserControlsStateProvider,
+            @NonNull WindowAndroid windowAndroid, @NonNull ViewGroup compositorViewHolder,
+            int toolbarHeight, @NonNull Supplier<Tab> currentTabSupplier) {
+        super(context, layoutManager, toolbarHeight);
         mLayoutManager = layoutManager;
         mContentFactory = this;
+        mBrowserControlsStateProvider = browserControlsStateProvider;
+        mWindowAndroid = windowAndroid;
+        mCompositorViewHolder = compositorViewHolder;
+        mCurrentTabSupplier = currentTabSupplier;
 
         mPanelManager = panelManager;
         mPanelManager.registerPanel(this);
@@ -183,8 +212,8 @@
                 closePanel(StateChangeReason.UNKNOWN, false);
             }
         };
-        // mLayoutManager will be null in testing.
-        if (mLayoutManager != null) mLayoutManager.addSceneChangeObserver(mSceneChangeObserver);
+
+        mLayoutManager.addSceneChangeObserver(mSceneChangeObserver);
     }
 
     /**
@@ -192,7 +221,7 @@
      */
     public void destroy() {
         closePanel(StateChangeReason.UNKNOWN, false);
-        if (mLayoutManager != null) mLayoutManager.removeSceneChangeObserver(mSceneChangeObserver);
+        mLayoutManager.removeSceneChangeObserver(mSceneChangeObserver);
         ApplicationStatus.unregisterActivityStateListener(this);
     }
 
@@ -285,17 +314,15 @@
     }
 
     /**
-     * @param activity The ChromeActivity associated with the panel.
+     * @param activity The {@link Activity} associated with the panel.
      */
-    public void setChromeActivity(Activity activity) {
-        mActivity = (ChromeActivity) activity;
+    public void setActivity(Activity activity) {
+        mActivity = activity;
         if (mActivity != null) {
             ApplicationStatus.registerStateListenerForActivity(this, mActivity);
         } else {
             throw new RuntimeException("Activity provided to OverlayPanel cannot be null!");
         }
-
-        initializeUiState();
     }
 
     /**
@@ -337,7 +364,7 @@
      */
     protected float getBrowserControlsOffsetDp() {
         if (mActivity == null) return 0.0f;
-        return -mActivity.getBrowserControlsManager().getTopControlOffset() * mPxToDp;
+        return -mBrowserControlsStateProvider.getTopControlOffset() * mPxToDp;
     }
 
     /**
@@ -346,9 +373,10 @@
      * @param visible If the text controls are visible.
      */
     protected void setBasePageTextControlsVisibility(boolean visible) {
-        if (mActivity == null || mActivity.getActivityTab() == null) return;
+        if (mActivity == null) return;
+        if (!mCurrentTabSupplier.hasValue()) return;
 
-        WebContents baseWebContents = mActivity.getActivityTab().getWebContents();
+        WebContents baseWebContents = mCurrentTabSupplier.get().getWebContents();
         if (baseWebContents == null) return;
 
         // If the panel does not have focus or isn't open, return.
@@ -485,7 +513,7 @@
     public OverlayPanelContent createNewOverlayPanelContent() {
         return new OverlayPanelContent(new OverlayContentDelegate(),
                 new OverlayContentProgressObserver(), mActivity, /* isIncognito= */ false,
-                getBarHeight());
+                getBarHeight(), mCompositorViewHolder, mWindowAndroid, mCurrentTabSupplier);
     }
 
     /**
@@ -530,7 +558,7 @@
      *                should jump immediately.
      */
     public void updateBrowserControlsState(int current, boolean animate) {
-        TabBrowserControlsConstraintsHelper.update(mActivity.getActivityTab(), current, animate);
+        TabBrowserControlsConstraintsHelper.update(mCurrentTabSupplier.get(), current, animate);
     }
 
     /**
@@ -585,13 +613,6 @@
         }
     }
 
-    @Override
-    protected int getControlContainerHeightResource() {
-        // TODO(mdjones): Investigate passing this in to the constructor instead.
-        assert mActivity != null;
-        return mActivity.getControlContainerHeightResource();
-    }
-
     // ============================================================================================
     // Layout Integration
     // ============================================================================================
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
index bc44543..5ef6704 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
@@ -56,9 +56,10 @@
     /**
      * @param context The current Android {@link Context}.
      * @param updateHost The {@link LayoutUpdateHost} used to request updates in the Layout.
+     * @param toolbarHeight The height of the toolbar in pixels.
      */
-    public OverlayPanelAnimation(Context context, LayoutUpdateHost updateHost) {
-        super(context);
+    public OverlayPanelAnimation(Context context, LayoutUpdateHost updateHost, int toolbarHeight) {
+        super(context, toolbarHeight);
         mUpdateHost = updateHost;
     }
 
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 8e072e7..db7e4e6 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
@@ -16,7 +16,6 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.MathUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.ui.base.LocalizationUtils;
@@ -100,8 +99,8 @@
     /** Ratio of dps per pixel. */
     protected final float mPxToDp;
 
-    /** The height of the Toolbar in dps. */
-    private float mToolbarHeight;
+    /** The height of the Toolbar in pixels. */
+    private int mToolbarHeight;
 
     /** The background color of the Bar. */
     private final @ColorInt int mBarBackgroundColor;
@@ -133,9 +132,11 @@
 
     /**
      * @param context The current Android {@link Context}.
+     * @param toolbarHeight The current height of the toolbar in pixels.
      */
-    public OverlayPanelBase(Context context) {
+    public OverlayPanelBase(Context context, int toolbarHeight) {
         mContext = context;
+        mToolbarHeight = toolbarHeight;
         mPxToDp = 1.f / mContext.getResources().getDisplayMetrics().density;
 
         mBarMarginSide = BAR_ICON_SIDE_PADDING_DP;
@@ -190,12 +191,6 @@
     public abstract void showPanel(@StateChangeReason int reason);
 
     /**
-     * TODO(mdjones): This method should be removed from this class.
-     * @return The resource id that contains how large the browser controls are.
-     */
-    protected abstract int getControlContainerHeightResource();
-
-    /**
      * Handles when the Panel's container view size changes.
      * @param width The new width of the Panel's container view.
      * @param height The new height of the Panel's container view.
@@ -284,7 +279,7 @@
     /**
      * @return The height of the Chrome toolbar in dp.
      */
-    public float getToolbarHeight() {
+    public int getToolbarHeight() {
         return mToolbarHeight;
     }
 
@@ -733,20 +728,6 @@
     }
 
     /**
-     * Initializes the UI state.
-     */
-    protected void initializeUiState() {
-        // TODO(pedrosimonetti): Coordinate with mdjones@ to move this to the OverlayPanelBase
-        // constructor, once we are able to get the Activity during instantiation. The Activity
-        // is needed in order to get the correct height of the Toolbar, which varies depending
-        // on the Activity (WebApps have a smaller toolbar for example).
-        int toolbarHeightResource = getControlContainerHeightResource();
-        mToolbarHeight = toolbarHeightResource == ChromeActivity.NO_CONTROL_CONTAINER
-                ? 0
-                : mContext.getResources().getDimension(toolbarHeightResource) * mPxToDp;
-    }
-
-    /**
      * @return The fraction of the distance the panel has to be to its next state before animating
      *         itself there. Default is the panel must be half of the way to the next state.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
index 62f0bc4c..23d05de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
@@ -4,18 +4,20 @@
 
 package org.chromium.chrome.browser.compositor.bottombar;
 
+import android.app.Activity;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
 import android.view.ViewGroup.MarginLayoutParams;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.WebContentsFactory;
-import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.content.ContentUtils;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl;
@@ -35,6 +37,7 @@
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
 import org.chromium.ui.base.ViewAndroidDelegate;
+import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
 
 /**
@@ -43,6 +46,17 @@
  * panel has.
  */
 public class OverlayPanelContent {
+    /** The {@link CompositorViewHolder} for the current activity, used to add/remove views. */
+    private final ViewGroup mCompositorViewHolder;
+
+    /** The {@link WindowAndroid} for the current activity. */
+    private final WindowAndroid mWindowAndroid;
+
+    /** Supplies the current activity {@link Tab}. */
+    private final Supplier<Tab> mCurrentTabSupplier;
+
+    /** Used for progress bar events. */
+    private final WebContentsDelegateAndroid mWebContentsDelegate;
 
     /** The WebContents that this panel will display. */
     private WebContents mWebContents;
@@ -53,11 +67,8 @@
     /** The pointer to the native version of this class. */
     private long mNativeOverlayPanelContentPtr;
 
-    /** Used for progress bar events. */
-    private final WebContentsDelegateAndroid mWebContentsDelegate;
-
     /** The activity that this content is contained in. */
-    private ChromeActivity mActivity;
+    private Activity mActivity;
 
     /** Observer used for tracking loading and navigation. */
     private WebContentsObserver mWebContentsObserver;
@@ -144,7 +155,7 @@
         final ExternalNavigationHandler mExternalNavHandler;
 
         public InterceptNavigationDelegateImpl() {
-            Tab tab = mActivity.getActivityTab();
+            Tab tab = mCurrentTabSupplier.get();
             mExternalNavHandler = (tab != null && tab.getWebContents() != null)
                     ? new ExternalNavigationHandler(new ExternalNavigationDelegateImpl(tab))
                     : null;
@@ -170,19 +181,26 @@
      * @param contentDelegate An observer for events that occur on this content. If null is passed
      *                        for this parameter, the default one will be used.
      * @param progressObserver An observer for progress related events.
-     * @param activity The ChromeActivity that contains this object.
+     * @param activity The {@link Activity} that contains this object.
      * @param isIncognito {@True} if opened for an incognito tab
      * @param barHeight The height of the bar at the top of the OverlayPanel in dp.
+     * @param compositorViewHolder The {@link CompositorViewHolder} for the current activity.
+     * @param windowAndroid The {@link WindowAndroid} for the current activity.
+     * @param currentTabSupplier Supplies the current activity {@link Tab}.
      */
-    public OverlayPanelContent(OverlayContentDelegate contentDelegate,
-            OverlayContentProgressObserver progressObserver, ChromeActivity activity,
-            boolean isIncognito, float barHeight) {
+    public OverlayPanelContent(@NonNull OverlayContentDelegate contentDelegate,
+            @NonNull OverlayContentProgressObserver progressObserver, @NonNull Activity activity,
+            boolean isIncognito, float barHeight, @NonNull ViewGroup compositorViewHolder,
+            @NonNull WindowAndroid windowAndroid, @NonNull Supplier<Tab> currentTabSupplier) {
         mNativeOverlayPanelContentPtr = OverlayPanelContentJni.get().init(OverlayPanelContent.this);
         mContentDelegate = contentDelegate;
         mProgressObserver = progressObserver;
         mActivity = activity;
         mIsIncognito = isIncognito;
         mBarHeightPx = (int) (barHeight * mActivity.getResources().getDisplayMetrics().density);
+        mCompositorViewHolder = compositorViewHolder;
+        mWindowAndroid = windowAndroid;
+        mCurrentTabSupplier = currentTabSupplier;
 
         mWebContentsDelegate = new WebContentsDelegateAndroid() {
             private boolean mIsFullscreen;
@@ -224,8 +242,7 @@
 
             @Override
             public int getTopControlsHeight() {
-                return (int) (mBarHeightPx
-                        / mActivity.getWindowAndroid().getDisplay().getDipScale());
+                return (int) (mBarHeightPx / mWindowAndroid.getDisplay().getDipScale());
             }
 
             @Override
@@ -316,8 +333,7 @@
             destroyWebContents();
         }
 
-        Profile profile = IncognitoUtils.getProfileFromWindowAndroid(
-                mActivity.getWindowAndroid(), mIsIncognito);
+        Profile profile = IncognitoUtils.getProfileFromWindowAndroid(mWindowAndroid, mIsIncognito);
         // Creates an initially hidden WebContents which gets shown when the panel is opened.
         mWebContents = WebContentsFactory.createWebContents(profile, true);
 
@@ -332,8 +348,8 @@
         }
 
         OverlayViewDelegate delegate = new OverlayViewDelegate(cv);
-        mWebContents.initialize(ChromeVersionInfo.getProductVersion(), delegate, cv,
-                mActivity.getWindowAndroid(), WebContents.createDefaultInternalsHolder());
+        mWebContents.initialize(ChromeVersionInfo.getProductVersion(), delegate, cv, mWindowAndroid,
+                WebContents.createDefaultInternalsHolder());
         ContentUtils.setUserAgentOverride(mWebContents, /* overrideInNewTabs= */ false);
 
         // Transfers the ownership of the WebContents to the native OverlayPanelContent.
@@ -390,7 +406,7 @@
 
         mContentDelegate.onContentViewCreated();
         resizePanelContentView();
-        mActivity.getCompositorViewHolder().addView(mContainerView, 1);
+        mCompositorViewHolder.addView(mContainerView, 1);
     }
 
     /**
@@ -398,7 +414,7 @@
      */
     private void destroyWebContents() {
         if (mWebContents != null) {
-            mActivity.getCompositorViewHolder().removeView(mContainerView);
+            mCompositorViewHolder.removeView(mContainerView);
 
             // Native destroy will call up to destroy the Java WebContents.
             OverlayPanelContentJni.get().destroyWebContents(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index 60add717..0c8a099 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -9,11 +9,15 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.ActivityState;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContent;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager;
@@ -25,9 +29,12 @@
 import org.chromium.chrome.browser.flags.ActivityType;
 import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
 import org.chromium.components.browser_ui.widget.scrim.ScrimProperties;
 import org.chromium.ui.base.LocalizationUtils;
+import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.resources.ResourceManager;
 
@@ -85,6 +92,23 @@
     /** Used for logging state changes. */
     private final ContextualSearchPanelMetrics mPanelMetrics;
 
+    /**
+     * The {@link CompositorViewHolder}, used as an anchor view. Also injected into other classes.
+     */
+    private final CompositorViewHolder mCompositorViewHolder;
+
+    /** The {@link WindowAndroid} for the current activity.  */
+    private final WindowAndroid mWindowAndroid;
+
+    /** Used to query toolbar state. */
+    private final ToolbarManager mToolbarManager;
+
+    /** The {@link ActivityType} for the current activity. */
+    private final @ActivityType int mActivityType;
+
+    /** Supplies the current {@link Tab} for the activity. */
+    private final Supplier<Tab> mCurrentTabSupplier;
+
     /** The distance of the divider from the end of the bar, in dp. */
     private final float mEndButtonWidthDp;
 
@@ -120,12 +144,30 @@
      * @param context The current Android {@link Context}.
      * @param layoutManager A layout manager for observing scene changes.
      * @param panelManager The object managing the how different panels are shown.
+     * @param browserControlsStateProvider Used to measure the browser controls.
+     * @param windowAndroid The {@link WindowAndroid} for the current activity.
+     * @param compositorViewHolder The {@link CompositorViewHolder} for the current activity.
+     * @param toolbarHeight The height of the toolbar in pixels.
+     * @param toolbarManager The {@link ToolbarManager}, used to query for colors.
+     * @param activityType The {@link ActivityType} for the current activity.
+     * @param currentTabSupplier Supplies the current activity tab.
      */
-    public ContextualSearchPanel(
-            Context context, LayoutManagerImpl layoutManager, OverlayPanelManager panelManager) {
-        super(context, layoutManager, panelManager);
+    public ContextualSearchPanel(@NonNull Context context, @NonNull LayoutManagerImpl layoutManager,
+            @NonNull OverlayPanelManager panelManager,
+            @NonNull BrowserControlsStateProvider browserControlsStateProvider,
+            @NonNull WindowAndroid windowAndroid,
+            @NonNull CompositorViewHolder compositorViewHolder, int toolbarHeight,
+            @NonNull ToolbarManager toolbarManager, @ActivityType int activityType,
+            @NonNull Supplier<Tab> currentTabSupplier) {
+        super(context, layoutManager, panelManager, browserControlsStateProvider, windowAndroid,
+                compositorViewHolder, toolbarHeight, currentTabSupplier);
         mSceneLayer = createNewContextualSearchSceneLayer();
         mPanelMetrics = new ContextualSearchPanelMetrics();
+        mCompositorViewHolder = compositorViewHolder;
+        mWindowAndroid = windowAndroid;
+        mToolbarManager = toolbarManager;
+        mActivityType = activityType;
+        mCurrentTabSupplier = currentTabSupplier;
 
         mEndButtonWidthDp = mContext.getResources().getDimensionPixelSize(
                                     R.dimen.contextual_search_padded_button_width)
@@ -133,12 +175,10 @@
     }
 
     @Override
-    protected void initializeUiState() {}
-
-    @Override
     public OverlayPanelContent createNewOverlayPanelContent() {
         return new OverlayPanelContent(mManagementDelegate.getOverlayContentDelegate(),
-                new PanelProgressObserver(), mActivity, /* isIncognito= */ false, getBarHeight());
+                new PanelProgressObserver(), mActivity, /* isIncognito= */ false, getBarHeight(),
+                mCompositorViewHolder, mWindowAndroid, mCurrentTabSupplier);
     }
 
     // ============================================================================================
@@ -175,7 +215,7 @@
         if (mManagementDelegate != delegate) {
             mManagementDelegate = delegate;
             if (delegate != null) {
-                setChromeActivity(mManagementDelegate.getActivity());
+                setActivity(mManagementDelegate.getActivity());
             }
         }
     }
@@ -295,9 +335,7 @@
         if (isPeeking()) {
             if (getSearchBarControl().getQuickActionControl().hasQuickAction()
                     && isCoordinateInsideActionTarget(x)) {
-                mPanelMetrics.setWasQuickActionClicked();
-                getSearchBarControl().getQuickActionControl().sendIntent(
-                        mActivity.getActivityTab());
+                getSearchBarControl().getQuickActionControl().sendIntent(mCurrentTabSupplier.get());
             } else {
                 // super takes care of expanding the Panel when peeking.
                 super.handleBarClick(x, y);
@@ -651,10 +689,10 @@
 
         getSearchBarControl().setSearchTerm(searchTerm);
         getSearchBarControl().animateSearchTermResolution();
-        if (mActivity == null || mActivity.getToolbarManager() == null) return;
+        if (mActivity == null || mToolbarManager == null) return;
 
-        getSearchBarControl().setQuickAction(quickActionUri, quickActionCategory,
-                mActivity.getToolbarManager().getPrimaryColor());
+        getSearchBarControl().setQuickAction(
+                quickActionUri, quickActionCategory, mToolbarManager.getPrimaryColor());
         getImageControl().setThumbnailUrl(thumbnailUrl);
     }
 
@@ -797,8 +835,7 @@
                         new PropertyModel.Builder(ScrimProperties.REQUIRED_KEYS)
                                 .with(ScrimProperties.TOP_MARGIN, 0)
                                 .with(ScrimProperties.AFFECTS_STATUS_BAR, true)
-                                .with(ScrimProperties.ANCHOR_VIEW,
-                                        mActivity.getCompositorViewHolder())
+                                .with(ScrimProperties.ANCHOR_VIEW, mCompositorViewHolder)
                                 .with(ScrimProperties.SHOW_IN_FRONT_OF_ANCHOR_VIEW, false)
                                 .with(ScrimProperties.VISIBILITY_CALLBACK, null)
                                 .with(ScrimProperties.CLICK_DELEGATE, null)
@@ -1150,7 +1187,7 @@
      * @return Whether the panel content can be displayed in a new tab.
      */
     public boolean canPromoteToNewTab() {
-        return mActivity.getActivityType() == ActivityType.TABBED && canDisplayContentInPanel();
+        return mActivityType == ActivityType.TABBED && canDisplayContentInPanel();
     }
 
     // ============================================================================================
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
index 263e2bd..63124020 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -52,7 +52,7 @@
 import org.chromium.chrome.browser.share.ChromeShareExtras;
 import org.chromium.chrome.browser.share.LensUtils;
 import org.chromium.chrome.browser.share.ShareDelegate;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.share.ShareHelper;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
 import org.chromium.components.browser_ui.share.ShareParams;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index 4a225fb..3a7f97f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -28,6 +28,7 @@
 import org.chromium.cc.input.BrowserControlsState;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayContentDelegate;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
@@ -40,6 +41,7 @@
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchInternalStateController.InternalState;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionController.SelectionType;
 import org.chromium.chrome.browser.contextualsearch.ResolvedSearchTerm.CardTag;
+import org.chromium.chrome.browser.flags.ActivityType;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
 import org.chromium.chrome.browser.fullscreen.FullscreenOptions;
@@ -56,6 +58,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
+import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
@@ -247,7 +250,7 @@
 
     /**
      * Constructs the manager for the given activity, and will attach views to the given parent.
-     * @param activity The {@code ChromeActivity} in use.
+     * @param activity The {@link Activity} in use.
      * @param tabPromotionDelegate The {@link ContextualSearchTabPromotionDelegate} that is
      *        responsible for building tabs from contextual search {@link WebContents}.
      * @param scrimCoordinator A mechanism for showing and hiding the shared scrim.
@@ -316,9 +319,15 @@
      * @param layoutManager A means of attaching the OverlayPanel to the scene.
      * @param bottomSheetController The {@link BottomSheetController} that is used to show
      *                              {@link BottomSheetContent}.
+     * @param compositorViewHolder The {@link CompositorViewHolder} for the current activity.
+     * @param toolbarHeight The height of the toolbar in pixels.
+     * @param toolbarManager The manager of the toolbar, used to query toolbar state.
+     * @param activityType The type of the current activity.
      */
-    public void initialize(ViewGroup parentView, LayoutManagerImpl layoutManager,
-            BottomSheetController bottomSheetController) {
+    public void initialize(@NonNull ViewGroup parentView, @NonNull LayoutManagerImpl layoutManager,
+            @NonNull BottomSheetController bottomSheetController,
+            @NonNull CompositorViewHolder compositorViewHolder, int toolbarHeight,
+            @NonNull ToolbarManager toolbarManager, @ActivityType int activityType) {
         mNativeContextualSearchManagerPtr = ContextualSearchManagerJni.get().init(this);
 
         mParentView = parentView;
@@ -332,8 +341,10 @@
             panel = new ContextualSearchPanelCoordinator(
                     mActivity, mWindowAndroid, bottomSheetController, this::getBasePageHeight);
         } else {
-            panel = new ContextualSearchPanel(
-                    mActivity, mLayoutManager, mLayoutManager.getOverlayPanelManager());
+            panel = new ContextualSearchPanel(mActivity, mLayoutManager,
+                    mLayoutManager.getOverlayPanelManager(), mBrowserControlsStateProvider,
+                    mWindowAndroid, compositorViewHolder, toolbarHeight, toolbarManager,
+                    activityType, mTabSupplier);
         }
 
         panel.setManagementDelegate(this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DEPS
index 57885d0..38fbf7b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DEPS
@@ -11,8 +11,6 @@
   "+chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java",
-  "+chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegate.java",
-  "+chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java",
 
   "+base/android/java/src/org/chromium/base",
@@ -21,6 +19,7 @@
   "+chrome/browser/privacy/settings",
   "+chrome/browser/profiles/android",
   "+chrome/browser/search_engines/android",
+  "+chrome/browser/share/android",
   "+chrome/browser/signin/services/android",
   "+chrome/browser/tab",
   "+chrome/browser/tabmodel/android",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
index bc01b01..93cfb164 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
@@ -20,7 +20,7 @@
 import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable;
 import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties;
 import org.chromium.chrome.browser.share.ShareDelegate;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.tab.SadTab;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.components.favicon.LargeIconBridge;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java
index c86602da..810784e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java
@@ -69,7 +69,8 @@
             EligibilityFailureReason.AGSA_NOT_GOOGLE_SIGNED,
             EligibilityFailureReason.NON_GOOGLE_SEARCH_ENGINE,
             EligibilityFailureReason.NO_CHROME_ACCOUNT, EligibilityFailureReason.LOW_END_DEVICE,
-            EligibilityFailureReason.MULTIPLE_ACCOUNTS_ON_DEVICE})
+            EligibilityFailureReason.MULTIPLE_ACCOUNTS_ON_DEVICE,
+            EligibilityFailureReason.AGSA_NOT_INSTALLED})
     @Retention(RetentionPolicy.SOURCE)
     @interface EligibilityFailureReason {
         int AGSA_CANT_HANDLE_INTENT = 0;
@@ -86,10 +87,11 @@
         int NO_CHROME_ACCOUNT = 8;
         int LOW_END_DEVICE = 9;
         int MULTIPLE_ACCOUNTS_ON_DEVICE = 10;
+        int AGSA_NOT_INSTALLED = 11;
 
         // STOP: When updating this, also update values in enums.xml and make sure to update the
         // IntDef above.
-        int NUM_ENTRIES = 11;
+        int NUM_ENTRIES = 12;
     }
 
     /** Allows outside classes to listen for changes in this service. */
@@ -262,6 +264,11 @@
             boolean returnImmediately, List<Integer> outList) {
         assert returnImmediately || outList != null;
 
+        if (!mGsaState.isGsaInstalled()) {
+            if (returnImmediately) return false;
+            outList.add(EligibilityFailureReason.AGSA_NOT_INSTALLED);
+        }
+
         if (!mGsaState.canAgsaHandleIntent(getAssistantVoiceSearchIntent())) {
             if (returnImmediately) return false;
             outList.add(EligibilityFailureReason.AGSA_CANT_HANDLE_INTENT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButtonController.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButtonController.java
index ac7c2d5..278d12b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButtonController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButtonController.java
@@ -18,7 +18,7 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.ButtonData;
 import org.chromium.chrome.browser.toolbar.ButtonDataImpl;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java
index aab8f9e..3ac20da 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java
@@ -8,7 +8,6 @@
 import android.net.Uri;
 import android.text.TextUtils;
 
-import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
@@ -56,26 +55,6 @@
 public class ShareDelegateImpl implements ShareDelegate {
     static final String CANONICAL_URL_RESULT_HISTOGRAM = "Mobile.CanonicalURLResult";
 
-    // These values are persisted to logs. Entries should not be renumbered and numeric values
-    // should never be reused.
-    @IntDef({ShareOrigin.OVERFLOW_MENU, ShareOrigin.TOP_TOOLBAR, ShareOrigin.CONTEXT_MENU,
-            ShareOrigin.WEBSHARE_API, ShareOrigin.MOBILE_ACTION_MODE, ShareOrigin.EDIT_URL,
-            ShareOrigin.TAB_GROUP, ShareOrigin.WEBAPP_NOTIFICATION, ShareOrigin.FEED})
-    public @interface ShareOrigin {
-        int OVERFLOW_MENU = 0;
-        int TOP_TOOLBAR = 1;
-        int CONTEXT_MENU = 2;
-        int WEBSHARE_API = 3;
-        int MOBILE_ACTION_MODE = 4;
-        int EDIT_URL = 5;
-        int TAB_GROUP = 6;
-        int WEBAPP_NOTIFICATION = 7;
-        int FEED = 8;
-
-        // Must be the last one.
-        int COUNT = 9;
-    }
-
     private final BottomSheetController mBottomSheetController;
     private final ActivityLifecycleDispatcher mLifecycleDispatcher;
     private final Supplier<Tab> mTabProvider;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index 123623f..50cc4d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -64,7 +64,7 @@
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.share.ShareButtonController;
 import org.chromium.chrome.browser.share.ShareDelegate;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.share.ShareUtils;
 import org.chromium.chrome.browser.tab.AccessibilityVisibilityHandler;
 import org.chromium.chrome.browser.tab.AutofillSessionLifetimeController;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
index 24319a16..660bf6e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
@@ -28,7 +28,7 @@
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
 import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFactory;
 import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.components.browser_ui.notifications.NotificationManagerProxy;
 import org.chromium.components.browser_ui.notifications.NotificationManagerProxyImpl;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImplementationFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImplementationFactory.java
index b2b5f9e..01ffe24 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImplementationFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImplementationFactory.java
@@ -7,7 +7,7 @@
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.share.ChromeShareExtras;
 import org.chromium.chrome.browser.share.ShareDelegate;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.share.ShareDelegateSupplier;
 import org.chromium.components.browser_ui.share.ShareParams;
 import org.chromium.components.browser_ui.webshare.ShareServiceImpl;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java
index fcd5292..c94503e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java
@@ -6,20 +6,29 @@
 
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
+import android.view.ViewGroup;
 
 import androidx.annotation.Nullable;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.UiThreadTest;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.ui.base.WindowAndroid;
 
 /**
  * Tests logic in the OverlayPanelBase.
@@ -33,6 +42,22 @@
     private static final float MOCK_EXPANDED_HEIGHT = 400.0f;
     private static final float MOCK_MAXIMIZED_HEIGHT = 600.0f;
 
+    private static final int MOCK_TOOLBAR_HEIGHT = 100;
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private LayoutManagerImpl mLayoutManager;
+    @Mock
+    private BrowserControlsStateProvider mBrowserControlsStateProvider;
+    @Mock
+    private WindowAndroid mWindowAndroid;
+    @Mock
+    private ViewGroup mCompositorViewHolder;
+    @Mock
+    private Tab mTab;
+
     MockOverlayPanel mNoExpandPanel;
     MockOverlayPanel mExpandPanel;
 
@@ -40,8 +65,12 @@
      * Mock OverlayPanel.
      */
     private static class MockOverlayPanel extends OverlayPanel {
-        public MockOverlayPanel(Context context, OverlayPanelManager manager) {
-            super(context, null, manager);
+        public MockOverlayPanel(Context context, LayoutManagerImpl layoutManager,
+                OverlayPanelManager manager,
+                BrowserControlsStateProvider browserControlsStateProvider,
+                WindowAndroid windowAndroid, ViewGroup compositorViewHolder, Tab tab) {
+            super(context, layoutManager, manager, browserControlsStateProvider, windowAndroid,
+                    compositorViewHolder, MOCK_TOOLBAR_HEIGHT, () -> tab);
         }
 
         /**
@@ -75,9 +104,12 @@
      * A MockOverlayPanel that does not support the EXPANDED panel state.
      */
     private static class NoExpandMockOverlayPanel extends MockOverlayPanel {
-
-        public NoExpandMockOverlayPanel(Context context, OverlayPanelManager manager) {
-            super(context, manager);
+        public NoExpandMockOverlayPanel(Context context, LayoutManagerImpl layoutManager,
+                OverlayPanelManager manager,
+                BrowserControlsStateProvider browserControlsStateProvider,
+                WindowAndroid windowAndroid, ViewGroup compositorViewHolder, Tab tab) {
+            super(context, layoutManager, manager, browserControlsStateProvider, windowAndroid,
+                    compositorViewHolder, tab);
         }
 
         @Override
@@ -95,10 +127,12 @@
     public void setUp() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             OverlayPanelManager panelManager = new OverlayPanelManager();
-            mExpandPanel =
-                    new MockOverlayPanel(InstrumentationRegistry.getTargetContext(), panelManager);
+            mExpandPanel = new MockOverlayPanel(InstrumentationRegistry.getTargetContext(),
+                    mLayoutManager, panelManager, mBrowserControlsStateProvider, mWindowAndroid,
+                    mCompositorViewHolder, mTab);
             mNoExpandPanel = new NoExpandMockOverlayPanel(
-                    InstrumentationRegistry.getTargetContext(), panelManager);
+                    InstrumentationRegistry.getTargetContext(), mLayoutManager, panelManager,
+                    mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab);
         });
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java
index 13b9012..2f94acc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.compositor.bottombar;
 
+import android.app.Activity;
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 import android.view.MotionEvent;
@@ -14,15 +15,22 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.UiThreadTest;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
 import org.chromium.chrome.browser.compositor.layouts.eventfilter.OverlayPanelEventFilter;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
-
+import org.chromium.ui.base.WindowAndroid;
 /**
  * Class responsible for testing the OverlayPanelEventFilter.
  */
@@ -37,6 +45,28 @@
     // A small value used to check whether two floats are almost equal.
     private static final float EPSILON = 1e-04f;
 
+    private static final int MOCK_TOOLBAR_HEIGHT = 100;
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private LayoutManagerImpl mLayoutManager;
+    @Mock
+    private BrowserControlsStateProvider mBrowserControlsStateProvider;
+    @Mock
+    private WindowAndroid mWindowAndroid;
+    @Mock
+    private ViewGroup mCompositorViewHolder;
+    @Mock
+    private Tab mTab;
+    @Mock
+    private OverlayContentDelegate mOverlayContentDelegate;
+    @Mock
+    private OverlayContentProgressObserver mOverlayContentProgressObserver;
+    @Mock
+    private Activity mActivity;
+
     private float mTouchSlopDp;
     private float mDpToPx;
 
@@ -106,8 +136,12 @@
         private boolean mWasTapDetectedOnPanel;
         private boolean mWasScrollDetectedOnPanel;
 
-        public MockOverlayPanel(Context context, OverlayPanelManager panelManager) {
-            super(context, null, panelManager);
+        public MockOverlayPanel(Context context, LayoutManagerImpl layoutManager,
+                OverlayPanelManager manager,
+                BrowserControlsStateProvider browserControlsStateProvider,
+                WindowAndroid windowAndroid, ViewGroup compositorViewHolder, Tab tab) {
+            super(context, layoutManager, manager, browserControlsStateProvider, windowAndroid,
+                    compositorViewHolder, MOCK_TOOLBAR_HEIGHT, () -> tab);
         }
 
         @Override
@@ -120,7 +154,9 @@
          */
         private class MockOverlayPanelContent extends OverlayPanelContent {
             public MockOverlayPanelContent() {
-                super(null, null, null, false, 0);
+                super(mOverlayContentDelegate, mOverlayContentProgressObserver, mActivity,
+                        /* isIncognito= */ false, MOCK_TOOLBAR_HEIGHT, mCompositorViewHolder,
+                        mWindowAndroid, () -> mTab);
             }
 
             @Override
@@ -210,7 +246,8 @@
         mTouchSlopDp = ViewConfiguration.get(context).getScaledTouchSlop() / mDpToPx;
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mPanel = new MockOverlayPanel(context, new OverlayPanelManager());
+            mPanel = new MockOverlayPanel(context, mLayoutManager, new OverlayPanelManager(),
+                    mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab);
             mEventFilter = new OverlayPanelEventFilterWrapper(context, mPanel);
 
             mPanel.setSearchBarHeightForTesting(BAR_HEIGHT_DP);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java
index 25eea98..54e169b7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java
@@ -12,17 +12,24 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Assert;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.UiThreadTest;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.OverlayPanelManagerObserver;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.PanelPriority;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 
 import java.util.concurrent.TimeoutException;
@@ -32,6 +39,22 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class OverlayPanelManagerTest {
+    private static final int MOCK_TOOLBAR_HEIGHT = 100;
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private LayoutManagerImpl mLayoutManager;
+    @Mock
+    private BrowserControlsStateProvider mBrowserControlsStateProvider;
+    @Mock
+    private WindowAndroid mWindowAndroid;
+    @Mock
+    private ViewGroup mCompositorViewHolder;
+    @Mock
+    private Tab mTab;
+
     // --------------------------------------------------------------------------------------------
     // MockOverlayPanel
     // --------------------------------------------------------------------------------------------
@@ -45,10 +68,13 @@
         private ViewGroup mContainerView;
         private DynamicResourceLoader mResourceLoader;
 
-        public MockOverlayPanel(Context context, LayoutManagerImpl updateHost,
-                OverlayPanelManager panelManager, @PanelPriority int priority,
-                boolean canBeSuppressed) {
-            super(context, updateHost, panelManager);
+        public MockOverlayPanel(Context context, LayoutManagerImpl layoutManager,
+                OverlayPanelManager manager,
+                BrowserControlsStateProvider browserControlsStateProvider,
+                WindowAndroid windowAndroid, ViewGroup compositorViewHolder, Tab tab,
+                @PanelPriority int priority, boolean canBeSuppressed) {
+            super(context, layoutManager, manager, browserControlsStateProvider, windowAndroid,
+                    compositorViewHolder, MOCK_TOOLBAR_HEIGHT, () -> tab);
             mPriority = priority;
             mCanBeSuppressed = canBeSuppressed;
         }
@@ -105,7 +131,7 @@
          */
         private static class MockOverlayPanelContent extends OverlayPanelContent {
             public MockOverlayPanelContent() {
-                super(null, null, null, false, 0);
+                super(null, null, null, false, 0, null, null, null);
             }
 
             @Override
@@ -125,8 +151,9 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        OverlayPanel panel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, false);
+        OverlayPanel panel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.MEDIUM, false);
 
         panel.requestPanelShow(StateChangeReason.UNKNOWN);
 
@@ -141,8 +168,9 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        OverlayPanel panel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, false);
+        OverlayPanel panel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.MEDIUM, false);
 
         panel.requestPanelShow(StateChangeReason.UNKNOWN);
         panel.closePanel(StateChangeReason.UNKNOWN, false);
@@ -158,10 +186,12 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        OverlayPanel lowPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, false);
-        OverlayPanel highPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
+        OverlayPanel lowPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.LOW, false);
+        OverlayPanel highPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.HIGH, false);
 
         lowPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
         highPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
@@ -177,10 +207,12 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        OverlayPanel lowPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, true);
-        OverlayPanel highPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
+        OverlayPanel lowPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.LOW, true);
+        OverlayPanel highPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.HIGH, false);
 
         lowPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
         highPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
@@ -197,10 +229,12 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        OverlayPanel lowPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, false);
-        OverlayPanel highPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
+        OverlayPanel lowPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.LOW, false);
+        OverlayPanel highPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.HIGH, false);
 
         lowPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
         highPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
@@ -217,10 +251,12 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        OverlayPanel lowPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, true);
-        OverlayPanel highPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
+        OverlayPanel lowPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.LOW, true);
+        OverlayPanel highPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.HIGH, false);
 
         lowPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
         highPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
@@ -239,12 +275,15 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        OverlayPanel lowPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, true);
-        OverlayPanel mediumPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, true);
-        OverlayPanel highPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
+        OverlayPanel lowPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.LOW, true);
+        OverlayPanel mediumPriorityPanel = new MockOverlayPanel(context, mLayoutManager,
+                panelManager, mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder,
+                mTab, PanelPriority.MEDIUM, true);
+        OverlayPanel highPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.HIGH, false);
 
         // Only one panel is showing, should be medium priority.
         mediumPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
@@ -282,12 +321,15 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        OverlayPanel lowPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, true);
-        OverlayPanel mediumPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, true);
-        OverlayPanel highPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
+        OverlayPanel lowPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.LOW, true);
+        OverlayPanel mediumPriorityPanel = new MockOverlayPanel(context, mLayoutManager,
+                panelManager, mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder,
+                mTab, PanelPriority.MEDIUM, true);
+        OverlayPanel highPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.HIGH, false);
 
         // Odd ordering for showing panels should still produce ordered suppression.
         highPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
@@ -320,15 +362,17 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         OverlayPanelManager panelManager = new OverlayPanelManager();
-        MockOverlayPanel earlyPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, true);
+        MockOverlayPanel earlyPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.MEDIUM, true);
 
         // Set necessary vars before any other panels are registered in the manager.
         panelManager.setContainerView(new LinearLayout(InstrumentationRegistry.getTargetContext()));
         panelManager.setDynamicResourceLoader(new DynamicResourceLoader(0, null));
 
-        MockOverlayPanel latePanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, true);
+        MockOverlayPanel latePanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.MEDIUM, true);
 
         Assert.assertTrue(earlyPanel.getContainerView() == latePanel.getContainerView());
         Assert.assertTrue(
@@ -358,10 +402,12 @@
             }
         });
 
-        OverlayPanel lowPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, true);
-        OverlayPanel highPriorityPanel =
-                new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
+        OverlayPanel lowPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.LOW, true);
+        OverlayPanel highPriorityPanel = new MockOverlayPanel(context, mLayoutManager, panelManager,
+                mBrowserControlsStateProvider, mWindowAndroid, mCompositorViewHolder, mTab,
+                PanelPriority.HIGH, false);
 
         lowPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java
index d118546f..fcbb832 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java
@@ -401,7 +401,9 @@
         OverlayPanelContentWrapper(OverlayContentDelegate contentDelegate,
                 OverlayContentProgressObserver progressObserver, ChromeActivity activity,
                 float barHeight) {
-            super(contentDelegate, progressObserver, activity, false, barHeight);
+            super(contentDelegate, progressObserver, activity, false, barHeight,
+                    activity.getCompositorViewHolder(), activity.getWindowAndroid(),
+                    activity::getActivityTab);
         }
 
         @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTest.java
index 665c87be..fac19db 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTest.java
@@ -88,7 +88,7 @@
     private static class ContextualSearchPanelWrapper extends ContextualSearchPanel {
         public ContextualSearchPanelWrapper(Context context, LayoutManagerImpl layoutManager,
                 OverlayPanelManager panelManager) {
-            super(context, layoutManager, panelManager);
+            super(context, layoutManager, panelManager, null, null, null, 0, null, 0, null);
         }
 
         @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java
index a469d67..4f213d8e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java
@@ -40,7 +40,7 @@
 import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.share.ShareDelegate;
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
 import org.chromium.chrome.browser.tab.SadTab;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.util.browser.Features;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java
index 5e230e9..a7a62ec 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceRenderTest.java
@@ -21,7 +21,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mockito;
+import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
@@ -65,19 +65,23 @@
     @Rule
     public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
 
+    @Mock
+    private GSAState mGsaState;
+    @Mock
+    private ExternalAuthUtils mExternalAuthUtils;
+
     @Before
     public void setUp() throws Exception {
         SharedPreferencesManager.getInstance().writeBoolean(ASSISTANT_VOICE_SEARCH_ENABLED, true);
 
-        GSAState gsaState = Mockito.mock(GSAState.class);
-        doReturn(false).when(gsaState).isAgsaVersionBelowMinimum(anyString(), anyString());
-        doReturn(true).when(gsaState).canAgsaHandleIntent(anyObject());
-        GSAState.setInstanceForTesting(gsaState);
+        doReturn(false).when(mGsaState).isAgsaVersionBelowMinimum(anyString(), anyString());
+        doReturn(true).when(mGsaState).canAgsaHandleIntent(anyObject());
+        doReturn(true).when(mGsaState).isGsaInstalled();
+        GSAState.setInstanceForTesting(mGsaState);
 
-        ExternalAuthUtils externalAuthUtils = Mockito.mock(ExternalAuthUtils.class);
-        doReturn(true).when(externalAuthUtils).isGoogleSigned(anyString());
-        doReturn(true).when(externalAuthUtils).isChromeGoogleSigned();
-        ExternalAuthUtils.setInstanceForTesting(externalAuthUtils);
+        doReturn(true).when(mExternalAuthUtils).isGoogleSigned(anyString());
+        doReturn(true).when(mExternalAuthUtils).isChromeGoogleSigned();
+        ExternalAuthUtils.setInstanceForTesting(mExternalAuthUtils);
 
         mActivityTestRule.startMainActivityOnBlankPage();
         mAccountManagerTestRule.addTestAccountThenSigninAndEnableSync();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java
index 426012f..5275f5e7 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java
@@ -111,6 +111,7 @@
         doReturn(true).when(mExternalAuthUtils).isChromeGoogleSigned();
         doReturn(true).when(mExternalAuthUtils).isGoogleSigned(IntentHandler.PACKAGE_GSA);
         doReturn(true).when(mTemplateUrlService).isDefaultSearchEngineGoogle();
+        doReturn(true).when(mGsaState).isGsaInstalled();
         doReturn(false).when(mGsaState).isAgsaVersionBelowMinimum(any(), any());
         doReturn(AGSA_VERSION_NUMBER).when(mGsaState).parseAgsaMajorMinorVersionAsInteger(any());
         doReturn(true).when(mGsaState).canAgsaHandleIntent(any());
@@ -288,6 +289,19 @@
 
     @Test
     @Feature("OmniboxAssistantVoiceSearch")
+    public void testAssistantEligibility_AGSA_not_installed() throws Exception {
+        doReturn(false).when(mGsaState).isGsaInstalled();
+
+        List<Integer> reasons = new ArrayList<>();
+        boolean eligible = mAssistantVoiceSearchService.isDeviceEligibleForAssistant(
+                /* returnImmediately= */ false, /* outList= */ reasons);
+        Assert.assertEquals(1, reasons.size());
+        Assert.assertEquals(EligibilityFailureReason.AGSA_NOT_INSTALLED, (int) reasons.get(0));
+        Assert.assertFalse(eligible);
+    }
+
+    @Test
+    @Feature("OmniboxAssistantVoiceSearch")
     public void getMicButtonColorStateList_ColorfulMicEnabled() {
         mAssistantVoiceSearchService.setColorfulMicEnabledForTesting(true);
         Assert.assertNull(mAssistantVoiceSearchService.getMicButtonColorStateList(0, mContext));
@@ -347,4 +361,4 @@
         doReturn(false).when(mAccountManagerFacade).isCachePopulated();
         Assert.assertTrue(mAssistantVoiceSearchService.doesViolateMultiAccountCheck());
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/app/OWNERS b/chrome/app/OWNERS
index 6671e0f7..85ad8c04 100644
--- a/chrome/app/OWNERS
+++ b/chrome/app/OWNERS
@@ -18,7 +18,7 @@
 
 per-file app_management_strings.grdp=file://chrome/browser/ui/webui/app_management/OWNERS
 
-per-file web_time_limit_error_page_strings.grdp=file://chrome/browser/chromeos/child_accounts/OWNERS
+per-file web_time_limit_error_page_strings.grdp=file://chrome/browser/ash/child_accounts/OWNERS
 
 per-file global_media_controls_strings.grdp=file://chrome/browser/ui/global_media_controls/OWNERS
 
diff --git a/chrome/app/PRESUBMIT.py b/chrome/app/PRESUBMIT.py
index 541da20..2ce4332 100644
--- a/chrome/app/PRESUBMIT.py
+++ b/chrome/app/PRESUBMIT.py
@@ -64,18 +64,18 @@
   """Check text version for IDS_EDU_LOGIN_INFO_* strings.
 
   If any of IDS_EDU_LOGIN_INFO_* strings changed, text version in
-  chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.cc
+  chrome/browser/ash/child_accounts/secondary_account_consent_logger.cc
   has to be updated.
   """
 
   CHROMEOS_STRINGS_PATH = input_api.os_path.join(
       input_api.change.RepositoryRoot(), "chrome/app/chromeos_strings.grdp")
   TEXT_VERSION_PATH = input_api.os_path.join(input_api.change.RepositoryRoot(),
-  "chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.cc")
+  "chrome/browser/ash/child_accounts/secondary_account_consent_logger.cc")
   UPDATE_TEXT_VERSION_MESSAGE = (
       "You have changed EDU login parental consent text "
       "(IDS_EDU_LOGIN_INFO_* strings). Update kConsentScreenTextVersion in "
-      "chrome/browser/chromeos/child_accounts/"
+      "chrome/browser/ash/child_accounts/"
       "secondary_account_consent_logger.cc to the value of \"%s\"."
   )
   UPDATE_INVALIDATION_VERSION_MESSAGE = (
@@ -83,7 +83,7 @@
       "(IDS_EDU_LOGIN_INFO_* strings). If you want to invalidate secondary "
       "accounts added with previous consent versions, also update "
       "kSecondaryAccountsInvalidationVersion in "
-      "chrome/browser/chromeos/child_accounts/"
+      "chrome/browser/ash/child_accounts/"
       "secondary_account_consent_logger.cc to the value of \"%s\"."
   )
 
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index ea85ecbb..dc7f5c0 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -5546,7 +5546,7 @@
   <!--
     ==================================================================================
     If you change any IDS_EDU_LOGIN_INFO_* string, update kConsentScreenTextVersion in
-    chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.cc
+    chrome/browser/ash/child_accounts/secondary_account_consent_logger.cc
     to the value of "v<GERRIT_CL_NUMBER>"
   -->
   <message name="IDS_EDU_LOGIN_INFO_COEXISTENCE_TITLE" desc="Title for the screen explaining co-existence to a parent.">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 0a83e80..137868a 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5732,7 +5732,7 @@
         Even Better Module
       </message>
       <message name="IDS_NTP_MODULES_DRIVE_TITLE" desc="Title shown in the header of the drive module and various other UIs.">
-        From Google Drive
+        From your Google Drive
       </message>
       <message name="IDS_NTP_MODULES_KALEIDOSCOPE_TITLE" desc="Title shown in the header of the Kaleidoscope module.">
         Top picks for you
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_DRIVE_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_DRIVE_TITLE.png.sha1
index 9026909..b2e9add 100644
--- a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_DRIVE_TITLE.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_DRIVE_TITLE.png.sha1
@@ -1 +1 @@
-0daf7e9f8bc94f5e7afc2791b5042ddf9a41fc40
\ No newline at end of file
+a0d33253046d230a3144a10e335040553a672486
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 8199e92..5d3d99d0 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1126,6 +1126,12 @@
   <message name="IDS_SETTINGS_LANGUAGES_ENABLED_LANGUAGES" desc="Header for the list of enabled languages, which the user can use to disable languages, on the Manage Languages page.">
     Enabled languages
   </message>
+  <message name="IDS_SETTINGS_LANGUAGES_NO_LANGUAGES_ADDED" desc="Placeholder for language list settings when no languages have been added, on the Manage Languages page.">
+    No languages added
+  </message>
+  <message name="IDS_SETTINGS_LANGUAGES_AUTOMATIC_TRANSLATE" desc="Title of Translation settings that lists languages that should be automatically translated.">
+    Automatically translate these languages
+  </message>
   <message name="IDS_SETTINGS_LANGUAGES_SPELL_CHECK_TITLE" desc="Title for the section containing all the options for spell check settings. The options include picking between using the system's spell check or using Google's web service and a list of the enabled languages which support spell checking.">
     Spell check
   </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_AUTOMATIC_TRANSLATE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_AUTOMATIC_TRANSLATE.png.sha1
new file mode 100644
index 0000000..6ec7715
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_AUTOMATIC_TRANSLATE.png.sha1
@@ -0,0 +1 @@
+bf726da0a4da776ff690c78e81153ae187e6aaae
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_NO_LANGUAGES_ADDED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_NO_LANGUAGES_ADDED.png.sha1
new file mode 100644
index 0000000..d5359c3c7
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_NO_LANGUAGES_ADDED.png.sha1
@@ -0,0 +1 @@
+2e931fbc55ba6f86bf7f8262d84f345b1b4f45d4
\ No newline at end of file
diff --git a/chrome/app_shim/app_shim_controller.h b/chrome/app_shim/app_shim_controller.h
index 5d3589f..d072dd1 100644
--- a/chrome/app_shim/app_shim_controller.h
+++ b/chrome/app_shim/app_shim_controller.h
@@ -63,6 +63,11 @@
   // Called when a profile is selected from the profiles NSMenu.
   void ProfileMenuItemSelected(uint32_t index);
 
+  // Called by AppShimDelegate in response to an URL being opened. If this
+  // occurs before OnDidFinishLaunching, then the argument is the files that
+  // triggered the launch of the app.
+  void OpenUrls(const std::vector<GURL>& urls);
+
  private:
   friend class TestShimClient;
   friend class apps::MachBootstrapAcceptorTest;
@@ -135,6 +140,10 @@
   // was called.
   std::vector<base::FilePath> launch_files_;
 
+  // Populated by OpenUrls if it was called before nAppFinishedLaunching
+  // was called.
+  std::vector<GURL> launch_urls_;
+
   // This is the Chrome process that this app is committed to connecting to.
   // The app will quit if this process is terminated before the mojo connection
   // is established.
diff --git a/chrome/app_shim/app_shim_controller.mm b/chrome/app_shim/app_shim_controller.mm
index 7237f74..ab2a95aa5 100644
--- a/chrome/app_shim/app_shim_controller.mm
+++ b/chrome/app_shim/app_shim_controller.mm
@@ -337,6 +337,7 @@
           ? chrome::mojom::AppShimLaunchType::kRegisterOnly
           : chrome::mojom::AppShimLaunchType::kNormal;
   app_shim_info->files = launch_files_;
+  app_shim_info->urls = launch_urls_;
 
   if (base::mac::WasLaunchedAsHiddenLoginItem()) {
     app_shim_info->login_item_restore_state =
@@ -516,3 +517,11 @@
     }
   }
 }
+
+void AppShimController::OpenUrls(const std::vector<GURL>& urls) {
+  if (init_state_ == InitState::kWaitingForAppToFinishLaunch) {
+    launch_urls_ = urls;
+  } else {
+    host_->UrlsOpened(urls);
+  }
+}
diff --git a/chrome/app_shim/app_shim_delegate.mm b/chrome/app_shim/app_shim_delegate.mm
index 3d94394..7372b4a 100644
--- a/chrome/app_shim/app_shim_delegate.mm
+++ b/chrome/app_shim/app_shim_delegate.mm
@@ -6,6 +6,7 @@
 
 #include "base/mac/foundation_util.h"
 #include "chrome/app_shim/app_shim_controller.h"
+#include "net/base/mac/url_conversions.h"
 
 @implementation AppShimDelegate
 
@@ -34,6 +35,14 @@
   [app replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
 }
 
+- (void)application:(NSApplication*)app openURLs:(NSArray<NSURL*>*)urls {
+  std::vector<GURL> urls_to_open;
+  for (NSURL* url in urls)
+    urls_to_open.push_back(net::GURLWithNSURL(url));
+  _appShimController->OpenUrls(urls_to_open);
+  [app replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
+}
+
 - (void)applicationWillBecomeActive:(NSNotification*)notification {
   return _appShimController->host()->FocusApp();
 }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index f9c230a0..7ec6e44 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -7188,6 +7188,10 @@
      FEATURE_VALUE_TYPE(
          optimization_guide::features::kOptimizationGuideModelDownloading)},
 
+    {"media-session-webrtc", flag_descriptions::kMediaSessionWebRTCName,
+     flag_descriptions::kMediaSessionWebRTCDescription, kOsAll,
+     FEATURE_VALUE_TYPE(media::kMediaSessionWebRTC)},
+
     {"webid", flag_descriptions::kWebIdName,
      flag_descriptions::kWebIdDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kWebID)},
diff --git a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc
index 348c81d4..5e60e997 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc
@@ -119,6 +119,10 @@
   return app_shim_info_->login_item_restore_state;
 }
 
+const std::vector<GURL>& AppShimHostBootstrap::GetLaunchUrls() const {
+  return app_shim_info_->urls;
+}
+
 bool AppShimHostBootstrap::IsMultiProfile() const {
   // PWAs and bookmark apps are multi-profile capable.
   return app_shim_info_->app_url.is_valid();
diff --git a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h
index dd3f744..f098bdc 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h
@@ -71,6 +71,9 @@
   // Indicates if the app launched during OS login.
   chrome::mojom::AppShimLoginItemRestoreState GetLoginItemRestoreState() const;
 
+  // If non-empty, holds an array of urls given as arguments.
+  const std::vector<GURL>& GetLaunchUrls() const;
+
   // Returns true if this app supports multiple profiles. If so, it will not be
   // required that GetProfilePath be a valid profile path.
   bool IsMultiProfile() const;
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.cc b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
index d2b5312f..56b88e4 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
@@ -159,6 +159,10 @@
   client_->OnShimSelectedProfile(this, profile_path);
 }
 
+void AppShimHost::UrlsOpened(const std::vector<GURL>& urls) {
+  client_->OnShimOpenedUrls(this, urls);
+}
+
 base::FilePath AppShimHost::GetProfilePath() const {
   // This should only be used by single-profile-app paths.
   DCHECK(!profile_path_.empty());
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.h b/chrome/browser/apps/app_shim/app_shim_host_mac.h
index d3c7659..ae88863 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac.h
@@ -65,6 +65,11 @@
     // Invoked when a profile is selected from the menu bar.
     virtual void OnShimSelectedProfile(AppShimHost* host,
                                        const base::FilePath& profile_path) = 0;
+
+    // Invoked by the shim host when the shim opens a url, e.g, clicking a link
+    // in mail.
+    virtual void OnShimOpenedUrls(AppShimHost* host,
+                                  const std::vector<GURL>& urls) = 0;
   };
 
   AppShimHost(Client* client,
@@ -120,6 +125,7 @@
   void ReopenApp() override;
   void FilesOpened(const std::vector<base::FilePath>& files) override;
   void ProfileSelectedFromMenu(const base::FilePath& profile_path) override;
+  void UrlsOpened(const std::vector<GURL>& urls) override;
 
   // Weak, owns |this|.
   Client* const client_;
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
index ff7ef2bc..58d14f6 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
@@ -187,6 +187,8 @@
                          const std::vector<base::FilePath>& files) override {}
   void OnShimSelectedProfile(AppShimHost* host,
                              const base::FilePath& profile_path) override {}
+  void OnShimOpenedUrls(AppShimHost* host,
+                        const std::vector<GURL>& urls) override {}
 
   chrome::mojom::AppShimLaunchResult launch_result_ =
       chrome::mojom::AppShimLaunchResult::kSuccess;
diff --git a/chrome/browser/apps/app_shim/app_shim_listener_browsertest_mac.mm b/chrome/browser/apps/app_shim/app_shim_listener_browsertest_mac.mm
index fe6ecfbf..8a5e6a8 100644
--- a/chrome/browser/apps/app_shim/app_shim_listener_browsertest_mac.mm
+++ b/chrome/browser/apps/app_shim/app_shim_listener_browsertest_mac.mm
@@ -152,6 +152,7 @@
   void ReopenApp() override {}
   void FilesOpened(const std::vector<base::FilePath>& files) override {}
   void ProfileSelectedFromMenu(const base::FilePath& profile_path) override {}
+  void UrlsOpened(const std::vector<GURL>& urls) override {}
 
   std::unique_ptr<base::RunLoop> runner_;
   mojo::Receiver<chrome::mojom::AppShimHost> receiver_{this};
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac.cc b/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
index f07817c..d7b3b31 100644
--- a/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
@@ -330,12 +330,13 @@
       const base::FilePath profile_path = bootstrap->GetProfilePath();
       const std::vector<base::FilePath> launch_files =
           bootstrap->GetLaunchFiles();
+      const std::vector<GURL> launch_urls = bootstrap->GetLaunchUrls();
       const chrome::mojom::AppShimLoginItemRestoreState
           login_item_restore_state = bootstrap->GetLoginItemRestoreState();
       LoadAndLaunchAppCallback launch_callback = base::BindOnce(
           &AppShimManager::OnShimProcessConnectedAndAllLaunchesDone,
           weak_factory_.GetWeakPtr(), std::move(bootstrap));
-      LoadAndLaunchApp(app_id, profile_path, launch_files,
+      LoadAndLaunchApp(app_id, profile_path, launch_files, launch_urls,
                        login_item_restore_state, std::move(launch_callback));
       break;
     }
@@ -388,13 +389,14 @@
     const web_app::AppId& app_id,
     const base::FilePath& profile_path,
     const std::vector<base::FilePath>& launch_files,
+    const std::vector<GURL>& launch_urls,
     chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state,
     LoadAndLaunchAppCallback launch_callback) {
   // Check to see if the app is already running for a profile compatible with
   // |profile_path|. If so, early-out.
   if (LoadAndLaunchApp_TryExistingProfileStates(
-          app_id, profile_path, launch_files, login_item_restore_state,
-          &launch_callback)) {
+          app_id, profile_path, launch_files, launch_urls,
+          login_item_restore_state, &launch_callback)) {
     // If we used an existing profile, |launch_callback| should have been run.
     DCHECK(!launch_callback);
     return;
@@ -423,8 +425,8 @@
   base::OnceClosure callback =
       base::BindOnce(&AppShimManager::LoadAndLaunchApp_OnProfilesAndAppReady,
                      weak_factory_.GetWeakPtr(), app_id, launch_files,
-                     login_item_restore_state, profile_paths_to_launch,
-                     std::move(launch_callback));
+                     launch_urls, login_item_restore_state,
+                     profile_paths_to_launch, std::move(launch_callback));
   {
     // This will update |callback| to be a chain of callbacks that load the
     // profiles in |profile_paths_to_load|, one by one, using
@@ -450,6 +452,7 @@
     const web_app::AppId& app_id,
     const base::FilePath& profile_path,
     const std::vector<base::FilePath>& launch_files,
+    const std::vector<GURL>& launch_urls,
     chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state,
     LoadAndLaunchAppCallback* launch_callback) {
   auto found_app = apps_.find(app_id);
@@ -484,7 +487,8 @@
 
   // Launch the app, if appropriate.
   LoadAndLaunchApp_LaunchIfAppropriate(profile, profile_state, app_id,
-                                       launch_files, login_item_restore_state);
+                                       launch_files, launch_urls,
+                                       login_item_restore_state);
 
   std::move(*launch_callback)
       .Run(profile_state, chrome::mojom::AppShimLaunchResult::kSuccess);
@@ -494,6 +498,7 @@
 void AppShimManager::LoadAndLaunchApp_OnProfilesAndAppReady(
     const web_app::AppId& app_id,
     const std::vector<base::FilePath>& launch_files,
+    const std::vector<GURL>& launch_urls,
     chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state,
     const std::vector<base::FilePath>& profile_paths_to_launch,
     LoadAndLaunchAppCallback launch_callback) {
@@ -527,8 +532,9 @@
       profile_state = GetOrCreateProfileState(profile, app_id);
 
     // Launch the app, if appropriate.
-    LoadAndLaunchApp_LaunchIfAppropriate(
-        profile, profile_state, app_id, launch_files, login_item_restore_state);
+    LoadAndLaunchApp_LaunchIfAppropriate(profile, profile_state, app_id,
+                                         launch_files, launch_urls,
+                                         login_item_restore_state);
 
     // If we successfully created a profile state, save it for |bootstrap| to
     // connect to once all launches are done.
@@ -541,6 +547,10 @@
     if (!launch_files.empty())
       break;
 
+    // If urls were specified, only open one new window.
+    if (!launch_urls.empty())
+      break;
+
     // If this was the first profile in |profile_paths_to_launch|, then this
     // was the profile specified in the bootstrap, so stop here.
     if (iter == 0)
@@ -611,10 +621,11 @@
     ProfileState* profile_state,
     const web_app::AppId& app_id,
     const std::vector<base::FilePath>& launch_files,
+    const std::vector<GURL>& launch_urls,
     chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state) {
-  // If |launch_files| is non-empty, then always do a launch to open the
-  // files.
-  bool do_launch = !launch_files.empty();
+  // If |launch_files| or |launch_urls| is non-empty, then always
+  // do a launch to open the files or URLs.
+  bool do_launch = (!launch_files.empty() || !launch_urls.empty());
 
   // Otherwise, only launch if there are no open windows.
   if (!do_launch) {
@@ -626,9 +637,10 @@
       do_launch = true;
   }
 
-  if (do_launch)
-    delegate_->LaunchApp(profile, app_id, launch_files,
+  if (do_launch) {
+    delegate_->LaunchApp(profile, app_id, launch_files, launch_urls,
                          login_item_restore_state);
+  }
 }
 
 // static
@@ -836,7 +848,7 @@
   LoadAndLaunchApp(
       host->GetAppId(),
       app_state->IsMultiProfile() ? base::FilePath() : host->GetProfilePath(),
-      std::vector<base::FilePath>(),
+      std::vector<base::FilePath>(), std::vector<GURL>(),
       chrome::mojom::AppShimLoginItemRestoreState::kNone, base::DoNothing());
 }
 
@@ -849,14 +861,27 @@
   LoadAndLaunchApp(
       host->GetAppId(),
       app_state->IsMultiProfile() ? base::FilePath() : host->GetProfilePath(),
-      files, chrome::mojom::AppShimLoginItemRestoreState::kNone,
-      base::DoNothing());
+      files, std::vector<GURL>(),
+      chrome::mojom::AppShimLoginItemRestoreState::kNone, base::DoNothing());
 }
 
 void AppShimManager::OnShimSelectedProfile(AppShimHost* host,
                                            const base::FilePath& profile_path) {
+  LoadAndLaunchApp(host->GetAppId(), profile_path,
+                   std::vector<base::FilePath>(), std::vector<GURL>(),
+                   chrome::mojom::AppShimLoginItemRestoreState::kNone,
+                   base::DoNothing());
+}
+
+void AppShimManager::OnShimOpenedUrls(AppShimHost* host,
+                                      const std::vector<GURL>& urls) {
+  auto found_app = apps_.find(host->GetAppId());
+  DCHECK(found_app != apps_.end());
+  AppState* app_state = found_app->second.get();
   LoadAndLaunchApp(
-      host->GetAppId(), profile_path, std::vector<base::FilePath>(),
+      host->GetAppId(),
+      app_state->IsMultiProfile() ? base::FilePath() : host->GetProfilePath(),
+      std::vector<base::FilePath>(), urls,
       chrome::mojom::AppShimLoginItemRestoreState::kNone, base::DoNothing());
 }
 
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac.h b/chrome/browser/apps/app_shim/app_shim_manager_mac.h
index e89ecd9a..56338e0 100644
--- a/chrome/browser/apps/app_shim/app_shim_manager_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_manager_mac.h
@@ -92,6 +92,7 @@
     virtual void LaunchApp(Profile* profile,
                            const web_app::AppId& app_id,
                            const std::vector<base::FilePath>& files,
+                           const std::vector<GURL>& urls,
                            chrome::mojom::AppShimLoginItemRestoreState
                                login_item_restore_state) = 0;
 
@@ -152,6 +153,8 @@
                          const std::vector<base::FilePath>& files) override;
   void OnShimSelectedProfile(AppShimHost* host,
                              const base::FilePath& profile_path) override;
+  void OnShimOpenedUrls(AppShimHost* host,
+                        const std::vector<GURL>& urls) override;
 
   // AppLifetimeMonitor::Observer overrides:
   void OnAppStart(content::BrowserContext* context,
@@ -263,17 +266,20 @@
       const web_app::AppId& app_id,
       const base::FilePath& profile_path,
       const std::vector<base::FilePath>& launch_files,
+      const std::vector<GURL>& launch_urls,
       chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state,
       LoadAndLaunchAppCallback launch_callback);
   bool LoadAndLaunchApp_TryExistingProfileStates(
       const web_app::AppId& app_id,
       const base::FilePath& profile_path,
       const std::vector<base::FilePath>& launch_files,
+      const std::vector<GURL>& launch_urls,
       chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state,
       LoadAndLaunchAppCallback* launch_callback);
   void LoadAndLaunchApp_OnProfilesAndAppReady(
       const web_app::AppId& app_id,
       const std::vector<base::FilePath>& launch_files,
+      const std::vector<GURL>& launch_urls,
       chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state,
       const std::vector<base::FilePath>& profile_paths_to_launch,
       LoadAndLaunchAppCallback launch_callback);
@@ -282,6 +288,7 @@
       ProfileState* profile_state,
       const web_app::AppId& app_id,
       const std::vector<base::FilePath>& launch_files,
+      const std::vector<GURL>& launch_urls,
       chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state);
 
   // The final step of both paths for OnShimProcessConnected. This will connect
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac_unittest.cc b/chrome/browser/apps/app_shim/app_shim_manager_mac_unittest.cc
index f614bdb..5a23bc9 100644
--- a/chrome/browser/apps/app_shim/app_shim_manager_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/app_shim_manager_mac_unittest.cc
@@ -53,10 +53,11 @@
   MOCK_METHOD2(AppIsMultiProfile, bool(Profile*, const std::string&));
   MOCK_METHOD3(EnableExtension,
                void(Profile*, const std::string&, base::OnceCallback<void()>));
-  MOCK_METHOD4(LaunchApp,
+  MOCK_METHOD5(LaunchApp,
                void(Profile*,
                     const std::string& app_id,
                     const std::vector<base::FilePath>&,
+                    const std::vector<GURL>&,
                     chrome::mojom::AppShimLoginItemRestoreState));
 
   // Conditionally mock LaunchShim. Some tests will execute |launch_callback|
@@ -189,6 +190,7 @@
   void DoTestLaunch(
       chrome::mojom::AppShimLaunchType launch_type,
       const std::vector<base::FilePath>& files,
+      const std::vector<GURL>& urls,
       chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state) {
     mojo::Remote<chrome::mojom::AppShimHost> host;
     auto app_shim_info = chrome::mojom::AppShimInfo::New();
@@ -198,6 +200,7 @@
       app_shim_info->app_url = GURL("https://example.com");
     app_shim_info->launch_type = launch_type;
     app_shim_info->files = files;
+    app_shim_info->urls = urls;
     app_shim_info->login_item_restore_state = login_item_restore_state;
     OnShimConnected(
         host.BindNewPipeAndPassReceiver(), std::move(app_shim_info),
@@ -284,6 +287,7 @@
   using AppShimHost::FilesOpened;
   using AppShimHost::ProfileSelectedFromMenu;
   using AppShimHost::ReopenApp;
+  using AppShimHost::UrlsOpened;
 
   std::unique_ptr<TestAppShim> test_app_shim_;
 
@@ -415,7 +419,7 @@
         .WillRepeatedly(Return(false));
     EXPECT_CALL(*delegate_, AppIsInstalled(_, kTestAppIdB))
         .WillRepeatedly(Return(true));
-    EXPECT_CALL(*delegate_, LaunchApp(_, _, _, _)).WillRepeatedly(Return());
+    EXPECT_CALL(*delegate_, LaunchApp(_, _, _, _, _)).WillRepeatedly(Return());
   }
 
   void TearDown() override {
@@ -449,17 +453,18 @@
       std::unique_ptr<TestHost> host,
       chrome::mojom::AppShimLaunchType launch_type,
       const std::vector<base::FilePath>& files,
+      const std::vector<GURL>& urls,
       chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state) {
     if (host)
       manager_->SetHostForCreate(std::move(host));
-    bootstrap->DoTestLaunch(launch_type, files, login_item_restore_state);
+    bootstrap->DoTestLaunch(launch_type, files, urls, login_item_restore_state);
   }
 
   void NormalLaunch(base::WeakPtr<TestingAppShimHostBootstrap> bootstrap,
                     std::unique_ptr<TestHost> host) {
     DoShimLaunch(bootstrap, std::move(host),
                  chrome::mojom::AppShimLaunchType::kNormal,
-                 std::vector<base::FilePath>(),
+                 std::vector<base::FilePath>(), std::vector<GURL>(),
                  chrome::mojom::AppShimLoginItemRestoreState::kNone);
   }
 
@@ -467,7 +472,7 @@
                           std::unique_ptr<TestHost> host) {
     DoShimLaunch(bootstrap, std::move(host),
                  chrome::mojom::AppShimLaunchType::kRegisterOnly,
-                 std::vector<base::FilePath>(),
+                 std::vector<base::FilePath>(), std::vector<GURL>(),
                  chrome::mojom::AppShimLoginItemRestoreState::kNone);
   }
 
@@ -604,11 +609,12 @@
   EXPECT_EQ(host_ab_.get(), manager_->FindHost(&profile_a_, kTestAppIdB));
 
   std::vector<base::FilePath> some_file(1, base::FilePath("some_file"));
+  std::vector<GURL> some_url(1, GURL("web+test://foo"));
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_b_, kTestAppIdB, some_file,
+              LaunchApp(&profile_b_, kTestAppIdB, some_file, some_url,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone));
   DoShimLaunch(bootstrap_bb_, std::move(host_bb_unique_),
-               chrome::mojom::AppShimLaunchType::kNormal, some_file,
+               chrome::mojom::AppShimLaunchType::kNormal, some_file, some_url,
                chrome::mojom::AppShimLoginItemRestoreState::kNone);
   EXPECT_EQ(host_bb_.get(), manager_->FindHost(&profile_b_, kTestAppIdB));
 
@@ -621,7 +627,7 @@
 
   // Starting and closing a second host does nothing.
   DoShimLaunch(bootstrap_aa_duplicate_, std::move(host_aa_duplicate_unique_),
-               chrome::mojom::AppShimLaunchType::kNormal, some_file,
+               chrome::mojom::AppShimLaunchType::kNormal, some_file, some_url,
                chrome::mojom::AppShimLoginItemRestoreState::kNone);
   EXPECT_EQ(chrome::mojom::AppShimLaunchResult::kDuplicateHost,
             *bootstrap_aa_duplicate_result_);
@@ -642,12 +648,13 @@
 
   // Run on OS Login Launch
   std::vector<base::FilePath> some_file(1, base::FilePath("some_file"));
+  std::vector<GURL> some_url(1, GURL("web+test://foo"));
   EXPECT_CALL(
       *delegate_,
-      LaunchApp(&profile_b_, kTestAppIdB, some_file,
+      LaunchApp(&profile_b_, kTestAppIdB, some_file, some_url,
                 chrome::mojom::AppShimLoginItemRestoreState::kWindowed));
   DoShimLaunch(bootstrap_bb_, std::move(host_bb_unique_),
-               chrome::mojom::AppShimLaunchType::kNormal, some_file,
+               chrome::mojom::AppShimLaunchType::kNormal, some_file, some_url,
                chrome::mojom::AppShimLoginItemRestoreState::kWindowed);
   EXPECT_EQ(host_bb_.get(), manager_->FindHost(&profile_b_, kTestAppIdB));
 
@@ -660,7 +667,7 @@
 
   // Starting and closing a second host does nothing.
   DoShimLaunch(bootstrap_aa_duplicate_, std::move(host_aa_duplicate_unique_),
-               chrome::mojom::AppShimLaunchType::kNormal, some_file,
+               chrome::mojom::AppShimLaunchType::kNormal, some_file, some_url,
                chrome::mojom::AppShimLoginItemRestoreState::kNone);
   EXPECT_EQ(chrome::mojom::AppShimLaunchResult::kDuplicateHost,
             *bootstrap_aa_duplicate_result_);
@@ -689,7 +696,8 @@
 
   // Normal shim launch adds an entry in the map.
   // App should not be launched here, but return success to the shim.
-  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _)).Times(0);
+  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _, _))
+      .Times(0);
   RegisterOnlyLaunch(bootstrap_aa_, nullptr);
   EXPECT_EQ(chrome::mojom::AppShimLaunchResult::kSuccess,
             *bootstrap_aa_result_);
@@ -698,31 +706,42 @@
   // Return no app windows for OnShimFocus. This will do nothing.
   EXPECT_CALL(*delegate_, ShowAppWindows(&profile_a_, kTestAppIdA))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _)).Times(0);
+  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _, _))
+      .Times(0);
   ShimNormalFocus(host_aa_.get());
 
   // Return no app windows for OnShimReopen. This will result in a launch call.
   EXPECT_CALL(*delegate_, ShowAppWindows(&profile_a_, kTestAppIdA))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _)).Times(1);
+  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _, _))
+      .Times(1);
   host_aa_->ReopenApp();
 
   // Return one window. This should do nothing.
   EXPECT_CALL(*delegate_, ShowAppWindows(&profile_a_, kTestAppIdA))
       .WillRepeatedly(Return(true));
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_a_, kTestAppIdA, _,
+              LaunchApp(&profile_a_, kTestAppIdA, _, _,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone))
       .Times(0);
   host_aa_->ReopenApp();
 
   // Open files should trigger a launch with those files.
   std::vector<base::FilePath> some_file(1, base::FilePath("some_file"));
-  EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_a_, kTestAppIdA, some_file,
-                        chrome::mojom::AppShimLoginItemRestoreState::kNone));
+  EXPECT_CALL(
+      *delegate_,
+      LaunchApp(&profile_a_, kTestAppIdA, some_file, std::vector<GURL>(),
+                chrome::mojom::AppShimLoginItemRestoreState::kNone));
   host_aa_->FilesOpened(some_file);
 
+  // Open urls should trigger a launch with those urls
+  std::vector<GURL> some_url(1, GURL("web+test://foo"));
+  EXPECT_CALL(
+      *delegate_,
+      LaunchApp(&profile_a_, kTestAppIdA, std::vector<base::FilePath>(),
+                some_url, chrome::mojom::AppShimLoginItemRestoreState::kNone));
+  host_aa_->UrlsOpened(some_url);
+
   // OnAppDeactivated should not close the shim.
   EXPECT_CALL(*manager_, MaybeTerminate()).Times(0);
   manager_->OnAppDeactivated(&profile_a_, kTestAppIdA);
@@ -747,7 +766,8 @@
 
   // Normal shim launch adds an entry in the map.
   // App should not be launched here, but return success to the shim.
-  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _)).Times(0);
+  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _, _))
+      .Times(0);
   RegisterOnlyLaunch(bootstrap_aa_, nullptr);
   EXPECT_EQ(chrome::mojom::AppShimLaunchResult::kSuccess,
             *bootstrap_aa_result_);
@@ -756,26 +776,37 @@
   // Return no app windows for OnShimFocus. This will do nothing.
   EXPECT_CALL(*delegate_, ShowAppWindows(&profile_a_, kTestAppIdA))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _)).Times(0);
+  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _, _))
+      .Times(0);
   ShimNormalFocus(host_aa_.get());
 
   // Return no app windows for OnShimReopen. This will result in a launch call.
   EXPECT_CALL(*delegate_, ShowAppWindows(&profile_a_, kTestAppIdA))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _)).Times(1);
+  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _, _))
+      .Times(1);
   host_aa_->ReopenApp();
 
   // Return one window. This should do nothing.
   EXPECT_CALL(*delegate_, ShowAppWindows(&profile_a_, kTestAppIdA))
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _)).Times(0);
+  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, _, _, _))
+      .Times(0);
   host_aa_->ReopenApp();
 
   // Open files should trigger a launch with those files.
   std::vector<base::FilePath> some_file(1, base::FilePath("some_file"));
-  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, some_file, _));
+  EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, kTestAppIdA, some_file,
+                                    std::vector<GURL>(), _));
   host_aa_->FilesOpened(some_file);
 
+  // Open urls should trigger a launch with those urls
+  std::vector<GURL> some_url(1, GURL("web+test://foo"));
+  EXPECT_CALL(*delegate_,
+              LaunchApp(&profile_a_, kTestAppIdA, std::vector<base::FilePath>(),
+                        some_url, _));
+  host_aa_->UrlsOpened(some_url);
+
   // Process disconnect will cause the host to be deleted.
   manager_->OnShimProcessDisconnected(host_aa_.get());
   EXPECT_EQ(nullptr, host_aa_.get());
@@ -971,7 +1002,7 @@
 TEST_F(AppShimManagerTest, RegisterOnly) {
   // For an chrome::mojom::AppShimLaunchType::kRegisterOnly, don't launch the
   // app.
-  EXPECT_CALL(*delegate_, LaunchApp(_, _, _, _)).Times(0);
+  EXPECT_CALL(*delegate_, LaunchApp(_, _, _, _, _)).Times(0);
   RegisterOnlyLaunch(bootstrap_aa_, std::move(host_aa_unique_));
   EXPECT_EQ(chrome::mojom::AppShimLaunchResult::kSuccess,
             *bootstrap_aa_result_);
@@ -986,7 +1017,7 @@
   delegate_->SetAppCanCreateHost(false);
 
   // The app should be launched.
-  EXPECT_CALL(*delegate_, LaunchApp(_, _, _, _)).Times(1);
+  EXPECT_CALL(*delegate_, LaunchApp(_, _, _, _, _)).Times(1);
   NormalLaunch(bootstrap_ab_, std::move(host_ab_unique_));
   // But the bootstrap should be closed.
   EXPECT_EQ(chrome::mojom::AppShimLaunchResult::kSuccessAndDisconnect,
@@ -1039,13 +1070,13 @@
   // Launch the app for this host. It should find the pre-existing host, and the
   // pre-existing host's launch result should be set.
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_a_, kTestAppIdA, _,
+              LaunchApp(&profile_a_, kTestAppIdA, _, _,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone))
       .Times(0);
   EXPECT_FALSE(host_aa_->did_connect_to_host());
   DoShimLaunch(bootstrap_aa_, nullptr,
                chrome::mojom::AppShimLaunchType::kRegisterOnly,
-               std::vector<base::FilePath>(),
+               std::vector<base::FilePath>(), std::vector<GURL>(),
                chrome::mojom::AppShimLoginItemRestoreState::kNone);
   EXPECT_TRUE(host_aa_->did_connect_to_host());
   EXPECT_EQ(chrome::mojom::AppShimLaunchResult::kSuccess,
@@ -1056,7 +1087,7 @@
   // profile should remain.
   DoShimLaunch(bootstrap_aa_duplicate_, nullptr,
                chrome::mojom::AppShimLaunchType::kRegisterOnly,
-               std::vector<base::FilePath>(),
+               std::vector<base::FilePath>(), std::vector<GURL>(),
                chrome::mojom::AppShimLoginItemRestoreState::kNone);
   EXPECT_TRUE(host_aa_->did_connect_to_host());
   EXPECT_EQ(chrome::mojom::AppShimLaunchResult::kDuplicateHost,
@@ -1153,7 +1184,7 @@
   // Select profile B from the menu. This should request that the app be
   // launched.
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_b_, kTestAppIdA, _,
+              LaunchApp(&profile_b_, kTestAppIdA, _, _,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone));
   host_aa_->ProfileSelectedFromMenu(profile_path_b_);
   EXPECT_CALL(*delegate_, DoLaunchShim(_, _, _)).Times(0);
@@ -1164,7 +1195,7 @@
   EXPECT_CALL(*delegate_, ShowAppWindows(_, _)).WillRepeatedly(Return(true));
   EXPECT_CALL(
       *delegate_,
-      LaunchApp(_, _, _, chrome::mojom::AppShimLoginItemRestoreState::kNone))
+      LaunchApp(_, _, _, _, chrome::mojom::AppShimLoginItemRestoreState::kNone))
       .Times(0);
   host_aa_->ProfileSelectedFromMenu(profile_path_a_);
   host_aa_->ProfileSelectedFromMenu(profile_path_b_);
@@ -1194,7 +1225,7 @@
 
   // Launch the shim.
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_a_, kTestAppIdA, _,
+              LaunchApp(&profile_a_, kTestAppIdA, _, _,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone))
       .Times(0);
   RegisterOnlyLaunch(bootstrap_aa_, nullptr);
@@ -1251,11 +1282,11 @@
   // Launch the shim requesting profile C.
   manager_->SetHostForCreate(std::move(host_aa_unique_));
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_a_, kTestAppIdA, _,
+              LaunchApp(&profile_a_, kTestAppIdA, _, _,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone))
       .Times(1);
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_b_, kTestAppIdA, _,
+              LaunchApp(&profile_b_, kTestAppIdA, _, _,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone))
       .Times(0);
   EXPECT_CALL(*delegate_, EnableExtension(&profile_c_, kTestAppIdA, _))
@@ -1274,11 +1305,11 @@
   // Launch the shim without specifying a profile.
   manager_->SetHostForCreate(std::move(host_aa_unique_));
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_a_, kTestAppIdA, _,
+              LaunchApp(&profile_a_, kTestAppIdA, _, _,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone))
       .Times(1);
   EXPECT_CALL(*delegate_,
-              LaunchApp(&profile_b_, kTestAppIdA, _,
+              LaunchApp(&profile_b_, kTestAppIdA, _, _,
                         chrome::mojom::AppShimLoginItemRestoreState::kNone))
       .Times(0);
   NormalLaunch(bootstrap_xa_, nullptr);
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
index 10c311e..c739cb5 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
@@ -88,10 +88,11 @@
     Profile* profile,
     const AppId& app_id,
     const std::vector<base::FilePath>& files,
+    const std::vector<GURL>& urls,
     chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state) {
   DCHECK(AppIsInstalled(profile, app_id));
   if (UseFallback(profile, app_id)) {
-    fallback_delegate_->LaunchApp(profile, app_id, files,
+    fallback_delegate_->LaunchApp(profile, app_id, files, urls,
                                   login_item_restore_state);
     return;
   }
@@ -110,6 +111,9 @@
                                WindowOpenDisposition::NEW_FOREGROUND_TAB,
                                launch_source);
   params.launch_files = files;
+  // We only support launching the one url, so take the first one.
+  if (!urls.empty())
+    params.protocol_handler_launch_url = urls[0];
 
   apps::AppServiceProxyFactory::GetForProfile(profile)
       ->BrowserAppLauncher()
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h
index 793be87..c64fc52 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h
@@ -27,6 +27,7 @@
   void LaunchApp(Profile* profile,
                  const AppId& app_id,
                  const std::vector<base::FilePath>& files,
+                 const std::vector<GURL>& urls,
                  chrome::mojom::AppShimLoginItemRestoreState
                      login_item_restore_state) override;
   void LaunchShim(Profile* profile,
diff --git a/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.cc b/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.cc
index c1f5ee3..65bf5bf 100644
--- a/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.cc
+++ b/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.cc
@@ -188,6 +188,7 @@
     Profile* profile,
     const web_app::AppId& app_id,
     const std::vector<base::FilePath>& files,
+    const std::vector<GURL>& urls,
     chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state) {
   const Extension* extension = MaybeGetAppExtension(profile, app_id);
   DCHECK(extension);
diff --git a/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.h b/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.h
index 35aabbe..cff25e6 100644
--- a/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.h
+++ b/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.h
@@ -29,6 +29,7 @@
   void LaunchApp(Profile* profile,
                  const web_app::AppId& app_id,
                  const std::vector<base::FilePath>& files,
+                 const std::vector<GURL>& urls,
                  chrome::mojom::AppShimLoginItemRestoreState
                      login_item_restore_state) override;
   void LaunchShim(Profile* profile,
diff --git a/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller.cc b/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller.cc
index 9d5381b..1216218 100644
--- a/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller.cc
+++ b/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller.cc
@@ -11,7 +11,7 @@
 #include "base/logging.h"
 #include "base/optional.h"
 #include "chrome/browser/ash/account_manager/account_manager_util.h"
-#include "chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.h"
+#include "chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_chromeos.h"
 #include "components/account_manager_core/account_manager_facade.h"
diff --git a/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc b/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc
index 09402c0b..d4670fa 100644
--- a/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc
+++ b/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/callback_forward.h"
 #include "base/values.h"
 #include "chrome/browser/account_manager_facade_factory.h"
-#include "chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.h"
+#include "chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_chromeos.h"
diff --git a/chrome/browser/ash/account_manager/account_manager_policy_controller.cc b/chrome/browser/ash/account_manager/account_manager_policy_controller.cc
index b097794..1c9e296c 100644
--- a/chrome/browser/ash/account_manager/account_manager_policy_controller.cc
+++ b/chrome/browser/ash/account_manager/account_manager_policy_controller.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/account_manager_facade_factory.h"
 #include "chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller.h"
 #include "chrome/browser/ash/account_manager/account_manager_util.h"
-#include "chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.h"
+#include "chrome/browser/ash/child_accounts/secondary_account_consent_logger.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/supervised_user/supervised_user_features.h"
 #include "components/account_manager_core/account_manager_facade.h"
diff --git a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.cc b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.cc
index 21cf1f9..4dcd6f7c 100644
--- a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.cc
+++ b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.cc
@@ -54,6 +54,12 @@
   return ArcCastReceiverServiceFactory::GetForBrowserContext(context);
 }
 
+// static
+ArcCastReceiverService* ArcCastReceiverService::GetForBrowserContextForTesting(
+    content::BrowserContext* context) {
+  return ArcCastReceiverServiceFactory::GetForBrowserContextForTesting(context);
+}
+
 ArcCastReceiverService::ArcCastReceiverService(content::BrowserContext* context,
                                                ArcBridgeService* bridge_service)
     : arc_bridge_service_(bridge_service) {
diff --git a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h
index 9b6a835a..96e4a69 100644
--- a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h
+++ b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h
@@ -32,6 +32,8 @@
   // or nullptr if the browser |context| is not allowed to use ARC.
   static ArcCastReceiverService* GetForBrowserContext(
       content::BrowserContext* context);
+  static ArcCastReceiverService* GetForBrowserContextForTesting(
+      content::BrowserContext* context);
 
   ArcCastReceiverService(content::BrowserContext* context,
                          ArcBridgeService* bridge_service);
diff --git a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service_unittest.cc b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service_unittest.cc
new file mode 100644
index 0000000..1a72f0f
--- /dev/null
+++ b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service_unittest.cc
@@ -0,0 +1,110 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h"
+
+#include <string>
+
+#include "base/optional.h"
+#include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chromeos/settings/cros_settings_names.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/session/arc_bridge_service.h"
+#include "components/arc/test/connection_holder_util.h"
+#include "components/arc/test/fake_cast_receiver_instance.h"
+#include "components/prefs/pref_service.h"
+#include "components/session_manager/core/session_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcCastReceiverServiceTest : public testing::Test {
+ protected:
+  ArcCastReceiverServiceTest()
+      // Reuse the settings service |profile_| automatically creates.
+      : settings_helper_(/*create_settings_service=*/false) {}
+  ArcCastReceiverServiceTest(const ArcCastReceiverServiceTest&) = delete;
+  ArcCastReceiverServiceTest& operator=(const ArcCastReceiverServiceTest&) =
+      delete;
+  ~ArcCastReceiverServiceTest() override = default;
+
+  void SetUp() override {
+    // Initialize prefs and settings.
+    prefs()->SetBoolean(prefs::kCastReceiverEnabled, false);
+    settings_helper()->ReplaceDeviceSettingsProviderWithStub();
+    settings_helper()->SetString(chromeos::kCastReceiverName, std::string());
+
+    bridge_ = ArcCastReceiverService::GetForBrowserContextForTesting(&profile_);
+    // This results in ArcCastReceiverService::OnInstanceReady being called.
+    ArcServiceManager::Get()
+        ->arc_bridge_service()
+        ->cast_receiver()
+        ->SetInstance(&cast_receiver_instance_);
+    WaitForInstanceReady(
+        ArcServiceManager::Get()->arc_bridge_service()->cast_receiver());
+  }
+
+  ArcCastReceiverService* bridge() { return bridge_; }
+  PrefService* prefs() { return profile_.GetPrefs(); }
+  ash::ScopedCrosSettingsTestHelper* settings_helper() {
+    return &settings_helper_;
+  }
+  const FakeCastReceiverInstance* cast_receiver_instance() const {
+    return &cast_receiver_instance_;
+  }
+
+ private:
+  content::BrowserTaskEnvironment task_environment_;
+  ArcServiceManager arc_service_manager_;
+  FakeCastReceiverInstance cast_receiver_instance_;
+  TestingProfile profile_;
+  ash::ScopedCrosSettingsTestHelper settings_helper_;
+  ArcCastReceiverService* bridge_ = nullptr;
+};
+
+TEST_F(ArcCastReceiverServiceTest, ConstructDestruct) {
+  EXPECT_NE(nullptr, bridge());
+}
+
+// Test that OnConnectionReady has already been called because of the
+// SetInstance() call in SetUp().
+TEST_F(ArcCastReceiverServiceTest, OnConnectionReady) {
+  const base::Optional<bool>& last_enabled =
+      cast_receiver_instance()->last_enabled();
+  ASSERT_TRUE(last_enabled);    // SetEnabled() has already been called.
+  EXPECT_FALSE(*last_enabled);  // ..and it is called with false.
+
+  const base::Optional<std::string>& last_name =
+      cast_receiver_instance()->last_name();
+  EXPECT_FALSE(last_name);  // SetName() hasn't been called yet.
+}
+
+// Tests that updating prefs::kCastReceiverEnabled triggers the mojo call.
+TEST_F(ArcCastReceiverServiceTest, OnCastReceiverEnabledChanged) {
+  prefs()->SetBoolean(prefs::kCastReceiverEnabled, true);
+
+  const base::Optional<bool>& last_enabled =
+      cast_receiver_instance()->last_enabled();
+  // Verify that the call was made with true.
+  ASSERT_TRUE(last_enabled);
+  EXPECT_TRUE(*last_enabled);
+}
+
+// Tests that updating chromeos::kCastReceiverName triggers the mojo call.
+TEST_F(ArcCastReceiverServiceTest, OnCastReceiverNameChanged) {
+  settings_helper()->SetString(chromeos::kCastReceiverName, "name");
+
+  const base::Optional<std::string>& last_name =
+      cast_receiver_instance()->last_name();
+  // Verify that the call was made with "name".
+  ASSERT_TRUE(last_name);
+  EXPECT_EQ("name", *last_name);
+}
+
+}  // namespace
+}  // namespace arc
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.cc b/chrome/browser/ash/arc/session/arc_service_launcher.cc
index 3982276..36233082 100644
--- a/chrome/browser/ash/arc/session/arc_service_launcher.cc
+++ b/chrome/browser/ash/arc/session/arc_service_launcher.cc
@@ -190,6 +190,7 @@
   // List in lexicographical order.
   ArcAccessibilityHelperBridge::GetForBrowserContext(profile);
   ArcAdbdMonitorBridge::GetForBrowserContext(profile);
+  ArcAppPerformanceTracing::GetForBrowserContext(profile);
   ArcAppPermissionsBridge::GetForBrowserContext(profile);
   ArcAudioBridge::GetForBrowserContext(profile);
   ArcAuthService::GetForBrowserContext(profile);
@@ -244,7 +245,6 @@
   ArcSharesheetBridge::GetForBrowserContext(profile);
   ArcTimerBridge::GetForBrowserContext(profile);
   ArcTracingBridge::GetForBrowserContext(profile);
-  ArcAppPerformanceTracing::GetForBrowserContext(profile);
   ArcTtsService::GetForBrowserContext(profile);
   ArcUsbHostBridge::GetForBrowserContext(profile)->SetDelegate(
       std::make_unique<ArcUsbHostBridgeDelegate>());
diff --git a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.cc b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.cc
index a93c67db..1609b0e 100644
--- a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.cc
+++ b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.cc
@@ -44,6 +44,12 @@
   return ArcSharesheetBridgeFactory::GetForBrowserContext(context);
 }
 
+// static
+ArcSharesheetBridge* ArcSharesheetBridge::GetForBrowserContextForTesting(
+    content::BrowserContext* context) {
+  return ArcSharesheetBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
 ArcSharesheetBridge::ArcSharesheetBridge(content::BrowserContext* context,
                                          ArcBridgeService* bridge_service)
     : arc_bridge_service_(bridge_service),
diff --git a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h
index 89a2447..a1a2ff2 100644
--- a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h
+++ b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h
@@ -28,6 +28,8 @@
   // or nullptr if the browser |context| is not allowed to use ARC.
   static ArcSharesheetBridge* GetForBrowserContext(
       content::BrowserContext* context);
+  static ArcSharesheetBridge* GetForBrowserContextForTesting(
+      content::BrowserContext* context);
 
   ArcSharesheetBridge(content::BrowserContext* context,
                       ArcBridgeService* bridge_service);
diff --git a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge_unittest.cc b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge_unittest.cc
new file mode 100644
index 0000000..6ce962b
--- /dev/null
+++ b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge_unittest.cc
@@ -0,0 +1,57 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h"
+
+#include "chrome/test/base/testing_profile.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/session/arc_bridge_service.h"
+#include "components/arc/test/connection_holder_util.h"
+#include "components/arc/test/fake_sharesheet_instance.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcSharesheetBridgeTest : public testing::Test {
+ protected:
+  ArcSharesheetBridgeTest() = default;
+  ArcSharesheetBridgeTest(const ArcSharesheetBridgeTest&) = delete;
+  ArcSharesheetBridgeTest& operator=(const ArcSharesheetBridgeTest&) = delete;
+  ~ArcSharesheetBridgeTest() override = default;
+
+  void SetUp() override {
+    bridge_ = ArcSharesheetBridge::GetForBrowserContextForTesting(&profile_);
+
+    EXPECT_EQ(0u, sharesheet_instance()->num_init_called());
+    // This results in ArcSharesheetBridge::OnInstanceReady being called.
+    ArcServiceManager::Get()->arc_bridge_service()->sharesheet()->SetInstance(
+        &sharesheet_instance_);
+    WaitForInstanceReady(
+        ArcServiceManager::Get()->arc_bridge_service()->sharesheet());
+    // Tests that SharesheetInstance's Init() method is called after the
+    // instance connects to the host.
+    EXPECT_EQ(1u, sharesheet_instance()->num_init_called());
+  }
+
+  ArcSharesheetBridge* bridge() { return bridge_; }
+  const FakeSharesheetInstance* sharesheet_instance() const {
+    return &sharesheet_instance_;
+  }
+
+ private:
+  content::BrowserTaskEnvironment task_environment_;
+  ArcServiceManager arc_service_manager_;
+  FakeSharesheetInstance sharesheet_instance_;
+  TestingProfile profile_;
+  ArcSharesheetBridge* bridge_ = nullptr;
+};
+
+TEST_F(ArcSharesheetBridgeTest, ConstructDestruct) {
+  EXPECT_NE(nullptr, bridge());
+}
+
+}  // namespace
+}  // namespace arc
diff --git a/chrome/browser/ash/arc/user_session/arc_user_session_service.cc b/chrome/browser/ash/arc/user_session/arc_user_session_service.cc
index 02364ba..4ae552b 100644
--- a/chrome/browser/ash/arc/user_session/arc_user_session_service.cc
+++ b/chrome/browser/ash/arc/user_session/arc_user_session_service.cc
@@ -34,11 +34,18 @@
 
 }  // namespace
 
+// static
 ArcUserSessionService* ArcUserSessionService::GetForBrowserContext(
     content::BrowserContext* context) {
   return ArcUserSessionServiceFactory::GetForBrowserContext(context);
 }
 
+// static
+ArcUserSessionService* ArcUserSessionService::GetForBrowserContextForTesting(
+    content::BrowserContext* context) {
+  return ArcUserSessionServiceFactory::GetForBrowserContextForTesting(context);
+}
+
 ArcUserSessionService::ArcUserSessionService(content::BrowserContext* context,
                                              ArcBridgeService* bridge_service)
     : arc_bridge_service_(bridge_service) {
diff --git a/chrome/browser/ash/arc/user_session/arc_user_session_service.h b/chrome/browser/ash/arc/user_session/arc_user_session_service.h
index 141dc1b..3f6cecfcd 100644
--- a/chrome/browser/ash/arc/user_session/arc_user_session_service.h
+++ b/chrome/browser/ash/arc/user_session/arc_user_session_service.h
@@ -28,6 +28,8 @@
   // or nullptr if the browser |context| is not allowed to use ARC.
   static ArcUserSessionService* GetForBrowserContext(
       content::BrowserContext* context);
+  static ArcUserSessionService* GetForBrowserContextForTesting(
+      content::BrowserContext* context);
 
   ArcUserSessionService(content::BrowserContext* context,
                         ArcBridgeService* bridge_service);
diff --git a/chrome/browser/ash/arc/user_session/arc_user_session_service_unittest.cc b/chrome/browser/ash/arc/user_session/arc_user_session_service_unittest.cc
new file mode 100644
index 0000000..f95a4d91
--- /dev/null
+++ b/chrome/browser/ash/arc/user_session/arc_user_session_service_unittest.cc
@@ -0,0 +1,76 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/arc/user_session/arc_user_session_service.h"
+
+#include "chrome/test/base/testing_profile.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
+#include "components/arc/session/arc_bridge_service.h"
+#include "components/arc/test/connection_holder_util.h"
+#include "components/arc/test/fake_intent_helper_instance.h"
+#include "components/session_manager/core/session_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcUserSessionServiceTest : public testing::Test {
+ protected:
+  ArcUserSessionServiceTest() = default;
+  ArcUserSessionServiceTest(const ArcUserSessionServiceTest&) = delete;
+  ArcUserSessionServiceTest& operator=(const ArcUserSessionServiceTest&) =
+      delete;
+  ~ArcUserSessionServiceTest() override = default;
+
+  void SetUp() override {
+    ArcIntentHelperBridge::GetForBrowserContextForTesting(&profile_);
+    ArcUserSessionService::GetForBrowserContextForTesting(&profile_);
+    // This results in ArcUserSessionService::OnConnectionReady being called
+    // by intent_helper().
+    // Note that unlike other bridges, ArcUserSessionServices piggybacks on
+    // intent_helper().
+    ArcServiceManager::Get()
+        ->arc_bridge_service()
+        ->intent_helper()
+        ->SetInstance(&intent_helper_instance_);
+    WaitForInstanceReady(
+        ArcServiceManager::Get()->arc_bridge_service()->intent_helper());
+  }
+
+  session_manager::SessionManager* session_manager() {
+    return &session_manager_;
+  }
+  const FakeIntentHelperInstance* intent_helper_instance() const {
+    return &intent_helper_instance_;
+  }
+
+ private:
+  content::BrowserTaskEnvironment task_environment_;
+  session_manager::SessionManager session_manager_;
+  ArcServiceManager arc_service_manager_;
+  FakeIntentHelperInstance intent_helper_instance_;
+  TestingProfile profile_;
+};
+
+TEST_F(ArcUserSessionServiceTest, ConstructDestruct) {}
+
+TEST_F(ArcUserSessionServiceTest, OnSessionStateChanged) {
+  const auto& broadcasts = intent_helper_instance()->broadcasts();
+  EXPECT_TRUE(broadcasts.empty());
+
+  // Set the state to "logged in".
+  session_manager()->SetSessionState(session_manager::SessionState::ACTIVE);
+  // Verify a broadcast is sent.
+  EXPECT_EQ(1u, broadcasts.size());
+
+  // Set the state to "locked".
+  session_manager()->SetSessionState(session_manager::SessionState::LOCKED);
+  // Verify a broadcast is not sent.
+  EXPECT_EQ(1u, broadcasts.size());
+}
+
+}  // namespace
+}  // namespace arc
diff --git a/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.cc b/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.cc
index a47edfb35..ca3f656 100644
--- a/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.cc
+++ b/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.cc
@@ -159,6 +159,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   gfx::ImageSkia image =
       WallpaperControllerClientImpl::Get()->GetWallpaperImage();
+  image.SetReadOnly();
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&EncodeImagePng, image), std::move(callback));
diff --git a/chrome/browser/chromeos/child_accounts/child_account_test_utils.cc b/chrome/browser/ash/child_accounts/child_account_test_utils.cc
similarity index 87%
rename from chrome/browser/chromeos/child_accounts/child_account_test_utils.cc
rename to chrome/browser/ash/child_accounts/child_account_test_utils.cc
index 2f057aaf..f6edd562e 100644
--- a/chrome/browser/chromeos/child_accounts/child_account_test_utils.cc
+++ b/chrome/browser/ash/child_accounts/child_account_test_utils.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/child_account_test_utils.h"
+#include "chrome/browser/ash/child_accounts/child_account_test_utils.h"
 
 #include "base/base64.h"
 #include "base/strings/stringprintf.h"
diff --git a/chrome/browser/chromeos/child_accounts/child_account_test_utils.h b/chrome/browser/ash/child_accounts/child_account_test_utils.h
similarity index 62%
rename from chrome/browser/chromeos/child_accounts/child_account_test_utils.h
rename to chrome/browser/ash/child_accounts/child_account_test_utils.h
index 30eb1c5..fd79a8d3 100644
--- a/chrome/browser/chromeos/child_accounts/child_account_test_utils.h
+++ b/chrome/browser/ash/child_accounts/child_account_test_utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
 
 #include <string>
 
@@ -16,4 +16,4 @@
 }  // namespace test
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
diff --git a/chrome/browser/chromeos/child_accounts/child_policy_observer.cc b/chrome/browser/ash/child_accounts/child_policy_observer.cc
similarity index 97%
rename from chrome/browser/chromeos/child_accounts/child_policy_observer.cc
rename to chrome/browser/ash/child_accounts/child_policy_observer.cc
index 543bab1..4c27a775 100644
--- a/chrome/browser/chromeos/child_accounts/child_policy_observer.cc
+++ b/chrome/browser/ash/child_accounts/child_policy_observer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/child_policy_observer.h"
+#include "chrome/browser/ash/child_accounts/child_policy_observer.h"
 
 #include "base/optional.h"
 #include "base/timer/timer.h"
diff --git a/chrome/browser/chromeos/child_accounts/child_policy_observer.h b/chrome/browser/ash/child_accounts/child_policy_observer.h
similarity index 93%
rename from chrome/browser/chromeos/child_accounts/child_policy_observer.h
rename to chrome/browser/ash/child_accounts/child_policy_observer.h
index ea1e8e7..51de234 100644
--- a/chrome/browser/chromeos/child_accounts/child_policy_observer.h
+++ b/chrome/browser/ash/child_accounts/child_policy_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_POLICY_OBSERVER_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_POLICY_OBSERVER_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_POLICY_OBSERVER_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_POLICY_OBSERVER_H_
 
 #include <memory>
 #include <utility>
@@ -93,4 +93,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_POLICY_OBSERVER_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_POLICY_OBSERVER_H_
diff --git a/chrome/browser/chromeos/child_accounts/child_status_reporting_service.cc b/chrome/browser/ash/child_accounts/child_status_reporting_service.cc
similarity index 94%
rename from chrome/browser/chromeos/child_accounts/child_status_reporting_service.cc
rename to chrome/browser/ash/child_accounts/child_status_reporting_service.cc
index 389a13e..9fb415d 100644
--- a/chrome/browser/chromeos/child_accounts/child_status_reporting_service.cc
+++ b/chrome/browser/ash/child_accounts/child_status_reporting_service.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
+#include "chrome/browser/ash/child_accounts/event_based_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
 #include "chrome/browser/chromeos/policy/status_collector/child_status_collector.h"
 #include "chrome/browser/chromeos/policy/status_uploader.h"
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
diff --git a/chrome/browser/chromeos/child_accounts/child_status_reporting_service.h b/chrome/browser/ash/child_accounts/child_status_reporting_service.h
similarity index 89%
rename from chrome/browser/chromeos/child_accounts/child_status_reporting_service.h
rename to chrome/browser/ash/child_accounts/child_status_reporting_service.h
index c3f8bdc0..5b76d42f 100644
--- a/chrome/browser/chromeos/child_accounts/child_status_reporting_service.h
+++ b/chrome/browser/ash/child_accounts/child_status_reporting_service.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_H_
 
 #include <memory>
 
@@ -69,4 +69,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_H_
diff --git a/chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.cc b/chrome/browser/ash/child_accounts/child_status_reporting_service_factory.cc
similarity index 87%
rename from chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.cc
rename to chrome/browser/ash/child_accounts/child_status_reporting_service_factory.cc
index ad95e128..1354527 100644
--- a/chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.cc
+++ b/chrome/browser/ash/child_accounts/child_status_reporting_service_factory.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
 
 #include "base/macros.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h b/chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h
similarity index 84%
rename from chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h
rename to chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h
index 9c8384d..bb14a19 100644
--- a/chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h
+++ b/chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_FACTORY_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -45,4 +45,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_FACTORY_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_STATUS_REPORTING_SERVICE_FACTORY_H_
diff --git a/chrome/browser/chromeos/child_accounts/child_user_service.cc b/chrome/browser/ash/child_accounts/child_user_service.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/child_user_service.cc
rename to chrome/browser/ash/child_accounts/child_user_service.cc
index 6def6f6b..b964c3d 100644
--- a/chrome/browser/chromeos/child_accounts/child_user_service.cc
+++ b/chrome/browser/ash/child_accounts/child_user_service.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
 
 #include "base/time/time.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_registry.h"
diff --git a/chrome/browser/chromeos/child_accounts/child_user_service.h b/chrome/browser/ash/child_accounts/child_user_service.h
similarity index 92%
rename from chrome/browser/chromeos/child_accounts/child_user_service.h
rename to chrome/browser/ash/child_accounts/child_user_service.h
index d9ee32cf..454011a5 100644
--- a/chrome/browser/chromeos/child_accounts/child_user_service.h
+++ b/chrome/browser/ash/child_accounts/child_user_service.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_USER_SERVICE_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_USER_SERVICE_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_USER_SERVICE_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_USER_SERVICE_H_
 
 #include <memory>
 #include <set>
 #include <string>
 
+#include "chrome/browser/ash/child_accounts/family_user_parental_control_metrics.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_report_interface.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace base {
@@ -111,4 +111,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_USER_SERVICE_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_USER_SERVICE_H_
diff --git a/chrome/browser/chromeos/child_accounts/child_user_service_factory.cc b/chrome/browser/ash/child_accounts/child_user_service_factory.cc
similarity index 88%
rename from chrome/browser/chromeos/child_accounts/child_user_service_factory.cc
rename to chrome/browser/ash/child_accounts/child_user_service_factory.cc
index e8252770..72e8e42 100644
--- a/chrome/browser/chromeos/child_accounts/child_user_service_factory.cc
+++ b/chrome/browser/ash/child_accounts/child_user_service_factory.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/child_accounts/child_user_service_factory.h b/chrome/browser/ash/child_accounts/child_user_service_factory.h
similarity index 84%
rename from chrome/browser/chromeos/child_accounts/child_user_service_factory.h
rename to chrome/browser/ash/child_accounts/child_user_service_factory.h
index ad0c445..b04ad09 100644
--- a/chrome/browser/chromeos/child_accounts/child_user_service_factory.h
+++ b/chrome/browser/ash/child_accounts/child_user_service_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_USER_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_USER_SERVICE_FACTORY_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_USER_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_USER_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -40,4 +40,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_USER_SERVICE_FACTORY_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_CHILD_USER_SERVICE_FACTORY_H_
diff --git a/chrome/browser/chromeos/child_accounts/child_user_service_unittest.cc b/chrome/browser/ash/child_accounts/child_user_service_unittest.cc
similarity index 96%
rename from chrome/browser/chromeos/child_accounts/child_user_service_unittest.cc
rename to chrome/browser/ash/child_accounts/child_user_service_unittest.cc
index d50cd1e9..11f00ae 100644
--- a/chrome/browser/chromeos/child_accounts/child_user_service_unittest.cc
+++ b/chrome/browser/ash/child_accounts/child_user_service_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
 
 #include <memory>
 #include <vector>
@@ -10,12 +10,12 @@
 #include "base/feature_list.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.cc b/chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.cc
similarity index 97%
rename from chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.cc
rename to chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.cc
index b3b374f..04382db 100644
--- a/chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.cc
+++ b/chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.h"
+#include "chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h"
 
 #include "ash/constants/ash_pref_names.h"
 #include "base/logging.h"
diff --git a/chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.h b/chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h
similarity index 90%
rename from chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.h
rename to chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h
index 3eb2e19..c95bc5c7 100644
--- a/chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.h
+++ b/chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EDU_COEXISTENCE_TOS_STORE_UTILS_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EDU_COEXISTENCE_TOS_STORE_UTILS_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EDU_COEXISTENCE_TOS_STORE_UTILS_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EDU_COEXISTENCE_TOS_STORE_UTILS_H_
 
 #include <string>
 #include <vector>
@@ -59,4 +59,4 @@
 }  // namespace edu_coexistence
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EDU_COEXISTENCE_TOS_STORE_UTILS_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EDU_COEXISTENCE_TOS_STORE_UTILS_H_
diff --git a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.cc b/chrome/browser/ash/child_accounts/event_based_status_reporting_service.cc
similarity index 93%
rename from chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.cc
rename to chrome/browser/ash/child_accounts/event_based_status_reporting_service.cc
index db7fa68..13a9f1fe 100644
--- a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.cc
+++ b/chrome/browser/ash/child_accounts/event_based_status_reporting_service.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h"
+#include "chrome/browser/ash/child_accounts/event_based_status_reporting_service.h"
 
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/session_manager/core/session_manager.h"
diff --git a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h b/chrome/browser/ash/child_accounts/event_based_status_reporting_service.h
similarity index 89%
rename from chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h
rename to chrome/browser/ash/child_accounts/event_based_status_reporting_service.h
index 1f5f8282..f5bb1112 100644
--- a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h
+++ b/chrome/browser/ash/child_accounts/event_based_status_reporting_service.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_H_
 
 #include <string>
 
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -95,4 +95,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_H_
diff --git a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_factory.cc b/chrome/browser/ash/child_accounts/event_based_status_reporting_service_factory.cc
similarity index 81%
rename from chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_factory.cc
rename to chrome/browser/ash/child_accounts/event_based_status_reporting_service_factory.cc
index a1a9422..dd95493e 100644
--- a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_factory.cc
+++ b/chrome/browser/ash/child_accounts/event_based_status_reporting_service_factory.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/event_based_status_reporting_service_factory.h"
 
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/event_based_status_reporting_service.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
diff --git a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_factory.h b/chrome/browser/ash/child_accounts/event_based_status_reporting_service_factory.h
similarity index 82%
rename from chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_factory.h
rename to chrome/browser/ash/child_accounts/event_based_status_reporting_service_factory.h
index fce832a..1f67938 100644
--- a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_factory.h
+++ b/chrome/browser/ash/child_accounts/event_based_status_reporting_service_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_FACTORY_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_FACTORY_H_
 
 #include "base/macros.h"
 #include "base/no_destructor.h"
@@ -42,4 +42,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_FACTORY_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_EVENT_BASED_STATUS_REPORTING_SERVICE_FACTORY_H_
diff --git a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc b/chrome/browser/ash/child_accounts/event_based_status_reporting_service_unittest.cc
similarity index 96%
rename from chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc
rename to chrome/browser/ash/child_accounts/event_based_status_reporting_service_unittest.cc
index 71e8914..6c81ed4d3 100644
--- a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc
+++ b/chrome/browser/ash/child_accounts/event_based_status_reporting_service_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h"
+#include "chrome/browser/ash/child_accounts/event_based_status_reporting_service.h"
 
 #include <memory>
 
@@ -10,11 +10,11 @@
 #include "base/macros.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller_factory.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/chromeos/child_accounts/family_features.cc b/chrome/browser/ash/child_accounts/family_features.cc
similarity index 91%
rename from chrome/browser/chromeos/child_accounts/family_features.cc
rename to chrome/browser/ash/child_accounts/family_features.cc
index d63b313..a406cff 100644
--- a/chrome/browser/chromeos/child_accounts/family_features.cc
+++ b/chrome/browser/ash/child_accounts/family_features.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_features.h"
+#include "chrome/browser/ash/child_accounts/family_features.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/child_accounts/family_features.h b/chrome/browser/ash/child_accounts/family_features.h
similarity index 79%
rename from chrome/browser/chromeos/child_accounts/family_features.h
rename to chrome/browser/ash/child_accounts/family_features.h
index 751818e..9caedeec 100644
--- a/chrome/browser/chromeos/child_accounts/family_features.h
+++ b/chrome/browser/ash/child_accounts/family_features.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_FEATURES_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_FEATURES_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_FEATURES_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_FEATURES_H_
 
 #include "base/feature_list.h"
 
@@ -24,4 +24,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_FEATURES_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_FEATURES_H_
diff --git a/chrome/browser/chromeos/child_accounts/family_user_app_metrics.cc b/chrome/browser/ash/child_accounts/family_user_app_metrics.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/family_user_app_metrics.cc
rename to chrome/browser/ash/child_accounts/family_user_app_metrics.cc
index fad87a47..7411f88d 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_app_metrics.cc
+++ b/chrome/browser/ash/child_accounts/family_user_app_metrics.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_app_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_app_metrics.h"
 
 #include <memory>
 
diff --git a/chrome/browser/chromeos/child_accounts/family_user_app_metrics.h b/chrome/browser/ash/child_accounts/family_user_app_metrics.h
similarity index 89%
rename from chrome/browser/chromeos/child_accounts/family_user_app_metrics.h
rename to chrome/browser/ash/child_accounts/family_user_app_metrics.h
index 1b902abc..cf907d9 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_app_metrics.h
+++ b/chrome/browser/ash/child_accounts/family_user_app_metrics.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_APP_METRICS_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_APP_METRICS_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_APP_METRICS_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_APP_METRICS_H_
 
 #include <set>
 #include <string>
 
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 
@@ -82,4 +82,4 @@
 };
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_APP_METRICS_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_APP_METRICS_H_
diff --git a/chrome/browser/chromeos/child_accounts/family_user_app_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
similarity index 99%
rename from chrome/browser/chromeos/child_accounts/family_user_app_metrics_unittest.cc
rename to chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
index 8be53994..24680b6 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_app_metrics_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_app_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_app_metrics.h"
 
 #include <memory>
 #include <vector>
diff --git a/chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.cc b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.cc
similarity index 97%
rename from chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.cc
rename to chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.cc
index 119de900..4b923d7 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.cc
+++ b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.h"
 
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
diff --git a/chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.h b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.h
similarity index 87%
rename from chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.h
rename to chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.h
index a55d7ca..7ba88de3 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.h
+++ b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_CHROME_ACTIVITY_METRICS_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_CHROME_ACTIVITY_METRICS_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_CHROME_ACTIVITY_METRICS_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_CHROME_ACTIVITY_METRICS_H_
 
 #include <set>
 
 #include "base/time/time.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
 
 class PrefRegistrySimple;
 class PrefService;
@@ -70,4 +70,4 @@
 };
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_CHROME_ACTIVITY_METRICS_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_CHROME_ACTIVITY_METRICS_H_
diff --git a/chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics_unittest.cc
rename to chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
index 6354aec0..78ca81c8 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.h"
 
 #include <memory>
 #include <vector>
diff --git a/chrome/browser/chromeos/child_accounts/family_user_device_metrics.cc b/chrome/browser/ash/child_accounts/family_user_device_metrics.cc
similarity index 97%
rename from chrome/browser/chromeos/child_accounts/family_user_device_metrics.cc
rename to chrome/browser/ash/child_accounts/family_user_device_metrics.cc
index d8424c9..2195768 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_device_metrics.cc
+++ b/chrome/browser/ash/child_accounts/family_user_device_metrics.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_device_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_device_metrics.h"
 
 #include <string>
 
diff --git a/chrome/browser/chromeos/child_accounts/family_user_device_metrics.h b/chrome/browser/ash/child_accounts/family_user_device_metrics.h
similarity index 89%
rename from chrome/browser/chromeos/child_accounts/family_user_device_metrics.h
rename to chrome/browser/ash/child_accounts/family_user_device_metrics.h
index 0f31e41..1661fc4 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_device_metrics.h
+++ b/chrome/browser/ash/child_accounts/family_user_device_metrics.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_DEVICE_METRICS_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_DEVICE_METRICS_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_DEVICE_METRICS_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_DEVICE_METRICS_H_
 
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
 #include "chrome/browser/ash/settings/device_settings_service.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
 #include "components/session_manager/core/session_manager_observer.h"
 
 namespace user_manager {
@@ -69,4 +69,4 @@
 };
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_DEVICE_METRICS_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_DEVICE_METRICS_H_
diff --git a/chrome/browser/chromeos/child_accounts/family_user_device_metrics_browsertest.cc b/chrome/browser/ash/child_accounts/family_user_device_metrics_browsertest.cc
similarity index 99%
rename from chrome/browser/chromeos/child_accounts/family_user_device_metrics_browsertest.cc
rename to chrome/browser/ash/child_accounts/family_user_device_metrics_browsertest.cc
index 9ca4881..6c7123f 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_device_metrics_browsertest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_device_metrics_browsertest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_device_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_device_metrics.h"
 
 #include <memory>
 #include <tuple>
diff --git a/chrome/browser/chromeos/child_accounts/family_user_metrics_service.cc b/chrome/browser/ash/child_accounts/family_user_metrics_service.cc
similarity index 85%
rename from chrome/browser/chromeos/child_accounts/family_user_metrics_service.cc
rename to chrome/browser/ash/child_accounts/family_user_metrics_service.cc
index 0db8ac3f..56ff5886 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_metrics_service.cc
+++ b/chrome/browser/ash/child_accounts/family_user_metrics_service.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
 
 #include "base/check.h"
 #include "base/time/time.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_app_metrics.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_device_metrics.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_session_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_app_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_device_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_parental_control_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_session_metrics.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/chromeos/child_accounts/family_user_metrics_service.h b/chrome/browser/ash/child_accounts/family_user_metrics_service.h
similarity index 89%
rename from chrome/browser/chromeos/child_accounts/family_user_metrics_service.h
rename to chrome/browser/ash/child_accounts/family_user_metrics_service.h
index 8b73ce8..0896336e 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_metrics_service.h
+++ b/chrome/browser/ash/child_accounts/family_user_metrics_service.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_H_
 
 #include <memory>
 #include <vector>
@@ -69,4 +69,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_H_
diff --git a/chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.cc b/chrome/browser/ash/child_accounts/family_user_metrics_service_factory.cc
similarity index 86%
rename from chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.cc
rename to chrome/browser/ash/child_accounts/family_user_metrics_service_factory.cc
index 911e3364..f5030e1 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.cc
+++ b/chrome/browser/ash/child_accounts/family_user_metrics_service_factory.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service_factory.h"
 
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.h b/chrome/browser/ash/child_accounts/family_user_metrics_service_factory.h
similarity index 84%
rename from chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.h
rename to chrome/browser/ash/child_accounts/family_user_metrics_service_factory.h
index c477b83..2408f3f 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.h
+++ b/chrome/browser/ash/child_accounts/family_user_metrics_service_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_FACTORY_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -45,4 +45,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_FACTORY_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_METRICS_SERVICE_FACTORY_H_
diff --git a/chrome/browser/chromeos/child_accounts/family_user_metrics_service_unittest.cc b/chrome/browser/ash/child_accounts/family_user_metrics_service_unittest.cc
similarity index 97%
rename from chrome/browser/chromeos/child_accounts/family_user_metrics_service_unittest.cc
rename to chrome/browser/ash/child_accounts/family_user_metrics_service_unittest.cc
index 52fc52cb..0856fc3 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_metrics_service_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_metrics_service_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
 
 #include <memory>
 
diff --git a/chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.cc b/chrome/browser/ash/child_accounts/family_user_parental_control_metrics.cc
similarity index 93%
rename from chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.cc
rename to chrome/browser/ash/child_accounts/family_user_parental_control_metrics.cc
index 96ad6cf..421ffc1 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.cc
+++ b/chrome/browser/ash/child_accounts/family_user_parental_control_metrics.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_parental_control_metrics.h"
 
 #include <set>
 
 #include "base/check.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/values.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/supervised_user/supervised_user_service.h"
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
diff --git a/chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.h b/chrome/browser/ash/child_accounts/family_user_parental_control_metrics.h
similarity index 86%
rename from chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.h
rename to chrome/browser/ash/child_accounts/family_user_parental_control_metrics.h
index eeebcc4c..0ebbb54b2 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.h
+++ b/chrome/browser/ash/child_accounts/family_user_parental_control_metrics.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_PARENTAL_CONTROL_METRICS_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_PARENTAL_CONTROL_METRICS_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_PARENTAL_CONTROL_METRICS_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_PARENTAL_CONTROL_METRICS_H_
 
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
 
 class Profile;
 
@@ -62,4 +62,4 @@
 };
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_PARENTAL_CONTROL_METRICS_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_PARENTAL_CONTROL_METRICS_H_
diff --git a/chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_parental_control_metrics_unittest.cc
similarity index 97%
rename from chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics_unittest.cc
rename to chrome/browser/ash/child_accounts/family_user_parental_control_metrics_unittest.cc
index a2fad0e..59f2f18 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_parental_control_metrics_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_parental_control_metrics.h"
 
 #include <memory>
 #include <string>
@@ -15,15 +15,15 @@
 #include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/apps/app_service/app_service_test.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/ash/child_accounts/time_limit_test_utils.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limits_policy_builder.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_test_utils.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
diff --git a/chrome/browser/chromeos/child_accounts/family_user_session_metrics.cc b/chrome/browser/ash/child_accounts/family_user_session_metrics.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/family_user_session_metrics.cc
rename to chrome/browser/ash/child_accounts/family_user_session_metrics.cc
index e0dafaa..227ec26 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_session_metrics.cc
+++ b/chrome/browser/ash/child_accounts/family_user_session_metrics.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_session_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_session_metrics.h"
 
 #include <string>
 #include <utility>
diff --git a/chrome/browser/chromeos/child_accounts/family_user_session_metrics.h b/chrome/browser/ash/child_accounts/family_user_session_metrics.h
similarity index 86%
rename from chrome/browser/chromeos/child_accounts/family_user_session_metrics.h
rename to chrome/browser/ash/child_accounts/family_user_session_metrics.h
index 158f1e2d..80528b0 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_session_metrics.h
+++ b/chrome/browser/ash/child_accounts/family_user_session_metrics.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_SESSION_METRICS_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_SESSION_METRICS_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_SESSION_METRICS_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_SESSION_METRICS_H_
 
 #include "base/time/time.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
+#include "chrome/browser/ash/child_accounts/usage_time_state_notifier.h"
 
 class PrefRegistrySimple;
 class PrefService;
@@ -66,4 +66,4 @@
 };
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_SESSION_METRICS_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_FAMILY_USER_SESSION_METRICS_H_
diff --git a/chrome/browser/chromeos/child_accounts/family_user_session_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_session_metrics_unittest.cc
similarity index 99%
rename from chrome/browser/chromeos/child_accounts/family_user_session_metrics_unittest.cc
rename to chrome/browser/ash/child_accounts/family_user_session_metrics_unittest.cc
index c275dc3d4..dce9494 100644
--- a/chrome/browser/chromeos/child_accounts/family_user_session_metrics_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_session_metrics_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/family_user_session_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_session_metrics.h"
 
 #include <memory>
 
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc b/chrome/browser/ash/child_accounts/screen_time_controller.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/screen_time_controller.cc
rename to chrome/browser/ash/child_accounts/screen_time_controller.cc
index 9027c89..a990fdd 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
+++ b/chrome/browser/ash/child_accounts/screen_time_controller.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller.h"
 
 #include <algorithm>
 #include <string>
@@ -15,11 +15,11 @@
 #include "base/time/clock.h"
 #include "base/time/default_clock.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/time_limit_override.h"
 #include "chrome/browser/ash/login/lock/screen_locker.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_override.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.h b/chrome/browser/ash/child_accounts/screen_time_controller.h
similarity index 93%
rename from chrome/browser/chromeos/child_accounts/screen_time_controller.h
rename to chrome/browser/ash/child_accounts/screen_time_controller.h
index 613d662..e7409ad 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller.h
+++ b/chrome/browser/ash/child_accounts/screen_time_controller.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
 
 #include <memory>
 #include <string>
@@ -14,9 +14,9 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/child_accounts/parent_access_code/parent_access_service.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_notifier.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h"
+#include "chrome/browser/ash/child_accounts/time_limit_notifier.h"
+#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
+#include "chrome/browser/ash/child_accounts/usage_time_state_notifier.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -180,4 +180,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc b/chrome/browser/ash/child_accounts/screen_time_controller_browsertest.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc
rename to chrome/browser/ash/child_accounts/screen_time_controller_browsertest.cc
index 482d4c4..0d9d3a5 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc
+++ b/chrome/browser/ash/child_accounts/screen_time_controller_browsertest.cc
@@ -11,15 +11,15 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller_factory.h"
+#include "chrome/browser/ash/child_accounts/time_limit_override.h"
+#include "chrome/browser/ash/child_accounts/time_limit_test_utils.h"
 #include "chrome/browser/ash/login/lock/screen_locker.h"
 #include "chrome/browser/ash/login/lock/screen_locker_tester.h"
 #include "chrome/browser/ash/login/test/logged_in_user_mixin.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_override.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_test_utils.h"
 #include "chrome/browser/chromeos/policy/user_policy_test_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller_factory.cc b/chrome/browser/ash/child_accounts/screen_time_controller_factory.cc
similarity index 82%
rename from chrome/browser/chromeos/child_accounts/screen_time_controller_factory.cc
rename to chrome/browser/ash/child_accounts/screen_time_controller_factory.cc
index 72f5bda..5bb245db 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller_factory.cc
+++ b/chrome/browser/ash/child_accounts/screen_time_controller_factory.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller_factory.h"
 
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h b/chrome/browser/ash/child_accounts/screen_time_controller_factory.h
similarity index 82%
rename from chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h
rename to chrome/browser/ash/child_accounts/screen_time_controller_factory.h
index 1a2b450d..56881461 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h
+++ b/chrome/browser/ash/child_accounts/screen_time_controller_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_FACTORY_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_FACTORY_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_FACTORY_H_
 
 #include "base/no_destructor.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -40,4 +40,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_FACTORY_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_FACTORY_H_
diff --git a/chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.cc b/chrome/browser/ash/child_accounts/secondary_account_consent_logger.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.cc
rename to chrome/browser/ash/child_accounts/secondary_account_consent_logger.cc
index 962e97e6..232103f 100644
--- a/chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.cc
+++ b/chrome/browser/ash/child_accounts/secondary_account_consent_logger.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.h"
+#include "chrome/browser/ash/child_accounts/secondary_account_consent_logger.h"
 
 #include <utility>
 
diff --git a/chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.h b/chrome/browser/ash/child_accounts/secondary_account_consent_logger.h
similarity index 93%
rename from chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.h
rename to chrome/browser/ash/child_accounts/secondary_account_consent_logger.h
index 2875e4e..fdff29e 100644
--- a/chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.h
+++ b/chrome/browser/ash/child_accounts/secondary_account_consent_logger.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SECONDARY_ACCOUNT_CONSENT_LOGGER_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SECONDARY_ACCOUNT_CONSENT_LOGGER_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SECONDARY_ACCOUNT_CONSENT_LOGGER_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SECONDARY_ACCOUNT_CONSENT_LOGGER_H_
 
 #include <memory>
 #include <string>
@@ -103,4 +103,4 @@
   SEQUENCE_CHECKER(sequence_checker_);
 };
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SECONDARY_ACCOUNT_CONSENT_LOGGER_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_SECONDARY_ACCOUNT_CONSENT_LOGGER_H_
diff --git a/chrome/browser/chromeos/child_accounts/secondary_account_consent_logger_unittest.cc b/chrome/browser/ash/child_accounts/secondary_account_consent_logger_unittest.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/secondary_account_consent_logger_unittest.cc
rename to chrome/browser/ash/child_accounts/secondary_account_consent_logger_unittest.cc
index 0510e9e0..d80d0dc 100644
--- a/chrome/browser/chromeos/child_accounts/secondary_account_consent_logger_unittest.cc
+++ b/chrome/browser/ash/child_accounts/secondary_account_consent_logger_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.h"
+#include "chrome/browser/ash/child_accounts/secondary_account_consent_logger.h"
 
 #include <vector>
 
diff --git a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc
index a198b3b..7287c725 100644
--- a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc
+++ b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc
@@ -6,7 +6,7 @@
 
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_test_utils.h"
+#include "chrome/browser/ash/child_accounts/time_limit_test_utils.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter.h b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter.h
index 994c4d8..226b3fcb 100644
--- a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter.h
+++ b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter.h
@@ -12,7 +12,7 @@
 
 #include "base/optional.h"
 #include "chrome/browser/ash/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
+#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
 
 namespace base {
 class Value;
diff --git a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc
index b179720..5b2d998 100644
--- a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc
+++ b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/time/time.h"
 #include "chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_test_utils.h"
 #include "chrome/browser/ash/child_accounts/time_limit_consistency_test/proto_matcher.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_test_utils.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
+#include "chrome/browser/ash/child_accounts/time_limit_test_utils.h"
+#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_loader_unittest.cc b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_loader_unittest.cc
index f6cb7d9..1941d8f9 100644
--- a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_loader_unittest.cc
+++ b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_loader_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/files/file_util.h"
 #include "base/path_service.h"
 #include "chrome/browser/ash/child_accounts/time_limit_consistency_test/proto_matcher.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_test_utils.h"
+#include "chrome/browser/ash/child_accounts/time_limit_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_test.cc b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_test.cc
index 4a5d1e0..fb60035 100644
--- a/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_test.cc
+++ b/chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_test.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/ash/child_accounts/time_limit_consistency_test/consistency_golden_loader.h"
 #include "chrome/browser/ash/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h"
 #include "chrome/browser/ash/child_accounts/time_limit_consistency_test/proto_matcher.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
+#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
 #include "chromeos/settings/timezone_settings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc b/chrome/browser/ash/child_accounts/time_limit_notifier.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/time_limit_notifier.cc
rename to chrome/browser/ash/child_accounts/time_limit_notifier.cc
index 23fd4961..b492d5b 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc
+++ b/chrome/browser/ash/child_accounts/time_limit_notifier.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/time_limit_notifier.h"
+#include "chrome/browser/ash/child_accounts/time_limit_notifier.h"
 
 #include <memory>
 #include <string>
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_notifier.h b/chrome/browser/ash/child_accounts/time_limit_notifier.h
similarity index 89%
rename from chrome/browser/chromeos/child_accounts/time_limit_notifier.h
rename to chrome/browser/ash/child_accounts/time_limit_notifier.h
index 985bf9a8..496a1a24 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_notifier.h
+++ b/chrome/browser/ash/child_accounts/time_limit_notifier.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
 
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
@@ -59,4 +59,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_notifier_unittest.cc b/chrome/browser/ash/child_accounts/time_limit_notifier_unittest.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/time_limit_notifier_unittest.cc
rename to chrome/browser/ash/child_accounts/time_limit_notifier_unittest.cc
index a3ae92e..3b7df573 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_notifier_unittest.cc
+++ b/chrome/browser/ash/child_accounts/time_limit_notifier_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/time_limit_notifier.h"
+#include "chrome/browser/ash/child_accounts/time_limit_notifier.h"
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_override.cc b/chrome/browser/ash/child_accounts/time_limit_override.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/time_limit_override.cc
rename to chrome/browser/ash/child_accounts/time_limit_override.cc
index 7f2c49d..bd246de 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_override.cc
+++ b/chrome/browser/ash/child_accounts/time_limit_override.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/time_limit_override.h"
+#include "chrome/browser/ash/child_accounts/time_limit_override.h"
 
 #include <utility>
 
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_override.h b/chrome/browser/ash/child_accounts/time_limit_override.h
similarity index 91%
rename from chrome/browser/chromeos/child_accounts/time_limit_override.h
rename to chrome/browser/ash/child_accounts/time_limit_override.h
index 7e0877d..4fba3e2 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_override.h
+++ b/chrome/browser/ash/child_accounts/time_limit_override.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_OVERRIDE_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_OVERRIDE_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_OVERRIDE_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_OVERRIDE_H_
 
 #include <string>
 
@@ -82,4 +82,4 @@
 }  // namespace usage_time_limit
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_OVERRIDE_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_OVERRIDE_H_
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_test_utils.cc b/chrome/browser/ash/child_accounts/time_limit_test_utils.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/time_limit_test_utils.cc
rename to chrome/browser/ash/child_accounts/time_limit_test_utils.cc
index f259522..13c57d36 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_test_utils.cc
+++ b/chrome/browser/ash/child_accounts/time_limit_test_utils.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/time_limit_test_utils.h"
+#include "chrome/browser/ash/child_accounts/time_limit_test_utils.h"
 
 #include <algorithm>
 #include <utility>
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_test_utils.h b/chrome/browser/ash/child_accounts/time_limit_test_utils.h
similarity index 92%
rename from chrome/browser/chromeos/child_accounts/time_limit_test_utils.h
rename to chrome/browser/ash/child_accounts/time_limit_test_utils.h
index e1f63e85..07ff543 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_test_utils.h
+++ b/chrome/browser/ash/child_accounts/time_limit_test_utils.h
@@ -4,15 +4,15 @@
 //
 // Helper functions to create and modify Usage Time Limit policies.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_TEST_UTILS_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_TEST_UTILS_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_TEST_UTILS_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_TEST_UTILS_H_
 
 #include <memory>
 #include <string>
 
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_override.h"
+#include "chrome/browser/ash/child_accounts/time_limit_override.h"
 
 namespace chromeos {
 namespace time_limit_test_utils {
@@ -92,4 +92,4 @@
 }  // namespace time_limit_test_utils
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_TEST_UTILS_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_TIME_LIMIT_TEST_UTILS_H_
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_activity_report_interface.cc b/chrome/browser/ash/child_accounts/time_limits/app_activity_report_interface.cc
index cb7e39c..63b4103aa 100644
--- a/chrome/browser/ash/child_accounts/time_limits/app_activity_report_interface.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/app_activity_report_interface.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_report_interface.h"
 
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 
 namespace chromeos {
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_time_browsertest.cc b/chrome/browser/ash/child_accounts/time_limits/app_time_browsertest.cc
index 24a1c8b..f2c56ab 100644
--- a/chrome/browser/ash/child_accounts/time_limits/app_time_browsertest.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/app_time_browsertest.cc
@@ -12,6 +12,8 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.h"
@@ -21,8 +23,6 @@
 #include "chrome/browser/ash/login/test/scoped_policy_update.h"
 #include "chrome/browser/ash/login/test/user_policy_mixin.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/chromeos/policy/user_policy_test_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_time_controller.cc b/chrome/browser/ash/child_accounts/time_limits/app_time_controller.cc
index ad7c78d..6d731fe 100644
--- a/chrome/browser/ash/child_accounts/time_limits/app_time_controller.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/app_time_controller.cc
@@ -16,6 +16,7 @@
 #include "base/values.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.h"
@@ -24,7 +25,6 @@
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
 #include "chrome/browser/ash/child_accounts/time_limits/web_time_activity_provider.h"
 #include "chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
 #include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/notifications/notification_display_service.h"
 #include "chrome/browser/notifications/notification_handler.h"
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.cc b/chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.cc
index 339e4abe..5ea168f 100644
--- a/chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.h"
 
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 
 namespace chromeos {
diff --git a/chrome/browser/ash/child_accounts/time_limits/web_time_calculation_browsertest.cc b/chrome/browser/ash/child_accounts/time_limits/web_time_calculation_browsertest.cc
index f0c1ce9..10bda39f 100644
--- a/chrome/browser/ash/child_accounts/time_limits/web_time_calculation_browsertest.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/web_time_calculation_browsertest.cc
@@ -12,6 +12,8 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_utils.h"
@@ -20,8 +22,6 @@
 #include "chrome/browser/ash/child_accounts/time_limits/web_time_navigation_observer.h"
 #include "chrome/browser/ash/login/test/logged_in_user_mixin.h"
 #include "chrome/browser/ash/login/test/scoped_policy_update.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/chromeos/policy/user_policy_test_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/supervised_user/navigation_finished_waiter.h"
diff --git a/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc b/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc
index 736e45a6..04fe45d 100644
--- a/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc
@@ -11,6 +11,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limits_allowlist_policy_test_utils.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
@@ -20,8 +22,6 @@
 #include "chrome/browser/ash/login/test/scoped_policy_update.h"
 #include "chrome/browser/ash/login/test/user_policy_mixin.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/chromeos/policy/user_policy_test_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
diff --git a/chrome/browser/ash/child_accounts/time_limits/web_time_limit_navigation_throttle.cc b/chrome/browser/ash/child_accounts/time_limits/web_time_limit_navigation_throttle.cc
index 0a85945..ba8ecae7 100644
--- a/chrome/browser/ash/child_accounts/time_limits/web_time_limit_navigation_throttle.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/web_time_limit_navigation_throttle.cc
@@ -9,13 +9,13 @@
 #include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
 #include "chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer.h"
 #include "chrome/browser/ash/child_accounts/time_limits/web_time_limit_error_page/web_time_limit_error_page.h"
 #include "chrome/browser/ash/child_accounts/time_limits/web_time_navigation_observer.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc b/chrome/browser/ash/child_accounts/usage_time_limit_processor.cc
similarity index 99%
rename from chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc
rename to chrome/browser/ash/child_accounts/usage_time_limit_processor.cc
index e0e874bf..4aadecb 100644
--- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc
+++ b/chrome/browser/ash/child_accounts/usage_time_limit_processor.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
+#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
 
 #include <algorithm>
 #include <string>
@@ -12,7 +12,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_override.h"
+#include "chrome/browser/ash/child_accounts/time_limit_override.h"
 
 namespace chromeos {
 namespace usage_time_limit {
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h b/chrome/browser/ash/child_accounts/usage_time_limit_processor.h
similarity index 95%
rename from chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h
rename to chrome/browser/ash/child_accounts/usage_time_limit_processor.h
index 14673ce..fc7ca28 100644
--- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h
+++ b/chrome/browser/ash/child_accounts/usage_time_limit_processor.h
@@ -6,8 +6,8 @@
 // of the client, for example if it is locked and the reason why it may be
 // locked.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_USAGE_TIME_LIMIT_PROCESSOR_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_USAGE_TIME_LIMIT_PROCESSOR_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_USAGE_TIME_LIMIT_PROCESSOR_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_USAGE_TIME_LIMIT_PROCESSOR_H_
 
 #include <memory>
 #include <set>
@@ -16,7 +16,7 @@
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/time/time.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_parental_control_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_parental_control_metrics.h"
 #include "chromeos/settings/timezone_settings.h"
 
 namespace base {
@@ -214,4 +214,4 @@
 }  // namespace usage_time_limit
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_USAGE_TIME_LIMIT_PROCESSOR_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_USAGE_TIME_LIMIT_PROCESSOR_H_
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc b/chrome/browser/ash/child_accounts/usage_time_limit_processor_unittest.cc
similarity index 99%
rename from chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc
rename to chrome/browser/ash/child_accounts/usage_time_limit_processor_unittest.cc
index 23de4a46..0879c9cc 100644
--- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc
+++ b/chrome/browser/ash/child_accounts/usage_time_limit_processor_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
+#include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h"
 
 #include <memory>
 #include <set>
@@ -10,8 +10,8 @@
 #include <utility>
 
 #include "base/values.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_override.h"
-#include "chrome/browser/chromeos/child_accounts/time_limit_test_utils.h"
+#include "chrome/browser/ash/child_accounts/time_limit_override.h"
+#include "chrome/browser/ash/child_accounts/time_limit_test_utils.h"
 #include "chromeos/settings/timezone_settings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier.cc b/chrome/browser/ash/child_accounts/usage_time_state_notifier.cc
similarity index 97%
rename from chrome/browser/chromeos/child_accounts/usage_time_state_notifier.cc
rename to chrome/browser/ash/child_accounts/usage_time_state_notifier.cc
index cce601a..25bd7d0 100644
--- a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier.cc
+++ b/chrome/browser/ash/child_accounts/usage_time_state_notifier.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h"
+#include "chrome/browser/ash/child_accounts/usage_time_state_notifier.h"
 
 #include "base/check.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h b/chrome/browser/ash/child_accounts/usage_time_state_notifier.h
similarity index 91%
rename from chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h
rename to chrome/browser/ash/child_accounts/usage_time_state_notifier.h
index f475170..6277df50 100644
--- a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h
+++ b/chrome/browser/ash/child_accounts/usage_time_state_notifier.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_USAGE_TIME_STATE_NOTIFIER_H_
-#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_USAGE_TIME_STATE_NOTIFIER_H_
+#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_USAGE_TIME_STATE_NOTIFIER_H_
+#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_USAGE_TIME_STATE_NOTIFIER_H_
 
 #include "base/macros.h"
 #include "base/no_destructor.h"
@@ -75,4 +75,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_USAGE_TIME_STATE_NOTIFIER_H_
+#endif  // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_USAGE_TIME_STATE_NOTIFIER_H_
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier_unittest.cc b/chrome/browser/ash/child_accounts/usage_time_state_notifier_unittest.cc
similarity index 98%
rename from chrome/browser/chromeos/child_accounts/usage_time_state_notifier_unittest.cc
rename to chrome/browser/ash/child_accounts/usage_time_state_notifier_unittest.cc
index a70c4d67..600b5a7a 100644
--- a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier_unittest.cc
+++ b/chrome/browser/ash/child_accounts/usage_time_state_notifier_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h"
+#include "chrome/browser/ash/child_accounts/usage_time_state_notifier.h"
 
 #include <memory>
 #include <vector>
diff --git a/chrome/browser/ash/login/screens/parental_handoff_screen.cc b/chrome/browser/ash/login/screens/parental_handoff_screen.cc
index fed1b19..40ae24a5 100644
--- a/chrome/browser/ash/login/screens/parental_handoff_screen.cc
+++ b/chrome/browser/ash/login/screens/parental_handoff_screen.cc
@@ -6,8 +6,8 @@
 
 #include <string>
 
+#include "chrome/browser/ash/child_accounts/family_features.h"
 #include "chrome/browser/ash/login/oobe_screen.h"
-#include "chrome/browser/chromeos/child_accounts/family_features.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/supervised_user/supervised_user_features.h"
diff --git a/chrome/browser/ash/login/screens/parental_handoff_screen_browsertest.cc b/chrome/browser/ash/login/screens/parental_handoff_screen_browsertest.cc
index 60654e5f..78fadcc 100644
--- a/chrome/browser/ash/login/screens/parental_handoff_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/parental_handoff_screen_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ash/child_accounts/family_features.h"
 #include "chrome/browser/ash/login/screens/assistant_optin_flow_screen.h"
 #include "chrome/browser/ash/login/screens/edu_coexistence_login_screen.h"
 #include "chrome/browser/ash/login/test/fake_gaia_mixin.h"
@@ -26,7 +27,6 @@
 #include "chrome/browser/ash/login/test/wizard_controller_screen_exit_waiter.h"
 #include "chrome/browser/ash/login/wizard_context.h"
 #include "chrome/browser/ash/login/wizard_controller.h"
-#include "chrome/browser/chromeos/child_accounts/family_features.h"
 #include "chrome/browser/supervised_user/supervised_user_features.h"
 #include "chrome/browser/supervised_user/supervised_user_service.h"
 #include "chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h"
diff --git a/chrome/browser/ash/login/session/chrome_session_manager.cc b/chrome/browser/ash/login/session/chrome_session_manager.cc
index 2885338..2fc94361 100644
--- a/chrome/browser/ash/login/session/chrome_session_manager.cc
+++ b/chrome/browser/ash/login/session/chrome_session_manager.cc
@@ -17,6 +17,9 @@
 #include "chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/ash/arc/session/arc_service_launcher.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller_factory.h"
 #include "chrome/browser/ash/lock_screen_apps/state_controller.h"
 #include "chrome/browser/ash/login/demo_mode/demo_resources.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
@@ -32,9 +35,6 @@
 #include "chrome/browser/browser_process_platform_part_chromeos.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/boot_times_recorder.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/policy/app_install_event_log_manager_wrapper.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
diff --git a/chrome/browser/ash/login/session/user_session_initializer.cc b/chrome/browser/ash/login/session/user_session_initializer.cc
index 8a5ad21b..082ab16 100644
--- a/chrome/browser/ash/login/session/user_session_initializer.cc
+++ b/chrome/browser/ash/login/session/user_session_initializer.cc
@@ -13,6 +13,10 @@
 #include "base/task/thread_pool.h"
 #include "chrome/browser/ash/arc/session/arc_service_launcher.h"
 #include "chrome/browser/ash/camera_mic/vm_camera_mic_manager.h"
+#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service_factory.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller_factory.h"
 #include "chrome/browser/ash/lock_screen_apps/state_controller.h"
 #include "chrome/browser/ash/login/startup_utils.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_manager.h"
@@ -21,10 +25,6 @@
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part_chromeos.h"
-#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service_factory.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/eche_app/eche_app_manager_factory.h"
 #include "chrome/browser/chromeos/phonehub/phone_hub_manager_factory.h"
diff --git a/chrome/browser/ash/login/session/user_session_manager.cc b/chrome/browser/ash/login/session/user_session_manager.cc
index 9d7fac6..84ba2656 100644
--- a/chrome/browser/ash/login/session/user_session_manager.cc
+++ b/chrome/browser/ash/login/session/user_session_manager.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/ash/arc/arc_migration_guide_notification.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/base/locale_util.h"
+#include "chrome/browser/ash/child_accounts/child_policy_observer.h"
 #include "chrome/browser/ash/login/auth/chrome_cryptohome_authenticator.h"
 #include "chrome/browser/ash/login/chrome_restart_request.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
@@ -73,7 +74,6 @@
 #include "chrome/browser/browser_process_platform_part_chromeos.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/boot_times_recorder.h"
-#include "chrome/browser/chromeos/child_accounts/child_policy_observer.h"
 #include "chrome/browser/chromeos/first_run/first_run.h"
 #include "chrome/browser/chromeos/full_restore/full_restore_service.h"
 #include "chrome/browser/chromeos/hats/hats_config.h"
diff --git a/chrome/browser/ash/login/session/user_session_manager.h b/chrome/browser/ash/login/session/user_session_manager.h
index b7a9879..c55e2ffd 100644
--- a/chrome/browser/ash/login/session/user_session_manager.h
+++ b/chrome/browser/ash/login/session/user_session_manager.h
@@ -22,11 +22,11 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/base/locale_util.h"
+#include "chrome/browser/ash/child_accounts/child_policy_observer.h"
 #include "chrome/browser/ash/login/oobe_screen.h"
 #include "chrome/browser/ash/login/signin/oauth2_login_manager.h"
 #include "chrome/browser/ash/login/signin/token_handle_util.h"
 #include "chrome/browser/ash/net/secure_dns_manager.h"
-#include "chrome/browser/chromeos/child_accounts/child_policy_observer.h"
 #include "chrome/browser/chromeos/eol_notification.h"
 #include "chrome/browser/chromeos/hats/hats_notification_controller.h"
 #include "chrome/browser/chromeos/release_notes/release_notes_notification.h"
diff --git a/chrome/browser/ash/login/test/fake_gaia_mixin.cc b/chrome/browser/ash/login/test/fake_gaia_mixin.cc
index b28c3e33..2644edb 100644
--- a/chrome/browser/ash/login/test/fake_gaia_mixin.cc
+++ b/chrome/browser/ash/login/test/fake_gaia_mixin.cc
@@ -6,8 +6,8 @@
 
 #include "ash/public/cpp/ash_switches.h"
 #include "base/command_line.h"
+#include "chrome/browser/ash/child_accounts/child_account_test_utils.h"
 #include "chrome/browser/ash/login/test/js_checker.h"
-#include "chrome/browser/chromeos/child_accounts/child_account_test_utils.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_switches.h"
 #include "google_apis/gaia/gaia_urls.h"
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc b/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc
index e6d8756..614e7bc 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc
@@ -81,7 +81,7 @@
     }
 
     {
-      EntryBuilder entry("Policy are configured correctly");
+      EntryBuilder entry("Policies are configured correctly");
       const std::string standard_top_error =
           "One or more policies are not configured correctly. Please contact "
           "your administrator";
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index b56c8a3..c6ca68a 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -975,12 +975,54 @@
     "../ash/certificate_provider/sign_requests.h",
     "../ash/certificate_provider/thread_safe_certificate_map.cc",
     "../ash/certificate_provider/thread_safe_certificate_map.h",
+    "../ash/child_accounts/child_policy_observer.cc",
+    "../ash/child_accounts/child_policy_observer.h",
+    "../ash/child_accounts/child_status_reporting_service.cc",
+    "../ash/child_accounts/child_status_reporting_service.h",
+    "../ash/child_accounts/child_status_reporting_service_factory.cc",
+    "../ash/child_accounts/child_status_reporting_service_factory.h",
+    "../ash/child_accounts/child_user_service.cc",
+    "../ash/child_accounts/child_user_service.h",
+    "../ash/child_accounts/child_user_service_factory.cc",
+    "../ash/child_accounts/child_user_service_factory.h",
+    "../ash/child_accounts/edu_coexistence_tos_store_utils.cc",
+    "../ash/child_accounts/edu_coexistence_tos_store_utils.h",
+    "../ash/child_accounts/event_based_status_reporting_service.cc",
+    "../ash/child_accounts/event_based_status_reporting_service.h",
+    "../ash/child_accounts/event_based_status_reporting_service_factory.cc",
+    "../ash/child_accounts/event_based_status_reporting_service_factory.h",
+    "../ash/child_accounts/family_features.cc",
+    "../ash/child_accounts/family_features.h",
+    "../ash/child_accounts/family_user_app_metrics.cc",
+    "../ash/child_accounts/family_user_app_metrics.h",
+    "../ash/child_accounts/family_user_chrome_activity_metrics.cc",
+    "../ash/child_accounts/family_user_chrome_activity_metrics.h",
+    "../ash/child_accounts/family_user_device_metrics.cc",
+    "../ash/child_accounts/family_user_device_metrics.h",
+    "../ash/child_accounts/family_user_metrics_service.cc",
+    "../ash/child_accounts/family_user_metrics_service.h",
+    "../ash/child_accounts/family_user_metrics_service_factory.cc",
+    "../ash/child_accounts/family_user_metrics_service_factory.h",
+    "../ash/child_accounts/family_user_parental_control_metrics.cc",
+    "../ash/child_accounts/family_user_parental_control_metrics.h",
+    "../ash/child_accounts/family_user_session_metrics.cc",
+    "../ash/child_accounts/family_user_session_metrics.h",
     "../ash/child_accounts/parent_access_code/authenticator.cc",
     "../ash/child_accounts/parent_access_code/authenticator.h",
     "../ash/child_accounts/parent_access_code/config_source.cc",
     "../ash/child_accounts/parent_access_code/config_source.h",
     "../ash/child_accounts/parent_access_code/parent_access_service.cc",
     "../ash/child_accounts/parent_access_code/parent_access_service.h",
+    "../ash/child_accounts/screen_time_controller.cc",
+    "../ash/child_accounts/screen_time_controller.h",
+    "../ash/child_accounts/screen_time_controller_factory.cc",
+    "../ash/child_accounts/screen_time_controller_factory.h",
+    "../ash/child_accounts/secondary_account_consent_logger.cc",
+    "../ash/child_accounts/secondary_account_consent_logger.h",
+    "../ash/child_accounts/time_limit_notifier.cc",
+    "../ash/child_accounts/time_limit_notifier.h",
+    "../ash/child_accounts/time_limit_override.cc",
+    "../ash/child_accounts/time_limit_override.h",
     "../ash/child_accounts/time_limits/app_activity_registry.cc",
     "../ash/child_accounts/time_limits/app_activity_registry.h",
     "../ash/child_accounts/time_limits/app_activity_report_interface.cc",
@@ -1010,6 +1052,10 @@
     "../ash/child_accounts/time_limits/web_time_limit_navigation_throttle.h",
     "../ash/child_accounts/time_limits/web_time_navigation_observer.cc",
     "../ash/child_accounts/time_limits/web_time_navigation_observer.h",
+    "../ash/child_accounts/usage_time_limit_processor.cc",
+    "../ash/child_accounts/usage_time_limit_processor.h",
+    "../ash/child_accounts/usage_time_state_notifier.cc",
+    "../ash/child_accounts/usage_time_state_notifier.h",
     "../ash/crosapi/automation_ash.cc",
     "../ash/crosapi/automation_ash.h",
     "../ash/crosapi/browser_data_migrator.cc",
@@ -1793,52 +1839,6 @@
     "camera_detector.h",
     "camera_presence_notifier.cc",
     "camera_presence_notifier.h",
-    "child_accounts/child_policy_observer.cc",
-    "child_accounts/child_policy_observer.h",
-    "child_accounts/child_status_reporting_service.cc",
-    "child_accounts/child_status_reporting_service.h",
-    "child_accounts/child_status_reporting_service_factory.cc",
-    "child_accounts/child_status_reporting_service_factory.h",
-    "child_accounts/child_user_service.cc",
-    "child_accounts/child_user_service.h",
-    "child_accounts/child_user_service_factory.cc",
-    "child_accounts/child_user_service_factory.h",
-    "child_accounts/edu_coexistence_tos_store_utils.cc",
-    "child_accounts/edu_coexistence_tos_store_utils.h",
-    "child_accounts/event_based_status_reporting_service.cc",
-    "child_accounts/event_based_status_reporting_service.h",
-    "child_accounts/event_based_status_reporting_service_factory.cc",
-    "child_accounts/event_based_status_reporting_service_factory.h",
-    "child_accounts/family_features.cc",
-    "child_accounts/family_features.h",
-    "child_accounts/family_user_app_metrics.cc",
-    "child_accounts/family_user_app_metrics.h",
-    "child_accounts/family_user_chrome_activity_metrics.cc",
-    "child_accounts/family_user_chrome_activity_metrics.h",
-    "child_accounts/family_user_device_metrics.cc",
-    "child_accounts/family_user_device_metrics.h",
-    "child_accounts/family_user_metrics_service.cc",
-    "child_accounts/family_user_metrics_service.h",
-    "child_accounts/family_user_metrics_service_factory.cc",
-    "child_accounts/family_user_metrics_service_factory.h",
-    "child_accounts/family_user_parental_control_metrics.cc",
-    "child_accounts/family_user_parental_control_metrics.h",
-    "child_accounts/family_user_session_metrics.cc",
-    "child_accounts/family_user_session_metrics.h",
-    "child_accounts/screen_time_controller.cc",
-    "child_accounts/screen_time_controller.h",
-    "child_accounts/screen_time_controller_factory.cc",
-    "child_accounts/screen_time_controller_factory.h",
-    "child_accounts/secondary_account_consent_logger.cc",
-    "child_accounts/secondary_account_consent_logger.h",
-    "child_accounts/time_limit_notifier.cc",
-    "child_accounts/time_limit_notifier.h",
-    "child_accounts/time_limit_override.cc",
-    "child_accounts/time_limit_override.h",
-    "child_accounts/usage_time_limit_processor.cc",
-    "child_accounts/usage_time_limit_processor.h",
-    "child_accounts/usage_time_state_notifier.cc",
-    "child_accounts/usage_time_state_notifier.h",
     "chrome_browser_main_chromeos.cc",
     "chrome_browser_main_chromeos.h",
     "chrome_content_browser_client_chromeos_part.cc",
@@ -3364,6 +3364,8 @@
     "../ash/cert_provisioning/mock_cert_provisioning_scheduler.h",
     "../ash/certificate_provider/test_certificate_provider_extension.cc",
     "../ash/certificate_provider/test_certificate_provider_extension.h",
+    "../ash/child_accounts/child_account_test_utils.cc",
+    "../ash/child_accounts/child_account_test_utils.h",
     "../ash/drive/drivefs_test_support.cc",
     "../ash/drive/drivefs_test_support.h",
     "../ash/lock_screen_apps/fake_lock_screen_profile_creator.cc",
@@ -3437,8 +3439,6 @@
     "android_sms/fake_android_sms_app_setup_controller.h",
     "android_sms/fake_connection_establisher.cc",
     "android_sms/fake_connection_establisher.h",
-    "child_accounts/child_account_test_utils.cc",
-    "child_accounts/child_account_test_utils.h",
     "crostini/ansible/ansible_management_test_helper.cc",
     "crostini/ansible/ansible_management_test_helper.h",
     "crostini/crostini_test_helper.cc",
@@ -3554,6 +3554,7 @@
     "../ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc",
     "../ash/arc/bluetooth/arc_bluetooth_task_queue_unittest.cc",
     "../ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc",
+    "../ash/arc/cast_receiver/arc_cast_receiver_service_unittest.cc",
     "../ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc",
     "../ash/arc/enterprise/arc_force_installed_apps_tracker_unittest.cc",
     "../ash/arc/enterprise/arc_snapshot_reboot_notification_impl_unittest.cc",
@@ -3599,6 +3600,7 @@
     "../ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc",
     "../ash/arc/session/arc_provisioning_result_unittest.cc",
     "../ash/arc/session/arc_session_manager_unittest.cc",
+    "../ash/arc/sharesheet/arc_sharesheet_bridge_unittest.cc",
     "../ash/arc/tracing/arc_app_performance_tracing_unittest.cc",
     "../ash/arc/tracing/arc_cpu_event_unittest.cc",
     "../ash/arc/tracing/arc_graphics_jank_detector_unittest.cc",
@@ -3608,6 +3610,7 @@
     "../ash/arc/tracing/arc_tracing_model_unittest.cc",
     "../ash/arc/tracing/arc_value_event_unittest.cc",
     "../ash/arc/tts/arc_tts_service_unittest.cc",
+    "../ash/arc/user_session/arc_user_session_service_unittest.cc",
     "../ash/arc/wallpaper/arc_wallpaper_service_unittest.cc",
     "../ash/assistant/assistant_util_unittest.cc",
     "../ash/attestation/attestation_ca_client_unittest.cc",
@@ -3655,9 +3658,19 @@
     "../ash/cert_provisioning/mock_cert_provisioning_worker.cc",
     "../ash/cert_provisioning/mock_cert_provisioning_worker.h",
     "../ash/certificate_provider/certificate_provider_service_unittest.cc",
+    "../ash/child_accounts/child_user_service_unittest.cc",
+    "../ash/child_accounts/event_based_status_reporting_service_unittest.cc",
+    "../ash/child_accounts/family_user_app_metrics_unittest.cc",
+    "../ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc",
+    "../ash/child_accounts/family_user_metrics_service_unittest.cc",
+    "../ash/child_accounts/family_user_parental_control_metrics_unittest.cc",
+    "../ash/child_accounts/family_user_session_metrics_unittest.cc",
     "../ash/child_accounts/parent_access_code/authenticator_unittest.cc",
     "../ash/child_accounts/parent_access_code/parent_access_test_utils.cc",
     "../ash/child_accounts/parent_access_code/parent_access_test_utils.h",
+    "../ash/child_accounts/secondary_account_consent_logger_unittest.cc",
+    "../ash/child_accounts/time_limit_notifier_unittest.cc",
+    "../ash/child_accounts/time_limit_test_utils.cc",
     "../ash/child_accounts/time_limits/app_activity_registry_unittest.cc",
     "../ash/child_accounts/time_limits/app_service_wrapper_unittest.cc",
     "../ash/child_accounts/time_limits/app_time_controller_unittest.cc",
@@ -3669,6 +3682,8 @@
     "../ash/child_accounts/time_limits/app_time_test_utils.h",
     "../ash/child_accounts/time_limits/app_types_unittest.cc",
     "../ash/child_accounts/time_limits/persisted_app_info_unittest.cc",
+    "../ash/child_accounts/usage_time_limit_processor_unittest.cc",
+    "../ash/child_accounts/usage_time_state_notifier_unittest.cc",
     "../ash/crosapi/browser_data_migrator_unittest.cc",
     "../ash/crosapi/browser_loader_unittest.cc",
     "../ash/crosapi/browser_manager_unittest.cc",
@@ -3811,18 +3826,6 @@
     "android_sms/connection_manager_unittest.cc",
     "android_sms/fcm_connection_establisher_unittest.cc",
     "android_sms/pairing_lost_notifier_unittest.cc",
-    "child_accounts/child_user_service_unittest.cc",
-    "child_accounts/event_based_status_reporting_service_unittest.cc",
-    "child_accounts/family_user_app_metrics_unittest.cc",
-    "child_accounts/family_user_chrome_activity_metrics_unittest.cc",
-    "child_accounts/family_user_metrics_service_unittest.cc",
-    "child_accounts/family_user_parental_control_metrics_unittest.cc",
-    "child_accounts/family_user_session_metrics_unittest.cc",
-    "child_accounts/secondary_account_consent_logger_unittest.cc",
-    "child_accounts/time_limit_notifier_unittest.cc",
-    "child_accounts/time_limit_test_utils.cc",
-    "child_accounts/usage_time_limit_processor_unittest.cc",
-    "child_accounts/usage_time_state_notifier_unittest.cc",
     "chrome_content_browser_client_chromeos_part_unittest.cc",
     "concierge_helper_service_unittest.cc",
     "crostini/ansible/ansible_management_service_unittest.cc",
diff --git a/chrome/browser/chromeos/child_accounts/OWNERS b/chrome/browser/chromeos/child_accounts/OWNERS
deleted file mode 100644
index 15c5917..0000000
--- a/chrome/browser/chromeos/child_accounts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# TODO(https://crbug.com/1164001): Share OWNERS until the migration of
-# //chrome/browser/chromeos/child_accounts completes.
-file://chrome/browser/ash/child_accounts/OWNERS
\ No newline at end of file
diff --git a/chrome/browser/chromeos/policy/status_collector/child_status_collector.h b/chrome/browser/chromeos/policy/status_collector/child_status_collector.h
index ce55b8e..d9b9852 100644
--- a/chrome/browser/chromeos/policy/status_collector/child_status_collector.h
+++ b/chrome/browser/chromeos/policy/status_collector/child_status_collector.h
@@ -21,7 +21,7 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_report_interface.h"
-#include "chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h"
+#include "chrome/browser/ash/child_accounts/usage_time_state_notifier.h"
 #include "chrome/browser/chromeos/policy/status_collector/status_collector.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 
diff --git a/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
index 991591a..7537e4e 100644
--- a/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
@@ -23,6 +23,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limits_policy_builder.h"
@@ -32,8 +34,6 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h"
 #include "chrome/browser/chrome_content_browser_client.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
 #include "chrome/browser/chromeos/policy/status_collector/child_status_collector.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_content_client.h"
diff --git a/chrome/browser/crash_recovery_browsertest.cc b/chrome/browser/crash_recovery_browsertest.cc
index f0f2b05..551885a 100644
--- a/chrome/browser/crash_recovery_browsertest.cc
+++ b/chrome/browser/crash_recovery_browsertest.cc
@@ -33,6 +33,7 @@
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/base/page_transition_types.h"
 
 using content::OpenURLParams;
@@ -48,7 +49,7 @@
   content::RenderProcessHostWatcher crash_observer(
       browser->tab_strip_model()->GetActiveWebContents(),
       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-  browser->OpenURL(OpenURLParams(GURL(content::kChromeUICrashURL), Referrer(),
+  browser->OpenURL(OpenURLParams(GURL(blink::kChromeUICrashURL), Referrer(),
                                  WindowOpenDisposition::CURRENT_TAB,
                                  ui::PAGE_TRANSITION_TYPED, false));
   crash_observer.Wait();
@@ -166,9 +167,10 @@
   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
                                                 &title_before_crash));
   SimulateRendererCrash(browser());
-  ASSERT_EQ(GURL(content::kChromeUICrashURL),
-            GetActiveWebContents()->GetController().GetVisibleEntry()->
-                GetVirtualURL());
+  ASSERT_EQ(GURL(blink::kChromeUICrashURL), GetActiveWebContents()
+                                                ->GetController()
+                                                .GetVisibleEntry()
+                                                ->GetVirtualURL());
   chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
   EXPECT_TRUE(content::WaitForLoadStop(GetActiveWebContents()));
   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
diff --git a/chrome/browser/devtools/devtools_browsertest.cc b/chrome/browser/devtools/devtools_browsertest.cc
index 81ccefa1..34a50303 100644
--- a/chrome/browser/devtools/devtools_browsertest.cc
+++ b/chrome/browser/devtools/devtools_browsertest.cc
@@ -109,6 +109,7 @@
 #include "net/test/embedded_test_server/http_response.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/compositor/compositor_switches.h"
@@ -1916,7 +1917,7 @@
     content::RenderProcessHostWatcher crash_observer(
         GetInspectedTab(),
         content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-    ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
+    ui_test_utils::NavigateToURL(browser(), GURL(blink::kChromeUICrashURL));
     crash_observer.Wait();
     content::TestNavigationObserver navigation_observer(GetInspectedTab(), 1);
     chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
diff --git a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
index a76cb5b..10a9f93 100644
--- a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
+++ b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
@@ -225,7 +225,8 @@
 
   // Put the arguments in the right format.
   std::vector<GURL> gurls;
-  const std::vector<std::string>& urls = *params->urls;
+  const std::vector<std::string>& urls = params->urls;
+  gurls.reserve(urls.size());
   for (const std::string& url : urls)
     gurls.push_back(GURL(url));
 
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index 3709757..ea06c0a 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -322,8 +322,10 @@
       settings_api::PrefType::PREF_TYPE_STRING;
   (*s_allowlist)[language::prefs::kForcedLanguages] =
       settings_api::PrefType::PREF_TYPE_LIST;
-  (*s_allowlist)[translate::TranslatePrefs::kPrefTranslateRecentTarget] =
+  (*s_allowlist)[::prefs::kPrefTranslateRecentTarget] =
       settings_api::PrefType::PREF_TYPE_STRING;
+  (*s_allowlist)[prefs::kPrefAlwaysTranslateList] =
+      settings_api::PrefType::PREF_TYPE_LIST;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   (*s_allowlist)[::prefs::kLanguageImeMenuActivated] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index f191092a..443eea94 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -50,6 +50,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
 #include "third_party/blink/public/common/switches.h"
 #include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
@@ -550,7 +551,7 @@
 
   content::RenderProcessHostWatcher process_watcher(
       tab, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-  ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
+  ui_test_utils::NavigateToURL(browser(), GURL(blink::kChromeUICrashURL));
   process_watcher.Wait();
 
   url = GURL(embedded_test_server()->GetURL(
diff --git a/chrome/browser/extensions/chrome_extension_web_contents_observer.cc b/chrome/browser/extensions/chrome_extension_web_contents_observer.cc
index 34d4233..82e253d 100644
--- a/chrome/browser/extensions/chrome_extension_web_contents_observer.cc
+++ b/chrome/browser/extensions/chrome_extension_web_contents_observer.cc
@@ -28,6 +28,7 @@
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/extension_urls.h"
 #include "extensions/common/switches.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 
 namespace extensions {
 
@@ -73,7 +74,7 @@
   if ((extension->is_extension() || extension->is_platform_app()) &&
       Manifest::IsComponentLocation(extension->location())) {
     policy->GrantRequestOrigin(
-        process_id, url::Origin::Create(GURL(content::kChromeUIResourcesURL)));
+        process_id, url::Origin::Create(GURL(blink::kChromeUIResourcesURL)));
     policy->GrantRequestOrigin(
         process_id, url::Origin::Create(GURL(chrome::kChromeUIThemeURL)));
   }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 373395a..0e12da5b 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3504,6 +3504,11 @@
     "expiry_milestone": -1
   },
   {
+    "name": "media-session-webrtc",
+    "owners": [ "steimel", "media-dev" ],
+    "expiry_milestone": 100
+  },
+  {
     "name": "memlog",
     "owners": [ "erikchen", "ssid", "etienneb", "alph" ],
     // Memlog is Chrome's heap profiler. It is used for both automated and
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 0ab5e3e..a525df2 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1478,6 +1478,10 @@
     "Have the Media Router connect to Cast devices on all IP addresses, not "
     "just RFC1918/RFC4193 private addresses.";
 
+const char kMediaSessionWebRTCName[] = "Enable WebRTC actions in Media Session";
+const char kMediaSessionWebRTCDescription[] =
+    "Adds new actions into Media Session for video conferencing.";
+
 const char kMemoriesName[] = "Memories";
 const char kMemoriesDescription[] = "Enables chrome://memories.";
 
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index a6f5a6c..f17e5b2a 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -866,6 +866,9 @@
 extern const char kMediaRouterCastAllowAllIPsName[];
 extern const char kMediaRouterCastAllowAllIPsDescription[];
 
+extern const char kMediaSessionWebRTCName[];
+extern const char kMediaSessionWebRTCDescription[];
+
 extern const char kMemoriesName[];
 extern const char kMemoriesDescription[];
 
diff --git a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java b/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java
index b6b67909..44d444d0 100644
--- a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java
+++ b/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java
@@ -170,6 +170,16 @@
         return mGsaAvailable;
     }
 
+    /** Returns whether the GSA package is installed on device. */
+    public boolean isGsaInstalled() {
+        try {
+            PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(PACKAGE_NAME, 0);
+            return true;
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+    }
+
     /**
      * Check whether the given package meets min requirements for using full document mode.
      * @param packageName The package name we are inquiring about.
diff --git a/chrome/browser/lacros/immersive_context_lacros.cc b/chrome/browser/lacros/immersive_context_lacros.cc
index 26ee258..4107b98 100644
--- a/chrome/browser/lacros/immersive_context_lacros.cc
+++ b/chrome/browser/lacros/immersive_context_lacros.cc
@@ -6,10 +6,10 @@
 
 #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_tree_host_platform.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/platform_window/extensions/wayland_extension.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
 #include "ui/views/widget/widget.h"
 
 ImmersiveContextLacros::ImmersiveContextLacros() = default;
@@ -20,15 +20,11 @@
     chromeos::ImmersiveFullscreenController* controller,
     bool entering) {
   aura::Window* window = controller->widget()->GetNativeWindow();
-  // Lacros is based on Ozone/Wayland, which uses ui::PlatformWindow and
-  // aura::WindowTreeHostPlatform.
-  auto* wth_platform =
-      static_cast<aura::WindowTreeHostPlatform*>(window->GetHost());
-  ui::PlatformWindow* platform_window = wth_platform->platform_window();
 
-  auto* wayland_extension = ui::GetWaylandExtension(*platform_window);
-  DCHECK(wayland_extension)
-      << "Exo Wayland extensions are always present in Lacros.";
+  // Lacros is based on Ozone/Wayland, which uses ui::PlatformWindow and
+  // views::DesktopWindowTreeHostLinux.
+  auto* dwth_linux = views::DesktopWindowTreeHostLinux::From(window->GetHost());
+  auto* wayland_extension = dwth_linux->GetWaylandExtension();
   wayland_extension->SetImmersiveFullscreenStatus(entering);
 }
 
diff --git a/chrome/browser/lacros/snap_controller_lacros.cc b/chrome/browser/lacros/snap_controller_lacros.cc
index 5872205b..15e07729 100644
--- a/chrome/browser/lacros/snap_controller_lacros.cc
+++ b/chrome/browser/lacros/snap_controller_lacros.cc
@@ -6,8 +6,8 @@
 
 #include "base/notreached.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_tree_host_platform.h"
 #include "ui/platform_window/extensions/wayland_extension.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
 
 namespace {
 
@@ -25,15 +25,9 @@
 
 ui::WaylandExtension* WaylandExtensionForAuraWindow(aura::Window* window) {
   // Lacros is based on Ozone/Wayland, which uses ui::PlatformWindow and
-  // aura::WindowTreeHostPlatform.
-  auto* wth_platform =
-      static_cast<aura::WindowTreeHostPlatform*>(window->GetHost());
-  ui::PlatformWindow* platform_window = wth_platform->platform_window();
-
-  auto* wayland_extension = ui::GetWaylandExtension(*platform_window);
-  DCHECK(wayland_extension)
-      << "Exo Wayland extensions are always present in Lacros.";
-  return wayland_extension;
+  // views::DesktopWindowTreeHostLinux.
+  auto* dwth_linux = views::DesktopWindowTreeHostLinux::From(window->GetHost());
+  return dwth_linux->GetWaylandExtension();
 }
 
 }  // namespace
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
index e422f41..49e32fde 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
@@ -178,6 +178,9 @@
                 AddLanguageFragment.LANGUAGE_OPTIONS_TRANSLATE_LANGUAGES,
                 REQUEST_CODE_CHANGE_TARGET_LANGUAGE,
                 LanguagesManager.LanguageSettingsPageType.CHANGE_TARGET_LANGUAGE);
+        mPrefChangeRegistrar.addObserver(Pref.PREF_TRANSLATE_RECENT_TARGET, () -> {
+            targetLanguagePreference.setLanguageItem(TranslateBridge.getTargetLanguage());
+        });
 
         // Setup always translate preference.
         LanguageItemListPreference alwaysTranslatePreference =
@@ -247,6 +250,7 @@
             LanguagesManager.recordAction(
                     LanguagesManager.LanguageSettingsActionType.CHANGE_CHROME_LANGUAGE);
             mAppLanguageDelegate.startLanguageSplitDownload(code);
+            TranslateBridge.setDefaultTargetLanguage(code);
         } else if (requestCode == REQUEST_CODE_CHANGE_TARGET_LANGUAGE) {
             LanguageItemPickerPreference targetLanguagePreference =
                     (LanguageItemPickerPreference) findPreference(TARGET_LANGUAGE_KEY);
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 52c6a8e..3c812ee 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -148,8 +148,8 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/feature_list.h"
+#include "chrome/browser/ash/child_accounts/family_features.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/chromeos/child_accounts/family_features.h"
 #include "chrome/browser/chromeos/printing/printer_metrics_provider.h"
 #include "chrome/browser/metrics/ambient_mode_metrics_provider.h"
 #include "chrome/browser/metrics/assistant_service_metrics_provider.h"
diff --git a/chrome/browser/metrics/family_link_user_metrics_provider_browsertest.cc b/chrome/browser/metrics/family_link_user_metrics_provider_browsertest.cc
index 2384c7a..ebfc8e30 100644
--- a/chrome/browser/metrics/family_link_user_metrics_provider_browsertest.cc
+++ b/chrome/browser/metrics/family_link_user_metrics_provider_browsertest.cc
@@ -10,11 +10,11 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/child_accounts/family_features.h"
 #include "chrome/browser/ash/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/ash/login/test/guest_session_mixin.h"
 #include "chrome/browser/ash/login/test/logged_in_user_mixin.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/child_accounts/family_features.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "components/metrics/delegating_provider.h"
 #include "components/metrics/metrics_service.h"
diff --git a/chrome/browser/metrics/family_user_metrics_provider_browsertest.cc b/chrome/browser/metrics/family_user_metrics_provider_browsertest.cc
index c6d76b61..d2f1aa80 100644
--- a/chrome/browser/metrics/family_user_metrics_provider_browsertest.cc
+++ b/chrome/browser/metrics/family_user_metrics_provider_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/child_accounts/family_features.h"
 #include "chrome/browser/ash/login/test/device_state_mixin.h"
 #include "chrome/browser/ash/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/ash/login/test/guest_session_mixin.h"
@@ -15,7 +16,6 @@
 #include "chrome/browser/ash/login/test/scoped_policy_update.h"
 #include "chrome/browser/ash/login/test/user_policy_mixin.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/child_accounts/family_features.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/metrics/metrics_service_browsertest.cc b/chrome/browser/metrics/metrics_service_browsertest.cc
index 4e3572f8..1fc4e1f2 100644
--- a/chrome/browser/metrics/metrics_service_browsertest.cc
+++ b/chrome/browser/metrics/metrics_service_browsertest.cc
@@ -42,6 +42,7 @@
 #include "net/base/filename_util.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/base/window_open_disposition.h"
 #include "url/gurl.h"
 
@@ -178,7 +179,7 @@
 IN_PROC_BROWSER_TEST_F(MetricsServiceBrowserTest, MAYBE_CrashRenderers) {
   base::HistogramTester histogram_tester;
 
-  OpenTabsAndNavigateToCrashyUrl(content::kChromeUICrashURL);
+  OpenTabsAndNavigateToCrashyUrl(blink::kChromeUICrashURL);
 
   // Verify that the expected stability metrics were recorded.
   const PrefService* prefs = g_browser_process->local_state();
@@ -212,7 +213,7 @@
                        MAYBE_HeapCorruptionInRenderer) {
   base::HistogramTester histogram_tester;
 
-  OpenTabsAndNavigateToCrashyUrl(content::kChromeUIHeapCorruptionCrashURL);
+  OpenTabsAndNavigateToCrashyUrl(blink::kChromeUIHeapCorruptionCrashURL);
 
   // Verify that the expected stability metrics were recorded.
   const PrefService* prefs = g_browser_process->local_state();
@@ -232,7 +233,7 @@
 IN_PROC_BROWSER_TEST_F(MetricsServiceBrowserTest, MAYBE_CheckCrashRenderers) {
   base::HistogramTester histogram_tester;
 
-  OpenTabsAndNavigateToCrashyUrl(content::kChromeUICheckCrashURL);
+  OpenTabsAndNavigateToCrashyUrl(blink::kChromeUICheckCrashURL);
 
   // Verify that the expected stability metrics were recorded.
   const PrefService* prefs = g_browser_process->local_state();
@@ -264,7 +265,7 @@
 
   base::HistogramTester histogram_tester;
 
-  OpenTabsAndNavigateToCrashyUrl(content::kChromeUIMemoryExhaustURL);
+  OpenTabsAndNavigateToCrashyUrl(blink::kChromeUIMemoryExhaustURL);
 
   // Verify that the expected stability metrics were recorded.
   const PrefService* prefs = g_browser_process->local_state();
diff --git a/chrome/browser/metrics/oom/out_of_memory_reporter_browsertest.cc b/chrome/browser/metrics/oom/out_of_memory_reporter_browsertest.cc
index c525b393..80d94b3 100644
--- a/chrome/browser/metrics/oom/out_of_memory_reporter_browsertest.cc
+++ b/chrome/browser/metrics/oom/out_of_memory_reporter_browsertest.cc
@@ -23,6 +23,7 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/features.h"
 #include "url/gurl.h"
 
@@ -85,7 +86,7 @@
   // this URL will cause an OOM associated with the previous committed URL.
   ScopedAllowRendererCrashes allow_renderer_crashes(
       browser()->tab_strip_model()->GetActiveWebContents());
-  NavigateToURL(browser(), GURL(content::kChromeUIMemoryExhaustURL));
+  NavigateToURL(browser(), GURL(blink::kChromeUIMemoryExhaustURL));
   EXPECT_EQ(crash_url, last_oom_url_.value());
 }
 
@@ -123,7 +124,7 @@
   OutOfMemoryReporter::FromWebContents(web_contents)->AddObserver(this);
 
   const GURL url(embedded_test_server()->GetURL("/portal/activate.html"));
-  const GURL memory_exhaust_url(content::kChromeUIMemoryExhaustURL);
+  const GURL memory_exhaust_url(blink::kChromeUIMemoryExhaustURL);
 
   // Navigate the main web contents to a page with a <portal> element.
   ui_test_utils::NavigateToURL(browser(), url);
@@ -168,7 +169,7 @@
   const GURL main_url(embedded_test_server()->GetURL("/portal/activate.html"));
   const GURL crash_url(
       embedded_test_server()->GetURL("/portal/activate-portal.html"));
-  const GURL memory_exhaust_url(content::kChromeUIMemoryExhaustURL);
+  const GURL memory_exhaust_url(blink::kChromeUIMemoryExhaustURL);
 
   // Navigate the main web contents to a page with a <portal> element.
   ui_test_utils::NavigateToURL(browser(), main_url);
diff --git a/chrome/browser/net/reporting_browsertest.cc b/chrome/browser/net/reporting_browsertest.cc
index 042c12aa..41932eb 100644
--- a/chrome/browser/net/reporting_browsertest.cc
+++ b/chrome/browser/net/reporting_browsertest.cc
@@ -33,6 +33,7 @@
 #include "net/test/embedded_test_server/http_request.h"
 #include "services/network/public/cpp/features.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "url/gurl.h"
 
 namespace {
@@ -294,7 +295,7 @@
 
   // Simulate a crash on the page.
   content::ScopedAllowRendererCrashes allow_renderer_crashes(contents);
-  contents->GetController().LoadURL(GURL(content::kChromeUICrashURL),
+  contents->GetController().LoadURL(GURL(blink::kChromeUICrashURL),
                                     content::Referrer(),
                                     ui::PAGE_TRANSITION_TYPED, std::string());
 
diff --git a/chrome/browser/notifications/notification_interactive_uitest.cc b/chrome/browser/notifications/notification_interactive_uitest.cc
index d49b267..1314678 100644
--- a/chrome/browser/notifications/notification_interactive_uitest.cc
+++ b/chrome/browser/notifications/notification_interactive_uitest.cc
@@ -691,8 +691,7 @@
 // The Fake OSX fullscreen window doesn't like drawing a second fullscreen
 // window when another is visible.
 #if !defined(OS_MAC)
-// Disabled on other platforms because it is flaky.  http://crbug.com/1195324
-IN_PROC_BROWSER_TEST_F(NotificationsTest, DISABLED_TestShouldDisplayMultiFullscreen) {
+IN_PROC_BROWSER_TEST_F(NotificationsTest, TestShouldDisplayMultiFullscreen) {
   ASSERT_TRUE(embedded_test_server()->Start());
   AllowAllOrigins();
 
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
index 327da28..8fe2c96 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
@@ -51,16 +51,6 @@
 
 namespace {
 
-// Delay between retries on failed fetch and store of prediction models and
-// host model features from the remote Optimization Guide Service.
-constexpr base::TimeDelta kFetchRetryDelay = base::TimeDelta::FromMinutes(16);
-
-// The amount of time to wait after a successful fetch of models and host model
-// features before requesting an update from the remote Optimization Guide
-// Service.
-constexpr base::TimeDelta kUpdateModelsAndFeaturesDelay =
-    base::TimeDelta::FromHours(24);
-
 // Provide a random time delta in seconds before fetching models and host model
 // features.
 base::TimeDelta RandomFetchDelay() {
@@ -437,9 +427,8 @@
         base::TimeTicks::Now() - model_evaluation_start_time);
   }
 
-  if (optimization_guide::features::
-          ShouldOverrideOptimizationTargetDecisionForMetricsPurposes(
-              optimization_target)) {
+  if (features::ShouldOverrideOptimizationTargetDecisionForMetricsPurposes(
+          optimization_target)) {
     return optimization_guide::OptimizationTargetDecision::
         kModelPredictionHoldback;
   }
@@ -491,9 +480,11 @@
   if (!ShouldFetchModelsAndHostModelFeatures(profile_))
     return;
 
-  ScheduleModelsAndHostModelFeaturesFetch();
+  // Models and host model features should not be fetched if there are no
+  // optimization targets registered.
+  if (registered_optimization_targets_and_metadata_.empty())
+    return;
 
-  // We cannot download any models from the server, so don't refresh them.
   if (prediction_model_download_manager_) {
     bool download_service_available =
         prediction_model_download_manager_->IsAvailableForDownloads();
@@ -501,19 +492,17 @@
         "OptimizationGuide.PredictionManager."
         "DownloadServiceAvailabilityBlockedFetch",
         !download_service_available);
-    if (!download_service_available)
+    if (!download_service_available) {
+      // We cannot download any models from the server, so don't refresh them.
       return;
+    }
+
+    prediction_model_download_manager_->CancelAllPendingDownloads();
   }
 
-  // Models and host model features should not be fetched if there are no
-  // optimization targets registered.
-  if (registered_optimization_targets_and_metadata_.empty())
-    return;
-
-  // Cancel all pending downloads since the server will probably give us new
-  // ones to fetch.
-  if (prediction_model_download_manager_)
-    prediction_model_download_manager_->CancelAllPendingDownloads();
+  // NOTE: ALL PRECONDITIONS FOR THIS FUNCTION MUST BE CHECKED ABOVE THIS LINE.
+  // It is assumed that if we proceed past here, that a fetch will at least be
+  // attempted.
 
   std::vector<std::string> top_hosts;
   std::vector<proto::FieldTrial> active_field_trials;
@@ -581,11 +570,19 @@
     models_info.push_back(model_info);
   }
 
-  prediction_model_fetcher_->FetchOptimizationGuideServiceModels(
-      models_info, top_hosts, active_field_trials,
-      optimization_guide::proto::CONTEXT_BATCH_UPDATE,
-      base::BindOnce(&PredictionManager::OnModelsAndHostFeaturesFetched,
-                     ui_weak_ptr_factory_.GetWeakPtr()));
+  bool fetch_initiated =
+      prediction_model_fetcher_->FetchOptimizationGuideServiceModels(
+          models_info, top_hosts, active_field_trials,
+          optimization_guide::proto::CONTEXT_BATCH_UPDATE,
+          base::BindOnce(&PredictionManager::OnModelsAndHostFeaturesFetched,
+                         ui_weak_ptr_factory_.GetWeakPtr()));
+
+  if (fetch_initiated)
+    SetLastModelAndFeaturesFetchAttemptTime(clock_->Now());
+  // Schedule the next fetch regardless since we may not have initiated a fetch
+  // due to a network condition and trying in the next minute to see if that is
+  // unblocked is only a timer firing and not an actual query to the server.
+  ScheduleModelsAndHostModelFeaturesFetch();
 }
 
 void PredictionManager::OnModelsAndHostFeaturesFetched(
@@ -595,6 +592,8 @@
   if (!get_models_response_data)
     return;
 
+  SetLastModelFetchSuccessTime(clock_->Now());
+
   // Update host model features, even if empty so the store metadata
   // that contains the update time for new models and features to be fetched
   // from the remote Optimization Guide Service is updated.
@@ -608,7 +607,7 @@
 
   fetch_timer_.Stop();
   fetch_timer_.Start(
-      FROM_HERE, kUpdateModelsAndFeaturesDelay, this,
+      FROM_HERE, features::PredictionModelFetchInterval(), this,
       &PredictionManager::ScheduleModelsAndHostModelFeaturesFetch);
 }
 
@@ -618,7 +617,8 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::unique_ptr<StoreUpdateData> host_model_features_update_data =
       StoreUpdateData::CreateHostModelFeaturesStoreUpdateData(
-          /*update_time=*/clock_->Now() + kUpdateModelsAndFeaturesDelay,
+          /*update_time=*/clock_->Now() +
+              features::PredictionModelFetchInterval(),
           /*expiry_time=*/clock_->Now() +
               features::StoredHostModelFeaturesFreshnessDuration());
   for (const auto& host_model_features : host_model_features) {
@@ -1036,9 +1036,7 @@
   if (!ShouldFetchModelsAndHostModelFeatures(profile_))
     return;
 
-  if (optimization_guide::switches::
-          ShouldOverrideFetchModelsAndFeaturesTimer()) {
-    SetLastModelAndFeaturesFetchAttemptTime(clock_->Now());
+  if (switches::ShouldOverrideFetchModelsAndFeaturesTimer()) {
     fetch_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this,
                        &PredictionManager::FetchModelsAndHostModelFeatures);
   } else {
@@ -1053,18 +1051,25 @@
           pref_service_->GetInt64(prefs::kModelAndFeaturesLastFetchAttempt)));
 }
 
+base::Time PredictionManager::GetLastFetchSuccessTime() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return base::Time::FromDeltaSinceWindowsEpoch(
+      base::TimeDelta::FromMicroseconds(
+          pref_service_->GetInt64(prefs::kModelLastFetchSuccess)));
+}
+
 void PredictionManager::ScheduleModelsAndHostModelFeaturesFetch() {
   DCHECK(!fetch_timer_.IsRunning());
   DCHECK(store_is_ready_);
   const base::TimeDelta time_until_update_time =
-      model_and_features_store_->GetHostModelFeaturesUpdateTime() -
+      GetLastFetchSuccessTime() + features::PredictionModelFetchInterval() -
       clock_->Now();
   const base::TimeDelta time_until_retry =
-      GetLastFetchAttemptTime() + kFetchRetryDelay - clock_->Now();
+      GetLastFetchAttemptTime() + features::PredictionModelFetchRetryDelay() -
+      clock_->Now();
   base::TimeDelta fetcher_delay =
       std::max(time_until_update_time, time_until_retry);
   if (fetcher_delay <= base::TimeDelta()) {
-    SetLastModelAndFeaturesFetchAttemptTime(clock_->Now());
     fetch_timer_.Start(FROM_HERE, RandomFetchDelay(), this,
                        &PredictionManager::FetchModelsAndHostModelFeatures);
     return;
@@ -1082,6 +1087,14 @@
       last_attempt_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
 }
 
+void PredictionManager::SetLastModelFetchSuccessTime(
+    base::Time last_success_time) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  pref_service_->SetInt64(
+      prefs::kModelLastFetchSuccess,
+      last_success_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+}
+
 void PredictionManager::SetClockForTesting(const base::Clock* clock) {
   clock_ = clock;
 }
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.h b/chrome/browser/optimization_guide/prediction/prediction_manager.h
index f1b61807..08e056f 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager.h
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager.h
@@ -299,6 +299,14 @@
   // was last attempted to |last_attempt_time|.
   void SetLastModelAndFeaturesFetchAttemptTime(base::Time last_attempt_time);
 
+  // Return the time when a prediction model fetch was last successfully
+  // completed.
+  base::Time GetLastFetchSuccessTime() const;
+
+  // Set the last time when a fetch for prediction models last succeeded to
+  // |last_success_time|.
+  void SetLastModelFetchSuccessTime(base::Time last_success_time);
+
   // Determine whether to schedule fetching new prediction models and host model
   // features or fetch immediately due to override.
   void MaybeScheduleModelAndHostModelFeaturesFetch();
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
index d6442651..0ae54e0 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
@@ -47,9 +47,9 @@
 using leveldb_proto::test::FakeDB;
 
 namespace {
-// Retry delay is 16 minutes to allow for kFetchRetryDelaySecs +
-// some random delay to pass.
-constexpr int kTestFetchRetryDelaySecs = 60 * 16 + 62;
+// Retry delay is 2 minutes to allow for fetch retry delay + some random delay
+// to pass.
+constexpr int kTestFetchRetryDelaySecs = 60 * 2 + 62;
 // 24 hours + random fetch delay.
 constexpr int kUpdateFetchModelAndFeaturesTimeSecs = 24 * 60 * 60 + 62;
 
@@ -223,6 +223,16 @@
   kFetchSuccessWithModelDownloadUrls = 3,
 };
 
+void RunGetModelsCallback(
+    ModelsFetchedCallback callback,
+    std::unique_ptr<proto::GetModelsResponse> get_models_response) {
+  if (get_models_response) {
+    std::move(callback).Run(std::move(get_models_response));
+    return;
+  }
+  std::move(callback).Run(base::nullopt);
+}
+
 // A mock class implementation of PredictionModelFetcher.
 class TestPredictionModelFetcher : public PredictionModelFetcher {
  public:
@@ -247,28 +257,32 @@
       return false;
     }
 
+    std::unique_ptr<proto::GetModelsResponse> get_models_response;
     count_hosts_fetched_ = hosts.size();
     switch (fetch_state_) {
       case PredictionModelFetcherEndState::kFetchFailed:
-        std::move(models_fetched_callback).Run(base::nullopt);
-        return false;
+        get_models_response = nullptr;
+        break;
       case PredictionModelFetcherEndState::
           kFetchSuccessWithModelsAndHostsModelFeatures:
         models_fetched_ = true;
-        std::move(models_fetched_callback).Run(BuildGetModelsResponse(hosts));
-        return true;
+        get_models_response = BuildGetModelsResponse(hosts);
+        break;
       case PredictionModelFetcherEndState::kFetchSuccessWithEmptyResponse:
         models_fetched_ = true;
-        std::move(models_fetched_callback)
-            .Run(BuildGetModelsResponse(/*hosts=*/{}));
-        return true;
+        get_models_response = BuildGetModelsResponse(/*hosts=*/{});
+        break;
       case PredictionModelFetcherEndState::kFetchSuccessWithModelDownloadUrls:
         models_fetched_ = true;
-        std::move(models_fetched_callback)
-            .Run(BuildGetModelsResponse(hosts,
-                                        /*output_model_as_download_url=*/true));
-        return true;
+        get_models_response =
+            BuildGetModelsResponse(hosts,
+                                   /*output_model_as_download_url=*/true);
+        break;
     }
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&RunGetModelsCallback,
+                                  std::move(models_fetched_callback),
+                                  std::move(get_models_response)));
     return true;
   }
 
diff --git a/chrome/browser/password_manager/android/credential_leak_controller_android.cc b/chrome/browser/password_manager/android/credential_leak_controller_android.cc
index 96a48973..f6b7cff 100644
--- a/chrome/browser/password_manager/android/credential_leak_controller_android.cc
+++ b/chrome/browser/password_manager/android/credential_leak_controller_android.cc
@@ -84,7 +84,7 @@
 }
 
 std::u16string CredentialLeakControllerAndroid::GetDescription() const {
-  return password_manager::GetDescription(leak_type_, origin_);
+  return password_manager::GetDescription(leak_type_);
 }
 
 std::u16string CredentialLeakControllerAndroid::GetTitle() const {
diff --git a/chrome/browser/permissions/permission_manager_browsertest.cc b/chrome/browser/permissions/permission_manager_browsertest.cc
index 35773077..8acbecc 100644
--- a/chrome/browser/permissions/permission_manager_browsertest.cc
+++ b/chrome/browser/permissions/permission_manager_browsertest.cc
@@ -19,6 +19,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 
 namespace {
 
@@ -135,7 +136,7 @@
       incognito_browser()->tab_strip_model()->GetActiveWebContents(),
       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
   incognito_browser()->OpenURL(content::OpenURLParams(
-      GURL(content::kChromeUICrashURL), content::Referrer(),
+      GURL(blink::kChromeUICrashURL), content::Referrer(),
       WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
   crash_observer.Wait();
 
diff --git a/chrome/browser/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
index 0626aaa..12b899be 100644
--- a/chrome/browser/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
@@ -73,6 +73,7 @@
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
 
@@ -1299,7 +1300,7 @@
   content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
   std::unique_ptr<NoStatePrefetchHandle> no_state_prefetch_handle(
       GetNoStatePrefetchManager()->AddPrerenderFromExternalRequest(
-          GURL(content::kChromeUICrashURL), content::Referrer(),
+          GURL(blink::kChromeUICrashURL), content::Referrer(),
           storage_namespace, gfx::Rect(kSize)));
   ASSERT_EQ(no_state_prefetch_handle->contents(), test_prerender->contents());
   test_prerender->WaitForStop();
diff --git a/chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.cc b/chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.cc
index 1bb29a8b..33fc50a 100644
--- a/chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.cc
+++ b/chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.cc
@@ -37,6 +37,7 @@
 #include "net/test/embedded_test_server/request_handler_util.h"
 #include "ppapi/shared_impl/ppapi_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/base/l10n/l10n_util.h"
 
 using content::BrowserThread;
@@ -130,7 +131,7 @@
 bool TestNoStatePrefetchContents::CheckURL(const GURL& url) {
   // Prevent FINAL_STATUS_UNSUPPORTED_SCHEME when navigating to about:crash in
   // the PrerenderRendererCrash test.
-  if (url.spec() != content::kChromeUICrashURL)
+  if (url.spec() != blink::kChromeUICrashURL)
     return NoStatePrefetchContents::CheckURL(url);
   return true;
 }
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 8abf982..a8546c7 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -263,13 +263,13 @@
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/bluetooth/debug_logs_manager.h"
 #include "chrome/browser/ash/cert_provisioning/cert_provisioning_common.h"
+#include "chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics.h"
+#include "chrome/browser/ash/child_accounts/family_user_metrics_service.h"
+#include "chrome/browser/ash/child_accounts/family_user_session_metrics.h"
 #include "chrome/browser/ash/child_accounts/parent_access_code/parent_access_service.h"
+#include "chrome/browser/ash/child_accounts/screen_time_controller.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_controller.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_chrome_activity_metrics.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
-#include "chrome/browser/chromeos/child_accounts/family_user_session_metrics.h"
-#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
 #include "chrome/browser/chromeos/cryptauth/client_app_metadata_provider_service.h"
 #include "chrome/browser/chromeos/cryptauth/cryptauth_device_id_provider_impl.h"
@@ -281,6 +281,7 @@
 #endif
 #include "chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller.h"
 #include "chrome/browser/ash/borealis/borealis_prefs.h"
+#include "chrome/browser/ash/child_accounts/secondary_account_consent_logger.h"
 #include "chrome/browser/ash/guest_os/guest_os_pref_names.h"
 #include "chrome/browser/ash/lock_screen_apps/state_controller.h"
 #include "chrome/browser/ash/login/demo_mode/demo_mode_detector.h"
@@ -305,7 +306,6 @@
 #include "chrome/browser/ash/settings/device_settings_cache.h"
 #include "chrome/browser/ash/system/automatic_reboot_manager.h"
 #include "chrome/browser/ash/system/input_device_settings.h"
-#include "chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.h"
 #include "chrome/browser/chromeos/file_system_provider/registry.h"
 #include "chrome/browser/chromeos/first_run/first_run.h"
 #include "chrome/browser/chromeos/full_restore/full_restore_prefs.h"
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.html b/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.html
index 4b12790..5da40d01 100644
--- a/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.html
+++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.html
@@ -8,7 +8,8 @@
   }
 
   #button {
-    font-size: 32px;
+    --cr-icon-button-size: var(--emoji-group-button-size);
+    font-size: var(--emoji-group-button-size);
     margin: 0;
     padding: 0;
   }
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_search.html b/chrome/browser/resources/chromeos/emoji_picker/emoji_search.html
index f365692..75db80d 100644
--- a/chrome/browser/resources/chromeos/emoji_picker/emoji_search.html
+++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_search.html
@@ -7,33 +7,25 @@
   }
   cr-search-field {
     --cr-search-field-clear-icon-margin-end: 14px;
-    --cr-search-field-clear-icon-margin-end:14px;
     --cr-search-field-clear-icon-size:20px;
     --cr-search-field-input-border-bottom: none;
     --cr-search-field-input-padding-bottom: 0;
-    --cr-search-field-clear-icon-size:20px;
-    --cr-search-field-input-border-bottom: none;
-    --cr-search-field-input-padding-bottom: 0;
+    --cr-search-field-input-padding-start: 8px;
     --cr-search-field-input-padding-top: 0;
-    --cr-search-field-input-padding-top: 0;
-    --cr-search-field-input-width: calc(100% - 24px);
-    --cr-search-field-search-icon-padding: 0px 8px 0px 14px;
-    --cr-search-field-search-icon-size: 20px;
+    --cr-search-field-input-width: 100%;
+    --cr-search-field-search-icon-display: none;
+    --cr-search-field-search-icon-fill: var(--cr-secondary-text-color);
+    --cr-search-field-search-icon-inline-display: block;
+    --cr-search-field-search-icon-inline-margin-start: 14px;
     --cr-search-field-underline-display: none;
     align-items: center;
-    background-color: var(--cr-separator-color);
+    background-color: var(--google-grey-100);
     border-radius: 41px;
     height: 40px;
     line-height: 40px;
     margin-bottom: 8px;
   }
 
-  cr-search-field::part(searchIcon) {
-    height: 20px;
-    padding: 0 8px 0 14px;
-    width: 20px;
-  }
-
   #container {
     flex-grow: 1;
     overflow-y: scroll;
@@ -88,7 +80,7 @@
       </div>
     </template>
     <template is="dom-if" if="[[!results.length]]">
-      <div class="no-result">
+      <div class="name">
         No results
       </div>
     </template>
diff --git a/chrome/browser/resources/downloads/OWNERS b/chrome/browser/resources/downloads/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chrome/browser/resources/downloads/OWNERS
+++ /dev/null
diff --git a/chrome/browser/resources/memories/app.js b/chrome/browser/resources/memories/app.js
index b00e9a43..a741586 100644
--- a/chrome/browser/resources/memories/app.js
+++ b/chrome/browser/resources/memories/app.js
@@ -120,11 +120,14 @@
     if (searchField.getValue() !== this.query_) {
       searchField.setValue(this.query_);
     }
+    // <if expr="not is_official_build">
     this.onBrowserIdle_().then(() => {
-      this.pageHandler_.queryMemories(this.query_.trim()).then(({result}) => {
-        this.result_ = result;
-      });
+      this.pageHandler_.getSampleMemories(this.query_.trim())
+          .then(({result}) => {
+            this.result_ = result;
+          });
     });
+    // </if>
   }
 }
 
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html
index 8f0bef2..834020e 100644
--- a/chrome/browser/resources/new_tab_page/app.html
+++ b/chrome/browser/resources/new_tab_page/app.html
@@ -282,13 +282,13 @@
             on-ntp-middle-slot-promo-loaded="onMiddleSlotPromoLoaded_">
         </ntp-middle-slot-promo>
       </template>
-      <template is="dom-repeat" items="[[moduleDescriptors_]]" id="modules"
+      <template is="dom-repeat" items="[[modules_]]" id="modules"
           on-dom-change="onModulesLoaded_">
-        <ntp-module-wrapper descriptor="[[item]]"
+        <ntp-module-wrapper module="[[item]]"
             on-dismiss-module="onDismissModule_"
             on-disable-module="onDisableModule_"
             on-customize-module="onCustomizeModule_"
-            hidden="[[moduleDisabled_(item.id,
+            hidden="[[moduleDisabled_(item.descriptor.id,
                                       dismissedModules_.*,
                                       disabledModules_)]]">
         </ntp-module-wrapper>
diff --git a/chrome/browser/resources/new_tab_page/app.js b/chrome/browser/resources/new_tab_page/app.js
index 086bdab9..d6f4597 100644
--- a/chrome/browser/resources/new_tab_page/app.js
+++ b/chrome/browser/resources/new_tab_page/app.js
@@ -22,7 +22,7 @@
 import {BackgroundManager} from './background_manager.js';
 import {BackgroundSelection, BackgroundSelectionType, CustomizeDialogPage} from './customize_dialog_types.js';
 import {recordLoadDuration} from './metrics_utils.js';
-import {ModuleDescriptor} from './modules/module_descriptor.js';
+import {Module} from './modules/module_descriptor.js';
 import {ModuleRegistry} from './modules/module_registry.js';
 import {NewTabPageProxy} from './new_tab_page_proxy.js';
 import {oneGoogleBarApi} from './one_google_bar_api.js';
@@ -244,8 +244,8 @@
        */
       lazyRender_: Boolean,
 
-      /** @private {!Array<!ModuleDescriptor>} */
-      moduleDescriptors_: Object,
+      /** @private {!Array<!Module>} */
+      modules_: Object,
 
       /** @private {!Array<string>} */
       dismissedModules_: {
@@ -553,15 +553,15 @@
         !loadTimeData.getBoolean('modulesEnabled')) {
       return;
     }
-    const descriptors = await ModuleRegistry.getInstance().initializeModules(
+    const modules = await ModuleRegistry.getInstance().initializeModules(
         loadTimeData.getInteger('modulesLoadTimeout'));
-    if (descriptors) {
+    if (modules) {
       this.pageHandler_.onModulesLoadedWithData();
     }
     if (!loadTimeData.getBoolean('modulesEnabled')) {
       return;
     }
-    this.moduleDescriptors_ = descriptors;
+    this.modules_ = modules;
   }
 
   /** @private */
@@ -654,7 +654,7 @@
         loadTimeData.getBoolean('modulesEnabled')) {
       recordLoadDuration(
           'NewTabPage.Modules.ShownTime', WindowProxy.getInstance().now());
-      this.moduleDescriptors_.forEach(({id}) => {
+      this.modules_.forEach(({descriptor: {id}}) => {
         chrome.metricsPrivate.recordBoolean(
             `NewTabPage.Modules.EnabledOnNTPLoad.${id}`,
             !this.disabledModules_.all &&
@@ -898,7 +898,7 @@
    * @private
    */
   onDismissModule_(e) {
-    const id = $$(this, '#modules').itemForElement(e.target).id;
+    const id = $$(this, '#modules').itemForElement(e.target).descriptor.id;
     const restoreCallback = e.detail.restoreCallback;
     this.removedModuleData_ = {
       message: e.detail.message,
@@ -925,7 +925,7 @@
    * @private
    */
   onDisableModule_(e) {
-    const id = $$(this, '#modules').itemForElement(e.target).id;
+    const id = $$(this, '#modules').itemForElement(e.target).descriptor.id;
     const restoreCallback = e.detail.restoreCallback;
     this.removedModuleData_ = {
       message: e.detail.message,
diff --git a/chrome/browser/resources/new_tab_page/modules/drive/module.html b/chrome/browser/resources/new_tab_page/modules/drive/module.html
index af17f57..c2c80e78 100644
--- a/chrome/browser/resources/new_tab_page/modules/drive/module.html
+++ b/chrome/browser/resources/new_tab_page/modules/drive/module.html
@@ -44,7 +44,8 @@
 
   .file-title {
     flex-basis: 0;
-    flex-grow: 250;
+    flex-grow: 260;
+    margin-inline-end: 34px;
     overflow: hidden;
     text-overflow: ellipsis;
     white-space: nowrap;
@@ -65,14 +66,14 @@
     align-items: center;
     display: flex;
     flex-basis: 0;
-    flex-grow: 186;
+    flex-grow: 210;
     overflow: hidden;
   }
 
   .user-image {
     border-radius: 50%;
     margin-inline-end: 8px;
-    max-height: 30px;
+    max-height: 16px;
   }
 </style>
 <ntp-module-header
diff --git a/chrome/browser/resources/new_tab_page/modules/module_descriptor.js b/chrome/browser/resources/new_tab_page/modules/module_descriptor.js
index cfe822a3..0032437 100644
--- a/chrome/browser/resources/new_tab_page/modules/module_descriptor.js
+++ b/chrome/browser/resources/new_tab_page/modules/module_descriptor.js
@@ -10,11 +10,12 @@
  * module descriptor and register it at the NTP.
  */
 
-/**
- * @typedef {function(): !Promise<?HTMLElement>}
- */
+/** @typedef {function(): !Promise<?HTMLElement>} */
 let InitializeModuleCallback;
 
+/** @typedef {{element: !HTMLElement, descriptor: !ModuleDescriptor}} */
+export let Module;
+
 export class ModuleDescriptor {
   /**
    * @param {string} id
@@ -26,8 +27,6 @@
     this.id_ = id;
     /** @private {string} */
     this.name_ = name;
-    /** @private {HTMLElement} */
-    this.element_ = null;
     /** @private {!InitializeModuleCallback} */
     this.initializeCallback_ = initializeCallback;
   }
@@ -42,29 +41,23 @@
     return this.name_;
   }
 
-  /** @return {?HTMLElement} */
-  get element() {
-    return this.element_;
-  }
-
   /**
-   * Initializes the module. On success, |this.element| will be populated after
-   * the returned promise has resolved.
+   * Initializes the module and returns the module element on success.
    * @param {number} timeout Timeout in milliseconds after which initialization
    *     aborts.
-   * @return {!Promise}
+   * @return {!Promise<?HTMLElement>}
    */
   async initialize(timeout) {
     const loadStartTime = WindowProxy.getInstance().now();
-    this.element_ = await Promise.race([
+    const element = await Promise.race([
       this.initializeCallback_(), new Promise(resolve => {
         WindowProxy.getInstance().setTimeout(() => {
           resolve(null);
         }, timeout);
       })
     ]);
-    if (!this.element_) {
-      return;
+    if (!element) {
+      return null;
     }
     const loadEndTime = WindowProxy.getInstance().now();
     const duration = loadEndTime - loadStartTime;
@@ -72,5 +65,6 @@
     recordLoadDuration(`NewTabPage.Modules.Loaded.${this.id_}`, loadEndTime);
     recordDuration('NewTabPage.Modules.LoadDuration', duration);
     recordDuration(`NewTabPage.Modules.LoadDuration.${this.id_}`, duration);
+    return element;
   }
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/module_registry.js b/chrome/browser/resources/new_tab_page/modules/module_registry.js
index 06a7585..865a6a8 100644
--- a/chrome/browser/resources/new_tab_page/modules/module_registry.js
+++ b/chrome/browser/resources/new_tab_page/modules/module_registry.js
@@ -3,7 +3,8 @@
 // found in the LICENSE file.
 
 import {NewTabPageProxy} from '../new_tab_page_proxy.js';
-import {ModuleDescriptor} from './module_descriptor.js';
+
+import {Module, ModuleDescriptor} from './module_descriptor.js';
 import {descriptors} from './module_descriptors.js';
 
 /**
@@ -41,10 +42,10 @@
 
   /**
    * Initializes enabled modules previously set via |registerModules| and
-   * returns the initialized descriptors.
+   * returns the initialized modules.
    * @param {number} timeout Timeout in milliseconds after which initialization
    *     of a particular module aborts.
-   * @return {!Promise<!Array<!ModuleDescriptor>>}
+   * @return {!Promise<!Array<!Module>>}
    */
   async initializeModules(timeout) {
     // Capture updateDisabledModules -> setDisabledModules round trip in a
@@ -58,9 +59,11 @@
           });
       NewTabPageProxy.getInstance().handler.updateDisabledModules();
     });
-    await Promise.all(
-        this.descriptors_.filter(d => disabledIds.indexOf(d.id) < 0)
-            .map(d => d.initialize(timeout)));
-    return this.descriptors_.filter(descriptor => !!descriptor.element);
+    const descriptors =
+        this.descriptors_.filter(d => !disabledIds.includes(d.id));
+    const elements =
+        await Promise.all(descriptors.map(d => d.initialize(timeout)));
+    return elements.map((e, i) => ({element: e, descriptor: descriptors[i]}))
+        .filter(m => !!m.element);
   }
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/module_wrapper.js b/chrome/browser/resources/new_tab_page/modules/module_wrapper.js
index 8de30da..58eb0d0a 100644
--- a/chrome/browser/resources/new_tab_page/modules/module_wrapper.js
+++ b/chrome/browser/resources/new_tab_page/modules/module_wrapper.js
@@ -8,7 +8,7 @@
 import {recordLoadDuration, recordOccurence, recordPerdecage} from '../metrics_utils.js';
 import {WindowProxy} from '../window_proxy.js';
 
-import {ModuleDescriptor} from './module_descriptor.js';
+import {Module} from './module_descriptor.js';
 
 /** @fileoverview Element that implements the common module UI. */
 
@@ -23,28 +23,28 @@
 
   static get properties() {
     return {
-      /** @type {!ModuleDescriptor} */
-      descriptor: {
-        observer: 'onDescriptorChange_',
+      /** @type {!Module} */
+      module: {
+        observer: 'onModuleChange_',
         type: Object,
       },
     };
   }
 
   /**
-   * @param {ModuleDescriptor} newValue
-   * @param {ModuleDescriptor} oldValue
+   * @param {*} newValue
+   * @param {*} oldValue
    * @private
    */
-  onDescriptorChange_(newValue, oldValue) {
+  onModuleChange_(newValue, oldValue) {
     assert(!oldValue);
-    this.$.moduleElement.appendChild(this.descriptor.element);
+    this.$.moduleElement.appendChild(this.module.element);
 
     // Log at most one usage per module per NTP page load. This is possible,
     // if a user opens a link in a new tab.
-    this.descriptor.element.addEventListener('usage', () => {
+    this.module.element.addEventListener('usage', () => {
       recordOccurence('NewTabPage.Modules.Usage');
-      recordOccurence(`NewTabPage.Modules.Usage.${this.descriptor.id}`);
+      recordOccurence(`NewTabPage.Modules.Usage.${this.module.descriptor.id}`);
     }, {once: true});
 
     // Install observer to log module header impression.
@@ -54,7 +54,7 @@
         const time = WindowProxy.getInstance().now();
         recordLoadDuration('NewTabPage.Modules.Impression', time);
         recordLoadDuration(
-            `NewTabPage.Modules.Impression.${this.descriptor.id}`, time);
+            `NewTabPage.Modules.Impression.${this.module.descriptor.id}`, time);
         this.dispatchEvent(new Event('detect-impression'));
       }
     }, {threshold: 1.0});
@@ -70,7 +70,7 @@
       recordPerdecage(
           'NewTabPage.Modules.ImpressionRatio', intersectionPerdecage);
       recordPerdecage(
-          `NewTabPage.Modules.ImpressionRatio.${this.descriptor.id}`,
+          `NewTabPage.Modules.ImpressionRatio.${this.module.descriptor.id}`,
           intersectionPerdecage);
     });
 
@@ -86,7 +86,7 @@
     // Track whether the user hovered on the module.
     this.addEventListener('mouseover', () => {
       chrome.metricsPrivate.recordSparseHashable(
-          'NewTabPage.Modules.Hover', this.descriptor.id);
+          'NewTabPage.Modules.Hover', this.module.descriptor.id);
     }, {
       useCapture: true,  // So that modules cannot swallow event.
       once: true,        // Only one log per NTP load.
diff --git a/chrome/browser/resources/settings/languages_page/add_languages_dialog.html b/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
index c9ee9b88..225ddce 100644
--- a/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
+++ b/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
@@ -30,6 +30,7 @@
       <div id="dialog-title" slot="title">
         <span>$i18n{addLanguagesDialogTitle}</span>
         <cr-search-field label="$i18n{searchLanguages}" id="search"
+            clear-label="$i18n{clearSearch}"
             on-search-changed="onSearchChanged_"
             on-keydown="onKeydown_" autofocus>
         </cr-search-field>
diff --git a/chrome/browser/resources/settings/languages_page/languages.js b/chrome/browser/resources/settings/languages_page/languages.js
index 062c136..571f8555 100644
--- a/chrome/browser/resources/settings/languages_page/languages.js
+++ b/chrome/browser/resources/settings/languages_page/languages.js
@@ -179,6 +179,8 @@
   observers: [
     // All observers wait for the model to be populated by including the
     // |languages| property.
+    'alwaysTranslateLanguagesPrefChanged_(' +
+        'prefs.translate_whitelists.value.*, languages)',
     'prospectiveUILanguageChanged_(prefs.intl.app_locale.value, languages)',
     'preferredLanguagesPrefChanged_(' +
         'prefs.' + preferredLanguagesPrefName + '.value, languages)',
@@ -534,6 +536,21 @@
     };
   },
 
+  /**
+   * Updates the list of always translate languages from translate prefs.
+   * @private
+   */
+  alwaysTranslateLanguagesPrefChanged_() {
+    if (this.prefs === undefined || this.languages === undefined) {
+      return;
+    }
+    const alwaysTranslateCodes = Object.keys(
+        /** @type {!Object} */ (this.getPref('translate_whitelists').value));
+    const alwaysTranslateLanguages =
+        alwaysTranslateCodes.map(code => this.getLanguage(code));
+    this.set('languages.alwaysTranslate', alwaysTranslateLanguages);
+  },
+
   /** @private */
   translateLanguagesPrefChanged_() {
     if (this.prefs === undefined || this.languages === undefined) {
@@ -839,6 +856,23 @@
   },
 
   /**
+   *  @param {!chrome.languageSettingsPrivate.Language} language
+   *  @return {boolean} True if the language can be translated by Chrome.
+   */
+  isLanguageTranslatable(language) {
+    if (language.code === 'zh-CN' || language.code === 'zh-TW') {
+      // In Translate, general Chinese is not used, and the sub code is
+      // necessary as a language code for the Translate server.
+      return true;
+    }
+    if (language.code === this.getLanguageCodeWithoutRegion(language.code) &&
+        language.supportsTranslate) {
+      return true;
+    }
+    return false;
+  },
+
+  /**
    * @param {string} languageCode
    * @return {boolean} True if the language is enabled.
    */
diff --git a/chrome/browser/resources/settings/languages_page/languages_subpage.html b/chrome/browser/resources/settings/languages_page/languages_subpage.html
index 53a7122..8b0e283 100644
--- a/chrome/browser/resources/settings/languages_page/languages_subpage.html
+++ b/chrome/browser/resources/settings/languages_page/languages_subpage.html
@@ -91,7 +91,32 @@
       label="$i18n{offerToEnableTranslate}"
       on-settings-boolean-control-change="onTranslateToggleChange_">
   </settings-toggle-button>
-
+  <template is="dom-if" if="[[enableDesktopDetailedLanguageSettings_]]">
+    <div class="cr-row continuation">
+      <h2 class="flex">$i18n{automaticallyTranslateLanguages}</h2>
+      <cr-button id="addAlwaysTranslate" class="header-aligned-button"
+          on-click="onAddAlwaysTranslateLanguagesClick_">
+        $i18n{add}
+      </cr-button>
+    </div>
+    <div class="list-frame">
+      <div id="alwaysTranslateList" class="vertical-list">
+        <template is="dom-repeat" items="[[languages.alwaysTranslate]]">
+          <div class="list-item">
+            <div class="start cr-padded-text">[[item.displayName]]</div>
+            <cr-icon-button class="icon-clear"
+                on-click="onRemoveAlwaysTranslateLanguageClick_">
+            </cr-icon-button>
+          </div>
+        </template>
+      </div>
+      <div id="noAlwaysTranslateLabel" 
+          class="list-item" 
+          hidden$="[[hasSome_(languages.alwaysTranslate)]]">
+        $i18n{noLanguagesAdded}
+      </div>
+    </div>
+  </template>
   <cr-lazy-render id="menu">
       <template>
         <cr-action-menu role-description="$i18n{menu}"
@@ -159,6 +184,15 @@
       on-close="onAddLanguagesDialogClose_">
   </settings-add-languages-dialog>
 </template>
+<template is="dom-if" if="[[enableDesktopDetailedLanguageSettings_]]">
+  <template is="dom-if" if="[[showAddAlwaysTranslateDialog_]]" restamp>
+    <settings-add-languages-dialog languages="[[addLanguagesDialogLanguages_]]"
+        id="alwaysTranslateDialog"
+        on-close="onAlwaysTranslateDialogClose_"
+        on-languages-added="onAlwaysTranslateLanguagesAdded_">
+    </settings-add-languages-dialog>
+  </template>
+</template>
 <template is="dom-if" if="[[showManagedLanguageDialog_]]" restamp>
   <managed-dialog on-close="onManagedLanguageDialogClosed_"
       title="[[i18n('languageManagedDialogTitle')]]"
diff --git a/chrome/browser/resources/settings/languages_page/languages_subpage.js b/chrome/browser/resources/settings/languages_page/languages_subpage.js
index ccc06fe..f26af18 100644
--- a/chrome/browser/resources/settings/languages_page/languages_subpage.js
+++ b/chrome/browser/resources/settings/languages_page/languages_subpage.js
@@ -91,6 +91,9 @@
     /** @private */
     showAddLanguagesDialog_: Boolean,
 
+    /** @private */
+    showAddAlwaysTranslateDialog_: Boolean,
+
     /** @private {?Array<!chrome.languageSettingsPrivate.Language>} */
     addLanguagesDialogLanguages_: Array,
 
@@ -127,6 +130,20 @@
       type: Boolean,
       value: false,
     },
+
+    /** @private */
+    enableDesktopDetailedLanguageSettings_: {
+      type: Boolean,
+      value() {
+        let enabled = false;
+        // <if expr="not chromeos and not lacros">
+        enabled =
+            loadTimeData.getBoolean('enableDesktopDetailedLanguageSettings');
+        // </if>
+        return enabled;
+      },
+    },
+
   },
 
   // <if expr="chromeos">
@@ -200,6 +217,51 @@
   },
 
   /**
+   * Stamps and opens the Add Languages dialog, registering a listener to
+   * disable the dialog's dom-if again on close.
+   * @param {!Event} e
+   * @private
+   */
+  onAddAlwaysTranslateLanguagesClick_(e) {
+    e.preventDefault();
+
+    const translatableLanguages = this.getTranslatableLanguages_();
+    this.addLanguagesDialogLanguages_ = translatableLanguages.filter(
+        language => !this.languages.alwaysTranslate.includes(language));
+    this.showAddAlwaysTranslateDialog_ = true;
+  },
+
+  /** @private */
+  onAlwaysTranslateDialogClose_() {
+    this.showAddAlwaysTranslateDialog_ = false;
+    this.addLanguagesDialogLanguages_ = null;
+    focusWithoutInk(assert(this.$$('#addAlwaysTranslate')));
+  },
+
+  /**
+   * Helper function fired by the add dialog's on-languages-added event. Adds
+   * selected languages to the always-translate languages list.
+   * @param {!CustomEvent<!Array<string>>} e
+   * @private
+   */
+  onAlwaysTranslateLanguagesAdded_(e) {
+    const languagesToAdd = e.detail;
+    languagesToAdd.forEach(languageCode => {
+      this.languageHelper.setLanguageAlwaysTranslateState(languageCode, true);
+    });
+  },
+
+  /**
+   * Removes a language from the always translate languages list.
+   * @param {!Event} e
+   * @private
+   */
+  onRemoveAlwaysTranslateLanguageClick_(e) {
+    const languageCode = e.model.item.code;
+    this.languageHelper.setLanguageAlwaysTranslateState(languageCode, false);
+  },
+
+  /**
    * Checks if there are supported languages that are not enabled but can be
    * enabled.
    * @param {LanguagesModel|undefined} languages
@@ -642,5 +704,25 @@
    */
   onManagedLanguageDialogClosed_() {
     this.showManagedLanguageDialog_ = false;
-  }
+  },
+
+  /**
+   * @param {Array<?>} list
+   * @return {boolean} Returns true if the list is non-null and has items.
+   * @private
+   */
+  hasSome_(list) {
+    return !!(list && list.length);
+  },
+
+  /**
+   * Gets the list of languages that chrome can translate
+   * @private
+   * @returns {!Array<!chrome.languageSettingsPrivate.Language>}
+   */
+  getTranslatableLanguages_() {
+    return this.languages.supported.filter(language => {
+      return this.languageHelper.isLanguageTranslatable(language);
+    });
+  },
 });
diff --git a/chrome/browser/resources/settings/languages_page/languages_types.js b/chrome/browser/resources/settings/languages_page/languages_types.js
index 84f0490..a40ba95 100644
--- a/chrome/browser/resources/settings/languages_page/languages_types.js
+++ b/chrome/browser/resources/settings/languages_page/languages_types.js
@@ -115,6 +115,12 @@
   isLanguageCodeForArcIme(languageCode) {}
 
   /**
+   *  @param {!chrome.languageSettingsPrivate.Language} language
+   *  @return {boolean}
+   */
+  isLanguageTranslatable(language) {}
+
+  /**
    * @param {string} languageCode
    * @return {boolean}
    */
@@ -181,6 +187,13 @@
   disableTranslateLanguage(languageCode) {}
 
   /**
+   * Sets whether a given language should always be automatically translated.
+   * @param {string} languageCode
+   * @param {boolean} alwaysTranslate
+   */
+  setLanguageAlwaysTranslateState(languageCode, alwaysTranslate) {}
+
+  /**
    * Enables or disables spell check for the given language.
    * @param {string} languageCode
    * @param {boolean} enable
diff --git a/chrome/browser/resources/welcome/shared/onboarding_background.html b/chrome/browser/resources/welcome/shared/onboarding_background.html
index 19a1135..6e1725f 100644
--- a/chrome/browser/resources/welcome/shared/onboarding_background.html
+++ b/chrome/browser/resources/welcome/shared/onboarding_background.html
@@ -212,45 +212,85 @@
   #yellow-connectagon {
     --connectagon-shape-color: var(--welcome-yellow);
     --connectagon-connector-color: var(--welcome-yellow-tinted);
+    animation: yellow-connectagon 4s alternate infinite linear;
     left: 549px;
     top: 156px;
     transform: translate(-50%, -50%) rotate(51deg);
   }
 
+  @keyframes yellow-connectagon {
+    to {
+      transform: translate(calc(-50% - 62px), calc(-50% - 36px)) rotate(411deg);
+    }
+  }
+
   #green-triangle {
     -webkit-mask: url(../images/background_svgs/triangle.svg);
+    animation: green-triangle 2s infinite linear;
     background-color: var(--welcome-green);
-    height: 400px;
     left: 1813px;
     top: 151px;
-    transform: translate(-50%, -50%) rotate(50deg);
-    width: 400px;
+    transform: translate(-50%, -50%) rotate(0deg);
+    transform-origin: 250px 250px;
+  }
+
+  @keyframes green-triangle {
+    to {
+      transform: translate(-50%, -50%) rotate(360deg);
+    }
   }
 
   #blue-connectagon {
     --connectagon-shape-color: var(--welcome-blue);
     --connectagon-connector-color: var(--welcome-blue-tinted);
+    animation: blue-connectagon 4s alternate infinite linear;
     left: 2157px;
     top: 249px;
     transform: translate(-50%, -50%) rotate(152deg);
   }
 
+  @keyframes blue-connectagon {
+    50% {
+      transform: translate(calc(-50% + 10px), calc(-50% + 20px)) rotate(152deg);
+    }
+
+    100% {
+      transform: translate(calc(-50%), calc(-50% + 40px)) rotate(152deg);
+    }
+  }
+
   #green-connectagon {
     --connectagon-shape-color: var(--welcome-green);
     --connectagon-connector-color: var(--welcome-green-tinted);
+    animation: green-connectagon 8s alternate infinite linear;
     left: 851px;
     top: 766px;
     transform: translate(-50%, -50%) rotate(139deg);
   }
 
+  @keyframes green-connectagon {
+    50% {
+      transform: translate(calc(-50% + 40px), calc(-50% + 10px)) rotate(499deg);
+    }
+
+    100% {
+      transform: translate(calc(-50% + 80px), calc(-50% + 20px)) rotate(139deg);
+    }
+  }
+
   #square {
     -webkit-mask: url(../images/background_svgs/square.svg);
+    animation: square 4s infinite linear;
     background-color: var(--welcome-yellow);
-    height: 400px;
     left: 1822px;
     top: 716px;
     transform: translate(-50%, -50%) rotate(29deg);
-    width: 400px;
+  }
+
+  @keyframes square {
+    to {
+      transform: translate(-50%, -50%) rotate(389deg);
+    }
   }
 
   #grey-triangle {
diff --git a/chrome/browser/share/BUILD.gn b/chrome/browser/share/BUILD.gn
index 9fc72b5..40b2d89 100644
--- a/chrome/browser/share/BUILD.gn
+++ b/chrome/browser/share/BUILD.gn
@@ -32,11 +32,14 @@
 android_library("java") {
   sources = [
     "android/java/src/org/chromium/chrome/browser/share/ChromeShareExtras.java",
+    "android/java/src/org/chromium/chrome/browser/share/ShareDelegate.java",
     "android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeOptionShareCallback.java",
   ]
 
   deps = [
+    "//chrome/browser/tab:java",
     "//components/browser_ui/share/android:java",
+    "//third_party/androidx:androidx_annotation_annotation_java",
     "//url:gurl_java",
   ]
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegate.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ShareDelegate.java
similarity index 62%
rename from chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegate.java
rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ShareDelegate.java
index 0fc798f..b80bbe3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegate.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ShareDelegate.java
@@ -4,7 +4,8 @@
 
 package org.chromium.chrome.browser.share;
 
-import org.chromium.chrome.browser.share.ShareDelegateImpl.ShareOrigin;
+import androidx.annotation.IntDef;
+
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.components.browser_ui.share.ShareParams;
 
@@ -12,6 +13,26 @@
  * Interface to expose sharing to external classes.
  */
 public interface ShareDelegate {
+    // These values are persisted to logs. Entries should not be renumbered and numeric values
+    // should never be reused.
+    @IntDef({ShareOrigin.OVERFLOW_MENU, ShareOrigin.TOP_TOOLBAR, ShareOrigin.CONTEXT_MENU,
+            ShareOrigin.WEBSHARE_API, ShareOrigin.MOBILE_ACTION_MODE, ShareOrigin.EDIT_URL,
+            ShareOrigin.TAB_GROUP, ShareOrigin.WEBAPP_NOTIFICATION, ShareOrigin.FEED})
+    public @interface ShareOrigin {
+        int OVERFLOW_MENU = 0;
+        int TOP_TOOLBAR = 1;
+        int CONTEXT_MENU = 2;
+        int WEBSHARE_API = 3;
+        int MOBILE_ACTION_MODE = 4;
+        int EDIT_URL = 5;
+        int TAB_GROUP = 6;
+        int WEBAPP_NOTIFICATION = 7;
+        int FEED = 8;
+
+        // Must be the last one.
+        int COUNT = 9;
+    }
+
     /**
      * Initiate a share based on the provided ShareParams.
      *
diff --git a/chrome/browser/speech/speech_recognition_client_browser_interface.cc b/chrome/browser/speech/speech_recognition_client_browser_interface.cc
index 2d8ec2f..128a364 100644
--- a/chrome/browser/speech/speech_recognition_client_browser_interface.cc
+++ b/chrome/browser/speech/speech_recognition_client_browser_interface.cc
@@ -36,10 +36,13 @@
       base::BindRepeating(&SpeechRecognitionClientBrowserInterface::
                               OnSpeechRecognitionLanguageChanged,
                           base::Unretained(this)));
+  speech::SodaInstaller::GetInstance()->AddObserver(this);
 }
 
 SpeechRecognitionClientBrowserInterface::
-    ~SpeechRecognitionClientBrowserInterface() = default;
+    ~SpeechRecognitionClientBrowserInterface() {
+  speech::SodaInstaller::GetInstance()->RemoveObserver(this);
+}
 
 void SpeechRecognitionClientBrowserInterface::BindReceiver(
     mojo::PendingReceiver<media::mojom::SpeechRecognitionClientBrowserInterface>
@@ -56,7 +59,6 @@
 }
 
 void SpeechRecognitionClientBrowserInterface::OnSodaInstalled() {
-  speech::SodaInstaller::GetInstance()->RemoveObserver(this);
   NotifyObservers(profile_prefs_->GetBoolean(prefs::kLiveCaptionEnabled));
 }
 
@@ -71,11 +73,8 @@
     if (!base::FeatureList::IsEnabled(media::kUseSodaForLiveCaption) ||
         speech::SodaInstaller::GetInstance()->IsSodaInstalled()) {
       NotifyObservers(enabled);
-    } else {
-      speech::SodaInstaller::GetInstance()->AddObserver(this);
     }
   } else {
-    speech::SodaInstaller::GetInstance()->RemoveObserver(this);
     NotifyObservers(enabled);
   }
 }
diff --git a/chrome/browser/speech/speech_recognition_service_browsertest.cc b/chrome/browser/speech/speech_recognition_service_browsertest.cc
index 95acd25..01679c4 100644
--- a/chrome/browser/speech/speech_recognition_service_browsertest.cc
+++ b/chrome/browser/speech/speech_recognition_service_browsertest.cc
@@ -49,7 +49,7 @@
 
 constexpr int kExpectedChannelCount = 1;
 
-constexpr base::FilePath::CharType kSodaBinaryRelativePath[] =
+constexpr base::FilePath::CharType kSodaBinaryForTestingRelativePath[] =
     FILE_PATH_LITERAL("libsoda_for_testing.so");
 
 // TODO: Should be a way to generate this, this seems way too brittle.
@@ -257,7 +257,7 @@
   g_browser_process->local_state()->SetFilePath(
       prefs::kSodaBinaryPath,
       test_data_dir_.Append(base::FilePath(kSodaResourcesDir))
-          .Append(kSodaBinaryRelativePath));
+          .Append(kSodaBinaryForTestingRelativePath));
   g_browser_process->local_state()->SetFilePath(
       prefs::kSodaEnUsConfigPath,
       test_data_dir_.Append(base::FilePath(kSodaResourcesDir))
@@ -342,7 +342,7 @@
   g_browser_process->local_state()->SetFilePath(
       prefs::kSodaBinaryPath,
       test_data_dir_.Append(base::FilePath(kSodaResourcesDir))
-          .Append(kSodaBinaryRelativePath));
+          .Append(kSodaBinaryForTestingRelativePath));
   g_browser_process->local_state()->SetFilePath(
       prefs::kSodaEnUsConfigPath,
       test_data_dir_.Append(base::FilePath(kSodaResourcesDir))
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 9245fb7..121cd66e 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -192,6 +192,7 @@
 #include "services/network/public/cpp/network_switches.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/page_state/page_state.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
@@ -8102,7 +8103,7 @@
 // SSL error related page in chrome://network-errors. Regression test for
 // crbug.com/953812
 IN_PROC_BROWSER_TEST_F(SSLUITest, NoInterstitialOnNetworkErrorPage) {
-  GURL invalid_cert_url(content::kChromeUINetworkErrorURL);
+  GURL invalid_cert_url(blink::kChromeUINetworkErrorURL);
   GURL::Replacements replacements;
   replacements.SetPathStr("-207");
   invalid_cert_url = invalid_cert_url.ReplaceComponents(replacements);
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
index bc4069c..01e3b69 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -71,6 +71,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "url/gurl.h"
 
 namespace subresource_filter {
@@ -665,7 +666,7 @@
       browser()->tab_strip_model()->GetActiveWebContents(),
       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
   browser()->OpenURL(content::OpenURLParams(
-      GURL(content::kChromeUICrashURL), content::Referrer(),
+      GURL(blink::kChromeUICrashURL), content::Referrer(),
       WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
   crash_observer.Wait();
 }
diff --git a/chrome/browser/ui/ash/recording_service_browsertest.cc b/chrome/browser/ui/ash/recording_service_browsertest.cc
index 498fb86..37b994d 100644
--- a/chrome/browser/ui/ash/recording_service_browsertest.cc
+++ b/chrome/browser/ui/ash/recording_service_browsertest.cc
@@ -151,11 +151,17 @@
 
   // Reads the video file at the given |path| and verifies its WebM contents. At
   // the end it deletes the file to save space, since video files can be big.
-  void VerifyVideoFileAndDelete(const base::FilePath& path) const {
+  // |allow_empty| can be set to true if an empty video file is possible.
+  void VerifyVideoFileAndDelete(const base::FilePath& path,
+                                bool allow_empty = false) const {
     base::ScopedAllowBlockingForTesting allow_blocking;
     ASSERT_TRUE(base::PathExists(path));
     std::string file_content;
     EXPECT_TRUE(base::ReadFileToString(path, &file_content));
+
+    if (allow_empty && file_content.empty())
+      return;
+
     EXPECT_FALSE(file_content.empty());
     EXPECT_TRUE(WebmVerifier().Verify(file_content));
     EXPECT_TRUE(base::DeleteFile(path));
@@ -253,6 +259,34 @@
   FinishVideoRecordingTest(&test_api);
 }
 
+IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest,
+                       RecordingServiceEndpointDropped) {
+  ash::CaptureModeTestApi test_api;
+  test_api.StartForFullscreen(/*for_video=*/true);
+  test_api.PerformCapture();
+  test_api.FlushRecordingServiceForTesting();
+  WaitForMilliseconds(1000);
+  test_api.ResetRecordingServiceRemote();
+  const base::FilePath video_path = WaitForVideoFileToBeSaved();
+  VerifyVideoFileAndDelete(video_path);
+}
+
+IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest,
+                       RecordingServiceClientEndpointDropped) {
+  ash::CaptureModeTestApi test_api;
+  test_api.StartForFullscreen(/*for_video=*/true);
+  test_api.PerformCapture();
+  test_api.FlushRecordingServiceForTesting();
+  WaitForMilliseconds(1000);
+  test_api.ResetRecordingServiceClientReceiver();
+  const base::FilePath video_path = WaitForVideoFileToBeSaved();
+  // Due to buffering on the service side, the channel might get dropped before
+  // any flushing of those beffers ever happens, and since dropping the client
+  // end point will immediately terminate the service, nothing may ever get
+  // flushed, and the resulting video file can be empty.
+  VerifyVideoFileAndDelete(video_path, /*allow_empty=*/true);
+}
+
 // Doing multiple recordings one after the other should produce non-corrupt webm
 // files (i.e. the recording service should send webm chunks that are not
 // affected by buffered chunks from a previous recording).
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
index 603019b2..751db534 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -27,6 +27,7 @@
 #include "ui/views/accessibility/ax_aura_obj_wrapper.h"
 #include "ui/views/accessibility/ax_event_manager.h"
 #include "ui/views/accessibility/ax_root_obj_wrapper.h"
+#include "ui/views/accessibility/ax_virtual_view.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
@@ -72,7 +73,8 @@
   }
 #endif
 
-  if (!automation_event_router_observer_.IsObserving()) {
+  if (!automation_event_router_observer_.IsObserving() &&
+      !automation_event_router_interface_) {
     automation_event_router_observer_.Observe(
         extensions::AutomationEventRouter::GetInstance());
   }
@@ -108,6 +110,21 @@
   PostEvent(obj->GetUniqueId(), event_type);
 }
 
+void AutomationManagerAura::OnVirtualViewEvent(
+    views::AXVirtualView* virtual_view,
+    ax::mojom::Event event_type) {
+  CHECK(virtual_view);
+
+  if (!enabled_)
+    return;
+
+  views::AXAuraObjWrapper* obj = virtual_view->GetOrCreateWrapper(cache_.get());
+  if (!obj)
+    return;
+
+  PostEvent(obj->GetUniqueId(), event_type);
+}
+
 void AutomationManagerAura::AllAutomationExtensionsGone() {
   Disable();
 }
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.h b/chrome/browser/ui/aura/accessibility/automation_manager_aura.h
index 73e2c81..6fa1d49 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.h
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.h
@@ -71,6 +71,8 @@
 
   // views::AXEventObserver:
   void OnViewEvent(views::View* view, ax::mojom::Event event_type) override;
+  void OnVirtualViewEvent(views::AXVirtualView* virtual_view,
+                          ax::mojom::Event event_type) override;
 
   // AutomationEventRouterObserver:
   void AllAutomationExtensionsGone() override;
@@ -89,6 +91,7 @@
   friend class base::NoDestructor<AutomationManagerAura>;
 
   FRIEND_TEST_ALL_PREFIXES(AutomationManagerAuraBrowserTest, ScrollView);
+  FRIEND_TEST_ALL_PREFIXES(AutomationManagerAuraBrowserTest, TableView);
   FRIEND_TEST_ALL_PREFIXES(AutomationManagerAuraBrowserTest, WebAppearsOnce);
   FRIEND_TEST_ALL_PREFIXES(AutomationManagerAuraBrowserTest, EventFromAction);
 
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc
index 957c732..c63139c 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura_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/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
@@ -27,6 +28,8 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/radio_button.h"
 #include "ui/views/controls/scroll_view.h"
+#include "ui/views/controls/table/table_view.h"
+#include "ui/views/controls/table/test_table_model.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/flex_layout.h"
 #include "ui/views/layout/flex_layout_types.h"
@@ -87,7 +90,7 @@
   // Returns immediately if the node with AXAuraObjCache ID |node_id|
   // has ever been focused, otherwise spins a loop until that node is
   // focused.
-  void WaitForNodeIdToBeFocused(int node_id) {
+  void WaitForNodeIdToBeFocused(ui::AXNodeID node_id) {
     if (WasNodeIdFocused(node_id))
       return;
 
@@ -110,18 +113,25 @@
     return false;
   }
 
+  ui::AXTree* ax_tree() { return &ax_tree_; }
+
  private:
   // extensions::AutomationEventRouterInterface:
   void DispatchAccessibilityEvents(const ui::AXTreeID& tree_id,
                                    std::vector<ui::AXTreeUpdate> updates,
                                    const gfx::Point& mouse_location,
                                    std::vector<ui::AXEvent> events) override {
-    if (node_id_to_wait_for_ != -1) {
-      for (const ui::AXTreeUpdate& update : updates) {
+    for (const ui::AXTreeUpdate& update : updates) {
+      if (!ax_tree_.Unserialize(update)) {
+        LOG(ERROR) << ax_tree_.error();
+        FAIL() << "Could not unserialize AXTreeUpdate";
+      }
+
+      if (node_id_to_wait_for_ != ui::kInvalidAXNodeID) {
         int focused_node_id = update.tree_data.focus_id;
         focused_node_ids_.push_back(focused_node_id);
         if (focused_node_id == node_id_to_wait_for_) {
-          node_id_to_wait_for_ = -1;
+          node_id_to_wait_for_ = ui::kInvalidAXNodeID;
           run_loop_->Quit();
         }
       }
@@ -151,8 +161,9 @@
       const ui::AXActionData& data,
       const base::Optional<gfx::Rect>& rect) override {}
 
+  ui::AXTree ax_tree_;
   std::unique_ptr<base::RunLoop> run_loop_;
-  int node_id_to_wait_for_ = -1;
+  ui::AXNodeID node_id_to_wait_for_ = ui::kInvalidAXNodeID;
   std::vector<int> focused_node_ids_;
 
   std::unique_ptr<ui::AXEvent> most_recent_event_;
@@ -161,6 +172,14 @@
   DISALLOW_COPY_AND_ASSIGN(AutomationEventWaiter);
 };
 
+ui::TableColumn TestTableColumn(int id, const std::string& title) {
+  ui::TableColumn column;
+  column.id = id;
+  column.title = base::ASCIIToUTF16(title.c_str());
+  column.sortable = true;
+  return column;
+}
+
 }  // namespace
 
 typedef InProcessBrowserTest AutomationManagerAuraBrowserTest;
@@ -212,6 +231,7 @@
   auto* cache_ptr = cache.get();
   AutomationManagerAura* manager = AutomationManagerAura::GetInstance();
   manager->set_ax_aura_obj_cache_for_testing(std::move(cache));
+  AutomationEventWaiter waiter;
   manager->Enable();
 
   views::Widget* widget = new views::Widget;
@@ -239,8 +259,6 @@
   widget->GetRootView()->AddChildView(view3);
   views::AXAuraObjWrapper* wrapper3 = cache_ptr->GetOrCreate(view3);
 
-  AutomationEventWaiter waiter;
-
   // Focus view1, then block until we get an accessibility event that
   // shows this view is focused.
   view1->RequestFocus();
@@ -347,11 +365,123 @@
   EXPECT_EQ(315, node_data.GetIntAttribute(ax::mojom::IntAttribute::kScrollY));
 }
 
+// Ensure that TableView accessibility works at the level of the
+// serialized accessibility tree generated by AutomationManagerAura.
+IN_PROC_BROWSER_TEST_F(AutomationManagerAuraBrowserTest, TableView) {
+  // Make our own AXAuraObjCache.
+  auto cache = std::make_unique<views::AXAuraObjCache>();
+  auto* cache_ptr = cache.get();
+  ASSERT_NE(nullptr, cache_ptr);
+
+  // Get the AutomationManagerAura and make it use our cache.
+  AutomationManagerAura* manager = AutomationManagerAura::GetInstance();
+  manager->set_ax_aura_obj_cache_for_testing(std::move(cache));
+
+  // Initialize this before we enable AutomationManagerAura because it's
+  // going to intercept all AXTreeUpdates and build an AXTree from the
+  // results.
+  AutomationEventWaiter waiter;
+
+  // Enable the AutomationManagerAura.
+  manager->Enable();
+
+  // Create a widget and give it explicit bounds that aren't at the top-left
+  // of the screen so that we can check that the global bounding rect of
+  // various accessibility nodes is correct.
+  views::Widget* widget = new views::Widget;
+  views::Widget::InitParams params(
+      views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+  constexpr int kLeft = 100;
+  constexpr int kTop = 500;
+  constexpr int kWidth = 300;
+  constexpr int kHeight = 200;
+  params.bounds = {kLeft, kTop, kWidth, kHeight};
+  widget->Init(std::move(params));
+
+  // Construct a simple table model for testing, and then make a TableView
+  // based on that. There are 4 columns specified here, and 4 rows
+  // (TestTableModel fills cells in with fake data automatically).
+  std::vector<ui::TableColumn> columns;
+  columns.push_back(TestTableColumn(0, "Fruit"));
+  columns.push_back(TestTableColumn(1, "Color"));
+  columns.push_back(TestTableColumn(2, "Origin"));
+  columns.push_back(TestTableColumn(3, "Price"));
+  auto model = std::make_unique<TestTableModel>(4);  // Create 4 rows.
+  auto table = std::make_unique<views::TableView>(
+      model.get(), columns, views::TEXT_ONLY, /* single_selection = */ true);
+  // Note: normally views are owned by their parent view, but we get a
+  // possible crash if the table outlives the table model (which is scoped
+  // to this function). So we make the table owned by client, and that
+  // ensures that both the table and model are destroyed when they go out
+  // of scope.
+  table->set_owned_by_client();
+
+  // Add the TableView to our Widget's root view and give it bounds.
+  views::View* root_view = widget->GetRootView();
+  root_view->AddChildView(table.get());
+  table->SetBounds(0, 0, 200, 200);
+
+  // Show the widget.
+  widget->Show();
+  widget->Activate();
+
+  // Find the virtual views for the first row and first cell within the
+  // table.
+  ASSERT_EQ(4U, table->GetViewAccessibility().virtual_children().size());
+  views::AXVirtualView* ax_row_0 =
+      table->GetViewAccessibility().virtual_children()[0].get();
+  ASSERT_EQ(4U, ax_row_0->children().size());
+  views::AXVirtualView* ax_cell_0_0 = ax_row_0->children()[0].get();
+  ASSERT_NE(nullptr, ax_cell_0_0);
+
+  // This is the key part! Tell the table to focus and select the first row.
+  // Then wait for an accessibility focus event on the first cell in the table!
+  views::AXAuraObjWrapper* ax_cell_0_0_wrapper =
+      ax_cell_0_0->GetOrCreateWrapper(cache_ptr);
+  table->RequestFocus();
+  table->Select(0);
+  waiter.WaitForNodeIdToBeFocused(ax_cell_0_0_wrapper->GetUniqueId());
+
+  // If we got this far, that means we got a focus event on the correct
+  // node in the table. Now, find that same node in the AXTree (which is
+  // after being serialized and unserialized) and ensure that the resulting
+  // bounding box for the table cell is correct.
+  {
+    ui::AXNode* cell =
+        waiter.ax_tree()->GetFromId(ax_cell_0_0_wrapper->GetUniqueId());
+    ASSERT_TRUE(cell);
+    EXPECT_EQ(ax::mojom::Role::kCell, cell->data().role);
+    gfx::RectF cell_bounds = waiter.ax_tree()->GetTreeBounds(cell);
+    SCOPED_TRACE("Cell: " + cell_bounds.ToString());
+
+    ui::AXNode* window = cell->parent();
+    while (window && window->data().role != ax::mojom::Role::kWindow)
+      window = window->parent();
+    ASSERT_TRUE(window);
+
+    gfx::RectF window_bounds = waiter.ax_tree()->GetTreeBounds(window);
+    SCOPED_TRACE("Window: " + window_bounds.ToString());
+    SCOPED_TRACE(waiter.ax_tree()->ToString());
+
+    // The cell should have the same x, y as the window (with 1 pixel of slop).
+    // The cell should have a width that's less than or equal to the window
+    // width, and the cell's height should be significantly smaller so we
+    // assert that the cell's height is greater than zero, but less than half
+    // the window height.
+    EXPECT_NEAR(cell_bounds.x(), window_bounds.x(), 1);
+    EXPECT_NEAR(cell_bounds.y(), window_bounds.y(), 1);
+    EXPECT_LE(cell_bounds.width(), window_bounds.width());
+    EXPECT_GT(cell_bounds.height(), 0);
+    EXPECT_LT(cell_bounds.height(), window_bounds.height() / 2);
+  }
+}
+
 IN_PROC_BROWSER_TEST_F(AutomationManagerAuraBrowserTest, EventFromAction) {
   auto cache = std::make_unique<views::AXAuraObjCache>();
   auto* cache_ptr = cache.get();
   AutomationManagerAura* manager = AutomationManagerAura::GetInstance();
   manager->set_ax_aura_obj_cache_for_testing(std::move(cache));
+  AutomationEventWaiter waiter;
   manager->Enable();
 
   views::Widget* widget = new views::Widget;
@@ -373,8 +503,6 @@
   widget->GetRootView()->AddChildView(view2);
   views::AXAuraObjWrapper* wrapper2 = cache_ptr->GetOrCreate(view2);
 
-  AutomationEventWaiter waiter;
-
   // Focus view1, simulating the non-accessibility action, block until we get an
   // accessibility event that shows this view is focused.
   view1->RequestFocus();
diff --git a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.cc b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.cc
index 421d930b..eab0b0f 100644
--- a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.cc
+++ b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.cc
@@ -16,9 +16,8 @@
 
 CredentialLeakDialogControllerImpl::CredentialLeakDialogControllerImpl(
     PasswordsLeakDialogDelegate* delegate,
-    CredentialLeakType leak_type,
-    const GURL& origin)
-    : delegate_(delegate), leak_type_(leak_type), origin_(origin) {}
+    CredentialLeakType leak_type)
+    : delegate_(delegate), leak_type_(leak_type) {}
 
 CredentialLeakDialogControllerImpl::~CredentialLeakDialogControllerImpl() {
   ResetDialog();
@@ -75,7 +74,7 @@
 }
 
 std::u16string CredentialLeakDialogControllerImpl::GetDescription() const {
-  return password_manager::GetDescription(leak_type_, origin_);
+  return password_manager::GetDescription(leak_type_);
 }
 
 std::u16string CredentialLeakDialogControllerImpl::GetTitle() const {
diff --git a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.h b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.h
index 0cad7b9..a0a76349 100644
--- a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.h
+++ b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.h
@@ -19,8 +19,7 @@
  public:
   CredentialLeakDialogControllerImpl(
       PasswordsLeakDialogDelegate* delegate,
-      password_manager::CredentialLeakType leak_type,
-      const GURL& origin);
+      password_manager::CredentialLeakType leak_type);
   ~CredentialLeakDialogControllerImpl() override;
 
   // Pop up the credential leak dialog.
@@ -45,7 +44,6 @@
   CredentialLeakPrompt* credential_leak_dialog_ = nullptr;
   PasswordsLeakDialogDelegate* delegate_;
   const password_manager::CredentialLeakType leak_type_;
-  const GURL origin_;
 
   DISALLOW_COPY_AND_ASSIGN(CredentialLeakDialogControllerImpl);
 };
diff --git a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc
index 9be7003..c024411 100644
--- a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc
+++ b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc
@@ -37,7 +37,7 @@
  public:
   void SetUpController(password_manager::CredentialLeakType leak_type) {
     controller_ = std::make_unique<CredentialLeakDialogControllerImpl>(
-        &ui_controller_mock_, leak_type, GURL("https://example.com"));
+        &ui_controller_mock_, leak_type);
   }
 
   base::HistogramTester& histogram_tester() { return histogram_tester_; }
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
index 4c42da9..d805b7ee 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -282,7 +282,7 @@
     ClearPopUpFlagForBubble();
 
   auto* raw_controller =
-      new CredentialLeakDialogControllerImpl(this, leak_type, origin);
+      new CredentialLeakDialogControllerImpl(this, leak_type);
   dialog_controller_.reset(raw_controller);
   raw_controller->ShowCredentialLeakPrompt(
       CreateCredentialLeakPrompt(raw_controller));
diff --git a/chrome/browser/ui/translate/translate_bubble_model_impl.cc b/chrome/browser/ui/translate/translate_bubble_model_impl.cc
index ed5798b5..d58649e 100644
--- a/chrome/browser/ui/translate/translate_bubble_model_impl.cc
+++ b/chrome/browser/ui/translate/translate_bubble_model_impl.cc
@@ -165,12 +165,18 @@
 }
 
 bool TranslateBubbleModelImpl::IsPageTranslatedInCurrentLanguages() const {
-  const translate::LanguageState& language_state =
+  const translate::LanguageState* language_state =
       ui_delegate_->GetLanguageState();
-  return ui_delegate_->GetSourceLanguageCode() ==
-             language_state.original_language() &&
-         ui_delegate_->GetTargetLanguageCode() ==
-             language_state.current_language();
+  if (language_state) {
+    return ui_delegate_->GetSourceLanguageCode() ==
+               language_state->original_language() &&
+           ui_delegate_->GetTargetLanguageCode() ==
+               language_state->current_language();
+  }
+  // If LanguageState does not exist, it means that TranslateManager has been
+  // destructed. Return true so that callers don't try to kick off any more
+  // translations.
+  return true;
 }
 
 void TranslateBubbleModelImpl::ReportUIInteraction(
diff --git a/chrome/browser/ui/user_education/feature_promo_snooze_service.cc b/chrome/browser/ui/user_education/feature_promo_snooze_service.cc
index f2c12af..e30b3204 100644
--- a/chrome/browser/ui/user_education/feature_promo_snooze_service.cc
+++ b/chrome/browser/ui/user_education/feature_promo_snooze_service.cc
@@ -24,25 +24,37 @@
 // PrefService path.
 const char kIPHSnoozeDataPath[] = "in_product_help.snoozed_feature";
 
-// Path to the boolean indicates if an IPH is dismissed.
+// Path to the boolean indicates if an IPH was dismissed.
 // in_product_help.snoozed_feature.[iph_name].is_dismissed
-constexpr char kIPHIsFeatureDismissed[] = "is_dismissed";
-// Path to the timestamp an IPH is snoozed.
+constexpr char kIPHIsDismissedPath[] = "is_dismissed";
+// Path to the timestamp an IPH was last shown.
+// in_product_help.snoozed_feature.[iph_name].last_show_time
+constexpr char kIPHLastShowTimePath[] = "last_show_time";
+// Path to the timestamp an IPH was last snoozed.
 // in_product_help.snoozed_feature.[iph_name].last_snooze_time
-constexpr char kIPHSnoozedFeatureTime[] = "last_snooze_time";
+constexpr char kIPHLastSnoozeTimePath[] = "last_snooze_time";
 // Path to the duration of snooze.
 // in_product_help.snoozed_feature.[iph_name].last_snooze_duration
-constexpr char kIPHSnoozedFeatureDuration[] = "last_snooze_duration";
+constexpr char kIPHLastSnoozeDurationPath[] = "last_snooze_duration";
 // Path to the count of how many times this IPH has been snoozed.
 // in_product_help.snoozed_feature.[iph_name].snooze_count
-constexpr char kIPHSnoozedFeatureCount[] = "snooze_count";
+constexpr char kIPHSnoozeCountPath[] = "snooze_count";
+// Path to the count of how many times this IPH has been shown.
+// in_product_help.snoozed_feature.[iph_name].show_count
+constexpr char kIPHShowCountPath[] = "show_count";
 
 // Finch parameter to control the snooze duration.
 // If this parameter is not specified or is zero, the default duration at the
 // client side will be used.
 constexpr base::FeatureParam<base::TimeDelta> kOverriddenDuration{
     &feature_engagement::kIPHDesktopSnoozeFeature,
-    "x_iph_snooze_overridden_duration ", base::TimeDelta::FromHours(0)};
+    "x_iph_snooze_overridden_duration", base::TimeDelta::FromHours(0)};
+
+constexpr base::FeatureParam<FeaturePromoSnoozeService::NonClickerPolicy>::
+    Option kNonClickerPolicyOptions[] = {
+        {FeaturePromoSnoozeService::NonClickerPolicy::kDismiss, "dismiss"},
+        {FeaturePromoSnoozeService::NonClickerPolicy::kLongSnooze,
+         "long_snooze"}};
 
 // Used in UMA histogram to track if the user snoozes for once or more.
 enum class SnoozeType {
@@ -101,6 +113,18 @@
       snooze_data->snooze_count, kUmaMaxSnoozeCount);
 }
 
+void FeaturePromoSnoozeService::OnPromoShown(const base::Feature& iph_feature) {
+  auto snooze_data = ReadSnoozeData(iph_feature);
+
+  if (!snooze_data)
+    snooze_data = SnoozeData();
+
+  snooze_data->last_show_time = base::Time::Now();
+  snooze_data->show_count++;
+
+  SaveSnoozeData(iph_feature, *snooze_data);
+}
+
 bool FeaturePromoSnoozeService::IsBlocked(const base::Feature& iph_feature) {
   auto snooze_data = ReadSnoozeData(iph_feature);
 
@@ -111,17 +135,37 @@
   if (snooze_data->is_dismissed)
     return true;
 
-  // This IPH has neither been dismissed nor snoozed.
-  if (snooze_data->snooze_count == 0)
+  // This IPH is shown for the first time.
+  if (snooze_data->show_count == 0)
     return false;
 
-  // Corruption: Snooze time is in the future.
-  if (snooze_data->last_snooze_time > base::Time::Now())
-    return true;
+  if (snooze_data->snooze_count > 0 &&
+      snooze_data->last_snooze_time >= snooze_data->last_show_time) {
+    // The IPH was snoozed on last display.
 
-  // This IPH is snoozed. Test if snooze period has expired.
-  return base::Time::Now() <
-         snooze_data->last_snooze_time + snooze_data->last_snooze_duration;
+    // Corruption: Snooze time is in the future.
+    if (snooze_data->last_snooze_time > base::Time::Now())
+      return true;
+
+    // This IPH is snoozed. Test if snooze period has expired.
+    return base::Time::Now() <
+           snooze_data->last_snooze_time + snooze_data->last_snooze_duration;
+  } else {
+    // The IPH was neither snoozed or dismissed on last display.
+    const base::FeatureParam<FeaturePromoSnoozeService::NonClickerPolicy>
+        kNonClickerPolicy{
+            &iph_feature, "x_iph_snooze_non_clicker_policy",
+            FeaturePromoSnoozeService::NonClickerPolicy::kLongSnooze,
+            &kNonClickerPolicyOptions};
+
+    NonClickerPolicy non_clicker_policy = kNonClickerPolicy.Get();
+
+    if (non_clicker_policy == NonClickerPolicy::kDismiss)
+      return true;
+
+    return base::Time::Now() <
+           snooze_data->last_show_time + base::TimeDelta::FromDays(14);
+  }
 }
 
 // static
@@ -149,13 +193,17 @@
   const base::DictionaryValue* pref_data =
       profile_->GetPrefs()->GetDictionary(kIPHSnoozeDataPath);
   base::Optional<bool> is_dismissed =
-      pref_data->FindBoolPath(path_prefix + kIPHIsFeatureDismissed);
+      pref_data->FindBoolPath(path_prefix + kIPHIsDismissedPath);
+  base::Optional<base::Time> show_time = util::ValueToTime(
+      pref_data->FindPath(path_prefix + kIPHLastShowTimePath));
   base::Optional<base::Time> snooze_time = util::ValueToTime(
-      pref_data->FindPath(path_prefix + kIPHSnoozedFeatureTime));
-  base::Optional<int> snooze_count =
-      pref_data->FindIntPath(path_prefix + kIPHSnoozedFeatureCount);
+      pref_data->FindPath(path_prefix + kIPHLastSnoozeTimePath));
   base::Optional<base::TimeDelta> snooze_duration = util::ValueToTimeDelta(
-      pref_data->FindPath(path_prefix + kIPHSnoozedFeatureDuration));
+      pref_data->FindPath(path_prefix + kIPHLastSnoozeDurationPath));
+  base::Optional<int> snooze_count =
+      pref_data->FindIntPath(path_prefix + kIPHSnoozeCountPath);
+  base::Optional<int> show_count =
+      pref_data->FindIntPath(path_prefix + kIPHShowCountPath);
 
   base::Optional<SnoozeData> snooze_data;
 
@@ -168,11 +216,20 @@
     return snooze_data;
   }
 
+  if (!show_time || !show_count) {
+    // This feature was shipped before without handling
+    // non-clickers. Assume previous displays were all snooozed.
+    show_time = *snooze_time - base::TimeDelta::FromSeconds(1);
+    show_count = *snooze_count;
+  }
+
   snooze_data = SnoozeData();
   snooze_data->is_dismissed = *is_dismissed;
+  snooze_data->last_show_time = *show_time;
   snooze_data->last_snooze_time = *snooze_time;
   snooze_data->last_snooze_duration = *snooze_duration;
   snooze_data->snooze_count = *snooze_count;
+  snooze_data->show_count = *show_count;
 
   return snooze_data;
 }
@@ -185,12 +242,16 @@
   DictionaryPrefUpdate update(profile_->GetPrefs(), kIPHSnoozeDataPath);
   base::DictionaryValue* pref_data = update.Get();
 
-  pref_data->SetBoolPath(path_prefix + kIPHIsFeatureDismissed,
+  pref_data->SetBoolPath(path_prefix + kIPHIsDismissedPath,
                          snooze_data.is_dismissed);
-  pref_data->SetPath(path_prefix + kIPHSnoozedFeatureTime,
+  pref_data->SetPath(path_prefix + kIPHLastShowTimePath,
+                     util::TimeToValue(snooze_data.last_show_time));
+  pref_data->SetPath(path_prefix + kIPHLastSnoozeTimePath,
                      util::TimeToValue(snooze_data.last_snooze_time));
-  pref_data->SetPath(path_prefix + kIPHSnoozedFeatureDuration,
+  pref_data->SetPath(path_prefix + kIPHLastSnoozeDurationPath,
                      util::TimeDeltaToValue(snooze_data.last_snooze_duration));
-  pref_data->SetIntPath(path_prefix + kIPHSnoozedFeatureCount,
+  pref_data->SetIntPath(path_prefix + kIPHSnoozeCountPath,
                         snooze_data.snooze_count);
+  pref_data->SetIntPath(path_prefix + kIPHShowCountPath,
+                        snooze_data.show_count);
 }
diff --git a/chrome/browser/ui/user_education/feature_promo_snooze_service.h b/chrome/browser/ui/user_education/feature_promo_snooze_service.h
index c364f05..3d915e5b 100644
--- a/chrome/browser/ui/user_education/feature_promo_snooze_service.h
+++ b/chrome/browser/ui/user_education/feature_promo_snooze_service.h
@@ -17,14 +17,21 @@
 class Profile;
 class PrefRegistrySimple;
 
-// This service manages snooze and dismiss of in-product help promo.
+// This service manages snooze and dismiss of snoozable in-product help promo.
 //
-// An IPH controller notifies this service when an IPH is snoozed or dismissed.
-// When the snooze period expires, this service will approve controller's
-// request to retrigger the IPH.
-// If an IPH is dismissed, this service will reject controller's request.
+// Before showing an IPH, the IPH controller should ask if the IPH is blocked.
+// The controller should also notify after the IPH is shown and after the user
+// clicks the snooze/dismiss button.
 class FeaturePromoSnoozeService {
  public:
+  // Policies to handler users who don't interact with the IPH.
+  enum class NonClickerPolicy {
+    // Permanently dismiss the IPH. Equivalent to clicking the dismiss button.
+    kDismiss = 0,
+    // Reshow the IPH later after at least 14 days.
+    kLongSnooze
+  };
+
   // Maximum count of snoozes to track in UMA histogram.
   // Snooze counts that are equal or larger than this value will be conflated.
   static const int kUmaMaxSnoozeCount;
@@ -48,6 +55,9 @@
   // after a fixed amount of time.
   void OnUserDismiss(const base::Feature& iph_feature);
 
+  // The IPH controller must call this method after an IPH is shown.
+  void OnPromoShown(const base::Feature& iph_feature);
+
   // The IPH controller must call this method to check if an IPH is blocked by
   // dismiss or snooze. An IPH will be approved if it is not snoozed or the
   // snoozing period has timed out.
@@ -70,9 +80,11 @@
   // in_product_help.snoozed_feature.[iph_name] in PerfService.
   struct SnoozeData {
     bool is_dismissed = false;
+    base::Time last_show_time = base::Time();
     base::Time last_snooze_time = base::Time();
     base::TimeDelta last_snooze_duration = base::TimeDelta();
     int snooze_count = 0;
+    int show_count = 0;
   };
 
   base::Optional<SnoozeData> ReadSnoozeData(const base::Feature& iph_feature);
diff --git a/chrome/browser/ui/user_education/feature_promo_snooze_service_unittest.cc b/chrome/browser/ui/user_education/feature_promo_snooze_service_unittest.cc
index 679f1a2..59bd3c43 100644
--- a/chrome/browser/ui/user_education/feature_promo_snooze_service_unittest.cc
+++ b/chrome/browser/ui/user_education/feature_promo_snooze_service_unittest.cc
@@ -7,9 +7,12 @@
 #include <memory>
 
 #include "base/feature_list.h"
+#include "base/metrics/field_trial_param_associator.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/feature_engagement/public/feature_constants.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -27,19 +30,31 @@
                               MOCK_TIME},
         service_{&profile_} {}
 
+  void SetNonClickerPolicy(base::test::ScopedFeatureList& feature_list,
+                           FeaturePromoSnoozeService::NonClickerPolicy policy) {
+    std::map<std::string, std::string> parameters = {
+        {"x_iph_snooze_non_clicker_policy",
+         policy == FeaturePromoSnoozeService::NonClickerPolicy::kDismiss
+             ? "dismiss"
+             : "long_snooze"}};
+    feature_list.InitAndEnableFeatureWithParameters(kTestIPHFeature,
+                                                    parameters);
+  }
+
  protected:
   content::BrowserTaskEnvironment task_environment_;
   TestingProfile profile_;
   FeaturePromoSnoozeService service_;
 };
 
-TEST_F(FeaturePromoSnoozeServiceTest, AllowNonSnoozedIPH) {
+TEST_F(FeaturePromoSnoozeServiceTest, AllowFirstTimeIPH) {
   service_.Reset(kTestIPHFeature);
   EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature));
 }
 
 TEST_F(FeaturePromoSnoozeServiceTest, BlockDismissedIPH) {
   service_.Reset(kTestIPHFeature);
+  service_.OnPromoShown(kTestIPHFeature);
   service_.OnUserDismiss(kTestIPHFeature);
   EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature));
   service_.Reset(kTestIPHFeature);
@@ -48,12 +63,14 @@
 
 TEST_F(FeaturePromoSnoozeServiceTest, BlockSnoozedIPH) {
   service_.Reset(kTestIPHFeature);
+  service_.OnPromoShown(kTestIPHFeature);
   service_.OnUserSnooze(kTestIPHFeature);
   EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature));
 }
 
 TEST_F(FeaturePromoSnoozeServiceTest, ReleaseSnoozedIPH) {
   service_.Reset(kTestIPHFeature);
+  service_.OnPromoShown(kTestIPHFeature);
   service_.OnUserSnooze(kTestIPHFeature, base::TimeDelta::FromHours(1));
   EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature));
   task_environment_.FastForwardBy(base::TimeDelta::FromHours(2));
@@ -63,7 +80,9 @@
 TEST_F(FeaturePromoSnoozeServiceTest, MultipleIPH) {
   service_.Reset(kTestIPHFeature);
   service_.Reset(kTestIPHFeature2);
+  service_.OnPromoShown(kTestIPHFeature);
   service_.OnUserSnooze(kTestIPHFeature, base::TimeDelta::FromHours(1));
+  service_.OnPromoShown(kTestIPHFeature2);
   service_.OnUserSnooze(kTestIPHFeature2, base::TimeDelta::FromHours(3));
   EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature));
   EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature2));
@@ -74,3 +93,25 @@
   EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature));
   EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature2));
 }
+
+TEST_F(FeaturePromoSnoozeServiceTest, SnoozeNonClicker) {
+  base::test::ScopedFeatureList feature_list;
+  SetNonClickerPolicy(feature_list,
+                      FeaturePromoSnoozeService::NonClickerPolicy::kLongSnooze);
+  service_.Reset(kTestIPHFeature);
+  service_.OnPromoShown(kTestIPHFeature);
+  EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature));
+  task_environment_.FastForwardBy(base::TimeDelta::FromDays(15));
+  EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature));
+}
+
+TEST_F(FeaturePromoSnoozeServiceTest, DismissNonClicker) {
+  base::test::ScopedFeatureList feature_list;
+  SetNonClickerPolicy(feature_list,
+                      FeaturePromoSnoozeService::NonClickerPolicy::kDismiss);
+  service_.Reset(kTestIPHFeature);
+  service_.OnPromoShown(kTestIPHFeature);
+  EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature));
+  task_environment_.FastForwardBy(base::TimeDelta::FromDays(15));
+  EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature));
+}
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble.cc b/chrome/browser/ui/views/accessibility/caption_bubble.cc
index 660ad20..f23a00a 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble.cc
+++ b/chrome/browser/ui/views/accessibility/caption_bubble.cc
@@ -483,7 +483,6 @@
 
   auto label = std::make_unique<CaptionBubbleLabel>();
   label->SetMultiLine(true);
-  label->SetMaximumWidth(kMaxWidthDip - kSidePaddingDip * 2);
   label->SetBackgroundColor(SK_ColorTRANSPARENT);
   label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
   label->SetVerticalAlignment(gfx::VerticalAlignment::ALIGN_TOP);
@@ -821,6 +820,7 @@
   error_text_->SetFontList(font_list);
 
   label_->SetLineHeight(kLineHeightDip * textScaleFactor);
+  label_->SetMaximumWidth(kMaxWidthDip * textScaleFactor - kSidePaddingDip * 2);
   title_->SetLineHeight(kLineHeightDip * textScaleFactor);
   error_text_->SetLineHeight(kLineHeightDip * textScaleFactor);
   error_icon_->SetImageSize(gfx::Size(kErrorImageSizeDip * textScaleFactor,
@@ -865,6 +865,7 @@
 
 void CaptionBubble::UpdateContentSize() {
   double text_scale_factor = GetTextScaleFactor();
+  int width = kMaxWidthDip * text_scale_factor;
   int content_height =
       (model_ && model_->HasError())
           ? kLineHeightDip * text_scale_factor
@@ -873,13 +874,11 @@
   int label_height = title_->GetVisible()
                          ? content_height - kLineHeightDip * text_scale_factor
                          : content_height;
-  label_->SetPreferredSize(
-      gfx::Size(kMaxWidthDip - kSidePaddingDip, label_height));
-  content_container_->SetPreferredSize(gfx::Size(kMaxWidthDip, content_height));
-  SetPreferredSize(
-      gfx::Size(kMaxWidthDip, content_height +
-                                  close_button_->GetPreferredSize().height() +
-                                  expand_button_->GetPreferredSize().height()));
+  label_->SetPreferredSize(gfx::Size(width - kSidePaddingDip, label_height));
+  content_container_->SetPreferredSize(gfx::Size(width, content_height));
+  SetPreferredSize(gfx::Size(
+      width, content_height + close_button_->GetPreferredSize().height() +
+                 expand_button_->GetPreferredSize().height()));
 }
 
 void CaptionBubble::Redraw() {
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
index 09f24be..fedbb59 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
@@ -621,6 +621,7 @@
   int text_size = 16;
   int line_height = 24;
   int bubble_height = 48;
+  int bubble_width = 536;
   int error_icon_height = 20;
   ui::CaptionStyle caption_style;
 
@@ -631,6 +632,7 @@
   EXPECT_EQ(line_height, GetLabel()->GetLineHeight());
   EXPECT_EQ(line_height, GetTitle()->GetLineHeight());
   EXPECT_GT(GetBubble()->GetPreferredSize().height(), bubble_height);
+  EXPECT_EQ(GetBubble()->GetPreferredSize().width(), bubble_width);
 
   // Set the text size to 200%.
   caption_style.text_size = "200%";
@@ -640,6 +642,7 @@
   EXPECT_EQ(line_height * 2, GetLabel()->GetLineHeight());
   EXPECT_EQ(line_height * 2, GetTitle()->GetLineHeight());
   EXPECT_GT(GetBubble()->GetPreferredSize().height(), bubble_height * 2);
+  EXPECT_EQ(GetBubble()->GetPreferredSize().width(), bubble_width * 2);
 
   // Set the text size to the empty string.
   caption_style.text_size = "";
@@ -649,6 +652,7 @@
   EXPECT_EQ(line_height, GetLabel()->GetLineHeight());
   EXPECT_EQ(line_height, GetTitle()->GetLineHeight());
   EXPECT_GT(GetBubble()->GetPreferredSize().height(), bubble_height);
+  EXPECT_EQ(GetBubble()->GetPreferredSize().width(), bubble_width);
 
   // Set the text size to 50% !important.
   caption_style.text_size = "50% !important";
@@ -658,6 +662,7 @@
   EXPECT_EQ(line_height / 2, GetLabel()->GetLineHeight());
   EXPECT_EQ(line_height / 2, GetTitle()->GetLineHeight());
   EXPECT_GT(GetBubble()->GetPreferredSize().height(), bubble_height / 2);
+  EXPECT_EQ(GetBubble()->GetPreferredSize().width(), bubble_width / 2);
 
   // Set the text size to a bad string.
   caption_style.text_size = "Ostriches can run up to 45mph";
@@ -667,6 +672,7 @@
   EXPECT_EQ(line_height, GetLabel()->GetLineHeight());
   EXPECT_EQ(line_height, GetTitle()->GetLineHeight());
   EXPECT_GT(GetBubble()->GetPreferredSize().height(), bubble_height);
+  EXPECT_EQ(GetBubble()->GetPreferredSize().width(), bubble_width);
 
   // Set the caption style to a floating point percent.
   caption_style.text_size = "62.5%";
@@ -676,6 +682,7 @@
   EXPECT_EQ(line_height * 0.625, GetLabel()->GetLineHeight());
   EXPECT_EQ(line_height * 0.625, GetTitle()->GetLineHeight());
   EXPECT_GT(GetBubble()->GetPreferredSize().height(), bubble_height * 0.625);
+  EXPECT_EQ(GetBubble()->GetPreferredSize().width(), bubble_width * 0.625);
 
   // Set the error message.
   caption_style.text_size = "50%";
@@ -684,6 +691,7 @@
   EXPECT_EQ(line_height / 2, GetErrorText()->GetLineHeight());
   EXPECT_EQ(error_icon_height / 2, GetErrorIcon()->GetImageBounds().height());
   EXPECT_GT(GetBubble()->GetPreferredSize().height(), line_height / 2);
+  EXPECT_EQ(GetBubble()->GetPreferredSize().width(), bubble_width / 2);
 }
 
 IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest,
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.mm b/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.mm
index 85b2f86..3aa8f82 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.mm
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.mm
@@ -57,6 +57,11 @@
   return self;
 }
 
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  [super dealloc];
+}
+
 - (void)onWindowWillStartLiveResize:(NSNotification*)notification {
   _nativeAppWindow->OnWindowWillStartLiveResize();
 }
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
index e8ef045..e39c073 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
@@ -37,6 +37,7 @@
   menu_button_controller_ = menu_button_controller.get();
   SetButtonController(std::move(menu_button_controller));
   SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_EXTENSIONS_BUTTON));
+  SetVectorIcon(vector_icons::kExtensionIcon);
   button_controller()->set_notify_action(
       views::ButtonController::NotifyAction::kOnPress);
   GetViewAccessibility().OverrideHasPopup(ax::mojom::HasPopup::kMenu);
@@ -83,10 +84,17 @@
 }
 
 void ExtensionsToolbarButton::UpdateIcon() {
-  SetImageModel(views::Button::STATE_NORMAL,
-                ui::ImageModel::FromVectorIcon(
-                    vector_icons::kExtensionIcon,
-                    extensions_container_->GetIconColor(), GetIconSize()));
+  if (browser_->app_controller()) {
+    // TODO(pbos): Remove this once PWAs have ThemeProvider color support for it
+    // and ToolbarButton can pick up icon sizes outside of a static lookup.
+    SetImageModel(views::Button::STATE_NORMAL,
+                  ui::ImageModel::FromVectorIcon(
+                      vector_icons::kExtensionIcon,
+                      extensions_container_->GetIconColor(), GetIconSize()));
+    return;
+  }
+
+  ToolbarButton::UpdateIcon();
 }
 
 void ExtensionsToolbarButton::OnWidgetDestroying(views::Widget* widget) {
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc
index 5aff6e5..6a36539 100644
--- a/chrome/browser/ui/views/frame/browser_frame.cc
+++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -46,6 +46,7 @@
 // of lacros-chrome is complete.
 #if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "ui/display/screen.h"
+#include "ui/views/linux_ui/linux_ui.h"
 #endif
 
 namespace {
@@ -112,6 +113,7 @@
   }
 
   Init(std::move(params));
+  SelectNativeTheme();
 
   if (!native_browser_frame_->UsesNativeSystemMenu()) {
     DCHECK(non_client_view());
@@ -178,6 +180,26 @@
   browser_frame_view_->OnBrowserViewInitViewsComplete();
 }
 
+void BrowserFrame::UserChangedTheme(BrowserThemeChangeType theme_change_type) {
+  // kWebAppTheme is triggered by web apps and will only change colors, not the
+  // frame type; just refresh the theme on all views in the browser window.
+  if (theme_change_type == BrowserThemeChangeType::kWebAppTheme) {
+    ThemeChanged();
+    return;
+  }
+
+  // When the browser theme changes, the NativeTheme may also change.
+  // In Incognito, the usage of dark or normal hinges on the browser theme.
+  if (theme_change_type == BrowserThemeChangeType::kBrowserTheme)
+    SelectNativeTheme();
+
+  if (!RegenerateFrameOnThemeChange(theme_change_type)) {
+    // If RegenerateFrame() returns true, ThemeChanged() was implicitly called,
+    // so no need to call it explicitly.
+    ThemeChanged();
+  }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserFrame, views::Widget overrides:
 
@@ -206,15 +228,6 @@
   return &ThemeService::GetThemeProviderForProfile(browser->profile());
 }
 
-const ui::NativeTheme* BrowserFrame::GetNativeTheme() const {
-  if (browser_view_->browser()->profile()->IsIncognitoProfile() &&
-      ThemeServiceFactory::GetForProfile(browser_view_->browser()->profile())
-          ->UsingDefaultTheme()) {
-    return ui::NativeTheme::GetInstanceForDarkUI();
-  }
-  return views::Widget::GetNativeTheme();
-}
-
 void BrowserFrame::OnNativeWidgetWorkspaceChanged() {
   chrome::SaveWindowWorkspace(browser_view_->browser(), GetWorkspace());
   chrome::SaveWindowVisibleOnAllWorkspaces(browser_view_->browser(),
@@ -234,13 +247,6 @@
   Widget::OnNativeWidgetWorkspaceChanged();
 }
 
-void BrowserFrame::PropagateNativeThemeChanged() {
-  // Instead of immediately propagating the native theme change to the root
-  // view, use BrowserView's custom handling, which may regenerate the frame
-  // first, then propgate the theme change to the root view automatically.
-  browser_view_->UserChangedTheme(BrowserThemeChangeType::kNativeTheme);
-}
-
 void BrowserFrame::ShowContextMenuForViewImpl(views::View* source,
                                               const gfx::Point& p,
                                               ui::MenuSourceType source_type) {
@@ -330,3 +336,56 @@
   }
   GetRootView()->Layout();
 }
+
+void BrowserFrame::SelectNativeTheme() {
+  // Select between regular, dark and GTK theme.
+  ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
+
+  if (browser_view_->browser()->profile()->IsIncognitoProfile() &&
+      ThemeServiceFactory::GetForProfile(browser_view_->browser()->profile())
+          ->UsingDefaultTheme()) {
+    native_theme = ui::NativeTheme::GetInstanceForDarkUI();
+  }
+
+#if defined(OS_LINUX) || defined(IS_CHROMEOS_LACROS)
+  const views::LinuxUI* linux_ui = views::LinuxUI::instance();
+  if (linux_ui)
+    native_theme = linux_ui->GetNativeTheme(GetNativeWindow());
+#endif
+
+  SetNativeTheme(native_theme);
+}
+
+bool BrowserFrame::RegenerateFrameOnThemeChange(
+    BrowserThemeChangeType theme_change_type) {
+  bool need_regenerate = false;
+  // TODO(crbug.com/1052397): Revisit the macro expression once build flag
+  // switch of lacros-chrome is complete.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+  // GTK and user theme changes can both change frame buttons, so the frame
+  // always needs to be regenerated on Linux.
+  need_regenerate = true;
+#endif
+
+#if defined(OS_WIN)
+  // On Windows, DWM transition does not performed for a frame regeneration in
+  // fullscreen mode, so do a lighweight theme change to refresh a bookmark bar
+  // on new tab. (see crbug/1002480)
+  need_regenerate |=
+      theme_change_type == BrowserThemeChangeType::kBrowserTheme &&
+      !IsFullscreen();
+#else
+  need_regenerate |= theme_change_type == BrowserThemeChangeType::kBrowserTheme;
+#endif
+
+  if (need_regenerate) {
+    // This is a heavyweight theme change that requires regenerating the frame
+    // as well as repainting the browser window.
+    // No need to call ThemeChanged(). It will be implicitly called by
+    // FrameTypeChanged().
+    FrameTypeChanged();
+    return true;
+  }
+
+  return false;
+}
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h
index 050c0e05..0ce7abd 100644
--- a/chrome/browser/ui/views/frame/browser_frame.h
+++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -8,6 +8,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "content/public/browser/keyboard_event_processing_result.h"
 #include "ui/base/pointer/touch_ui_controller.h"
 #include "ui/views/context_menu_controller.h"
@@ -111,6 +112,10 @@
   // Called when BrowserView creates all it's child views.
   void OnBrowserViewInitViewsComplete();
 
+  // ThemeService calls this when a user has changed their theme, indicating
+  // that it's time to redraw everything.
+  void UserChangedTheme(BrowserThemeChangeType theme_change_type);
+
   // views::Widget:
   views::internal::RootView* CreateRootView() override;
   std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView()
@@ -118,9 +123,7 @@
   bool GetAccelerator(int command_id,
                       ui::Accelerator* accelerator) const override;
   const ui::ThemeProvider* GetThemeProvider() const override;
-  const ui::NativeTheme* GetNativeTheme() const override;
   void OnNativeWidgetWorkspaceChanged() override;
-  void PropagateNativeThemeChanged() override;
 
   // views::ContextMenuController:
   void ShowContextMenuForViewImpl(views::View* source,
@@ -149,6 +152,13 @@
   // Callback for MenuRunner.
   void OnMenuClosed();
 
+  // Select a native theme that is appropriate for the current context.
+  void SelectNativeTheme();
+
+  // Regenerate the frame on theme change if necessary. Returns true if
+  // regenerated.
+  bool RegenerateFrameOnThemeChange(BrowserThemeChangeType theme_change_type);
+
   NativeBrowserFrame* native_browser_frame_;
 
   // A weak reference to the root view associated with the window. We save a
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 3c6d18bb..289d702 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1922,68 +1922,8 @@
 }
 
 void BrowserView::UserChangedTheme(BrowserThemeChangeType theme_change_type) {
-  // kWebAppTheme is triggered by web apps and will only change colors, not the
-  // frame type; just refresh the theme on all views in the browser window.
-  if (theme_change_type == BrowserThemeChangeType::kWebAppTheme) {
-    GetWidget()->ThemeChanged();
-    return;
-  }
-
-  // When the browser theme changes, the NativeTheme may also change.
-  // In Incognito, the usage of dark or normal hinges on the browser theme.
-  if (theme_change_type == BrowserThemeChangeType::kBrowserTheme &&
-      !GetRegularOrGuestSession()) {
-    ui::NativeTheme::GetInstanceForDarkUI()->NotifyOnNativeThemeUpdated();
-    ui::NativeTheme::GetInstanceForNativeUi()->NotifyOnNativeThemeUpdated();
-
-    // Early exit. A native theme change will update all the
-    // NativeThemeObservers, and then BrowserFrame will re-enter this method
-    // with |theme_change_type| == kNativeTheme, doing all the below things.
-    return;
-  }
-
-  // When the native theme changes in a way that doesn't change the frame type
-  // required, we can skip a frame regeneration. Frame regeneration can cause
-  // visible flicker (see crbug/945138) so it's best avoided if all that has
-  // changed is, for example, the titlebar color, or the user has switched from
-  // light to dark mode.
-  const bool should_use_native_frame = frame_->ShouldUseNativeFrame();
-
-  bool must_regenerate_frame;
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
-  // GTK and user theme changes can both change frame buttons, so the frame
-  // always needs to be regenerated on Linux.
-  must_regenerate_frame = true;
-#else
-  must_regenerate_frame = using_native_frame_ != should_use_native_frame;
-#endif
-
-#if defined(OS_WIN)
-  // On Windows, DWM transtion does not performed for a frame regeneration in
-  // fullscreen mode, so do a lighweight theme change to refresh a bookmark bar
-  // on new tab. (see crbug/1002480)
-  must_regenerate_frame |=
-      theme_change_type == BrowserThemeChangeType::kBrowserTheme &&
-      !IsFullscreen();
-#else
-  must_regenerate_frame |=
-      theme_change_type == BrowserThemeChangeType::kBrowserTheme;
-#endif
-
-  if (must_regenerate_frame) {
-    // This is a heavyweight theme change that requires regenerating the frame
-    // as well as repainting the browser window.
-    frame_->FrameTypeChanged();
-  } else {
-    // This is a lightweight theme change, so just refresh the theme on all
-    // views in the browser window.
-    GetWidget()->ThemeChanged();
-  }
-  using_native_frame_ = should_use_native_frame;
+  frame()->UserChangedTheme(theme_change_type);
 }
-
 void BrowserView::ShowAppMenu() {
   if (!toolbar_button_provider_->GetAppMenuButton())
     return;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
index d9c08b1..45fcbc8 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
@@ -34,6 +34,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/accessibility/accessibility_switches.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_node_data.h"
@@ -698,7 +699,7 @@
   // Kill the tab with chrome://kill
   {
     content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
-    ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUIKillURL));
+    ui_test_utils::NavigateToURL(browser(), GURL(blink::kChromeUIKillURL));
     EXPECT_TRUE(tab->IsCrashed());
   }
 
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index d1c84d1..8d8daaa 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -885,10 +885,6 @@
     move_loop_widget_ = nullptr;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
     views::Widget* browser_widget = GetAttachedBrowserWidget();
-    // Need to release the drag controller before starting the move loop as it's
-    // going to trigger capture lost, which cancels drag.
-    attached_context_->ReleaseDragController();
-    target_context->OwnDragController(this);
     // Disable animations so that we don't see a close animation on aero.
     browser_widget->SetVisibilityChangedAnimationsEnabled(false);
     if (can_release_capture_)
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index 383a453..bdd38180 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -314,14 +314,17 @@
                                           SkColor hovered_color,
                                           SkColor pressed_color,
                                           SkColor disabled_color) {
+  const int icon_size = ui::TouchUiController::Get()->touch_ui()
+                            ? kDefaultTouchableIconSize
+                            : kDefaultIconSize;
   SetImageModel(ButtonState::STATE_NORMAL,
-                ui::ImageModel::FromVectorIcon(icon, normal_color));
+                ui::ImageModel::FromVectorIcon(icon, normal_color, icon_size));
   SetImageModel(ButtonState::STATE_HOVERED,
-                ui::ImageModel::FromVectorIcon(icon, hovered_color));
+                ui::ImageModel::FromVectorIcon(icon, hovered_color, icon_size));
   SetImageModel(ButtonState::STATE_PRESSED,
-                ui::ImageModel::FromVectorIcon(icon, pressed_color));
-  SetImageModel(Button::STATE_DISABLED,
-                ui::ImageModel::FromVectorIcon(icon, disabled_color));
+                ui::ImageModel::FromVectorIcon(icon, pressed_color, icon_size));
+  SetImageModel(Button::STATE_DISABLED, ui::ImageModel::FromVectorIcon(
+                                            icon, disabled_color, icon_size));
 }
 
 void ToolbarButton::SetVectorIcon(const gfx::VectorIcon& icon) {
@@ -336,6 +339,9 @@
 }
 
 void ToolbarButton::UpdateIcon() {
+  // TODO(pbos): See if the default can turn into a DCHECK, if we don't provide
+  // vector icons we need to override this to properly update icons. This is a
+  // foot shooter.
   if (vector_icons_) {
     UpdateIconsWithStandardColors(ui::TouchUiController::Get()->touch_ui()
                                       ? vector_icons_->touch_icon
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 616fc04..cb170e02 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -143,7 +143,6 @@
     return extensions_container_;
   }
   ExtensionsToolbarButton* GetExtensionsButton() const;
-  ToolbarButton* back_button() const { return back_; }
   ReloadButton* reload_button() const { return reload_; }
   LocationBarView* location_bar() const { return location_bar_; }
   CustomTabBarView* custom_tab_bar() { return custom_tab_bar_; }
diff --git a/chrome/browser/ui/views/user_education/feature_promo_controller_views.cc b/chrome/browser/ui/views/user_education/feature_promo_controller_views.cc
index 603f3042..a241169 100644
--- a/chrome/browser/ui/views/user_education/feature_promo_controller_views.cc
+++ b/chrome/browser/ui/views/user_education/feature_promo_controller_views.cc
@@ -242,6 +242,8 @@
                                 snooze_count,
                                 snooze_service_->kUmaMaxSnoozeCount);
 
+  snooze_service_->OnPromoShown(iph_feature);
+
   ShowPromoBubbleImpl(params);
   close_callback_ = std::move(close_callback);
 
diff --git a/chrome/browser/ui/views/user_education/feature_promo_registry.cc b/chrome/browser/ui/views/user_education/feature_promo_registry.cc
index 6c037d7..4c885237 100644
--- a/chrome/browser/ui/views/user_education/feature_promo_registry.cc
+++ b/chrome/browser/ui/views/user_education/feature_promo_registry.cc
@@ -178,7 +178,7 @@
     params.body_string_specifier = IDS_TAB_GROUPS_NEW_GROUP_PROMO;
     params.arrow = views::BubbleBorder::TOP_LEFT;
 
-    // Turn on IPH Snooze only for Tab Group.
+    // Turn on IPH Snooze for Tab Group.
     if (base::FeatureList::IsEnabled(
             feature_engagement::kIPHDesktopSnoozeFeature)) {
       params.allow_focus = true;
@@ -232,6 +232,14 @@
     params.body_string_specifier = IDS_READING_LIST_ENTRY_POINT_PROMO;
     params.arrow = views::BubbleBorder::TOP_RIGHT;
 
+    // Turn on IPH Snooze for Read Later entry point.
+    if (base::FeatureList::IsEnabled(
+            feature_engagement::kIPHDesktopSnoozeFeature)) {
+      params.allow_focus = true;
+      params.persist_on_blur = true;
+      params.allow_snooze = true;
+    }
+
     RegisterFeature(feature_engagement::kIPHReadingListEntryPointFeature,
                     params, base::BindRepeating(GetReadingListStarView));
   }
diff --git a/chrome/browser/ui/views/user_education/feature_promo_snooze_interactive_uitest.cc b/chrome/browser/ui/views/user_education/feature_promo_snooze_interactive_uitest.cc
index 74fa032..c522445 100644
--- a/chrome/browser/ui/views/user_education/feature_promo_snooze_interactive_uitest.cc
+++ b/chrome/browser/ui/views/user_education/feature_promo_snooze_interactive_uitest.cc
@@ -83,7 +83,10 @@
 
   void CheckSnoozePrefs(const base::Feature& iph_feature,
                         bool is_dismissed,
+                        int show_count,
                         int snooze_count,
+                        base::Time last_show_time_min,
+                        base::Time last_show_time_max,
                         base::Time last_snooze_time_min,
                         base::Time last_snooze_time_max) {
     auto data = snooze_service_->ReadSnoozeData(iph_feature);
@@ -92,8 +95,15 @@
     ASSERT_TRUE(data.has_value());
 
     EXPECT_EQ(data->is_dismissed, is_dismissed);
+    EXPECT_EQ(data->show_count, show_count);
     EXPECT_EQ(data->snooze_count, snooze_count);
 
+    // last_show_time is only meaningful if a show has occurred.
+    if (data->show_count > 0) {
+      EXPECT_GE(data->last_show_time, last_show_time_min);
+      EXPECT_LE(data->last_show_time, last_show_time_max);
+    }
+
     // last_snooze_time is only meaningful if a snooze has occurred.
     if (data->snooze_count > 0) {
       EXPECT_GE(data->last_snooze_time, last_snooze_time_min);
@@ -103,12 +113,18 @@
 
   void SetSnoozePrefs(const base::Feature& iph_feature,
                       bool is_dismissed,
+                      base::Optional<int> show_count,
                       int snooze_count,
+                      base::Optional<base::Time> last_show_time,
                       base::Time last_snooze_time,
                       base::TimeDelta last_snooze_duration) {
     FeaturePromoSnoozeService::SnoozeData data;
     data.is_dismissed = is_dismissed;
+    if (show_count)
+      data.show_count = *show_count;
     data.snooze_count = snooze_count;
+    if (last_show_time)
+      data.last_show_time = *last_show_time;
     data.last_snooze_time = last_snooze_time;
     data.last_snooze_duration = last_snooze_duration;
     snooze_service_->SaveSnoozeData(iph_feature, data);
@@ -188,17 +204,27 @@
 
 IN_PROC_BROWSER_TEST_F(FeaturePromoSnoozeInteractiveTest,
                        DismissDoesNotSnooze) {
+  base::Time show_time_min = base::Time::Now();
   ASSERT_NO_FATAL_FAILURE(AttemptTabGroupsIPH(true));
+  base::Time show_time_max = base::Time::Now();
 
   FeaturePromoBubbleView* promo = promo_controller_->promo_bubble_for_testing();
   ClickButton(GetDismissButtonForTesting(promo));
   CheckSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
-                   true, 0, base::Time(), base::Time());
+                   /* is_dismiss */ true,
+                   /* show_count */ 1,
+                   /* snooze_count */ 0,
+                   /* last_show_time_min */ show_time_min,
+                   /* last_show_time_max */ show_time_max,
+                   /* last_snooze_time_min */ base::Time(),
+                   /* last_snooze_time_max */ base::Time());
 }
 
 IN_PROC_BROWSER_TEST_F(FeaturePromoSnoozeInteractiveTest,
                        SnoozeSetsCorrectTime) {
+  base::Time show_time_min = base::Time::Now();
   ASSERT_NO_FATAL_FAILURE(AttemptTabGroupsIPH(true));
+  base::Time show_time_max = base::Time::Now();
 
   FeaturePromoBubbleView* promo = promo_controller_->promo_bubble_for_testing();
 
@@ -207,17 +233,31 @@
   base::Time snooze_time_max = base::Time::Now();
 
   CheckSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
-                   false, 1, snooze_time_min, snooze_time_max);
+                   /* is_dismiss */ false,
+                   /* show_count */ 1,
+                   /* snooze_count */ 1,
+                   /* last_show_time_min */ show_time_min,
+                   /* last_show_time_max */ show_time_max,
+                   /* last_snooze_time_min */ snooze_time_min,
+                   /* last_snooze_time_max */ snooze_time_max);
 }
 
 IN_PROC_BROWSER_TEST_F(FeaturePromoSnoozeInteractiveTest, CanReSnooze) {
   // Simulate the user snoozing the IPH.
   base::TimeDelta snooze_duration = base::TimeDelta::FromHours(26);
   base::Time snooze_time = base::Time::Now() - snooze_duration;
-  SetSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature, false,
-                 1, snooze_time, snooze_duration);
+  base::Time show_time = snooze_time - base::TimeDelta::FromSeconds(1);
+  SetSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
+                 /* is_dismiss */ false,
+                 /* show_count */ 1,
+                 /* snooze_count */ 1,
+                 /* last_show_time */ show_time,
+                 /* last_snooze_time */ snooze_time,
+                 /* last_snooze_duration */ snooze_duration);
 
+  base::Time show_time_min = base::Time::Now();
   ASSERT_NO_FATAL_FAILURE(AttemptTabGroupsIPH(true));
+  base::Time show_time_max = base::Time::Now();
 
   FeaturePromoBubbleView* promo = promo_controller_->promo_bubble_for_testing();
 
@@ -226,14 +266,25 @@
   base::Time snooze_time_max = base::Time::Now();
 
   CheckSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
-                   false, 2, snooze_time_min, snooze_time_max);
+                   /* is_dismiss */ false,
+                   /* show_count */ 2,
+                   /* snooze_count */ 2,
+                   /* last_show_time_min */ show_time_min,
+                   /* last_show_time_max */ show_time_max,
+                   /* last_snooze_time_min */ snooze_time_min,
+                   /* last_snooze_time_max */ snooze_time_max);
 }
 
 IN_PROC_BROWSER_TEST_F(FeaturePromoSnoozeInteractiveTest,
                        DoesNotShowIfDismissed) {
   // Simulate the user dismissing the IPH.
-  SetSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature, true,
-                 0, base::Time(), base::TimeDelta());
+  SetSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
+                 /* is_dismiss */ true,
+                 /* show_count */ 1,
+                 /* snooze_count */ 0,
+                 /* last_show_time */ base::Time(),
+                 /* last_snooze_time */ base::Time(),
+                 /* last_snooze_duration */ base::TimeDelta());
 
   AttemptTabGroupsIPH(false);
 }
@@ -243,29 +294,69 @@
   // Simulate a very recent snooze.
   base::TimeDelta snooze_duration = base::TimeDelta::FromHours(26);
   base::Time snooze_time = base::Time::Now();
-  SetSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature, false,
-                 1, snooze_time, snooze_duration);
+  base::Time show_time = snooze_time - base::TimeDelta::FromSeconds(1);
+  SetSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
+                 /* is_dismiss */ false,
+                 /* show_count */ 1,
+                 /* snooze_count */ 1,
+                 /* last_show_time */ show_time,
+                 /* last_snooze_time */ snooze_time,
+                 /* last_snooze_duration */ snooze_duration);
 
   AttemptTabGroupsIPH(false);
 }
 
 IN_PROC_BROWSER_TEST_F(FeaturePromoSnoozeInteractiveTest,
-                       CloseBubbleSetsNoPrefs) {
+                       CloseBubbleSetsPrefs) {
+  base::Time show_time_min = base::Time::Now();
   ASSERT_NO_FATAL_FAILURE(AttemptTabGroupsIPH(true));
+  base::Time show_time_max = base::Time::Now();
 
   promo_controller_->CloseBubble(
       feature_engagement::kIPHDesktopTabGroupsNewGroupFeature);
-  EXPECT_FALSE(
-      HasSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature));
+
+  CheckSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
+                   /* is_dismiss */ false,
+                   /* show_count */ 1,
+                   /* snooze_count */ 0,
+                   /* last_show_time_min */ show_time_min,
+                   /* last_show_time_max */ show_time_max,
+                   /* last_snooze_time_min */ base::Time(),
+                   /* last_snooze_time_max */ base::Time());
 }
 
 IN_PROC_BROWSER_TEST_F(FeaturePromoSnoozeInteractiveTest,
-                       WidgetCloseSetsNoPrefs) {
+                       WidgetCloseSetsPrefs) {
+  base::Time show_time_min = base::Time::Now();
   ASSERT_NO_FATAL_FAILURE(AttemptTabGroupsIPH(true));
+  base::Time show_time_max = base::Time::Now();
 
   FeaturePromoBubbleView* promo = promo_controller_->promo_bubble_for_testing();
   promo->GetWidget()->CloseWithReason(
       views::Widget::ClosedReason::kEscKeyPressed);
-  EXPECT_FALSE(
-      HasSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature));
+  CheckSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
+                   /* is_dismiss */ false,
+                   /* show_count */ 1,
+                   /* snooze_count */ 0,
+                   /* last_show_time_min */ show_time_min,
+                   /* last_show_time_max */ show_time_max,
+                   /* last_snooze_time_min */ base::Time(),
+                   /* last_snooze_time_max */ base::Time());
+}
+
+IN_PROC_BROWSER_TEST_F(FeaturePromoSnoozeInteractiveTest,
+                       WorkWithoutNonClickerData) {
+  // Non-clicker policy shipped pref entries that don't exist before.
+  // Make sure empty entries are properly handled.
+  base::TimeDelta snooze_duration = base::TimeDelta::FromHours(26);
+  base::Time snooze_time = base::Time::Now() - snooze_duration;
+  SetSnoozePrefs(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
+                 /* is_dismiss */ false,
+                 /* show_count */ base::nullopt,
+                 /* snooze_count */ 1,
+                 /* last_show_time */ base::nullopt,
+                 /* last_snooze_time */ snooze_time,
+                 /* last_snooze_duration */ snooze_duration);
+
+  AttemptTabGroupsIPH(true);
 }
diff --git a/chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_browsertest.cc b/chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_browsertest.cc
index b4261ae..be508bc 100644
--- a/chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_browsertest.cc
@@ -12,9 +12,9 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h"
 #include "chrome/browser/ash/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/ash/login/test/logged_in_user_mixin.h"
-#include "chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/supervised_user/supervised_user_features.h"
diff --git a/chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_chromeos.cc b/chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_chromeos.cc
index e37f364..47ae89d4 100644
--- a/chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/chromeos/edu_coexistence/edu_coexistence_login_handler_chromeos.cc
@@ -19,10 +19,10 @@
 #include "base/system/sys_info.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h"
 #include "chrome/browser/ash/login/login_pref_names.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
-#include "chrome/browser/chromeos/child_accounts/edu_coexistence_tos_store_utils.h"
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/ui/webui/memories/memories.mojom b/chrome/browser/ui/webui/memories/memories.mojom
index aee3e02..7451d63 100644
--- a/chrome/browser/ui/webui/memories/memories.mojom
+++ b/chrome/browser/ui/webui/memories/memories.mojom
@@ -27,9 +27,12 @@
   // The MemoriesBrowserProxy singleton calls this when it's first initialized.
   SetPage(pending_remote<Page> page);
 
-  // Return memories related to |query| created from the user visit history.
-  // Note: Returns mock memories in non-official builds.
-  QueryMemories(string query) => (MemoriesResult result);
+  // Returns sample Memories related to |query| for experimentation with a POC.
+  // TODO(crbug.com/1179069): Remove this when real Memories are available.
+  GetSampleMemories(string query) => (MemoriesResult result);
+
+  // Return memories related to visit history.
+  GetMemories() => (MemoriesResult memories);
 };
 
 // WebUI-side handler for requests from the browser.
diff --git a/chrome/browser/ui/webui/memories/memories_handler.cc b/chrome/browser/ui/webui/memories/memories_handler.cc
index 1c76725..ca1e9e0 100644
--- a/chrome/browser/ui/webui/memories/memories_handler.cc
+++ b/chrome/browser/ui/webui/memories/memories_handler.cc
@@ -15,7 +15,7 @@
 #include "content/public/browser/web_contents.h"
 #include "url/gurl.h"
 
-#if !defined(CHROME_BRANDED)
+#if !defined(OFFICIAL_BUILD)
 #include "base/bind.h"
 #include "base/containers/contains.h"
 #include "base/i18n/case_conversion.h"
@@ -69,19 +69,22 @@
   page_.Bind(std::move(pending_page));
 }
 
-void MemoriesHandler::QueryMemories(const std::string& query,
-                                    QueryMemoriesCallback callback) {
-  auto termination_callback = base::BindOnce(
-      &MemoriesHandler::OnMemoriesQueryResults, weak_ptr_factory_.GetWeakPtr(),
-      std::move(callback), query);
-  if (memories::RemoteModelEndpoint().is_valid()) {
-    auto* memory_service =
-        MemoriesServiceFactory::GetForBrowserContext(profile_);
-    memory_service->QueryMemories(query, std::move(termination_callback));
-  } else {
-#if defined(CHROME_BRANDED)
-    std::move(callback).Run(memories::mojom::MemoriesResult::New());
+void MemoriesHandler::GetSampleMemories(const std::string& query,
+                                        MemoriesResultCallback callback) {
+#if defined(OFFICIAL_BUILD)
+  auto memories_result_mojom = memories::mojom::MemoriesResult::New();
+  std::move(callback).Run(std::move(memories_result_mojom));
+  return;
 #else
+  // If the query is empty and a remote model endpoint is set, then ask the
+  // MemoriesService for memories. The MemoriesService doesn't yet support
+  // filtering memories by query or an on-client clustering, so if either the
+  // query is non-empty or the endpoint is not set, fallback to sample memories
+  // from history.
+  if (query.empty() && memories::RemoteModelEndpoint().is_valid()) {
+    GetMemories(std::move(callback));
+  } else {
+    // Query HistoryService for URLs containing |query|.
     history::HistoryService* history_service =
         HistoryServiceFactory::GetForProfile(
             profile_, ServiceAccessType::EXPLICIT_ACCESS);
@@ -91,33 +94,24 @@
     history_service->QueryHistory(
         base::UTF8ToUTF16(query), query_options,
         base::BindOnce(&MemoriesHandler::OnHistoryQueryResults,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       std::move(termination_callback)),
+                       weak_ptr_factory_.GetWeakPtr(), query,
+                       std::move(callback)),
         &history_task_tracker_);
-#endif
   }
 }
 
-void MemoriesHandler::OnMemoriesQueryResults(
-    QueryMemoriesCallback callback,
-    const std::string& query,
-    std::vector<memories::mojom::MemoryPtr> memory_mojoms) {
-  auto result_mojom = memories::mojom::MemoriesResult::New();
-  result_mojom->title = base::UTF8ToUTF16(query);
-  result_mojom->thumbnail_url = GetRandomlySizedThumbnailUrl();
-  result_mojom->memories = std::move(memory_mojoms);
-  std::move(callback).Run(std::move(result_mojom));
-}
-
-#if !defined(CHROME_BRANDED)
-void MemoriesHandler::OnHistoryQueryResults(
-    MemoriesQueryResultsCallback callback,
-    history::QueryResults results) {
+void MemoriesHandler::OnHistoryQueryResults(const std::string& query,
+                                            MemoriesResultCallback callback,
+                                            history::QueryResults results) {
+  auto memories_result_mojom = memories::mojom::MemoriesResult::New();
   if (results.empty()) {
-    std::move(callback).Run({});
+    std::move(callback).Run(std::move(memories_result_mojom));
     return;
   }
 
+  memories_result_mojom->title = base::UTF8ToUTF16(query);
+  memories_result_mojom->thumbnail_url = GetRandomlySizedThumbnailUrl();
+
   auto memory_mojom = memories::mojom::Memory::New();
   memory_mojom->id = base::UnguessableToken::Create();
 
@@ -266,8 +260,17 @@
     }
   }
 
-  std::vector<memories::mojom::MemoryPtr> memory_mojoms;
-  memory_mojoms.push_back(std::move(memory_mojom));
-  std::move(callback).Run(std::move(memory_mojoms));
-}
+  memories_result_mojom->memories.push_back(std::move(memory_mojom));
+  std::move(callback).Run(std::move(memories_result_mojom));
 #endif
+}
+
+void MemoriesHandler::GetMemories(MemoriesResultCallback callback) {
+  auto* memory_service = MemoriesServiceFactory::GetForBrowserContext(profile_);
+  memory_service->GetMemories(base::BindOnce([](memories::Memories memories) {
+                                auto result =
+                                    memories::mojom::MemoriesResult::New();
+                                result->memories = std::move(memories);
+                                return result;
+                              }).Then(std::move(callback)));
+}
diff --git a/chrome/browser/ui/webui/memories/memories_handler.h b/chrome/browser/ui/webui/memories/memories_handler.h
index 0f811bb4..ed4cd8e2 100644
--- a/chrome/browser/ui/webui/memories/memories_handler.h
+++ b/chrome/browser/ui/webui/memories/memories_handler.h
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "chrome/browser/ui/webui/memories/memories.mojom.h"
 #include "components/history_clusters/core/memories.mojom.h"
+#include "components/history_clusters/core/memories_remote_model_helper.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -47,19 +48,18 @@
   // memories::mojom::PageHandler:
   void SetPage(
       mojo::PendingRemote<memories::mojom::Page> pending_page) override;
-  void QueryMemories(const std::string& query,
-                     QueryMemoriesCallback callback) override;
+
+  using MemoriesResultCallback =
+      base::OnceCallback<void(memories::mojom::MemoriesResultPtr)>;
+  void GetSampleMemories(const std::string& query,
+                         MemoriesResultCallback callback) override;
+
+  void GetMemories(MemoriesResultCallback callback) override;
 
  private:
-  void OnMemoriesQueryResults(
-      QueryMemoriesCallback callback,
-      const std::string& query,
-      std::vector<memories::mojom::MemoryPtr> memory_mojoms);
-
 #if !defined(OFFICIAL_BUILD)
-  using MemoriesQueryResultsCallback =
-      base::OnceCallback<void(std::vector<memories::mojom::MemoryPtr>)>;
-  void OnHistoryQueryResults(MemoriesQueryResultsCallback callback,
+  void OnHistoryQueryResults(const std::string& query,
+                             MemoriesResultCallback callback,
                              history::QueryResults results);
 #endif
 
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc b/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc
index 89e4176..c04adf1 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc
@@ -19,6 +19,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "url/gurl.h"
 
 using content::OpenURLParams;
@@ -79,7 +80,7 @@
 
   // Navigate to chrome://hang/ to stall the process.
   ui_test_utils::NavigateToURLWithDisposition(
-      browser(), GURL(content::kChromeUIHangURL),
+      browser(), GURL(blink::kChromeUIHangURL),
       WindowOpenDisposition::CURRENT_TAB, 0);
 
   // Visit a normal URL in another NTP that hasn't committed.
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
index 080e26d..70bc9f9 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
@@ -149,8 +149,12 @@
   keyboard_params.SetKey(
       "showAppleCommandKey",
       base::Value(keyboards_state.has_external_apple_keyboard));
-  keyboard_params.SetKey("hasInternalKeyboard",
-                         base::Value(keyboards_state.has_internal_keyboard));
+  // An external (USB/BT) ChromeOS keyboard is treated similarly to an internal
+  // ChromeOS keyboard. i.e. they are functionally the same.
+  keyboard_params.SetKey(
+      "hasInternalKeyboard",
+      base::Value(keyboards_state.has_internal_keyboard ||
+                  keyboards_state.has_external_chromeos_keyboard));
 
   const bool show_assistant_key_settings = ui::DeviceKeyboardHasAssistantKey();
   keyboard_params.SetKey("hasAssistantKey",
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
index a20eed2..e7784fd 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
@@ -238,6 +238,18 @@
       /*devtype=*/base::nullopt, /*sysattrs=*/{},
       /*properties=*/{{"CROS_KEYBOARD_TOP_ROW_LAYOUT", "1"}});
 
+  // Chrome OS external Bluetooth keyboard.
+  const ui::InputDevice external_bt_chromeos_kbd(
+      4, ui::INPUT_DEVICE_BLUETOOTH, "LG BT Keyboard", "",
+      base::FilePath("/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/"
+                     "0003:04CA:0082.000B/input/input5"),
+      0x04ca, 0x0082, 0x0111);
+  fake_udev->AddFakeDevice(
+      external_bt_chromeos_kbd.name, external_bt_chromeos_kbd.sys_path.value(),
+      /*subsystem=*/"input", /*devnode=*/base::nullopt,
+      /*devtype=*/base::nullopt, /*sysattrs=*/{},
+      /*properties=*/{{"CROS_KEYBOARD_TOP_ROW_LAYOUT", "1"}});
+
   // An internal keyboard shouldn't change the defaults.
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       chromeos::switches::kHasChromeOSKeyboard);
@@ -269,6 +281,16 @@
   EXPECT_FALSE(HasAppleCommandKey());
   EXPECT_FALSE(HasAssistantKey());
 
+  // Connecting external Bluetooth ChromeOS-branded keyboard, we should not
+  // see neither CapsLock not meta keys.
+  device_data_manager_test_api_.SetKeyboardDevices(
+      std::vector<ui::InputDevice>{external_bt_chromeos_kbd});
+  EXPECT_TRUE(HasInternalSearchKey());
+  EXPECT_FALSE(HasCapsLock());
+  EXPECT_FALSE(HasExternalMetaKey());
+  EXPECT_FALSE(HasAppleCommandKey());
+  EXPECT_FALSE(HasAssistantKey());
+
   // Simulate an external Apple keyboard being connected. Now users can remap
   // the command key.
   device_data_manager_test_api_.SetKeyboardDevices(
@@ -294,7 +316,7 @@
   // should show the capslock and external meta remapping.
   // https://crbug.com/834594.
   device_data_manager_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{
-      {5, ui::INPUT_DEVICE_USB, "Topre Corporation Realforce 87", "",
+      {6, ui::INPUT_DEVICE_USB, "Topre Corporation Realforce 87", "",
        external_generic_kbd.sys_path, 0x046d, 0xc31c, 0x0111}});
   EXPECT_FALSE(HasInternalSearchKey());
   EXPECT_TRUE(HasCapsLock());
diff --git a/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc b/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
index a304871e..652b587 100644
--- a/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
-#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
+#include "chrome/browser/ash/child_accounts/child_user_service.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
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 46a0676..baefd64 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -681,6 +681,9 @@
      IDS_SETTINGS_LANGUAGES_OFFER_TO_TRANSLATE_IN_THIS_LANGUAGE},
     {"offerToEnableTranslate",
      IDS_SETTINGS_LANGUAGES_OFFER_TO_ENABLE_TRANSLATE},
+    {"noLanguagesAdded", IDS_SETTINGS_LANGUAGES_NO_LANGUAGES_ADDED},
+    {"automaticallyTranslateLanguages",
+     IDS_SETTINGS_LANGUAGES_AUTOMATIC_TRANSLATE},
     {"translateTargetLabel", IDS_SETTINGS_LANGUAGES_TRANSLATE_TARGET},
     {"spellCheckTitle", IDS_SETTINGS_LANGUAGES_SPELL_CHECK_TITLE},
     {"spellCheckBasicLabel", IDS_SETTINGS_LANGUAGES_SPELL_CHECK_BASIC_LABEL},
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index 9d31f5f..c6b9bc6 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -292,6 +292,9 @@
   html_source->AddBoolean("enableDesktopRestructuredLanguageSettings",
                           base::FeatureList::IsEnabled(
                               language::kDesktopRestructuredLanguageSettings));
+  html_source->AddBoolean(
+      "enableDesktopDetailedLanguageSettings",
+      base::FeatureList::IsEnabled(language::kDesktopDetailedLanguageSettings));
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
index c7478da6..a458be3 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
@@ -17,9 +17,9 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/values.h"
 #include "chrome/browser/account_manager_facade_factory.h"
+#include "chrome/browser/ash/child_accounts/secondary_account_consent_logger.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
-#include "chrome/browser/chromeos/child_accounts/secondary_account_consent_logger.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/chrome_device_id_helper.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
diff --git a/chrome/browser/upgrade_detector/upgrade_detector.h b/chrome/browser/upgrade_detector/upgrade_detector.h
index 8fb7c37..0565ee0 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector.h
+++ b/chrome/browser/upgrade_detector/upgrade_detector.h
@@ -58,6 +58,10 @@
   // reached.
   static base::TimeDelta GetDefaultHighAnnoyanceThreshold();
 
+  // Returns the default delta from upgrade detection until elevated annoyance
+  // is reached.
+  static base::TimeDelta GetDefaultElevatedAnnoyanceThreshold();
+
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
   virtual void Init();
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_chromeos.cc b/chrome/browser/upgrade_detector/upgrade_detector_chromeos.cc
index 79fe1c092..cb7db9ad 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_chromeos.cc
+++ b/chrome/browser/upgrade_detector/upgrade_detector_chromeos.cc
@@ -42,10 +42,16 @@
 // upgrade is detected.
 constexpr base::TimeDelta kDefaultHighThreshold = base::TimeDelta::FromDays(7);
 
+// The default amount of time it takes for the detector's annoyance level
+// (upgrade_notification_stage()) to reach UPGRADE_ANNOYANCE_ELEVATED once an
+// upgrade is detected.
+constexpr base::TimeDelta kDefaultElevatedThreshold =
+    base::TimeDelta::FromDays(4);
+
 // The default amount of time between the detector's annoyance level change
-// from UPGRADE_ANNOYANCE_ELEVATED to UPGRADE_ANNOYANCE_HIGH in ms.
+// from UPGRADE_ANNOYANCE_ELEVATED to UPGRADE_ANNOYANCE_HIGH.
 constexpr base::TimeDelta kDefaultHeadsUpPeriod =
-    base::TimeDelta::FromDays(3);  // 3 days.
+    kDefaultHighThreshold - kDefaultElevatedThreshold;
 
 }  // namespace
 
@@ -55,7 +61,8 @@
     : UpgradeDetector(clock, tick_clock),
       upgrade_notification_timer_(tick_clock),
       initialized_(false),
-      toggled_update_flag_(false) {
+      toggled_update_flag_(false),
+      update_in_progress_(false) {
   // Not all tests provide a PrefService for local_state().
   PrefService* local_state = g_browser_process->local_state();
   if (local_state) {
@@ -136,6 +143,7 @@
     CalculateDeadlines();
   }
 
+  update_in_progress_ = false;
   set_is_rollback(build_state->update_type() ==
                   BuildState::UpdateType::kEnterpriseRollback);
   set_is_factory_reset_required(build_state->update_type() ==
@@ -244,6 +252,12 @@
     // Update engine broadcasts this state only when update is available but
     // downloading over cellular connection requires user's agreement.
     NotifyUpdateOverCellularAvailable();
+  } else if (!update_in_progress_ &&
+             status.current_operation() ==
+                 update_engine::Operation::DOWNLOADING) {
+    update_in_progress_ = true;
+    if (!upgrade_detected_time().is_null())
+      NotifyOnUpgrade();
   }
   if (!toggled_update_flag_) {
     // Only send feature flag status one time.
@@ -281,7 +295,11 @@
 
   const auto last_stage = upgrade_notification_stage();
   // These if statements must be sorted (highest interval first).
-  if (current_time >= high_deadline_) {
+  if (update_in_progress_) {
+    // Cancel any notification of a previous update (if there was one) while a
+    // new update is being downloaded.
+    set_upgrade_notification_stage(UPGRADE_ANNOYANCE_NONE);
+  } else if (current_time >= high_deadline_) {
     set_upgrade_notification_stage(UPGRADE_ANNOYANCE_HIGH);
   } else if (current_time >= elevated_deadline_) {
     set_upgrade_notification_stage(UPGRADE_ANNOYANCE_ELEVATED);
@@ -335,3 +353,8 @@
 base::TimeDelta UpgradeDetector::GetDefaultHighAnnoyanceThreshold() {
   return kDefaultHighThreshold;
 }
+
+// static
+base::TimeDelta UpgradeDetector::GetDefaultElevatedAnnoyanceThreshold() {
+  return kDefaultElevatedThreshold;
+}
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_chromeos.h b/chrome/browser/upgrade_detector/upgrade_detector_chromeos.h
index 60444d2c..0a47eea 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_chromeos.h
+++ b/chrome/browser/upgrade_detector/upgrade_detector_chromeos.h
@@ -115,6 +115,9 @@
   // Indicates whether the flag status has been sent to update engine.
   bool toggled_update_flag_;
 
+  // Indicates whether there is an update in progress.
+  bool update_in_progress_;
+
   base::WeakPtrFactory<UpgradeDetectorChromeos> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(UpgradeDetectorChromeos);
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc b/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
index 374ed27e..0bebeeb 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
+++ b/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
@@ -99,13 +99,22 @@
 
   void RunUntilIdle() { task_environment_.RunUntilIdle(); }
 
-  void NotifyUpdateReadyToInstall() {
+  void NotifyUpdateReadyToInstall(const std::string& version) {
     update_engine::StatusResult status;
+    if (!version.empty())
+      status.set_new_version(version);
     status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT);
     fake_update_engine_client_->set_default_status(status);
     fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
   }
 
+  void NotifyUpdateDownloading() {
+    update_engine::StatusResult status;
+    status.set_current_operation(update_engine::Operation::DOWNLOADING);
+    fake_update_engine_client_->set_default_status(status);
+    fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
+  }
+
   // Sets the browser.relaunch_notification preference in Local State to
   // |value|.
   void SetIsRelaunchNotificationPolicyEnabled(bool enabled) {
@@ -173,7 +182,7 @@
   ::testing::StrictMock<MockUpgradeObserver> mock_observer(&upgrade_detector);
   EXPECT_CALL(mock_observer, OnUpgradeRecommended());
 
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
 
   upgrade_detector.Shutdown();
 }
@@ -186,7 +195,7 @@
 
   // Observer should get some notifications about new version.
   EXPECT_CALL(mock_observer, OnUpgradeRecommended()).Times(testing::AtLeast(1));
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
 
   const auto deadline = upgrade_detector.GetHighAnnoyanceDeadline();
 
@@ -197,7 +206,7 @@
   // New notification could be sent or not.
   EXPECT_CALL(mock_observer, OnUpgradeRecommended())
       .Times(testing::AnyNumber());
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
 
   // Deadline wasn't changed because of new upgrade detected.
   EXPECT_EQ(upgrade_detector.GetHighAnnoyanceDeadline(), deadline);
@@ -222,7 +231,7 @@
   const auto second_notification_at = notification_period;
 
   // Observer should not get notifications about new version till 6-th day.
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
   FastForwardBy(no_notification_till);
   ::testing::Mock::VerifyAndClear(&mock_observer);
   EXPECT_EQ(upgrade_detector.upgrade_notification_stage(),
@@ -255,7 +264,7 @@
   SetHeadsUpPeriodPref(base::TimeDelta::FromDays(1));
 
   // Observer should not get notifications about new version first 4 days.
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
   FastForwardBy(base::TimeDelta::FromDays(4));
   RunUntilIdle();
   ::testing::Mock::VerifyAndClear(&mock_observer);
@@ -292,7 +301,7 @@
   SetHeadsUpPeriodPref(base::TimeDelta::FromDays(1));
 
   // Observer should not get notifications about new version first 4 days.
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
   FastForwardBy(base::TimeDelta::FromDays(4));
   RunUntilIdle();
   ::testing::Mock::VerifyAndClear(&mock_observer);
@@ -332,7 +341,7 @@
   // Observer should get notification because HeadsUpPeriod bigger than
   // NotificationPeriod.
   EXPECT_CALL(mock_observer, OnUpgradeRecommended());
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
   RunUntilIdle();
   ::testing::Mock::VerifyAndClear(&mock_observer);
   EXPECT_EQ(upgrade_detector.upgrade_notification_stage(),
@@ -383,7 +392,7 @@
   // Observer should get notification because HeadsUpPeriod is the same as
   // NotificationPeriod.
   EXPECT_CALL(mock_observer, OnUpgradeRecommended());
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
   RunUntilIdle();
   ::testing::Mock::VerifyAndClear(&mock_observer);
 
@@ -465,7 +474,7 @@
   SetNotificationPeriodPref(notification_period);
   SetHeadsUpPeriodPref(heads_up_period);
   // Simulate update installed.
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
   EXPECT_EQ(upgrade_detector.upgrade_notification_stage(),
             UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
 
@@ -496,7 +505,7 @@
   upgrade_detector.Init();
   ::testing::StrictMock<MockUpgradeObserver> mock_observer(&upgrade_detector);
 
-  NotifyUpdateReadyToInstall();
+  NotifyUpdateReadyToInstall("1.0.0.0");
   EXPECT_EQ(upgrade_detector.upgrade_notification_stage(),
             UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
 
@@ -515,3 +524,44 @@
   upgrade_detector.Shutdown();
   RunUntilIdle();
 }
+
+TEST_F(UpgradeDetectorChromeosTest, TestUpdateInProgress) {
+  TestUpgradeDetectorChromeos upgrade_detector(GetMockClock(),
+                                               GetMockTickClock());
+  upgrade_detector.Init();
+  ::testing::StrictMock<MockUpgradeObserver> mock_observer(&upgrade_detector);
+
+  // Finish the first update and set annoyance level to ELEVATED.
+  EXPECT_CALL(mock_observer, OnUpgradeRecommended()).Times(testing::AtLeast(1));
+  NotifyUpdateReadyToInstall("1.0.0.0");
+  FastForwardBy(upgrade_detector.GetDefaultElevatedAnnoyanceThreshold());
+  ::testing::Mock::VerifyAndClear(&mock_observer);
+  EXPECT_EQ(upgrade_detector.upgrade_notification_stage(),
+            UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED);
+
+  // Start a second update with a new version and make sure observers are
+  // notified when annoyance level changes to NONE during download.
+  EXPECT_CALL(mock_observer, OnUpgradeRecommended());
+  NotifyUpdateDownloading();
+  ::testing::Mock::VerifyAndClear(&mock_observer);
+  EXPECT_EQ(upgrade_detector.upgrade_notification_stage(),
+            UpgradeDetector::UPGRADE_ANNOYANCE_NONE);
+
+  // Complete update and make sure observers are notified when the annoyance
+  // level goes back to the previous state.
+  EXPECT_CALL(mock_observer, OnUpgradeRecommended());
+  NotifyUpdateReadyToInstall("2.0.0.0");
+  ::testing::Mock::VerifyAndClear(&mock_observer);
+  EXPECT_EQ(upgrade_detector.upgrade_notification_stage(),
+            UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED);
+
+  // Change level to HIGH and make sure observers are notified.
+  EXPECT_CALL(mock_observer, OnUpgradeRecommended()).Times(testing::AtLeast(1));
+  FastForwardBy(upgrade_detector.GetHighAnnoyanceLevelDelta());
+  ::testing::Mock::VerifyAndClear(&mock_observer);
+  EXPECT_EQ(upgrade_detector.upgrade_notification_stage(),
+            UpgradeDetector::UPGRADE_ANNOYANCE_HIGH);
+
+  upgrade_detector.Shutdown();
+  RunUntilIdle();
+}
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector/upgrade_detector_impl.cc
index 4c0d5fe..bbcba24 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc
+++ b/chrome/browser/upgrade_detector/upgrade_detector_impl.cc
@@ -542,3 +542,8 @@
 base::TimeDelta UpgradeDetector::GetDefaultHighAnnoyanceThreshold() {
   return kDefaultHighThreshold;
 }
+
+// static
+base::TimeDelta UpgradeDetector::GetDefaultElevatedAnnoyanceThreshold() {
+  return kDefaultElevatedThreshold;
+}
diff --git a/chrome/browser/web_applications/components/web_app_origin_association_manager_browsertest.cc b/chrome/browser/web_applications/components/web_app_origin_association_manager_browsertest.cc
index 04ec2809..9deccf11 100644
--- a/chrome/browser/web_applications/components/web_app_origin_association_manager_browsertest.cc
+++ b/chrome/browser/web_applications/components/web_app_origin_association_manager_browsertest.cc
@@ -21,6 +21,7 @@
 const std::string& kValidAppUrl = "https://b.com";
 const std::string& kValidAndInvalidAppsUrl = "https://c.com";
 const std::string& kMultipleValidAppsUrl = "https://d.com";
+const std::string& kValidAppWithTooManyPathsUrl = "https://e.com";
 
 constexpr char kInvalidFileContent[] = "invalid";
 constexpr char kValidAppFileContent[] =
@@ -64,6 +65,20 @@
     "  }"
     "]}";
 
+constexpr char kValidAppWithTooManyPathsFileContent[] =
+    "{\"web_apps\": ["
+    "  {"
+    "    \"manifest\": \"https://foo.com/manifest.json\","
+    "    \"details\": {"
+    "      \"paths\": [\"/1\", \"/2\", \"/3\", \"/4\", \"/5\", \"/6\","
+    "                  \"/7\", \"/8\", \"/9\", \"/10\", \"/11\"],"
+    "      \"exclude_paths\": [\"/1\", \"/2\", \"/3\", \"/4\", \"/5\","
+    "                          \"/6\", \"/7\", \"/8\", \"/9\", \"/10\","
+    "                          \"/11\"]"
+    "    }"
+    "  }"
+    "]}";
+
 }  // namespace
 
 namespace web_app {
@@ -87,6 +102,8 @@
     std::map<url::Origin, std::string> data = {
         {url::Origin::Create(GURL(kInvalidFileUrl)), kInvalidFileContent},
         {url::Origin::Create(GURL(kValidAppUrl)), kValidAppFileContent},
+        {url::Origin::Create(GURL(kValidAppWithTooManyPathsUrl)),
+         kValidAppWithTooManyPathsFileContent},
         {url::Origin::Create(GURL(kValidAndInvalidAppsUrl)),
          kValidAndInvalidAppsFileContent},
         {url::Origin::Create(GURL(kMultipleValidAppsUrl)),
@@ -100,6 +117,8 @@
     invalid_file_url_handler_.origin =
         url::Origin::Create(GURL(kInvalidFileUrl));
     valid_app_url_handler_.origin = url::Origin::Create(GURL(kValidAppUrl));
+    valid_app_with_too_many_paths_url_handler_.origin =
+        url::Origin::Create(GURL(kValidAppWithTooManyPathsUrl));
     valid_and_invalid_app_url_handler_.origin =
         url::Origin::Create(GURL(kValidAndInvalidAppsUrl));
     multiple_valid_apps_url_handler_.origin =
@@ -141,6 +160,7 @@
 
   apps::UrlHandlerInfo invalid_file_url_handler_;
   apps::UrlHandlerInfo valid_app_url_handler_;
+  apps::UrlHandlerInfo valid_app_with_too_many_paths_url_handler_;
   apps::UrlHandlerInfo valid_and_invalid_app_url_handler_;
   apps::UrlHandlerInfo multiple_valid_apps_url_handler_;
 };
@@ -192,6 +212,31 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppOriginAssociationManagerTest,
+                       OneValidAppWithTooManyPaths) {
+  base::RunLoop run_loop;
+  apps::UrlHandlers url_handlers{valid_app_with_too_many_paths_url_handler_};
+  manager_->GetWebAppOriginAssociations(
+      GURL(kManifestUrl), std::move(url_handlers),
+      base::BindLambdaForTesting([&](apps::UrlHandlers result) {
+        ASSERT_TRUE(result.size() == 1);
+        auto url_handler = std::move(result[0]);
+        EXPECT_EQ(url_handler.origin,
+                  valid_app_with_too_many_paths_url_handler_.origin);
+        EXPECT_EQ(
+            url_handler.has_origin_wildcard,
+            valid_app_with_too_many_paths_url_handler_.has_origin_wildcard);
+
+        ASSERT_EQ(10u, url_handler.paths.size());
+        EXPECT_EQ(url_handler.paths[9], "/10");
+
+        ASSERT_EQ(10u, url_handler.exclude_paths.size());
+        EXPECT_EQ(url_handler.exclude_paths[9], "/10");
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppOriginAssociationManagerTest,
                        ValidAndInvalidApps) {
   base::RunLoop run_loop;
 
diff --git a/chrome/browser/web_applications/components/web_app_origin_association_task.cc b/chrome/browser/web_applications/components/web_app_origin_association_task.cc
index 0981e84..8b1db71 100644
--- a/chrome/browser/web_applications/components/web_app_origin_association_task.cc
+++ b/chrome/browser/web_applications/components/web_app_origin_association_task.cc
@@ -14,6 +14,29 @@
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "url/gurl.h"
 
+namespace {
+// Keep in sync with
+// third_party/blink/renderer/modules/manifest/manifest_parser.cc.
+constexpr size_t kMaxPathsSize = 10;
+constexpr size_t kMaxPathLength = 2000;
+
+// Number of paths cannot exceed |kMaxPathsSize|, and each path cannot contain
+// more than |kMaxPathLength| characters.
+std::vector<std::string> GetValidPaths(std::vector<std::string> paths) {
+  std::vector<std::string> result;
+  for (const std::string& path : paths) {
+    if (result.size() == kMaxPathsSize)
+      break;
+
+    if (path.length() > kMaxPathLength)
+      continue;
+
+    result.push_back(std::move(path));
+  }
+  return result;
+}
+}  // namespace
+
 namespace web_app {
 
 WebAppOriginAssociationManager::Task::Task(
@@ -85,10 +108,12 @@
   for (auto& app : association->apps) {
     if (app->manifest_url == manifest_url_) {
       if (app->paths.has_value())
-        url_handler.paths = std::move(app->paths.value());
+        url_handler.paths = GetValidPaths(std::move(app->paths.value()));
 
-      if (app->exclude_paths.has_value())
-        url_handler.exclude_paths = std::move(app->exclude_paths.value());
+      if (app->exclude_paths.has_value()) {
+        url_handler.exclude_paths =
+            GetValidPaths(std::move(app->exclude_paths.value()));
+      }
 
       result_.push_back(std::move(url_handler));
       url_handler.Reset();
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
index 0da0e920..7ed2d3d 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -172,6 +172,56 @@
 
 ChromeWebAuthenticationDelegate::~ChromeWebAuthenticationDelegate() = default;
 
+base::Optional<std::string>
+ChromeWebAuthenticationDelegate::MaybeGetRelyingPartyIdOverride(
+    const std::string& claimed_relying_party_id,
+    const url::Origin& caller_origin) {
+  // Don't override cryptotoken processing.
+  constexpr char kCryptotokenOrigin[] =
+      "chrome-extension://kmendfapggjehodndflmmgagdbamhnfd";
+  if (caller_origin == url::Origin::Create(GURL(kCryptotokenOrigin))) {
+    return base::nullopt;
+  }
+
+  // Otherwise, allow extensions to use WebAuthn and map their origins
+  // directly to RP IDs.
+  if (caller_origin.scheme() == "chrome-extension") {
+    // The requested RP ID for an extension must simply be the extension
+    // identifier because no flexibility is permitted. If a caller doesn't
+    // specify an RP ID then Blink defaults the value to the origin's host.
+    if (claimed_relying_party_id != caller_origin.host()) {
+      return base::nullopt;
+    }
+    return caller_origin.Serialize();
+  }
+
+  return base::nullopt;
+}
+
+bool ChromeWebAuthenticationDelegate::ShouldPermitIndividualAttestation(
+    content::BrowserContext* browser_context,
+    const std::string& relying_party_id) {
+  constexpr char kGoogleCorpAppId[] =
+      "https://www.gstatic.com/securitykey/a/google.com/origins.json";
+
+  // If the RP ID is actually the Google corp App ID (because the request is
+  // actually a U2F request originating from cryptotoken), or is listed in the
+  // enterprise policy, signal that individual attestation is permitted.
+  return relying_party_id == kGoogleCorpAppId ||
+         IsWebauthnRPIDListedInEnterprisePolicy(browser_context,
+                                                relying_party_id);
+}
+
+bool ChromeWebAuthenticationDelegate::SupportsResidentKeys(
+    content::RenderFrameHost* render_frame_host) {
+  return true;
+}
+
+bool ChromeWebAuthenticationDelegate::IsFocused(
+    content::WebContents* web_contents) {
+  return web_contents->GetVisibility() == content::Visibility::VISIBLE;
+}
+
 #if defined(OS_MAC)
 // static
 ChromeWebAuthenticationDelegate::TouchIdAuthenticatorConfig
@@ -272,32 +322,6 @@
   return weak_ptr_factory_.GetWeakPtr();
 }
 
-base::Optional<std::string>
-ChromeAuthenticatorRequestDelegate::MaybeGetRelyingPartyIdOverride(
-    const std::string& claimed_relying_party_id,
-    const url::Origin& caller_origin) {
-  // Don't override cryptotoken processing.
-  constexpr char kCryptotokenOrigin[] =
-      "chrome-extension://kmendfapggjehodndflmmgagdbamhnfd";
-  if (caller_origin == url::Origin::Create(GURL(kCryptotokenOrigin))) {
-    return base::nullopt;
-  }
-
-  // Otherwise, allow extensions to use WebAuthn and map their origins
-  // directly to RP IDs.
-  if (caller_origin.scheme() == "chrome-extension") {
-    // The requested RP ID for an extension must simply be the extension
-    // identifier because no flexibility is permitted. If a caller doesn't
-    // specify an RP ID then Blink defaults the value to the origin's host.
-    if (claimed_relying_party_id != caller_origin.host()) {
-      return base::nullopt;
-    }
-    return caller_origin.Serialize();
-  }
-
-  return base::nullopt;
-}
-
 void ChromeAuthenticatorRequestDelegate::SetRelyingPartyId(
     const std::string& rp_id) {
   transient_dialog_model_holder_ =
@@ -369,19 +393,6 @@
       bluetooth_adapter_power_on_callback);
 }
 
-bool ChromeAuthenticatorRequestDelegate::ShouldPermitIndividualAttestation(
-    const std::string& relying_party_id) {
-  constexpr char kGoogleCorpAppId[] =
-      "https://www.gstatic.com/securitykey/a/google.com/origins.json";
-
-  // If the RP ID is actually the Google corp App ID (because the request is
-  // actually a U2F request originating from cryptotoken), or is listed in the
-  // enterprise policy, signal that individual attestation is permitted.
-  return relying_party_id == kGoogleCorpAppId ||
-         IsWebauthnRPIDListedInEnterprisePolicy(GetBrowserContext(),
-                                                relying_party_id);
-}
-
 void ChromeAuthenticatorRequestDelegate::ShouldReturnAttestation(
     const std::string& relying_party_id,
     const device::FidoAuthenticator* authenticator,
@@ -419,10 +430,6 @@
                                                    std::move(callback));
 }
 
-bool ChromeAuthenticatorRequestDelegate::SupportsResidentKeys() {
-  return true;
-}
-
 void ChromeAuthenticatorRequestDelegate::ConfigureCable(
     const url::Origin& origin,
     base::span<const device::CableDiscoveryData> pairings_from_extension,
@@ -501,13 +508,6 @@
   weak_dialog_model_->SelectAccount(std::move(responses), std::move(callback));
 }
 
-bool ChromeAuthenticatorRequestDelegate::IsFocused() {
-  auto* web_contents =
-      content::WebContents::FromRenderFrameHost(GetRenderFrameHost());
-  DCHECK(web_contents);
-  return web_contents->GetVisibility() == content::Visibility::VISIBLE;
-}
-
 void ChromeAuthenticatorRequestDelegate::DisableUI() {
   disable_ui_ = true;
 }
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
index 2345c4e8..1e94099 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
@@ -54,6 +54,15 @@
   ~ChromeWebAuthenticationDelegate() override;
 
   // content::WebAuthenticationDelegate:
+  base::Optional<std::string> MaybeGetRelyingPartyIdOverride(
+      const std::string& claimed_relying_party_id,
+      const url::Origin& caller_origin) override;
+  bool ShouldPermitIndividualAttestation(
+      content::BrowserContext* browser_context,
+      const std::string& relying_party_id) override;
+  bool SupportsResidentKeys(
+      content::RenderFrameHost* render_frame_host) override;
+  bool IsFocused(content::WebContents* web_contents) override;
 #if defined(OS_MAC)
   base::Optional<TouchIdAuthenticatorConfig> GetTouchIdAuthenticatorConfig(
       content::BrowserContext* browser_context) override;
@@ -83,9 +92,6 @@
   }
 
   // content::AuthenticatorRequestClientDelegate:
-  base::Optional<std::string> MaybeGetRelyingPartyIdOverride(
-      const std::string& claimed_relying_party_id,
-      const url::Origin& caller_origin) override;
   void SetRelyingPartyId(const std::string& rp_id) override;
   bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override;
   void RegisterActionCallbacks(
@@ -93,14 +99,11 @@
       base::RepeatingClosure start_over_callback,
       device::FidoRequestHandlerBase::RequestCallback request_callback,
       base::RepeatingClosure bluetooth_adapter_power_on_callback) override;
-  bool ShouldPermitIndividualAttestation(
-      const std::string& relying_party_id) override;
   void ShouldReturnAttestation(
       const std::string& relying_party_id,
       const device::FidoAuthenticator* authenticator,
       bool is_enterprise_attestation,
       base::OnceCallback<void(bool)> callback) override;
-  bool SupportsResidentKeys() override;
   void ConfigureCable(
       const url::Origin& origin,
       base::span<const device::CableDiscoveryData> pairings_from_extension,
@@ -109,7 +112,6 @@
       std::vector<device::AuthenticatorGetAssertionResponse> responses,
       base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
           callback) override;
-  bool IsFocused() override;
   void DisableUI() override;
   bool IsWebAuthnUIEnabled() override;
   void SetConditionalRequest(bool is_conditional) override;
diff --git a/chrome/browser/webshare/win/fake_data_transfer_manager_unittest.cc b/chrome/browser/webshare/win/fake_data_transfer_manager_unittest.cc
index 3af309a9..aeb75ed 100644
--- a/chrome/browser/webshare/win/fake_data_transfer_manager_unittest.cc
+++ b/chrome/browser/webshare/win/fake_data_transfer_manager_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "base/win/core_winrt_util.h"
+#include "base/win/scoped_winrt_initializer.h"
 #include "base/win/vector.h"
 #include "chrome/browser/webshare/win/fake_storage_file_statics.h"
 #include "chrome/browser/webshare/win/fake_uri_runtime_class_factory.h"
@@ -96,8 +97,7 @@
   void SetUp() override {
     if (!IsSupportedEnvironment())
       return;
-    ASSERT_HRESULT_SUCCEEDED(
-        base::win::RoInitialize(RO_INIT_TYPE::RO_INIT_MULTITHREADED));
+    ASSERT_TRUE(winrt_initializer_.Succeeded());
     fake_data_transfer_manager_ =
         Microsoft::WRL::Make<FakeDataTransferManager>();
   }
@@ -105,9 +105,9 @@
   void TearDown() override {
     if (!IsSupportedEnvironment())
       return;
-    base::win::RoUninitialize();
   }
 
+  base::win::ScopedWinrtInitializer winrt_initializer_;
   ComPtr<FakeDataTransferManager> fake_data_transfer_manager_;
 };
 
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 4a844b1..36bf027 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1618228674-b8b9cdf7c1aa900e7a920b03159f7e7b8dae9d5d.profdata
+chrome-linux-master-1618250085-357901c670c6b3979914700640de0ca558fd4c5a.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index b02d0b4..6e58ca8ba 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1618250085-ffa805180ec9d754cf5c51687ddbda93b14e3cf0.profdata
+chrome-mac-master-1618271818-3bb9ca9f3a5a54270291a634d0805f1d757133a7.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index c2339ac..4518293 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1618239101-c343067f4fe42b5b9cbeed20dc8eca6f73065154.profdata
+chrome-win32-master-1618250085-5770703059e16df14be29bfb79393f5f746dac25.profdata
diff --git a/chrome/common/extensions/api/activity_log_private.json b/chrome/common/extensions/api/activity_log_private.json
index cf24494..11b776e 100644
--- a/chrome/common/extensions/api/activity_log_private.json
+++ b/chrome/common/extensions/api/activity_log_private.json
@@ -145,8 +145,7 @@
             "name": "urls",
             "type": "array",
             "items": { "type": "string" },
-            "description": "Erases only the URLs listed; if empty, erases all URLs.",
-            "optional": true
+            "description": "Erases only the URLs listed; if empty, erases all URLs."
           }
         ]
       }
diff --git a/chrome/common/mac/app_shim.mojom b/chrome/common/mac/app_shim.mojom
index 3d2a3e6..77c4224 100644
--- a/chrome/common/mac/app_shim.mojom
+++ b/chrome/common/mac/app_shim.mojom
@@ -113,6 +113,9 @@
 
   // Called when a profile is selected from the profiles menu.
   ProfileSelectedFromMenu(mojo_base.mojom.FilePath profile_path);
+
+  // Sent when urls are opened by the app (e.g. clicking a link in mail)
+  UrlsOpened(array<url.mojom.Url> urls);
 };
 
 // Properties of an app shim that are specified when it connects to the browser
@@ -136,6 +139,9 @@
 
   // Indicates if the app launched during OS login.
   AppShimLoginItemRestoreState login_item_restore_state;
+
+  // The urls that are to be opened by this app.
+  array<url.mojom.Url> urls;
 };
 
 // The initial interface provided by the browser process. Used to bootstrap to
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 0226c542..1b2ca2d6 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -88,7 +88,7 @@
 const char kChromeSearchMostVisitedUrl[] = "chrome-search://most-visited/";
 
 const char kChromeUIUntrustedNewTabPageBackgroundUrl[] =
-    "chrome-untrusted://background.jpg";
+    "chrome-untrusted://new-tab-page/background.jpg";
 const char kChromeUIUntrustedNewTabPageBackgroundFilename[] = "background.jpg";
 
 const char kChromeSearchRemoteNtpHost[] = "remote-ntp";
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 5c3a07b..34b4a81 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -10,6 +10,7 @@
 #include "components/nacl/common/buildflags.h"
 #include "components/safe_browsing/core/web_ui/constants.h"
 #include "extensions/buildflags/buildflags.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 
 namespace chrome {
 
@@ -626,27 +627,27 @@
     base::size(kChromeInternalsPathURLs);
 
 const char* const kChromeDebugURLs[] = {
-    content::kChromeUIBadCastCrashURL,
-    content::kChromeUIBrowserCrashURL,
-    content::kChromeUICrashURL,
-    content::kChromeUIDumpURL,
-    content::kChromeUIKillURL,
-    content::kChromeUIHangURL,
-    content::kChromeUIShorthangURL,
-    content::kChromeUIGpuCleanURL,
-    content::kChromeUIGpuCrashURL,
-    content::kChromeUIGpuHangURL,
-    content::kChromeUIMemoryExhaustURL,
-    content::kChromeUIMemoryPressureCriticalURL,
-    content::kChromeUIMemoryPressureModerateURL,
-    content::kChromeUIPpapiFlashCrashURL,
-    content::kChromeUIPpapiFlashHangURL,
+    blink::kChromeUIBadCastCrashURL,
+    blink::kChromeUIBrowserCrashURL,
+    blink::kChromeUICrashURL,
+    blink::kChromeUIDumpURL,
+    blink::kChromeUIKillURL,
+    blink::kChromeUIHangURL,
+    blink::kChromeUIShorthangURL,
+    blink::kChromeUIGpuCleanURL,
+    blink::kChromeUIGpuCrashURL,
+    blink::kChromeUIGpuHangURL,
+    blink::kChromeUIMemoryExhaustURL,
+    blink::kChromeUIMemoryPressureCriticalURL,
+    blink::kChromeUIMemoryPressureModerateURL,
+    blink::kChromeUIPpapiFlashCrashURL,
+    blink::kChromeUIPpapiFlashHangURL,
 #if defined(OS_WIN)
-    content::kChromeUIBrowserHeapCorruptionURL,
-    content::kChromeUIHeapCorruptionCrashURL,
+    blink::kChromeUIBrowserHeapCorruptionURL,
+    blink::kChromeUIHeapCorruptionCrashURL,
 #endif
 #if defined(OS_ANDROID)
-    content::kChromeUIGpuJavaCrashURL,
+    blink::kChromeUIGpuJavaCrashURL,
     kChromeUIJavaCrashURL,
 #endif
 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 1bfe89f..f20c612 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2481,9 +2481,12 @@
         "../browser/ash/arc/user_session/arc_user_session_service_browsertest.cc",
         "../browser/ash/attestation/attestation_policy_browsertest.cc",
         "../browser/ash/base/locale_util_browsertest.cc",
+        "../browser/ash/child_accounts/family_user_device_metrics_browsertest.cc",
         "../browser/ash/child_accounts/parent_access_code/parent_access_service_browsertest.cc",
         "../browser/ash/child_accounts/parent_access_code/parent_access_test_utils.cc",
         "../browser/ash/child_accounts/parent_access_code/parent_access_test_utils.h",
+        "../browser/ash/child_accounts/screen_time_controller_browsertest.cc",
+        "../browser/ash/child_accounts/time_limit_test_utils.cc",
         "../browser/ash/child_accounts/time_limits/app_time_browsertest.cc",
         "../browser/ash/child_accounts/time_limits/app_time_limits_allowlist_policy_test_utils.cc",
         "../browser/ash/child_accounts/time_limits/app_time_limits_allowlist_policy_test_utils.h",
@@ -2653,9 +2656,6 @@
         "../browser/ash/web_applications/system_web_app_integration_test.h",
         "../browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_web_request_service_browsertest.cc",
         "../browser/chrome_main_browsertest.cc",
-        "../browser/chromeos/child_accounts/family_user_device_metrics_browsertest.cc",
-        "../browser/chromeos/child_accounts/screen_time_controller_browsertest.cc",
-        "../browser/chromeos/child_accounts/time_limit_test_utils.cc",
         "../browser/chromeos/chrome_content_browser_client_chromeos_part_browsertest.cc",
         "../browser/chromeos/crostini/crostini_browser_test_util.cc",
         "../browser/chromeos/crostini/crostini_browser_test_util.h",
@@ -7643,12 +7643,12 @@
       "../browser/ash/child_accounts/time_limit_consistency_test/consistency_test_utils.h",
       "../browser/ash/child_accounts/time_limit_consistency_test/proto_matcher.h",
       "../browser/ash/child_accounts/time_limit_consistency_test/run_all_unittests.cc",
-      "../browser/chromeos/child_accounts/time_limit_override.cc",
-      "../browser/chromeos/child_accounts/time_limit_override.h",
-      "../browser/chromeos/child_accounts/time_limit_test_utils.cc",
-      "../browser/chromeos/child_accounts/time_limit_test_utils.h",
-      "../browser/chromeos/child_accounts/usage_time_limit_processor.cc",
-      "../browser/chromeos/child_accounts/usage_time_limit_processor.h",
+      "../browser/ash/child_accounts/time_limit_override.cc",
+      "../browser/ash/child_accounts/time_limit_override.h",
+      "../browser/ash/child_accounts/time_limit_test_utils.cc",
+      "../browser/ash/child_accounts/time_limit_test_utils.h",
+      "../browser/ash/child_accounts/usage_time_limit_processor.cc",
+      "../browser/ash/child_accounts/usage_time_limit_processor.h",
     ]
     deps = [
       ":consistency_golden_proto",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index ebf2e9d..8fd1c681 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -8216,12 +8216,12 @@
     "os": ["win", "linux", "mac", "chromeos"],
     "policy_pref_mapping_tests": [
       {
-        "policies": { "DefaultFileHandlingGuardSetting": 1 },
-        "prefs": { "profile.managed_default_content_settings.file_handling_guard": { "value": 1 } }
-      },
-      {
         "policies": { "DefaultFileHandlingGuardSetting": 2 },
         "prefs": { "profile.managed_default_content_settings.file_handling_guard": { "value": 2 } }
+      },
+      {
+        "policies": { "DefaultFileHandlingGuardSetting": 3 },
+        "prefs": { "profile.managed_default_content_settings.file_handling_guard": { "value": 3 } }
       }
     ]
   },
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js b/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js
index 4d498b80..eda8a1f 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js
@@ -133,6 +133,9 @@
         mojom.NetworkType.kCellular, 'cellular');
     managedPropertiesActivated.typeProperties.cellular.activationState =
         mojom.ActivationStateType.kActivated;
+    managedPropertiesActivated.typeProperties.cellular.paymentPortal = {
+      url: 'url'
+    };
     mojoApi_.setManagedPropertiesForTest(managedPropertiesActivated);
 
     listItem.item =
@@ -142,6 +145,25 @@
     // Activate button should not be showing.
     assertFalse(!!listItem.$$('#activateButton'));
 
+    // Set item to an unactivated eSIM network with a payment URL.
+    const managedPropertiesESimNotActivated =
+        OncMojo.getDefaultManagedProperties(
+            mojom.NetworkType.kCellular, 'cellular');
+    managedPropertiesESimNotActivated.typeProperties.cellular.eid = 'eid';
+    managedPropertiesESimNotActivated.typeProperties.cellular.activationState =
+        mojom.ActivationStateType.kNotActivated;
+    managedPropertiesESimNotActivated.typeProperties.cellular.paymentPortal = {
+      url: 'url'
+    };
+    mojoApi_.setManagedPropertiesForTest(managedPropertiesESimNotActivated);
+
+    listItem.item = OncMojo.managedPropertiesToNetworkState(
+        managedPropertiesESimNotActivated);
+    await flushAsync();
+
+    // Activate button should not be showing.
+    assertFalse(!!listItem.$$('#activateButton'));
+
     // Set item to an unactivated pSIM network with a payment URL.
     const managedPropertiesNotActivated = OncMojo.getDefaultManagedProperties(
         mojom.NetworkType.kCellular, 'cellular');
diff --git a/chrome/test/data/webui/new_tab_page/app_test.js b/chrome/test/data/webui/new_tab_page/app_test.js
index 56bc5159..fabfe0a 100644
--- a/chrome/test/data/webui/new_tab_page/app_test.js
+++ b/chrome/test/data/webui/new_tab_page/app_test.js
@@ -483,11 +483,11 @@
         // Act.
         moduleResolver.resolve([
           {
-            id: 'foo',
+            descriptor: {id: 'foo'},
             element: document.createElement('div'),
           },
           {
-            id: 'bar',
+            descriptor: {id: 'bar'},
             element: document.createElement('div'),
           }
         ]);
@@ -520,7 +520,7 @@
 
       // Act.
       moduleResolver.resolve([{
-        id: 'foo',
+        descriptor: {id: 'foo'},
         element: moduleElement,
       }]);
       await flushTasks();  // Wait for module descriptor resolution.
@@ -568,8 +568,10 @@
 
       // Act.
       moduleResolver.resolve([{
-        id: 'foo',
-        name: 'bar',
+        descriptor: {
+          id: 'foo',
+          name: 'bar',
+        },
         element: moduleElement,
       }]);
       await flushTasks();  // Wait for module descriptor resolution.
@@ -625,7 +627,7 @@
       // Arrange.
       const moduleElement = document.createElement('div');
       moduleResolver.resolve([{
-        id: 'foo',
+        descriptor: {id: 'foo'},
         element: moduleElement,
       }]);
       await flushTasks();  // Wait for module descriptor resolution.
@@ -656,11 +658,11 @@
     // Act.
     moduleResolver.resolve([
       {
-        id: 'foo',
+        descriptor: {id: 'foo'},
         element: document.createElement('div'),
       },
       {
-        id: 'bar',
+        descriptor: {id: 'bar'},
         element: document.createElement('div'),
       }
     ]);
diff --git a/chrome/test/data/webui/new_tab_page/modules/cart/module_test.js b/chrome/test/data/webui/new_tab_page/modules/cart/module_test.js
index 0596129..94aaba6f 100644
--- a/chrome/test/data/webui/new_tab_page/modules/cart/module_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/cart/module_test.js
@@ -38,11 +38,11 @@
         'getMerchantCarts', Promise.resolve({carts: []}));
 
     // Act.
-    await chromeCartDescriptor.initialize();
+    const moduleElement = await chromeCartDescriptor.initialize();
 
     // Assert.
     assertEquals(1, testProxy.handler.getCallCount('getMerchantCarts'));
-    assertEquals(null, chromeCartDescriptor.element);
+    assertEquals(null, moduleElement);
   });
 
   test('creates module if cart item', async () => {
@@ -79,15 +79,14 @@
         'getMerchantCarts', Promise.resolve({carts}));
 
     // Act.
-    await chromeCartDescriptor.initialize();
-    const moduleElement = chromeCartDescriptor.element;
+    const moduleElement = await chromeCartDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.cartItemRepeat.render();
 
     // Assert.
     const cartItems = moduleElement.shadowRoot.querySelectorAll('.cart-item');
     assertEquals(4, cartItems.length);
-    assertEquals(220, chromeCartDescriptor.element.offsetHeight);
+    assertEquals(220, moduleElement.offsetHeight);
 
     assertEquals('https://amazon.com/', cartItems[0].href);
     assertEquals('Amazon', cartItems[0].querySelector('.merchant').innerText);
@@ -147,8 +146,7 @@
         'getWarmWelcomeVisible', Promise.resolve({visible: true}));
 
     // Arrange.
-    await chromeCartDescriptor.initialize();
-    const moduleElement = chromeCartDescriptor.element;
+    const moduleElement = await chromeCartDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.cartItemRepeat.render();
 
@@ -164,7 +162,7 @@
     assertEquals(
         loadTimeData.getString('modulesCartWarmWelcome'),
         headerDescription.innerText);
-    assertEquals(227, chromeCartDescriptor.element.offsetHeight);
+    assertEquals(227, moduleElement.offsetHeight);
   });
 
   test('Backend is notified when module is dismissed or restored', async () => {
@@ -187,8 +185,7 @@
     });
 
     // Arrange.
-    await chromeCartDescriptor.initialize();
-    const moduleElement = chromeCartDescriptor.element;
+    const moduleElement = await chromeCartDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.cartItemRepeat.render();
 
@@ -251,8 +248,7 @@
         'getMerchantCarts', Promise.resolve({carts}));
 
     // Arrange.
-    await chromeCartDescriptor.initialize();
-    const moduleElement = chromeCartDescriptor.element;
+    const moduleElement = await chromeCartDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.cartItemRepeat.render();
 
@@ -340,8 +336,7 @@
         'getMerchantCarts', Promise.resolve({carts}));
 
     // Arrange.
-    await chromeCartDescriptor.initialize();
-    const moduleElement = chromeCartDescriptor.element;
+    const moduleElement = await chromeCartDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.cartItemRepeat.render();
     const cartCarousel =
@@ -440,8 +435,7 @@
         'getMerchantCarts', Promise.resolve({carts}));
 
     // Arrange.
-    await chromeCartDescriptor.initialize();
-    const moduleElement = chromeCartDescriptor.element;
+    const moduleElement = await chromeCartDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.cartItemRepeat.render();
     const cartCarousel =
@@ -516,8 +510,7 @@
         'getMerchantCarts', Promise.resolve({carts}));
 
     // Arrange.
-    await chromeCartDescriptor.initialize();
-    const moduleElement = chromeCartDescriptor.element;
+    const moduleElement = await chromeCartDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.cartItemRepeat.render();
 
@@ -584,8 +577,7 @@
         'getMerchantCarts', Promise.resolve({carts}));
 
     // Act.
-    await chromeCartDescriptor.initialize();
-    const moduleElement = chromeCartDescriptor.element;
+    const moduleElement = await chromeCartDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.cartItemRepeat.render();
 
diff --git a/chrome/test/data/webui/new_tab_page/modules/drive/module_test.js b/chrome/test/data/webui/new_tab_page/modules/drive/module_test.js
index d36ae9f..31284d8 100644
--- a/chrome/test/data/webui/new_tab_page/modules/drive/module_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/drive/module_test.js
@@ -50,8 +50,7 @@
     };
     testProxy.handler.setResultFor('getFiles', Promise.resolve(data));
 
-    await driveDescriptor.initialize();
-    const module = driveDescriptor.element;
+    const module = await driveDescriptor.initialize();
     document.body.append(module);
     await testProxy.handler.whenCalled('getFiles');
     module.$.fileRepeat.render();
@@ -84,8 +83,8 @@
   test('documents do not show without data', async () => {
     testProxy.handler.setResultFor('getFiles', Promise.resolve({files: []}));
 
-    await driveDescriptor.initialize();
+    const module = await driveDescriptor.initialize();
     await testProxy.handler.whenCalled('getFiles');
-    assertFalse(!!driveDescriptor.element);
+    assertFalse(!!module);
   });
 });
diff --git a/chrome/test/data/webui/new_tab_page/modules/dummy/module_test.js b/chrome/test/data/webui/new_tab_page/modules/dummy/module_test.js
index 2849a73..f7515e2 100644
--- a/chrome/test/data/webui/new_tab_page/modules/dummy/module_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/dummy/module_test.js
@@ -37,8 +37,7 @@
       },
     ];
     testProxy.handler.setResultFor('getData', Promise.resolve({data}));
-    await dummyDescriptor.initialize();
-    const module = dummyDescriptor.element;
+    const module = await dummyDescriptor.initialize();
     document.body.append(module);
     module.$.tileList.render();
 
@@ -53,8 +52,7 @@
 
   test('creates module without data', async () => {
     // Act.
-    await dummyDescriptor.initialize();
-    const module = dummyDescriptor.element;
+    const module = await dummyDescriptor.initialize();
     document.body.append(module);
     module.$.tileList.render();
 
diff --git a/chrome/test/data/webui/new_tab_page/modules/module_descriptor_test.js b/chrome/test/data/webui/new_tab_page/modules/module_descriptor_test.js
index 0621464..4eac617 100644
--- a/chrome/test/data/webui/new_tab_page/modules/module_descriptor_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/module_descriptor_test.js
@@ -38,10 +38,10 @@
     windowProxy.setResultFor('now', 123);
 
     // Act.
-    await moduleDescriptor.initialize();
+    const moduleElement = await moduleDescriptor.initialize();
 
     // Assert.
-    assertEquals(element, moduleDescriptor.element);
+    assertEquals(element, moduleElement);
     assertEquals(1, metrics.count('NewTabPage.Modules.Loaded'));
     assertEquals(1, metrics.count('NewTabPage.Modules.Loaded', 128));
     assertEquals(1, metrics.count('NewTabPage.Modules.Loaded.foo'));
@@ -58,10 +58,10 @@
         new ModuleDescriptor('foo', 'bar', () => Promise.resolve(null));
 
     // Act.
-    await moduleDescriptor.initialize();
+    const moduleElement = await moduleDescriptor.initialize();
 
     // Assert.
-    assertEquals(null, moduleDescriptor.element);
+    assertEquals(null, moduleElement);
     assertEquals(0, metrics.count('NewTabPage.Modules.Loaded'));
     assertEquals(0, metrics.count('NewTabPage.Modules.Loaded.foo'));
     assertEquals(0, metrics.count('NewTabPage.Modules.LoadDuration'));
@@ -77,10 +77,10 @@
     const initializePromise = moduleDescriptor.initialize(123);
     const [callback, timeout] = await windowProxy.whenCalled('setTimeout');
     callback();
-    await initializePromise;
+    const moduleElement = await initializePromise;
 
     // Assert.
-    assertEquals(null, moduleDescriptor.element);
+    assertEquals(null, moduleElement);
     assertEquals(123, timeout);
   });
 });
diff --git a/chrome/test/data/webui/new_tab_page/modules/module_registry_test.js b/chrome/test/data/webui/new_tab_page/modules/module_registry_test.js
index b86a336d..ac481bf 100644
--- a/chrome/test/data/webui/new_tab_page/modules/module_registry_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/module_registry_test.js
@@ -76,9 +76,9 @@
     // Assert.
     assertEquals(1, handler.getCallCount('updateDisabledModules'));
     assertEquals(2, modules.length);
-    assertEquals('foo', modules[0].id);
+    assertEquals('foo', modules[0].descriptor.id);
     assertDeepEquals(fooModule, modules[0].element);
-    assertEquals('baz', modules[1].id);
+    assertEquals('baz', modules[1].descriptor.id);
     assertDeepEquals(bazModule, modules[1].element);
     assertEquals(2, metrics.count('NewTabPage.Modules.Loaded'));
     assertEquals(1, metrics.count('NewTabPage.Modules.Loaded', 5));
diff --git a/chrome/test/data/webui/new_tab_page/modules/module_wrapper_test.js b/chrome/test/data/webui/new_tab_page/modules/module_wrapper_test.js
index 1288d6db..526801e 100644
--- a/chrome/test/data/webui/new_tab_page/modules/module_wrapper_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/module_wrapper_test.js
@@ -42,8 +42,8 @@
     windowProxy.setResultFor('now', 123);
 
     // Act.
-    moduleWrapper.descriptor = {
-      id: 'foo',
+    moduleWrapper.module = {
+      descriptor: {id: 'foo'},
       element: moduleElement,
     };
     await detectedImpression;
@@ -60,13 +60,13 @@
 
   test('descriptor can only be set once', () => {
     const moduleElement = document.createElement('div');
-    moduleWrapper.descriptor = {
-      id: 'foo',
+    moduleWrapper.module = {
+      descriptor: {id: 'foo'},
       element: moduleElement,
     };
     assertThrows(() => {
-      moduleWrapper.descriptor = {
-        id: 'foo',
+      moduleWrapper.module = {
+        descriptor: {id: 'foo'},
         element: moduleElement,
       };
     });
@@ -75,8 +75,8 @@
   test('receiving usage events records usage', () => {
     // Arrange.
     const moduleElement = document.createElement('div');
-    moduleWrapper.descriptor = {
-      id: 'foo',
+    moduleWrapper.module = {
+      descriptor: {id: 'foo'},
       element: moduleElement,
     };
 
diff --git a/chrome/test/data/webui/new_tab_page/modules/task_module/module_test.js b/chrome/test/data/webui/new_tab_page/modules/task_module/module_test.js
index 5a6e440..d6f362ae 100644
--- a/chrome/test/data/webui/new_tab_page/modules/task_module/module_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/task_module/module_test.js
@@ -28,11 +28,11 @@
         'getPrimaryTask', Promise.resolve({task: null}));
 
     // Act.
-    await shoppingTasksDescriptor.initialize();
+    const moduleElement = await shoppingTasksDescriptor.initialize();
 
     // Assert.
     assertEquals(1, testProxy.handler.getCallCount('getPrimaryTask'));
-    assertEquals(null, shoppingTasksDescriptor.element);
+    assertEquals(null, moduleElement);
   });
 
   test('creates module if task', async () => {
@@ -69,8 +69,7 @@
     testProxy.handler.setResultFor('getPrimaryTask', Promise.resolve({task}));
 
     // Act.
-    await shoppingTasksDescriptor.initialize();
-    const moduleElement = shoppingTasksDescriptor.element;
+    const moduleElement = await shoppingTasksDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.taskItemsRepeat.render();
     moduleElement.$.relatedSearchesRepeat.render();
@@ -123,8 +122,7 @@
                                     })),
       }
     }));
-    await shoppingTasksDescriptor.initialize();
-    const moduleElement = shoppingTasksDescriptor.element;
+    const moduleElement = await shoppingTasksDescriptor.initialize();
     document.body.append(moduleElement);
     moduleElement.$.taskItemsRepeat.render();
     moduleElement.$.relatedSearchesRepeat.render();
@@ -181,8 +179,7 @@
     testProxy.handler.setResultFor('getPrimaryTask', Promise.resolve({task}));
 
     // Arrange.
-    await shoppingTasksDescriptor.initialize();
-    const moduleElement = shoppingTasksDescriptor.element;
+    const moduleElement = await shoppingTasksDescriptor.initialize();
     document.body.append(moduleElement);
     await flushTasks();
 
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index 537400e9..6c3b5e0 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -68,6 +68,7 @@
 
     #":languages_page_tests",
     #":languages_subpage_tests",
+    #":languages_subpage_details_tests",
     #":languages_tests",
     #":metrics_reporting_tests",
     #":on_startup_page_tests",
diff --git a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
index b9d3eb3a..5be3554 100644
--- a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
@@ -119,6 +119,25 @@
   mocha.grep(languages_subpage_tests.TestNames.LanguageMenu).run();
 });
 
+GEN('#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS)');
+// eslint-disable-next-line no-var
+var CrSettingsLanguagesSubpageDetailedV3Test =
+    class extends CrSettingsV3BrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://settings/test_loader.html?module=settings/languages_subpage_details_tests.js';
+  }
+};
+
+TEST_F(
+    'CrSettingsLanguagesSubpageDetailedV3Test', 'AlwaysTranslateDialog',
+    function() {
+      mocha
+          .grep(languages_subpage_details_tests.TestNames.AlwaysTranslateDialog)
+          .run();
+    });
+GEN('#endif');
+
 // eslint-disable-next-line no-var
 var CrSettingsLanguagesPageMetricsV3Test =
     class extends CrSettingsV3BrowserTest {
diff --git a/chrome/test/data/webui/settings/fake_language_settings_private.js b/chrome/test/data/webui/settings/fake_language_settings_private.js
index 02b225b..24d27cf 100644
--- a/chrome/test/data/webui/settings/fake_language_settings_private.js
+++ b/chrome/test/data/webui/settings/fake_language_settings_private.js
@@ -134,9 +134,6 @@
     ];
 
     /** @type {!Array<string>} */
-    this.alwaysTranslateList = ['de, es, nl'];
-
-    /** @type {!Array<string>} */
     this.neverTranslateList = ['en, fr'];
 
     /** @type {!Array<!chrome.languageSettingsPrivate.InputMethod>} */
@@ -217,7 +214,8 @@
   getAlwaysTranslateLanguages(callback) {
     setTimeout(function() {
       callback(
-          /** @type {!Array<!string>} */ (this.alwaysTranslateList));
+          /** @type {!Array<!string>} */ (
+              this.settingsPrefs_.get('prefs.translate_whitelists.value')));
     }.bind(this));
   }
 
@@ -227,15 +225,21 @@
    * @param {boolean} alwaysTranslate
    */
   setLanguageAlwaysTranslateState(languageCode, alwaysTranslate) {
+    const alwaysTranslateList =
+        this.settingsPrefs_.get('prefs.translate_whitelists.value');
     if (alwaysTranslate) {
-      this.alwaysTranslateList.push(languageCode);
+      if (!alwaysTranslateList.includes(languageCode)) {
+        alwaysTranslateList.push(languageCode);
+      }
     } else {
-      const index = this.alwaysTranslateList.indexOf(languageCode);
+      const index = alwaysTranslateList.indexOf(languageCode);
       if (index === -1) {
         return;
       }
-      this.alwaysTranslateList.splice(index, 1);
+      alwaysTranslateList.splice(index, 1);
     }
+    this.settingsPrefs_.set(
+        'prefs.translate_whitelists.value', alwaysTranslateList);
   }
 
   /**
@@ -537,6 +541,14 @@
       type: chrome.settingsPrivate.PrefType.LIST,
       value: ['en-US'],
     },
+    // Note: The real implementation of this pref is actually a dictionary
+    // of {always translate: target}, however only the keys are needed for
+    // testing.
+    {
+      key: 'translate_whitelists',
+      type: chrome.settingsPrivate.PrefType.LIST,
+      value: [],
+    },
     {
       key: 'translate_recent_target',
       type: chrome.settingsPrivate.PrefType.STRING,
diff --git a/chrome/test/data/webui/settings/languages_subpage_details_tests.js b/chrome/test/data/webui/settings/languages_subpage_details_tests.js
new file mode 100644
index 0000000..9f6b898a
--- /dev/null
+++ b/chrome/test/data/webui/settings/languages_subpage_details_tests.js
@@ -0,0 +1,179 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// clang-format off
+import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {LanguagesBrowserProxyImpl} from 'chrome://settings/lazy_load.js';
+import {CrSettingsPrefs} from 'chrome://settings/settings.js';
+import {getFakeLanguagePrefs} from 'chrome://test/settings/fake_language_settings_private.js';
+import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.js';
+import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.js';
+import {eventToPromise, fakeDataBind} from 'chrome://test/test_util.m.js';
+
+// clang-format on
+
+window.languages_subpage_details_tests = {};
+
+/** @enum {string} */
+window.languages_subpage_details_tests.TestNames = {
+  AlwaysTranslateDialog: 'always translate dialog',
+};
+
+suite('languages subpage detailed settings', function() {
+  /** @type {?LanguageHelper} */
+  let languageHelper = null;
+  /** @type {?SettingsLanguagesPageElement} */
+  let languagesSubpage = null;
+  /** @type {?CrActionMenuElement} */
+  let actionMenu = null;
+  /** @type {?LanguagesBrowserProxy} */
+  let browserProxy = null;
+
+  // Always Translate language pref name for the platform.
+  const alwaysTranslatePref = 'translate_whitelists';
+
+  suiteSetup(function() {
+    // TODO(crbug/1109431): Update this test once migration is completed.
+    loadTimeData.overrideValues({
+      isChromeOSLanguagesSettingsUpdate: false,
+      enableDesktopDetailedLanguageSettings: true,
+    });
+    testing.Test.disableAnimationsAndTransitions();
+    PolymerTest.clearBody();
+    CrSettingsPrefs.deferInitialization = true;
+  });
+
+  setup(function() {
+    const settingsPrefs = document.createElement('settings-prefs');
+    const settingsPrivate = new FakeSettingsPrivate(getFakeLanguagePrefs());
+    settingsPrefs.initialize(settingsPrivate);
+    document.body.appendChild(settingsPrefs);
+    return CrSettingsPrefs.initialized.then(function() {
+      // Set up test browser proxy.
+      browserProxy = new TestLanguagesBrowserProxy();
+      LanguagesBrowserProxyImpl.instance_ = browserProxy;
+
+      // Set up fake languageSettingsPrivate API.
+      const languageSettingsPrivate = browserProxy.getLanguageSettingsPrivate();
+      languageSettingsPrivate.setSettingsPrefs(settingsPrefs);
+
+      const settingsLanguages = document.createElement('settings-languages');
+      settingsLanguages.prefs = settingsPrefs.prefs;
+      fakeDataBind(settingsPrefs, settingsLanguages, 'prefs');
+      document.body.appendChild(settingsLanguages);
+
+      languagesSubpage = document.createElement('settings-languages-subpage');
+
+      languagesSubpage.prefs = settingsPrefs.prefs;
+      fakeDataBind(settingsPrefs, languagesSubpage, 'prefs');
+
+      languagesSubpage.languageHelper = settingsLanguages.languageHelper;
+      fakeDataBind(settingsLanguages, languagesSubpage, 'language-helper');
+
+      languagesSubpage.languages = settingsLanguages.languages;
+      fakeDataBind(settingsLanguages, languagesSubpage, 'languages');
+
+      document.body.appendChild(languagesSubpage);
+      flush();
+      actionMenu = languagesSubpage.$$('#menu').get();
+
+      languageHelper = languagesSubpage.languageHelper;
+      return languageHelper.whenReady();
+    });
+  });
+
+  teardown(function() {
+    PolymerTest.clearBody();
+  });
+
+  suite(
+      languages_subpage_details_tests.TestNames.AlwaysTranslateDialog,
+      function() {
+        let dialog;
+        let dialogItems;
+        let cancelButton;
+        let actionButton;
+        let dialogClosedResolver;
+        let dialogClosedObserver;
+
+        // Resolves the PromiseResolver if the mutation includes removal of the
+        // settings-add-languages-dialog.
+        // TODO(michaelpg): Extract into a common method similar to
+        // whenAttributeIs for use elsewhere.
+        const onMutation = function(mutations, observer) {
+          if (mutations.some(function(mutation) {
+                return mutation.type === 'childList' &&
+                    Array.from(mutation.removedNodes).includes(dialog);
+              })) {
+            // Sanity check: the dialog should no longer be in the DOM.
+            assertEquals(
+                null, languagesSubpage.$$('settings-add-languages-dialog'));
+            observer.disconnect();
+            assertTrue(!!dialogClosedResolver);
+            dialogClosedResolver.resolve();
+          }
+        };
+
+        setup(function() {
+          const addLanguagesButton = languagesSubpage.$$('#addAlwaysTranslate');
+          const whenDialogOpen =
+              eventToPromise('cr-dialog-open', languagesSubpage);
+          addLanguagesButton.click();
+
+          // The page stamps the dialog, registers listeners, and populates the
+          // iron-list asynchronously at microtask timing, so wait for a new
+          // task.
+          return whenDialogOpen.then(() => {
+            dialog = languagesSubpage.$$('settings-add-languages-dialog');
+            assertTrue(!!dialog);
+            assertEquals(dialog.id, 'alwaysTranslateDialog');
+
+            // Observe the removal of the dialog via MutationObserver since the
+            // HTMLDialogElement 'close' event fires at an unpredictable time.
+            dialogClosedResolver = new PromiseResolver();
+            dialogClosedObserver = new MutationObserver(onMutation);
+            dialogClosedObserver.observe(
+                languagesSubpage.root, {childList: true});
+
+            actionButton = dialog.$$('.action-button');
+            cancelButton = dialog.$$('.cancel-button');
+            flush();
+
+            // The fixed-height dialog's iron-list should stamp far fewer than
+            // 50 items.
+            dialogItems =
+                dialog.$.dialog.querySelectorAll('.list-item:not([hidden])');
+          });
+        });
+
+        teardown(function() {
+          dialogClosedObserver.disconnect();
+        });
+
+        test('add languages and cancel', function() {
+          // Check some languages.
+          dialogItems[1].click();  // en-CA.
+          dialogItems[2].click();  // tk.
+
+          // Canceling the dialog should close and remove it without enabling
+          // the checked languages.
+          cancelButton.click();
+          return dialogClosedResolver.promise.then(function() {
+            assertTrue(
+                languageHelper.getPref(alwaysTranslatePref).value.length === 0);
+          });
+        });
+
+        test('add languages and confirm', function() {
+          dialog.dispatchEvent(
+              new CustomEvent('languages-added', {detail: ['en', 'no']}));
+          dialog.$.dialog.close();
+          assertDeepEquals(
+              ['en', 'no'], languageHelper.getPref(alwaysTranslatePref).value);
+
+          return dialogClosedResolver.promise;
+        });
+      });
+});
\ No newline at end of file
diff --git a/chrome/test/gpu/webgl_infobar_browsertest.cc b/chrome/test/gpu/webgl_infobar_browsertest.cc
index d57e3ba..4b3b53d0 100644
--- a/chrome/test/gpu/webgl_infobar_browsertest.cc
+++ b/chrome/test/gpu/webgl_infobar_browsertest.cc
@@ -30,6 +30,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "gpu/config/gpu_test_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/gl/gl_implementation.h"
 
@@ -42,7 +43,7 @@
   // either of the NavigateToURL entry points to support these two
   // constraints, so we use Navigate directly.
   NavigateParams params(
-      browser, GURL(content::kChromeUIGpuCrashURL),
+      browser, GURL(blink::kChromeUIGpuCrashURL),
       ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
   params.disposition = WindowOpenDisposition::NEW_BACKGROUND_TAB;
diff --git a/chromecast/media/cdm/OWNERS b/chromecast/media/cdm/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromecast/media/cdm/OWNERS
+++ /dev/null
diff --git a/chromecast/media/common/media_pipeline_backend_manager.cc b/chromecast/media/common/media_pipeline_backend_manager.cc
index b6c9b62..46c7dc8 100644
--- a/chromecast/media/common/media_pipeline_backend_manager.cc
+++ b/chromecast/media/common/media_pipeline_backend_manager.cc
@@ -266,5 +266,18 @@
   }
 }
 
+void MediaPipelineBackendManager::TemporaryDisablePowerSave() {
+  MAKE_SURE_MEDIA_THREAD(TemporaryDisablePowerSave);
+  int playing_audio_streams = TotalPlayingAudioStreamsCount();
+  if (playing_audio_streams == 0) {
+    if (VolumeControl::SetPowerSaveMode) {
+      LOG(INFO) << "Temporarily disable power save";
+      VolumeControl::SetPowerSaveMode(false);
+      power_save_timer_.Start(FROM_HERE, kPowerSaveWaitTime, this,
+                              &MediaPipelineBackendManager::EnterPowerSaveMode);
+    }
+  }
+}
+
 }  // namespace media
 }  // namespace chromecast
diff --git a/chromecast/media/common/media_pipeline_backend_manager.h b/chromecast/media/common/media_pipeline_backend_manager.h
index 5f06dc6..1f38068 100644
--- a/chromecast/media/common/media_pipeline_backend_manager.h
+++ b/chromecast/media/common/media_pipeline_backend_manager.h
@@ -132,6 +132,11 @@
   // automatic power save will be disabled until this is called with |true|.
   void SetPowerSaveEnabled(bool power_save_enabled);
 
+  // Temporarily disables power save mode even if there are no currently-playing
+  // audio streams. Useful to disable power save ahead of time if audio will
+  // start playing soon (within 5 seconds).
+  void TemporaryDisablePowerSave();
+
  private:
   friend class ActiveMediaPipelineBackendWrapper;
 
diff --git a/chromeos/dbus/biod/OWNERS b/chromeos/dbus/biod/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/dbus/biod/OWNERS
+++ /dev/null
diff --git a/chromeos/network/onc/OWNERS b/chromeos/network/onc/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/network/onc/OWNERS
+++ /dev/null
diff --git a/chromeos/network/proxy/OWNERS b/chromeos/network/proxy/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/network/proxy/OWNERS
+++ /dev/null
diff --git a/chromeos/resources/OWNERS b/chromeos/resources/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/resources/OWNERS
+++ /dev/null
diff --git a/chromeos/services/OWNERS b/chromeos/services/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/services/OWNERS
+++ /dev/null
diff --git a/chromeos/services/media_perception/OWNERS b/chromeos/services/media_perception/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/services/media_perception/OWNERS
+++ /dev/null
diff --git a/chromeos/services/secure_channel/ble_characteristics_finder_unittest.cc b/chromeos/services/secure_channel/ble_characteristics_finder_unittest.cc
index d501b445..4dc6947 100644
--- a/chromeos/services/secure_channel/ble_characteristics_finder_unittest.cc
+++ b/chromeos/services/secure_channel/ble_characteristics_finder_unittest.cc
@@ -25,6 +25,17 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using device::BluetoothAdapter;
+using device::BluetoothAdapterFactory;
+using device::BluetoothDevice;
+using device::BluetoothGattService;
+using device::BluetoothRemoteGattCharacteristic;
+using device::BluetoothRemoteGattService;
+using device::BluetoothUUID;
+using device::MockBluetoothAdapter;
+using device::MockBluetoothDevice;
+using device::MockBluetoothGattCharacteristic;
+using device::MockBluetoothGattService;
 using testing::_;
 using testing::AtLeast;
 using testing::DoAll;
@@ -53,13 +64,11 @@
 
 const char kServiceID[] = "service id";
 
-const device::BluetoothRemoteGattCharacteristic::Properties
-    kCharacteristicProperties =
-        device::BluetoothRemoteGattCharacteristic::PROPERTY_BROADCAST |
-        device::BluetoothRemoteGattCharacteristic::PROPERTY_READ |
-        device::BluetoothRemoteGattCharacteristic::
-            PROPERTY_WRITE_WITHOUT_RESPONSE |
-        device::BluetoothRemoteGattCharacteristic::PROPERTY_INDICATE;
+const BluetoothRemoteGattCharacteristic::Properties kCharacteristicProperties =
+    BluetoothRemoteGattCharacteristic::PROPERTY_BROADCAST |
+    BluetoothRemoteGattCharacteristic::PROPERTY_READ |
+    BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE |
+    BluetoothRemoteGattCharacteristic::PROPERTY_INDICATE;
 
 const char kOtherCharUUID[] = "09731422-048A-11E5-8418-1697F925EC7B";
 const char kOtherCharID[] = "other id";
@@ -95,26 +104,23 @@
 
  protected:
   SecureChannelBluetoothLowEnergyCharacteristicFinderTest()
-      : adapter_(new NiceMock<device::MockBluetoothAdapter>),
-        device_(
-            new NiceMock<device::MockBluetoothDevice>(adapter_.get(),
-                                                      0,
-                                                      kDeviceName,
-                                                      kBluetoothAddress,
-                                                      /* paired */ false,
-                                                      /* connected */ false)),
-        remote_service_({device::BluetoothUUID(kServiceUUID), ""}),
-        to_peripheral_char_({device::BluetoothUUID(kToPeripheralCharUUID), ""}),
-        from_peripheral_char_(
-            {device::BluetoothUUID(kFromPeripheralCharUUID), ""}),
+      : adapter_(new NiceMock<MockBluetoothAdapter>),
+        device_(new NiceMock<MockBluetoothDevice>(adapter_.get(),
+                                                  0,
+                                                  kDeviceName,
+                                                  kBluetoothAddress,
+                                                  /* paired */ false,
+                                                  /* connected */ false)),
+        remote_service_({BluetoothUUID(kServiceUUID), ""}),
+        to_peripheral_char_({BluetoothUUID(kToPeripheralCharUUID), ""}),
+        from_peripheral_char_({BluetoothUUID(kFromPeripheralCharUUID), ""}),
         remote_device_(multidevice::CreateRemoteDeviceRefForTest()) {
-    device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
+    BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
 
     // The default behavior for |device_| is to have no services discovered. Can
     // be overrided later.
     ON_CALL(*device_, GetGattServices())
-        .WillByDefault(
-            Return(std::vector<device::BluetoothRemoteGattService*>()));
+        .WillByDefault(Return(std::vector<BluetoothRemoteGattService*>()));
   }
 
   void SetUp() {
@@ -140,14 +146,14 @@
     test_task_runner->RunUntilIdle();
   }
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic>
-  ExpectToFindCharacteristic(const device::BluetoothUUID& uuid,
-                             const std::string& id,
-                             bool valid = true) {
-    std::unique_ptr<device::MockBluetoothGattCharacteristic> characteristic(
-        new NiceMock<device::MockBluetoothGattCharacteristic>(
+  std::unique_ptr<MockBluetoothGattCharacteristic> ExpectToFindCharacteristic(
+      const BluetoothUUID& uuid,
+      const std::string& id,
+      bool valid = true) {
+    std::unique_ptr<MockBluetoothGattCharacteristic> characteristic(
+        new NiceMock<MockBluetoothGattCharacteristic>(
             /*service=*/nullptr, id, uuid, kCharacteristicProperties,
-            device::BluetoothRemoteGattCharacteristic::PERMISSION_NONE));
+            BluetoothRemoteGattCharacteristic::PERMISSION_NONE));
 
     ON_CALL(*characteristic.get(), GetUUID()).WillByDefault(Return(uuid));
     if (valid)
@@ -155,25 +161,23 @@
     return characteristic;
   }
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic>
-  ExpectEidCharacteristic(const std::string& id,
-                          bool read_success,
-                          bool correct_eid) {
-    std::unique_ptr<device::MockBluetoothGattCharacteristic> characteristic =
-        ExpectToFindCharacteristic(
-            device::BluetoothUUID(kEidCharacteristicUUID), id);
+  std::unique_ptr<MockBluetoothGattCharacteristic> ExpectEidCharacteristic(
+      const std::string& id,
+      bool read_success,
+      bool correct_eid) {
+    std::unique_ptr<MockBluetoothGattCharacteristic> characteristic =
+        ExpectToFindCharacteristic(BluetoothUUID(kEidCharacteristicUUID), id);
 
     // Posting to a task to allow the read to be asynchronous, although still
     // running only on one thread. Calls to
     // |task_environment_.RunUntilIdle()| in tests will process any
     // pending callbacks.
     ON_CALL(*characteristic.get(), ReadRemoteCharacteristic_(_, _))
-        .WillByDefault(
-            Invoke([read_success, correct_eid](
-                       device::BluetoothRemoteGattCharacteristic::ValueCallback&
-                           callback,
-                       device::BluetoothRemoteGattCharacteristic::ErrorCallback&
-                           error_callback) {
+        .WillByDefault(Invoke(
+            [read_success, correct_eid](
+                BluetoothRemoteGattCharacteristic::ValueCallback& callback,
+                BluetoothRemoteGattCharacteristic::ErrorCallback&
+                    error_callback) {
               base::ThreadTaskRunnerHandle::Get()->PostTask(
                   FROM_HERE,
                   read_success
@@ -182,19 +186,19 @@
                                                    : GetIncorrectEidValue())
                       : base::BindOnce(
                             std::move(error_callback),
-                            device::BluetoothGattService::GATT_ERROR_FAILED));
+                            BluetoothGattService::GATT_ERROR_FAILED));
             }));
     return characteristic;
   }
 
-  device::MockBluetoothGattService* SetUpServiceWithCharacteristics(
+  MockBluetoothGattService* SetUpServiceWithCharacteristics(
       const std::string& service_id,
-      std::vector<device::MockBluetoothGattCharacteristic*> characteristics,
+      std::vector<MockBluetoothGattCharacteristic*> characteristics,
       bool is_discovery_complete) {
-    auto service = std::make_unique<NiceMock<device::MockBluetoothGattService>>(
-        device_.get(), service_id, device::BluetoothUUID(kServiceUUID),
+    auto service = std::make_unique<NiceMock<MockBluetoothGattService>>(
+        device_.get(), service_id, BluetoothUUID(kServiceUUID),
         /*is_primary=*/true);
-    device::MockBluetoothGattService* service_ptr = service.get();
+    MockBluetoothGattService* service_ptr = service.get();
     services_.push_back(std::move(service));
     ON_CALL(*device_, GetGattServices())
         .WillByDefault(Return(GetRawServiceList()));
@@ -205,7 +209,7 @@
         .WillByDefault(Return(service_ptr));
 
     for (auto* characteristic : characteristics) {
-      std::vector<device::BluetoothRemoteGattCharacteristic*> chars_for_uuid{
+      std::vector<BluetoothRemoteGattCharacteristic*> chars_for_uuid{
           characteristic};
       ON_CALL(*service_ptr, GetCharacteristicsByUUID(characteristic->GetUUID()))
           .WillByDefault(Return(chars_for_uuid));
@@ -215,25 +219,25 @@
     return service_ptr;
   }
 
-  device::MockBluetoothGattService* SetUpServiceWithIds(
+  MockBluetoothGattService* SetUpServiceWithIds(
       const std::string& service_id,
       const std::string& from_char_id,
       const std::string& to_char_id,
       const std::string& eid_char_id = std::string(),
       bool correct_eid_value = true) {
-    std::unique_ptr<device::MockBluetoothGattCharacteristic> from_char =
-        ExpectToFindCharacteristic(
-            device::BluetoothUUID(kFromPeripheralCharUUID), from_char_id);
-    std::unique_ptr<device::MockBluetoothGattCharacteristic> to_char =
-        ExpectToFindCharacteristic(device::BluetoothUUID(kToPeripheralCharUUID),
+    std::unique_ptr<MockBluetoothGattCharacteristic> from_char =
+        ExpectToFindCharacteristic(BluetoothUUID(kFromPeripheralCharUUID),
+                                   from_char_id);
+    std::unique_ptr<MockBluetoothGattCharacteristic> to_char =
+        ExpectToFindCharacteristic(BluetoothUUID(kToPeripheralCharUUID),
                                    to_char_id);
-    std::vector<device::MockBluetoothGattCharacteristic*> characteristics{
+    std::vector<MockBluetoothGattCharacteristic*> characteristics{
         from_char.get(), to_char.get()};
     all_mock_characteristics_.push_back(std::move(from_char));
     all_mock_characteristics_.push_back(std::move(to_char));
 
     if (!eid_char_id.empty()) {
-      std::unique_ptr<device::MockBluetoothGattCharacteristic> eid_char =
+      std::unique_ptr<MockBluetoothGattCharacteristic> eid_char =
           ExpectEidCharacteristic(eid_char_id, /* read_success */ true,
                                   correct_eid_value);
       characteristics.push_back(eid_char.get());
@@ -254,8 +258,8 @@
     return fake_background_eid_generator;
   }
 
-  std::vector<device::BluetoothRemoteGattService*> GetRawServiceList() {
-    std::vector<device::BluetoothRemoteGattService*> service_list_raw;
+  std::vector<BluetoothRemoteGattService*> GetRawServiceList() {
+    std::vector<BluetoothRemoteGattService*> service_list_raw;
     std::transform(services_.begin(), services_.end(),
                    std::back_inserter(service_list_raw),
                    [](auto& service) { return service.get(); });
@@ -270,10 +274,10 @@
   std::unique_ptr<BluetoothLowEnergyCharacteristicsFinder>
       characteristic_finder_;
   base::test::TaskEnvironment task_environment_;
-  scoped_refptr<device::MockBluetoothAdapter> adapter_;
-  std::unique_ptr<device::MockBluetoothDevice> device_;
-  std::vector<std::unique_ptr<device::BluetoothRemoteGattService>> services_;
-  std::vector<std::unique_ptr<device::MockBluetoothGattCharacteristic>>
+  scoped_refptr<MockBluetoothAdapter> adapter_;
+  std::unique_ptr<MockBluetoothDevice> device_;
+  std::vector<std::unique_ptr<BluetoothRemoteGattService>> services_;
+  std::vector<std::unique_ptr<MockBluetoothGattCharacteristic>>
       all_mock_characteristics_;
   FakeBackgroundEidGenerator* fake_background_eid_generator_;
   RemoteAttribute remote_service_;
@@ -316,10 +320,9 @@
 TEST_F(SecureChannelBluetoothLowEnergyCharacteristicFinderTest,
        FindRightCharacteristicsWrongDevice) {
   // Make CharacteristicFinder which is supposed to listen for other device.
-  std::unique_ptr<device::BluetoothDevice> device(
-      new NiceMock<device::MockBluetoothDevice>(
-          adapter_.get(), 0, kDeviceName, kBluetoothAddress,
-          /* connected */ false, /* paired */ false));
+  std::unique_ptr<BluetoothDevice> device(new NiceMock<MockBluetoothDevice>(
+      adapter_.get(), 0, kDeviceName, kBluetoothAddress,
+      /* connected */ false, /* paired */ false));
   BluetoothLowEnergyCharacteristicsFinder characteristic_finder(
       adapter_, device.get(), remote_service_, to_peripheral_char_,
       from_peripheral_char_,
@@ -330,8 +333,8 @@
                          OnCharacteristicsFinderError,
                      base::Unretained(this)),
       remote_device_, CreateBackgroundEidGenerator());
-  device::BluetoothAdapter::Observer* observer =
-      static_cast<device::BluetoothAdapter::Observer*>(&characteristic_finder);
+  BluetoothAdapter::Observer* observer =
+      static_cast<BluetoothAdapter::Observer*>(&characteristic_finder);
 
   RemoteAttribute found_to_char, found_from_char;
   // These shouldn't be called at all since the GATT events below are for other
@@ -339,15 +342,15 @@
   EXPECT_CALL(*this, OnCharacteristicsFound(_, _, _)).Times(0);
   EXPECT_CALL(*this, OnCharacteristicsFinderError()).Times(0);
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> from_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kFromPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> from_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kFromPeripheralCharUUID),
                                  kFromPeripheralCharID);
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> to_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kToPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> to_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kToPeripheralCharUUID),
                                  kToPeripheralCharID);
 
-  std::vector<device::MockBluetoothGattCharacteristic*> characteristics{
-      from_char.get(), to_char.get()};
+  std::vector<MockBluetoothGattCharacteristic*> characteristics{from_char.get(),
+                                                                to_char.get()};
   SetUpServiceWithCharacteristics(kServiceID, characteristics,
                                   /* is_discovery_complete */ false);
 
@@ -359,10 +362,10 @@
   EXPECT_CALL(*this, OnCharacteristicsFound(_, _, _)).Times(0);
   EXPECT_CALL(*this, OnCharacteristicsFinderError());
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> other_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kOtherCharUUID),
-                                 kOtherCharID, /* valid */ false);
-  std::vector<device::MockBluetoothGattCharacteristic*> characteristics{
+  std::unique_ptr<MockBluetoothGattCharacteristic> other_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kOtherCharUUID), kOtherCharID,
+                                 /* valid */ false);
+  std::vector<MockBluetoothGattCharacteristic*> characteristics{
       other_char.get()};
   SetUpServiceWithCharacteristics(kServiceID, characteristics,
                                   /* is_discovery_complete */ false);
@@ -383,10 +386,10 @@
   EXPECT_CALL(*this, OnCharacteristicsFound(_, _, _)).Times(0);
   EXPECT_CALL(*this, OnCharacteristicsFinderError());
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> from_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kFromPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> from_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kFromPeripheralCharUUID),
                                  kFromPeripheralCharID);
-  std::vector<device::MockBluetoothGattCharacteristic*> characteristics{
+  std::vector<MockBluetoothGattCharacteristic*> characteristics{
       from_char.get()};
   SetUpServiceWithCharacteristics(kServiceID, characteristics,
                                   /* is_discovery_complete */ true);
@@ -402,16 +405,16 @@
           DoAll(SaveArg<1>(&found_to_char), SaveArg<2>(&found_from_char)));
   EXPECT_CALL(*this, OnCharacteristicsFinderError()).Times(0);
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> other_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kOtherCharUUID),
-                                 kOtherCharID, /* valid */ false);
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> from_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kFromPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> other_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kOtherCharUUID), kOtherCharID,
+                                 /* valid */ false);
+  std::unique_ptr<MockBluetoothGattCharacteristic> from_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kFromPeripheralCharUUID),
                                  kFromPeripheralCharID);
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> to_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kToPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> to_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kToPeripheralCharUUID),
                                  kToPeripheralCharID);
-  std::vector<device::MockBluetoothGattCharacteristic*> characteristics{
+  std::vector<MockBluetoothGattCharacteristic*> characteristics{
       other_char.get(), from_char.get(), to_char.get()};
   SetUpServiceWithCharacteristics(kServiceID, characteristics,
                                   /* is_discovery_complete */ false);
@@ -430,16 +433,16 @@
           DoAll(SaveArg<1>(&found_to_char), SaveArg<2>(&found_from_char)));
   EXPECT_CALL(*this, OnCharacteristicsFinderError()).Times(0);
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> from_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kFromPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> from_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kFromPeripheralCharUUID),
                                  kFromPeripheralCharID);
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> to_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kToPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> to_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kToPeripheralCharUUID),
                                  kToPeripheralCharID);
 
-  std::vector<device::MockBluetoothGattCharacteristic*> characteristics{
-      from_char.get(), to_char.get()};
+  std::vector<MockBluetoothGattCharacteristic*> characteristics{from_char.get(),
+                                                                to_char.get()};
   SetUpServiceWithCharacteristics(kServiceID, characteristics,
                                   /* is_discovery_complete */ true);
 
@@ -485,19 +488,19 @@
   EXPECT_CALL(*this, OnCharacteristicsFound(_, _, _)).Times(0);
   EXPECT_CALL(*this, OnCharacteristicsFinderError());
 
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> from_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kFromPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> from_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kFromPeripheralCharUUID),
                                  kFromPeripheralCharID);
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> to_char =
-      ExpectToFindCharacteristic(device::BluetoothUUID(kToPeripheralCharUUID),
+  std::unique_ptr<MockBluetoothGattCharacteristic> to_char =
+      ExpectToFindCharacteristic(BluetoothUUID(kToPeripheralCharUUID),
                                  kToPeripheralCharID);
   // NOTE: Explicitly passing false for read_success so that the GATT read
   // fails.
-  std::unique_ptr<device::MockBluetoothGattCharacteristic> eid_char =
+  std::unique_ptr<MockBluetoothGattCharacteristic> eid_char =
       ExpectEidCharacteristic(kEidCharID, /* read_success */ false,
                               /* correct_eid */ true);
 
-  std::vector<device::MockBluetoothGattCharacteristic*> characteristics{
+  std::vector<MockBluetoothGattCharacteristic*> characteristics{
       from_char.get(), to_char.get(), eid_char.get()};
   SetUpServiceWithCharacteristics(kServiceID, characteristics,
                                   /* is_discovery_complete */ false);
diff --git a/chromeos/strings/OWNERS b/chromeos/strings/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/strings/OWNERS
+++ /dev/null
diff --git a/chromeos/system/OWNERS b/chromeos/system/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/system/OWNERS
+++ /dev/null
diff --git a/chromeos/test/OWNERS b/chromeos/test/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/test/OWNERS
+++ /dev/null
diff --git a/chromeos/third_party/OWNERS b/chromeos/third_party/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/third_party/OWNERS
+++ /dev/null
diff --git a/chromeos/tools/OWNERS b/chromeos/tools/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/tools/OWNERS
+++ /dev/null
diff --git a/chromeos/tpm/OWNERS b/chromeos/tpm/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/chromeos/tpm/OWNERS
+++ /dev/null
diff --git a/components/about_ui/android/OWNERS b/components/about_ui/android/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/components/about_ui/android/OWNERS
+++ /dev/null
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index f7c7ff6..54d3988 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -354,6 +354,8 @@
     "test/fake_backup_settings_instance.h",
     "test/fake_bluetooth_instance.cc",
     "test/fake_bluetooth_instance.h",
+    "test/fake_cast_receiver_instance.cc",
+    "test/fake_cast_receiver_instance.h",
     "test/fake_clipboard_instance.cc",
     "test/fake_clipboard_instance.h",
     "test/fake_dark_theme_instance.cc",
@@ -372,6 +374,8 @@
     "test/fake_policy_instance.h",
     "test/fake_power_instance.cc",
     "test/fake_power_instance.h",
+    "test/fake_sharesheet_instance.cc",
+    "test/fake_sharesheet_instance.h",
     "test/fake_snapshot_reboot_notification.cc",
     "test/fake_snapshot_reboot_notification.h",
     "test/fake_storage_manager_instance.cc",
diff --git a/components/arc/ime/arc_ime_service.cc b/components/arc/ime/arc_ime_service.cc
index bdccd1cc..ca37a5d9 100644
--- a/components/arc/ime/arc_ime_service.cc
+++ b/components/arc/ime/arc_ime_service.cc
@@ -512,6 +512,11 @@
   return cursor_rect_;
 }
 
+gfx::Rect ArcImeService::GetSelectionBoundingBox() const {
+  NOTIMPLEMENTED_LOG_ONCE();
+  return gfx::Rect();
+}
+
 bool ArcImeService::GetTextRange(gfx::Range* range) const {
   if (!text_range_.IsValid())
     return false;
diff --git a/components/arc/ime/arc_ime_service.h b/components/arc/ime/arc_ime_service.h
index d80dc27a..c8d8e80 100644
--- a/components/arc/ime/arc_ime_service.h
+++ b/components/arc/ime/arc_ime_service.h
@@ -119,6 +119,7 @@
   void InsertChar(const ui::KeyEvent& event) override;
   ui::TextInputType GetTextInputType() const override;
   gfx::Rect GetCaretBounds() const override;
+  gfx::Rect GetSelectionBoundingBox() const override;
   bool GetTextRange(gfx::Range* range) const override;
   bool GetEditableSelectionRange(gfx::Range* range) const override;
   bool GetTextFromRange(const gfx::Range& range,
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.cc b/components/arc/intent_helper/arc_intent_helper_bridge.cc
index 00521b9..36d608ad 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge.cc
+++ b/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -91,6 +91,12 @@
 }
 
 // static
+ArcIntentHelperBridge* ArcIntentHelperBridge::GetForBrowserContextForTesting(
+    content::BrowserContext* context) {
+  return ArcIntentHelperBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
+// static
 KeyedServiceBaseFactory* ArcIntentHelperBridge::GetFactory() {
   return ArcIntentHelperBridgeFactory::GetInstance();
 }
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.h b/components/arc/intent_helper/arc_intent_helper_bridge.h
index c4c865e5..f910a59 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge.h
+++ b/components/arc/intent_helper/arc_intent_helper_bridge.h
@@ -51,6 +51,8 @@
   // or nullptr if the browser |context| is not allowed to use ARC.
   static ArcIntentHelperBridge* GetForBrowserContext(
       content::BrowserContext* context);
+  static ArcIntentHelperBridge* GetForBrowserContextForTesting(
+      content::BrowserContext* context);
 
   // Returns factory for the ArcIntentHelperBridge.
   static KeyedServiceBaseFactory* GetFactory();
diff --git a/components/arc/test/fake_cast_receiver_instance.cc b/components/arc/test/fake_cast_receiver_instance.cc
new file mode 100644
index 0000000..d6b6e51
--- /dev/null
+++ b/components/arc/test/fake_cast_receiver_instance.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/test/fake_cast_receiver_instance.h"
+
+#include <utility>
+
+namespace arc {
+
+FakeCastReceiverInstance::FakeCastReceiverInstance() = default;
+FakeCastReceiverInstance::~FakeCastReceiverInstance() = default;
+
+void FakeCastReceiverInstance::GetName(GetNameCallback callback) {
+  std::move(callback).Run(mojom::CastReceiverInstance::Result::SUCCESS,
+                          "cast name");
+}
+
+void FakeCastReceiverInstance::SetEnabled(bool enabled,
+                                          SetEnabledCallback callback) {
+  last_enabled_ = enabled;
+  std::move(callback).Run(mojom::CastReceiverInstance::Result::SUCCESS);
+}
+
+void FakeCastReceiverInstance::SetName(const std::string& name,
+                                       SetNameCallback callback) {
+  last_name_ = name;
+  std::move(callback).Run(mojom::CastReceiverInstance::Result::SUCCESS);
+}
+
+}  // namespace arc
diff --git a/components/arc/test/fake_cast_receiver_instance.h b/components/arc/test/fake_cast_receiver_instance.h
new file mode 100644
index 0000000..15e7a794
--- /dev/null
+++ b/components/arc/test/fake_cast_receiver_instance.h
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ARC_TEST_FAKE_CAST_RECEIVER_INSTANCE_H_
+#define COMPONENTS_ARC_TEST_FAKE_CAST_RECEIVER_INSTANCE_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "components/arc/mojom/cast_receiver.mojom.h"
+
+namespace arc {
+
+class FakeCastReceiverInstance : public mojom::CastReceiverInstance {
+ public:
+  FakeCastReceiverInstance();
+  FakeCastReceiverInstance(const FakeCastReceiverInstance&) = delete;
+  FakeCastReceiverInstance& operator=(const FakeCastReceiverInstance&) = delete;
+  ~FakeCastReceiverInstance() override;
+
+  // mojom::CastReceiverInstance overrides:
+  using GetNameCallback =
+      base::OnceCallback<void(mojom::CastReceiverInstance::Result,
+                              const std::string&)>;
+  void GetName(GetNameCallback callback) override;
+
+  using SetEnabledCallback =
+      base::OnceCallback<void(mojom::CastReceiverInstance::Result)>;
+  void SetEnabled(bool enabled, SetEnabledCallback callback) override;
+
+  using SetNameCallback =
+      base::OnceCallback<void(mojom::CastReceiverInstance::Result)>;
+  void SetName(const std::string& name, SetNameCallback callback) override;
+
+  const base::Optional<bool>& last_enabled() const { return last_enabled_; }
+  const base::Optional<std::string>& last_name() const { return last_name_; }
+
+ private:
+  base::Optional<bool> last_enabled_;
+  base::Optional<std::string> last_name_;
+};
+
+}  // namespace arc
+
+#endif  // COMPONENTS_ARC_TEST_FAKE_CAST_RECEIVER_INSTANCE_H_
diff --git a/components/arc/test/fake_sharesheet_instance.cc b/components/arc/test/fake_sharesheet_instance.cc
new file mode 100644
index 0000000..65d4f14
--- /dev/null
+++ b/components/arc/test/fake_sharesheet_instance.cc
@@ -0,0 +1,23 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "components/arc/test/fake_sharesheet_instance.h"
+
+namespace arc {
+
+FakeSharesheetInstance::FakeSharesheetInstance() = default;
+FakeSharesheetInstance::~FakeSharesheetInstance() = default;
+
+void FakeSharesheetInstance::Init(
+    mojo::PendingRemote<mojom::SharesheetHost> host_remote,
+    InitCallback callback) {
+  ++num_init_called_;
+  host_remote_.reset();
+  host_remote_.Bind(std::move(host_remote));
+  std::move(callback).Run();
+}
+
+}  // namespace arc
diff --git a/components/arc/test/fake_sharesheet_instance.h b/components/arc/test/fake_sharesheet_instance.h
new file mode 100644
index 0000000..28fd8dc
--- /dev/null
+++ b/components/arc/test/fake_sharesheet_instance.h
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ARC_TEST_FAKE_SHARESHEET_INSTANCE_H_
+#define COMPONENTS_ARC_TEST_FAKE_SHARESHEET_INSTANCE_H_
+
+#include "components/arc/mojom/sharesheet.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace arc {
+
+class FakeSharesheetInstance : public mojom::SharesheetInstance {
+ public:
+  FakeSharesheetInstance();
+  FakeSharesheetInstance(const FakeSharesheetInstance&) = delete;
+  FakeSharesheetInstance& operator=(const FakeSharesheetInstance&) = delete;
+  ~FakeSharesheetInstance() override;
+
+  // mojom::SharesheetInstance overrides:
+  void Init(mojo::PendingRemote<mojom::SharesheetHost> host_remote,
+            InitCallback callback) override;
+
+  size_t num_init_called() const { return num_init_called_; }
+
+ private:
+  mojo::Remote<mojom::SharesheetHost> host_remote_;
+  size_t num_init_called_ = 0;
+};
+
+}  // namespace arc
+
+#endif  // COMPONENTS_ARC_TEST_FAKE_SHARESHEET_INSTANCE_H_
diff --git a/components/cast/named_message_port_connector/named_message_port_connector.cc b/components/cast/named_message_port_connector/named_message_port_connector.cc
index 31138dc..9828dc8 100644
--- a/components/cast/named_message_port_connector/named_message_port_connector.cc
+++ b/components/cast/named_message_port_connector/named_message_port_connector.cc
@@ -46,7 +46,6 @@
     std::string* message,
     std::unique_ptr<MessagePort>* port) {
   constexpr char kControlPortConnectMessage[] = "cast.master.connect";
-  std::unique_ptr<MessagePort> control_port_for_web_engine;
   MessagePort::CreatePair(&control_port_, port);
   *message = kControlPortConnectMessage;
   control_port_->SetReceiver(this);
diff --git a/components/exo/text_input.cc b/components/exo/text_input.cc
index 8e33754..f3539f40 100644
--- a/components/exo/text_input.cc
+++ b/components/exo/text_input.cc
@@ -180,6 +180,11 @@
   return caret_bounds_ + window_->GetBoundsInScreen().OffsetFromOrigin();
 }
 
+gfx::Rect TextInput::GetSelectionBoundingBox() const {
+  NOTIMPLEMENTED();
+  return gfx::Rect();
+}
+
 bool TextInput::GetCompositionCharacterBounds(uint32_t index,
                                               gfx::Rect* rect) const {
   return false;
diff --git a/components/exo/text_input.h b/components/exo/text_input.h
index bdb6c22..14513ebd1 100644
--- a/components/exo/text_input.h
+++ b/components/exo/text_input.h
@@ -116,6 +116,7 @@
   int GetTextInputFlags() const override;
   bool CanComposeInline() const override;
   gfx::Rect GetCaretBounds() const override;
+  gfx::Rect GetSelectionBoundingBox() const override;
   bool GetCompositionCharacterBounds(uint32_t index,
                                      gfx::Rect* rect) const override;
   bool HasCompositionText() const override;
diff --git a/components/history/ios/OWNERS b/components/history/ios/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/components/history/ios/OWNERS
+++ /dev/null
diff --git a/components/history_clusters/core/memories_remote_model_helper.cc b/components/history_clusters/core/memories_remote_model_helper.cc
index c5ae9ac8..6be5ae3 100644
--- a/components/history_clusters/core/memories_remote_model_helper.cc
+++ b/components/history_clusters/core/memories_remote_model_helper.cc
@@ -136,10 +136,8 @@
     const std::vector<MemoriesVisit>& visits,
     MemoriesCallback callback) {
   const GURL endpoint(memories::RemoteModelEndpoint());
-  if (!endpoint.is_valid() || visits.empty()) {
-    std::move(callback).Run({});
-    return;
-  }
+  if (!endpoint.is_valid())
+    NOTREACHED();
   StopPendingRequests();
 
   std::string request_body;
diff --git a/components/history_clusters/core/memories_service.cc b/components/history_clusters/core/memories_service.cc
index eb231ea..6ae6b00d 100644
--- a/components/history_clusters/core/memories_service.cc
+++ b/components/history_clusters/core/memories_service.cc
@@ -51,9 +51,11 @@
   }
 }
 
-void MemoriesService::QueryMemories(const std::string& query,
-                                    MemoriesCallback callback) {
-  remote_model_helper_->GetMemories(visits_, std::move(callback));
+void MemoriesService::GetMemories(MemoriesCallback callback) {
+  if (visits_.empty())
+    std::move(callback).Run({});
+  else
+    remote_model_helper_->GetMemories(visits_, std::move(callback));
 }
 
 }  // namespace memories
diff --git a/components/history_clusters/core/memories_service.h b/components/history_clusters/core/memories_service.h
index c9619535..49cf983 100644
--- a/components/history_clusters/core/memories_service.h
+++ b/components/history_clusters/core/memories_service.h
@@ -7,7 +7,6 @@
 
 #include <map>
 #include <memory>
-#include <string>
 #include <vector>
 
 #include "base/macros.h"
@@ -47,8 +46,7 @@
   void CompleteVisitIfReady(int64_t nav_id);
 
   // Asks |remote_model_helper_| to construct memories from |visits_|.
-  // Note: |query| is ignored at the moment.
-  void QueryMemories(const std::string& query, MemoriesCallback callback);
+  void GetMemories(MemoriesCallback callback);
 
  private:
   friend class MemoriesServiceTestApi;
diff --git a/components/history_clusters/core/memories_service_unittest.cc b/components/history_clusters/core/memories_service_unittest.cc
index cea2d470..5777491 100644
--- a/components/history_clusters/core/memories_service_unittest.cc
+++ b/components/history_clusters/core/memories_service_unittest.cc
@@ -105,7 +105,7 @@
   int64_t next_navigation_id_ = 0;
 };
 
-TEST_F(MemoriesServiceTest, QueryMemories) {
+TEST_F(MemoriesServiceTest, GetMemories) {
   const char endpoint[] = "https://endpoint.com/";
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeatureWithParameters(
@@ -127,8 +127,8 @@
   AddVisitWithDetails(4, GURL{"https://github.com"}, u"Github title", 4, 5);
 
   EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-  memories_service_->QueryMemories(
-      "", base::BindLambdaForTesting([&](memories::Memories memories) {
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
         // Verify the parsed response.
         ASSERT_EQ(memories.size(), 2u);
         EXPECT_FALSE(memories[0]->id.is_empty());
@@ -216,14 +216,14 @@
   run_loop_.Run();
 }
 
-TEST_F(MemoriesServiceTest, QueryMemoriesWithEmptyVisits) {
+TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyVisits) {
   const char endpoint[] = "https://endpoint.com/";
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeatureWithParameters(
       memories::kMemories, {{memories::kRemoteModelEndpointParam, endpoint}});
 
-  memories_service_->QueryMemories(
-      "", base::BindLambdaForTesting([&](memories::Memories memories) {
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
         // Verify the parsed response.
         EXPECT_TRUE(memories.empty());
         run_loop_quit_.Run();
@@ -236,7 +236,7 @@
   run_loop_.Run();
 }
 
-TEST_F(MemoriesServiceTest, QueryMemoriesWithEmptyEndpoint) {
+TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyEndpoint) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeatureWithParameters(
       memories::kMemories, {{memories::kRemoteModelEndpointParam, ""}});
@@ -244,22 +244,14 @@
   AddVisit(0, GURL{"google.com"});
   AddVisit(1, GURL{"github.com"});
 
-  EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
-  memories_service_->QueryMemories(
-      "", base::BindLambdaForTesting([&](memories::Memories memories) {
-        // Verify the empty response.
-        EXPECT_TRUE(memories.empty());
-        run_loop_quit_.Run();
-      }));
+  EXPECT_DCHECK_DEATH(memories_service_->GetMemories(base::BindLambdaForTesting(
+      [&](memories::Memories memories) { NOTREACHED(); })));
 
   // Verify no request is made.
   EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
-
-  // Verify the callback is invoked.
-  run_loop_.Run();
 }
 
-TEST_F(MemoriesServiceTest, QueryMemoriesWithEmptyResponse) {
+TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyResponse) {
   const char endpoint[] = "https://endpoint.com/";
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeatureWithParameters(
@@ -269,8 +261,8 @@
   AddVisit(1, GURL{"github.com"});
 
   EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-  memories_service_->QueryMemories(
-      "", base::BindLambdaForTesting([&](memories::Memories memories) {
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
         // Verify the parsed response.
         EXPECT_TRUE(memories.empty());
         run_loop_quit_.Run();
@@ -287,7 +279,7 @@
   run_loop_.Run();
 }
 
-TEST_F(MemoriesServiceTest, QueryMemoriesWithInvalidJsonResponse) {
+TEST_F(MemoriesServiceTest, GetMemoriesWithInvalidJsonResponse) {
   const char endpoint[] = "https://endpoint.com/";
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeatureWithParameters(
@@ -297,8 +289,8 @@
   AddVisit(1, GURL{"github.com"});
 
   EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-  memories_service_->QueryMemories(
-      "", base::BindLambdaForTesting([&](memories::Memories memories) {
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
         // Verify the parsed response.
         EXPECT_TRUE(memories.empty());
         run_loop_quit_.Run();
@@ -315,7 +307,7 @@
   run_loop_.Run();
 }
 
-TEST_F(MemoriesServiceTest, QueryMemoriesWithEmptyJsonResponse) {
+TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyJsonResponse) {
   const char endpoint[] = "https://endpoint.com/";
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeatureWithParameters(
@@ -325,8 +317,8 @@
   AddVisit(1, GURL{"github.com"});
 
   EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-  memories_service_->QueryMemories(
-      "", base::BindLambdaForTesting([&](memories::Memories memories) {
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
         // Verify the parsed response.
         EXPECT_TRUE(memories.empty());
         run_loop_quit_.Run();
@@ -343,7 +335,7 @@
   run_loop_.Run();
 }
 
-TEST_F(MemoriesServiceTest, QueryMemoriesWithPendingRequest) {
+TEST_F(MemoriesServiceTest, GetMemoriesWithPendingRequest) {
   const char endpoint[] = "https://endpoint.com/";
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeatureWithParameters(
@@ -353,15 +345,15 @@
   AddVisit(1, GURL{"github.com"});
 
   EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-  memories_service_->QueryMemories(
-      "", base::BindLambdaForTesting([&](memories::Memories memories) {
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
         // Verify not reached.
         EXPECT_TRUE(false);
       }));
 
   EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
-  memories_service_->QueryMemories(
-      "", base::BindLambdaForTesting([&](memories::Memories memories) {
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
         // Verify the parsed response.
         EXPECT_EQ(memories.size(), 2u);
         run_loop_quit_.Run();
diff --git a/components/javascript_dialogs/views/OWNERS b/components/javascript_dialogs/views/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/components/javascript_dialogs/views/OWNERS
+++ /dev/null
diff --git a/components/mirroring/service/BUILD.gn b/components/mirroring/service/BUILD.gn
index fd23c82..89a59aa 100644
--- a/components/mirroring/service/BUILD.gn
+++ b/components/mirroring/service/BUILD.gn
@@ -32,8 +32,6 @@
     "value_util.h",
     "video_capture_client.cc",
     "video_capture_client.h",
-    "wifi_status_monitor.cc",
-    "wifi_status_monitor.h",
   ]
 
   public_deps = [ "//base" ]
@@ -90,7 +88,6 @@
     "session_unittest.cc",
     "udp_socket_client_unittest.cc",
     "video_capture_client_unittest.cc",
-    "wifi_status_monitor_unittest.cc",
   ]
 
   deps = [
diff --git a/components/mirroring/service/message_dispatcher_unittest.cc b/components/mirroring/service/message_dispatcher_unittest.cc
index 1f01b8ba8..04d1823 100644
--- a/components/mirroring/service/message_dispatcher_unittest.cc
+++ b/components/mirroring/service/message_dispatcher_unittest.cc
@@ -61,8 +61,8 @@
         base::BindRepeating(&MessageDispatcherTest::OnAnswerResponse,
                             base::Unretained(this)));
     message_dispatcher_->Subscribe(
-        ResponseType::STATUS_RESPONSE,
-        base::BindRepeating(&MessageDispatcherTest::OnStatusResponse,
+        ResponseType::RPC,
+        base::BindRepeating(&MessageDispatcherTest::OnRpcMessage,
                             base::Unretained(this)));
   }
   ~MessageDispatcherTest() override { task_environment_.RunUntilIdle(); }
@@ -75,8 +75,8 @@
     last_answer_response_ = response.CloneForTesting();
   }
 
-  void OnStatusResponse(const ReceiverResponse& response) {
-    last_status_response_ = response.CloneForTesting();
+  void OnRpcMessage(const ReceiverResponse& response) {
+    last_rpc_ = response.CloneForTesting();
   }
 
  protected:
@@ -96,7 +96,7 @@
   CastMessage last_outbound_message_;
   std::string last_error_message_;
   std::unique_ptr<ReceiverResponse> last_answer_response_;
-  std::unique_ptr<ReceiverResponse> last_status_response_;
+  std::unique_ptr<ReceiverResponse> last_rpc_;
 
  private:
   mojo::Receiver<mojom::CastMessageChannel> receiver_{this};
@@ -128,7 +128,7 @@
   SendInboundMessage(answer_message);
   task_environment_.RunUntilIdle();
   ASSERT_TRUE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   EXPECT_EQ(12345, last_answer_response_->sequence_number());
   EXPECT_EQ(ResponseType::ANSWER, last_answer_response_->type());
   ASSERT_TRUE(last_answer_response_->valid());
@@ -136,22 +136,28 @@
   last_answer_response_.reset();
   EXPECT_TRUE(last_error_message_.empty());
 
-  // Simulate a receiver STATUS_RESPONSE and expect that just the
-  // STATUS_RESPONSE subscriber processes the message.
-  const std::string status_response =
-      "{\"type\":\"STATUS_RESPONSE\",\"seqNum\":12345,\"result\":\"ok\","
-      "\"status\":{\"wifiSnr\":42}}";
-  const CastMessage status_message =
-      CastMessage{mojom::kWebRtcNamespace, status_response};
-  SendInboundMessage(status_message);
+  // Simulate a receiver RPC and expect that just the
+  // RPC subscriber processes the message.
+  const std::string message = "Hello from the Cast Receiver!";
+  std::string rpc_base64;
+  base::Base64Encode(message, &rpc_base64);
+  const std::string rpc =
+      R"({"sessionId": 735189,
+          "seqNum": 6789,
+          "type": "RPC",
+          "result": "ok",
+          "rpc": ")" +
+      rpc_base64 + R"("})";
+
+  const CastMessage rpc_message = CastMessage{mojom::kRemotingNamespace, rpc};
+  SendInboundMessage(rpc_message);
   task_environment_.RunUntilIdle();
   EXPECT_FALSE(last_answer_response_);
-  ASSERT_TRUE(last_status_response_);
-  EXPECT_EQ(12345, last_status_response_->sequence_number());
-  EXPECT_EQ(ResponseType::STATUS_RESPONSE, last_status_response_->type());
-  ASSERT_TRUE(last_status_response_->valid());
-  EXPECT_EQ(42, last_status_response_->status().wifi_snr);
-  last_status_response_.reset();
+  ASSERT_TRUE(last_rpc_);
+  EXPECT_EQ(6789, last_rpc_->sequence_number());
+  EXPECT_EQ(ResponseType::RPC, last_rpc_->type());
+  ASSERT_TRUE(last_rpc_->valid());
+  last_rpc_.reset();
   EXPECT_TRUE(last_error_message_.empty());
 
   // Unsubscribe from ANSWER messages, and when feeding-in an ANSWER message,
@@ -160,32 +166,32 @@
   SendInboundMessage(answer_message);
   task_environment_.RunUntilIdle();
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   EXPECT_FALSE(last_error_message_.empty());  // Expect an error reported.
   last_error_message_.clear();
 
-  // However, STATUS_RESPONSE messages should still be dispatcher to the
+  // However, RPC messages should still be dispatcher to the
   // remaining subscriber.
-  SendInboundMessage(status_message);
+  SendInboundMessage(rpc_message);
   task_environment_.RunUntilIdle();
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_TRUE(last_status_response_);
-  last_status_response_.reset();
+  EXPECT_TRUE(last_rpc_);
+  last_rpc_.reset();
   EXPECT_TRUE(last_error_message_.empty());
 
-  // Finally, unsubscribe from STATUS_RESPONSE messages, and when feeding-in
-  // either an ANSWER or a STATUS_RESPONSE message, nothing should happen.
-  message_dispatcher_->Unsubscribe(ResponseType::STATUS_RESPONSE);
+  // Finally, unsubscribe from RPC messages, and when feeding-in
+  // either an ANSWER or a RPC message, nothing should happen.
+  message_dispatcher_->Unsubscribe(ResponseType::RPC);
   SendInboundMessage(answer_message);
   task_environment_.RunUntilIdle();
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   EXPECT_FALSE(last_error_message_.empty());
   last_error_message_.clear();
-  SendInboundMessage(status_message);
+  SendInboundMessage(rpc_message);
   task_environment_.RunUntilIdle();
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   EXPECT_FALSE(last_error_message_.empty());
 }
 
@@ -195,7 +201,7 @@
   SendInboundMessage(message);
   task_environment_.RunUntilIdle();
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   EXPECT_FALSE(last_error_message_.empty());
 }
 
@@ -205,14 +211,14 @@
   SendInboundMessage(answer_message);
   task_environment_.RunUntilIdle();
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   // Messages with different namespace are ignored with no error reported.
   EXPECT_TRUE(last_error_message_.empty());
 }
 
 TEST_F(MessageDispatcherTest, RequestReply) {
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   message_dispatcher_->Unsubscribe(ResponseType::ANSWER);
   task_environment_.RunUntilIdle();
   const std::string fake_offer = "{\"type\":\"OFFER\",\"seqNum\":45623}";
@@ -233,7 +239,7 @@
   task_environment_.RunUntilIdle();
   // The answer message with mismatched sequence number is ignored.
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   EXPECT_TRUE(last_error_message_.empty());
 
   constexpr char kAnswerWithCorrectSeqNum[] = R"(
@@ -252,7 +258,7 @@
   SendInboundMessage(answer_message);
   task_environment_.RunUntilIdle();
   ASSERT_TRUE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   EXPECT_TRUE(last_error_message_.empty());
   EXPECT_EQ(45623, last_answer_response_->sequence_number());
   EXPECT_EQ(ResponseType::ANSWER, last_answer_response_->type());
@@ -264,7 +270,7 @@
   SendInboundMessage(answer_message);
   task_environment_.RunUntilIdle();
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
   EXPECT_FALSE(last_error_message_.empty());
   last_error_message_.clear();
 
@@ -279,13 +285,13 @@
   // Received the request to send the outbound message.
   EXPECT_TRUE(IsEqual(fake_message, last_outbound_message_));
   EXPECT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
 
   // Destroy the dispatcher.
   message_dispatcher_.reset();
   task_environment_.RunUntilIdle();
   ASSERT_FALSE(last_answer_response_);
-  EXPECT_FALSE(last_status_response_);
+  EXPECT_FALSE(last_rpc_);
 }
 
 }  // namespace mirroring
diff --git a/components/mirroring/service/receiver_response.cc b/components/mirroring/service/receiver_response.cc
index f3f99234..8f16652 100644
--- a/components/mirroring/service/receiver_response.cc
+++ b/components/mirroring/service/receiver_response.cc
@@ -20,8 +20,6 @@
 ResponseType ResponseTypeFromString(const std::string& type) {
   if (type == "ANSWER")
     return ResponseType::ANSWER;
-  if (type == "STATUS_RESPONSE")
-    return ResponseType::STATUS_RESPONSE;
   if (type == "CAPABILITIES_RESPONSE")
     return ResponseType::CAPABILITIES_RESPONSE;
   if (type == "RPC")
@@ -53,22 +51,6 @@
   return true;
 }
 
-bool GetDouble(const Json::Value& value, double* out) {
-  if (!value) {
-    *out = 0.0;
-    return true;
-  }
-  if (!value.isDouble()) {
-    return false;
-  }
-  const double i = value.asDouble();
-  if (i < 0) {
-    return false;
-  }
-  *out = i;
-  return true;
-}
-
 bool GetString(const Json::Value& value, std::string* out) {
   if (!value) {
     *out = {};
@@ -107,10 +89,6 @@
   return true;
 }
 
-bool GetIntArray(const Json::Value& value, std::vector<int>* out) {
-  return GetArray<int>(value, base::BindRepeating(&GetInt), out);
-}
-
 bool GetStringArray(const Json::Value& value, std::vector<std::string>* out) {
   return GetArray<std::string>(value, base::BindRepeating(&GetString), out);
 }
@@ -165,27 +143,8 @@
   return capability;
 }
 
-std::unique_ptr<ReceiverStatus> ParseStatus(const Json::Value& value) {
-  auto status = std::make_unique<ReceiverStatus>();
-  if (!GetDouble(value["wifiSnr"], &(status->wifi_snr)) ||
-      !GetIntArray(value["wifiSpeed"], &(status->wifi_speed))) {
-    return {};
-  }
-  return status;
-}
-
 }  // namespace
 
-ReceiverStatus::ReceiverStatus() = default;
-ReceiverStatus::~ReceiverStatus() = default;
-ReceiverStatus::ReceiverStatus(ReceiverStatus&& receiver_response) = default;
-ReceiverStatus::ReceiverStatus(const ReceiverStatus& receiver_response) =
-    default;
-ReceiverStatus& ReceiverStatus::operator=(ReceiverStatus&& receiver_response) =
-    default;
-ReceiverStatus& ReceiverStatus::operator=(
-    const ReceiverStatus& receiver_response) = default;
-
 ReceiverCapability::ReceiverCapability() = default;
 ReceiverCapability::~ReceiverCapability() = default;
 ReceiverCapability::ReceiverCapability(ReceiverCapability&& receiver_response) =
@@ -256,13 +215,6 @@
       }
       break;
 
-    case ResponseType::STATUS_RESPONSE:
-      response->status_ = ParseStatus(root_node["status"]);
-      if (!response->status_) {
-        response->valid_ = false;
-      }
-      break;
-
     case ResponseType::CAPABILITIES_RESPONSE:
       response->capabilities_ = ParseCapability(root_node["capabilities"]);
       if (!response->capabilities_) {
@@ -306,9 +258,6 @@
     case ResponseType::ANSWER:
       clone->answer_ = std::make_unique<openscreen::cast::Answer>(*answer_);
       break;
-    case ResponseType::STATUS_RESPONSE:
-      clone->status_ = std::make_unique<ReceiverStatus>(*status_);
-      break;
     case ResponseType::CAPABILITIES_RESPONSE:
       clone->capabilities_ =
           std::make_unique<ReceiverCapability>(*capabilities_);
diff --git a/components/mirroring/service/receiver_response.h b/components/mirroring/service/receiver_response.h
index ba68b25..b86a464 100644
--- a/components/mirroring/service/receiver_response.h
+++ b/components/mirroring/service/receiver_response.h
@@ -20,27 +20,10 @@
 enum class ResponseType {
   UNKNOWN,
   ANSWER,                 // Response to OFFER message.
-  STATUS_RESPONSE,        // Response to GET_STATUS message.
   CAPABILITIES_RESPONSE,  // Response to GET_CAPABILITIES message.
   RPC,                    // Rpc binary messages. The payload is base64 encoded.
 };
 
-struct COMPONENT_EXPORT(MIRRORING_SERVICE) ReceiverStatus {
-  ReceiverStatus();
-  ~ReceiverStatus();
-  ReceiverStatus(ReceiverStatus&& receiver_response);
-  ReceiverStatus(const ReceiverStatus& receiver_response);
-  ReceiverStatus& operator=(ReceiverStatus&& receiver_response);
-  ReceiverStatus& operator=(const ReceiverStatus& receiver_response);
-
-  // Current WiFi signal to noise ratio in decibels.
-  double wifi_snr = 0.0;
-
-  // Min, max, average, and current bandwidth in bps in order of the WiFi link.
-  // Example: [1200, 1300, 1250, 1230].
-  std::vector<int32_t> wifi_speed;
-};
-
 struct COMPONENT_EXPORT(MIRRORING_SERVICE) ReceiverCapability {
   ReceiverCapability();
   ~ReceiverCapability();
@@ -128,11 +111,6 @@
     return rpc_;
   }
 
-  const ReceiverStatus& status() const {
-    DCHECK(valid_ && type_ == ResponseType::STATUS_RESPONSE);
-    return *status_;
-  }
-
   const ReceiverCapability& capabilities() const {
     DCHECK(valid_ && type_ == ResponseType::CAPABILITIES_RESPONSE);
     return *capabilities_;
@@ -163,9 +141,6 @@
   // Contains the decoded (i.e. raw binary) RPC data.
   std::string rpc_;
 
-  // ResponseType::STATUS_RESPONSE
-  std::unique_ptr<ReceiverStatus> status_;
-
   // ResponseType::CAPABILITIES_RESPONSE
   std::unique_ptr<ReceiverCapability> capabilities_;
 
diff --git a/components/mirroring/service/receiver_response_unittest.cc b/components/mirroring/service/receiver_response_unittest.cc
index d9983fa..9005612d 100644
--- a/components/mirroring/service/receiver_response_unittest.cc
+++ b/components/mirroring/service/receiver_response_unittest.cc
@@ -79,7 +79,6 @@
   EXPECT_EQ(50691, response->answer().udp_port);
   EXPECT_EQ(std::vector<int32_t>({0, 1}), response->answer().send_indexes);
   EXPECT_EQ(std::vector<uint32_t>({40863u, 759293u}), response->answer().ssrcs);
-  EXPECT_EQ(false, response->answer().supports_wifi_status_reporting);
 }
 
 TEST_F(ReceiverResponseTest, ParseErrorMessage) {
@@ -114,28 +113,6 @@
   EXPECT_EQ(88, bar_value);
 }
 
-TEST_F(ReceiverResponseTest, ParseStatusMessage) {
-  const std::string response_string =
-      R"({"seqNum": 777,
-          "type": "STATUS_RESPONSE",
-          "result": "ok",
-          "sessionId": 12345323,
-          "status": {
-            "wifiSnr": 36.7,
-            "wifiSpeed": [1234, 5678, 3000, 3001],
-            "wifiFcsError": [12, 13, 12, 12]
-          }
-        })";
-  auto response = ReceiverResponse::Parse(response_string);
-  ASSERT_TRUE(response);
-  EXPECT_EQ(777, response->sequence_number());
-  EXPECT_EQ(ResponseType::STATUS_RESPONSE, response->type());
-  ASSERT_TRUE(response->valid());
-  EXPECT_EQ(36.7, response->status().wifi_snr);
-  const std::vector<int32_t> expect_speed({1234, 5678, 3000, 3001});
-  EXPECT_EQ(expect_speed, response->status().wifi_speed);
-}
-
 TEST_F(ReceiverResponseTest, ParseCapabilityMessage) {
   const std::string response_string =
       R"({"sessionId": 999888777,
@@ -229,7 +206,6 @@
             "sendIndexes": [0,1],
             "ssrcs": [152818,556029],
             "IV": null,
-            "receiverGetStatus": true,
             "castMode": "mirroring"
           },
           "status": null,
@@ -245,7 +221,6 @@
   EXPECT_EQ(std::vector<int32_t>({0, 1}), response->answer().send_indexes);
   EXPECT_EQ(std::vector<uint32_t>({152818u, 556029u}),
             response->answer().ssrcs);
-  EXPECT_EQ(true, response->answer().supports_wifi_status_reporting);
 }
 
 }  // namespace mirroring
diff --git a/components/mirroring/service/session.cc b/components/mirroring/service/session.cc
index 0e692a9d..4a19cc4 100644
--- a/components/mirroring/service/session.cc
+++ b/components/mirroring/service/session.cc
@@ -827,24 +827,15 @@
       media_remoter_->OnMirroringResumed();
   }
 
-  std::unique_ptr<WifiStatusMonitor> wifi_status_monitor;
-  if (answer.supports_wifi_status_reporting) {
-    wifi_status_monitor =
-        std::make_unique<WifiStatusMonitor>(message_dispatcher_.get());
-    // Nest Hub devices do not support remoting despite having a relatively new
-    // build version, so we cannot filter with
-    // NeedsWorkaroundForOlder1DotXVersions() here.
-    if (initially_starting_session &&
-        (base::StartsWith(session_params_.receiver_model_name, "Chromecast",
-                          base::CompareCase::SENSITIVE) ||
-         base::StartsWith(session_params_.receiver_model_name, "Eureka Dongle",
-                          base::CompareCase::SENSITIVE))) {
-      QueryCapabilitiesForRemoting();
-    }
-  } else {
-    LogInfoMessage(
-        base::StrCat({"Remoting is not supported on this receiver model: ",
-                      session_params_.receiver_model_name}));
+  // Nest Hub devices do not support remoting despite having a relatively new
+  // build version, so we cannot filter with
+  // NeedsWorkaroundForOlder1DotXVersions() here.
+  if (initially_starting_session &&
+      (base::StartsWith(session_params_.receiver_model_name, "Chromecast",
+                        base::CompareCase::SENSITIVE) ||
+       base::StartsWith(session_params_.receiver_model_name, "Eureka Dongle",
+                        base::CompareCase::SENSITIVE))) {
+    QueryCapabilitiesForRemoting();
   }
 
   if (initially_starting_session && observer_)
diff --git a/components/mirroring/service/session.h b/components/mirroring/service/session.h
index 623995ac..3244dd4 100644
--- a/components/mirroring/service/session.h
+++ b/components/mirroring/service/session.h
@@ -18,7 +18,6 @@
 #include "components/mirroring/service/mirror_settings.h"
 #include "components/mirroring/service/receiver_setup_querier.h"
 #include "components/mirroring/service/rtp_stream.h"
-#include "components/mirroring/service/wifi_status_monitor.h"
 #include "gpu/config/gpu_info.h"
 #include "media/capture/video/video_capture_feedback.h"
 #include "media/cast/cast_environment.h"
diff --git a/components/mirroring/service/session_unittest.cc b/components/mirroring/service/session_unittest.cc
index f61003a8e..0e547f2 100644
--- a/components/mirroring/service/session_unittest.cc
+++ b/components/mirroring/service/session_unittest.cc
@@ -65,11 +65,6 @@
         openscreen::cast::AspectRatio{16, 9},
         openscreen::cast::AspectRatioConstraint::kFixed,
     },
-    // We don't currently use the RTCP event log, or DSCP, or extensions.
-    {},
-    {},
-    true,  // receiver_get_status
-    {},
 };
 
 class MockRemotingSource final : public media::mojom::RemotingSource {
@@ -213,7 +208,6 @@
       answer.swap(answer_);
     } else {
       answer = std::make_unique<openscreen::cast::Answer>();
-      answer->supports_wifi_status_reporting = true;
     }
 
     answer->udp_port = receiver_endpoint_.port();
@@ -275,7 +269,6 @@
     EXPECT_CALL(*this, OnGetVideoCaptureHost()).Times(num_to_get_video_host);
     EXPECT_CALL(*this, OnCreateAudioStream()).Times(num_to_create_audio_stream);
     EXPECT_CALL(*this, OnError(_)).Times(0);
-    EXPECT_CALL(*this, OnOutboundMessage("GET_STATUS")).Times(AtLeast(1));
     EXPECT_CALL(*this, OnOutboundMessage("GET_CAPABILITIES")).Times(1);
     EXPECT_CALL(*this, DidStart()).Times(1);
     SendAnswer();
diff --git a/components/mirroring/service/wifi_status_monitor.cc b/components/mirroring/service/wifi_status_monitor.cc
deleted file mode 100644
index 549efa4f..0000000
--- a/components/mirroring/service/wifi_status_monitor.cc
+++ /dev/null
@@ -1,81 +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 "components/mirroring/service/wifi_status_monitor.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/check.h"
-#include "base/json/json_writer.h"
-#include "base/values.h"
-#include "components/mirroring/service/message_dispatcher.h"
-
-namespace mirroring {
-
-namespace {
-
-// The interval to query the status.
-constexpr base::TimeDelta kQueryInterval = base::TimeDelta::FromMinutes(2);
-
-// The maximum number of recent status to be kept.
-constexpr int kMaxRecords = 30;
-
-}  // namespace
-
-WifiStatusMonitor::WifiStatusMonitor(MessageDispatcher* message_dispatcher)
-    : message_dispatcher_(message_dispatcher) {
-  DCHECK(message_dispatcher_);
-  message_dispatcher_->Subscribe(
-      ResponseType::STATUS_RESPONSE,
-      base::BindRepeating(&WifiStatusMonitor::RecordStatus,
-                          base::Unretained(this)));
-  query_timer_.Start(FROM_HERE, kQueryInterval,
-                     base::BindRepeating(&WifiStatusMonitor::QueryStatus,
-                                         base::Unretained(this)));
-  QueryStatus();
-}
-
-WifiStatusMonitor::~WifiStatusMonitor() {
-  message_dispatcher_->Unsubscribe(ResponseType::STATUS_RESPONSE);
-}
-
-std::vector<WifiStatus> WifiStatusMonitor::GetRecentValues() {
-  std::vector<WifiStatus> recent_status(recent_status_.begin(),
-                                        recent_status_.end());
-  recent_status_.clear();
-  return recent_status;
-}
-
-void WifiStatusMonitor::QueryStatus() {
-  base::Value query(base::Value::Type::DICTIONARY);
-  query.SetKey("type", base::Value("GET_STATUS"));
-  query.SetKey("seqNum", base::Value(message_dispatcher_->GetNextSeqNumber()));
-  base::Value::ListStorage status;
-  status.emplace_back(base::Value("wifiSnr"));
-  status.emplace_back(base::Value("wifiSpeed"));
-  query.SetKey("get_status", base::Value(status));
-  mojom::CastMessagePtr get_status_message = mojom::CastMessage::New();
-  get_status_message->message_namespace = mojom::kWebRtcNamespace;
-  const bool did_serialize_query =
-      base::JSONWriter::Write(query, &get_status_message->json_format_data);
-  DCHECK(did_serialize_query);
-  message_dispatcher_->SendOutboundMessage(std::move(get_status_message));
-}
-
-void WifiStatusMonitor::RecordStatus(const ReceiverResponse& response) {
-  if (!response.valid() || response.status().wifi_speed.size() != 4)
-    return;
-
-  if (recent_status_.size() == kMaxRecords)
-    recent_status_.pop_front();
-
-  WifiStatus received_status;
-  received_status.snr = response.status().wifi_snr;
-  // Only records the current speed.
-  received_status.speed = response.status().wifi_speed[3];
-  received_status.timestamp = base::Time::Now();
-  recent_status_.emplace_back(received_status);
-}
-
-}  // namespace mirroring
diff --git a/components/mirroring/service/wifi_status_monitor.h b/components/mirroring/service/wifi_status_monitor.h
deleted file mode 100644
index ba25a3f..0000000
--- a/components/mirroring/service/wifi_status_monitor.h
+++ /dev/null
@@ -1,60 +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 COMPONENTS_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_
-#define COMPONENTS_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_
-
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/containers/circular_deque.h"
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-
-namespace mirroring {
-
-class MessageDispatcher;
-class ReceiverResponse;
-
-struct WifiStatus {
-  double snr;
-  int32_t speed;         // The current WiFi speed.
-  base::Time timestamp;  // Recording time of this status.
-};
-
-// Periodically sends requests to the Cast device for WiFi network status
-// updates, processes responses, and maintains a recent history of data points.
-// This data can be included in feedback logs to help identify and diagnose
-// issues related to lousy network performance.
-class COMPONENT_EXPORT(MIRRORING_SERVICE) WifiStatusMonitor {
- public:
-  // |message_dispatcher| must keep alive during the lifetime of this class.
-  explicit WifiStatusMonitor(MessageDispatcher* message_dispatcher);
-  ~WifiStatusMonitor();
-
-  // Gets the recorded status and clear |recent_status_|.
-  std::vector<WifiStatus> GetRecentValues();
-
-  // Sends GET_STATUS message to receiver.
-  void QueryStatus();
-
-  // Callback for the STATUS_RESPONSE message. Records the WiFi status reported
-  // by receiver.
-  void RecordStatus(const ReceiverResponse& response);
-
- private:
-  MessageDispatcher* const message_dispatcher_;  // Outlives this class.
-
-  base::RepeatingTimer query_timer_;
-
-  // Stores the recent status. Will be reset when GetRecentValues() is called.
-  base::circular_deque<WifiStatus> recent_status_;
-
-  DISALLOW_COPY_AND_ASSIGN(WifiStatusMonitor);
-};
-
-}  // namespace mirroring
-
-#endif  // COMPONENTS_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_
diff --git a/components/mirroring/service/wifi_status_monitor_unittest.cc b/components/mirroring/service/wifi_status_monitor_unittest.cc
deleted file mode 100644
index 68f8aad..0000000
--- a/components/mirroring/service/wifi_status_monitor_unittest.cc
+++ /dev/null
@@ -1,185 +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 "components/mirroring/service/wifi_status_monitor.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/json/json_reader.h"
-#include "base/macros.h"
-#include "base/test/mock_callback.h"
-#include "base/test/task_environment.h"
-#include "base/values.h"
-#include "components/mirroring/service/message_dispatcher.h"
-#include "components/mirroring/service/value_util.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using mirroring::mojom::CastMessage;
-
-namespace mirroring {
-
-namespace {
-
-bool IsNullMessage(const CastMessage& message) {
-  return message.message_namespace.empty() && message.json_format_data.empty();
-}
-
-std::string GetMessageType(const CastMessage& message) {
-  std::string type;
-  std::unique_ptr<base::Value> value =
-      base::JSONReader::ReadDeprecated(message.json_format_data);
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(GetString(*value, "type", &type));
-  return type;
-}
-
-void VerifyRecordedStatus(const std::vector<WifiStatus> recorded_status,
-                          double starting_snr,
-                          int starting_speed,
-                          int num_of_responses) {
-  EXPECT_EQ(num_of_responses, static_cast<int>(recorded_status.size()));
-  for (int i = 0; i < num_of_responses; ++i) {
-    EXPECT_EQ(starting_snr + i, recorded_status[i].snr);
-    EXPECT_EQ(starting_speed + i, recorded_status[i].speed);
-  }
-}
-
-}  // namespace
-
-class WifiStatusMonitorTest : public mojom::CastMessageChannel,
-                              public ::testing::Test {
- public:
-  WifiStatusMonitorTest()
-      : message_dispatcher_(receiver_.BindNewPipeAndPassRemote(),
-                            inbound_channel_.BindNewPipeAndPassReceiver(),
-                            error_callback_.Get()) {}
-
-  ~WifiStatusMonitorTest() override {}
-
-  // mojom::CastMessageChannel implementation. For outbound messages.
-  void Send(mojom::CastMessagePtr message) override {
-    last_outbound_message_.message_namespace = message->message_namespace;
-    last_outbound_message_.json_format_data = message->json_format_data;
-  }
-
- protected:
-  // Generates and sends |num_of_responses| responses.
-  void SendStatusResponses(double starting_snr,
-                           int starting_speed,
-                           int num_of_responses) {
-    for (int i = 0; i < num_of_responses; ++i) {
-      const std::string response =
-          "{\"seqNum\":" +
-          std::to_string(message_dispatcher_.GetNextSeqNumber()) +
-          ","
-          "\"type\": \"STATUS_RESPONSE\","
-          "\"result\": \"ok\","
-          "\"status\": {"
-          "\"wifiSnr\":" +
-          std::to_string(starting_snr + i) +
-          ","
-          "\"wifiSpeed\": [1234, 5678, 3000, " +
-          std::to_string(starting_speed + i) +
-          "],"
-          "\"wifiFcsError\": [12, 13, 12, 12]}"  // This will be ignored.
-          "}";
-      SendInboundMessage(response);
-    }
-  }
-
-  // Sends an inbound message to |message_dispatcher|.
-  void SendInboundMessage(const std::string& response) {
-    CastMessage message;
-    message.message_namespace = mojom::kWebRtcNamespace;
-    message.json_format_data = response;
-    inbound_channel_->Send(message.Clone());
-    task_environment_.RunUntilIdle();
-  }
-
-  // Creates a WifiStatusMonitor and start monitoring the status.
-  std::unique_ptr<WifiStatusMonitor> StartMonitoring() {
-    EXPECT_TRUE(IsNullMessage(last_outbound_message_));
-    EXPECT_CALL(error_callback_, Run(_)).Times(0);
-    auto status_monitor =
-        std::make_unique<WifiStatusMonitor>(&message_dispatcher_);
-    task_environment_.RunUntilIdle();
-    // Expect to receive request to send GET_STATUS message when create a
-    // WifiStatusMonitor.
-    EXPECT_EQ(mojom::kWebRtcNamespace,
-              last_outbound_message_.message_namespace);
-    EXPECT_EQ("GET_STATUS", GetMessageType(last_outbound_message_));
-    // Clear the old outbound message.
-    last_outbound_message_.message_namespace.clear();
-    last_outbound_message_.json_format_data.clear();
-    EXPECT_TRUE(IsNullMessage(last_outbound_message_));
-    return status_monitor;
-  }
-
-  void RunUntilIdle() { task_environment_.RunUntilIdle(); }
-
- private:
-  base::test::TaskEnvironment task_environment_;
-  mojo::Receiver<mojom::CastMessageChannel> receiver_{this};
-  mojo::Remote<mojom::CastMessageChannel> inbound_channel_;
-  base::MockCallback<MessageDispatcher::ErrorCallback> error_callback_;
-  MessageDispatcher message_dispatcher_;
-  CastMessage last_outbound_message_;
-
-  DISALLOW_COPY_AND_ASSIGN(WifiStatusMonitorTest);
-};
-
-TEST_F(WifiStatusMonitorTest, QueryStatusAndRecordResponse) {
-  std::unique_ptr<WifiStatusMonitor> status_monitor = StartMonitoring();
-
-  // Send two responses and verify the data are stored.
-  SendStatusResponses(36.7, 3001, 2);
-  std::vector<WifiStatus> recent_status = status_monitor->GetRecentValues();
-  VerifyRecordedStatus(recent_status, 36.7, 3001, 2);
-
-  // There should be no further status stored.
-  recent_status = status_monitor->GetRecentValues();
-  EXPECT_TRUE(recent_status.empty());
-
-  // Sends more than the maximum number (30) of records that can be stored.
-  SendStatusResponses(36.7, 3001, 40);
-  // Expect that only the recent 30 records were stored.
-  recent_status = status_monitor->GetRecentValues();
-  VerifyRecordedStatus(recent_status, 46.7, 3011, 30);
-}
-
-TEST_F(WifiStatusMonitorTest, IgnoreMalformedStatusMessage) {
-  std::unique_ptr<WifiStatusMonitor> status_monitor = StartMonitoring();
-
-  // Sends a response with incomplete wifiSpeed data and expects it is ignored.
-  const std::string response1 =
-      "{\"seqNum\": 123,"
-      "\"type\": \"STATUS_RESPONSE\","
-      "\"result\": \"ok\","
-      "\"status\": {"
-      "\"wifiSnr\": 32,"
-      "\"wifiSpeed\": [1234, 5678, 3000],"
-      "\"wifiFcsError\": [12, 13, 12, 12]}"
-      "}";
-  SendInboundMessage(response1);
-  std::vector<WifiStatus> recent_status = status_monitor->GetRecentValues();
-  RunUntilIdle();
-  EXPECT_TRUE(recent_status.empty());
-
-  // Sends a response with null status field and expects it is ignored.
-  const std::string response2 =
-      "{\"seqNum\": 123,"
-      "\"type\": \"STATUS_RESPONSE\","
-      "\"status\": null}";
-  SendInboundMessage(response2);
-  recent_status = status_monitor->GetRecentValues();
-  RunUntilIdle();
-  EXPECT_TRUE(recent_status.empty());
-}
-
-}  // namespace mirroring
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc
index 919652d0..5f1912a6 100644
--- a/components/optimization_guide/core/optimization_guide_features.cc
+++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -331,6 +331,16 @@
                                           "fetch_random_max_delay_secs", 60);
 }
 
+base::TimeDelta PredictionModelFetchRetryDelay() {
+  return base::TimeDelta::FromMinutes(GetFieldTrialParamByFeatureAsInt(
+      kOptimizationTargetPrediction, "fetch_retry_minutes", 2));
+}
+
+base::TimeDelta PredictionModelFetchInterval() {
+  return base::TimeDelta::FromHours(GetFieldTrialParamByFeatureAsInt(
+      kOptimizationTargetPrediction, "fetch_interval_hours", 24));
+}
+
 base::flat_set<std::string> ExternalAppPackageNamesApprovedForFetch() {
   std::string value = base::GetFieldTrialParamValueByFeature(
       kRemoteOptimizationGuideFetching, "approved_external_app_packages");
diff --git a/components/optimization_guide/core/optimization_guide_features.h b/components/optimization_guide/core/optimization_guide_features.h
index a89fac9..319141b4 100644
--- a/components/optimization_guide/core/optimization_guide_features.h
+++ b/components/optimization_guide/core/optimization_guide_features.h
@@ -170,6 +170,14 @@
 // fetch for prediction models and host model features.
 int PredictionModelFetchRandomMaxDelaySecs();
 
+// Returns the time to wait before retrying a failed fetch for prediction
+// models.
+base::TimeDelta PredictionModelFetchRetryDelay();
+
+// Returns the time to wait after a successful fetch of prediction models to
+// refresh models.
+base::TimeDelta PredictionModelFetchInterval();
+
 // Returns a set of external Android app packages whose predictions have been
 // approved for fetching from the remote Optimization Guide Service.
 base::flat_set<std::string> ExternalAppPackageNamesApprovedForFetch();
diff --git a/components/optimization_guide/core/optimization_guide_prefs.cc b/components/optimization_guide/core/optimization_guide_prefs.cc
index 153331be..2eada0a 100644
--- a/components/optimization_guide/core/optimization_guide_prefs.cc
+++ b/components/optimization_guide/core/optimization_guide_prefs.cc
@@ -23,6 +23,11 @@
 const char kModelAndFeaturesLastFetchAttempt[] =
     "optimization_guide.predictionmodelfetcher.last_fetch_attempt";
 
+// A pref that stores the last time a prediction model fetch was successful.
+// This helps determine when to schedule the next fetch.
+const char kModelLastFetchSuccess[] =
+    "optimization_guide.predictionmodelfetcher.last_fetch_success";
+
 // A dictionary pref that stores the set of hosts that cannot have hints fetched
 // for until visited again after fetching from the remote Optimization Guide
 // Service was first allowed. If The hash of the host is in the dictionary, then
@@ -78,6 +83,8 @@
       kModelAndFeaturesLastFetchAttempt,
       base::Time().ToDeltaSinceWindowsEpoch().InMicroseconds(),
       PrefRegistry::LOSSY_PREF);
+  registry->RegisterInt64Pref(kModelLastFetchSuccess, 0,
+                              PrefRegistry::LOSSY_PREF);
   registry->RegisterDictionaryPref(kHintsFetcherTopHostBlocklist,
                                    PrefRegistry::LOSSY_PREF);
   registry->RegisterDictionaryPref(kHintsFetcherHostsSuccessfullyFetched,
diff --git a/components/optimization_guide/core/optimization_guide_prefs.h b/components/optimization_guide/core/optimization_guide_prefs.h
index 6457738..95b31bb 100644
--- a/components/optimization_guide/core/optimization_guide_prefs.h
+++ b/components/optimization_guide/core/optimization_guide_prefs.h
@@ -14,6 +14,7 @@
 
 extern const char kHintsFetcherLastFetchAttempt[];
 extern const char kModelAndFeaturesLastFetchAttempt[];
+extern const char kModelLastFetchSuccess[];
 extern const char kHintsFetcherTopHostBlocklist[];
 extern const char kHintsFetcherTopHostBlocklistState[];
 extern const char kTimeHintsFetcherTopHostBlocklistLastInitialized[];
diff --git a/components/password_manager/core/browser/leak_detection_dialog_utils.cc b/components/password_manager/core/browser/leak_detection_dialog_utils.cc
index 54b4089..422057c 100644
--- a/components/password_manager/core/browser/leak_detection_dialog_utils.cc
+++ b/components/password_manager/core/browser/leak_detection_dialog_utils.cc
@@ -74,8 +74,7 @@
   return l10n_util::GetStringUTF16(IDS_CLOSE);
 }
 
-std::u16string GetDescription(CredentialLeakType leak_type,
-                              const GURL& /*origin*/) {
+std::u16string GetDescription(CredentialLeakType leak_type) {
   if (!ShouldCheckPasswords(leak_type)) {
     return l10n_util::GetStringUTF16(
         IDS_CREDENTIAL_LEAK_CHANGE_PASSWORD_MESSAGE);
diff --git a/components/password_manager/core/browser/leak_detection_dialog_utils.h b/components/password_manager/core/browser/leak_detection_dialog_utils.h
index ca6ca9a..3d4684b3a 100644
--- a/components/password_manager/core/browser/leak_detection_dialog_utils.h
+++ b/components/password_manager/core/browser/leak_detection_dialog_utils.h
@@ -54,34 +54,31 @@
 bool IsSyncingPasswordsNormally(CredentialLeakType leak_type);
 
 // Returns the label for the leak dialog accept button.
-std::u16string GetAcceptButtonLabel(
-    password_manager::CredentialLeakType leak_type);
+std::u16string GetAcceptButtonLabel(CredentialLeakType leak_type);
 
 // Returns the label for the leak dialog cancel button.
 std::u16string GetCancelButtonLabel();
 
 // Returns the leak dialog message based on leak type.
-std::u16string GetDescription(password_manager::CredentialLeakType leak_type,
-                              const GURL& origin);
+std::u16string GetDescription(CredentialLeakType leak_type);
 
 // Returns the leak dialog title based on leak type.
-std::u16string GetTitle(password_manager::CredentialLeakType leak_type);
+std::u16string GetTitle(CredentialLeakType leak_type);
 
 // Returns the leak dialog tooltip shown on (?) click.
 std::u16string GetLeakDetectionTooltip();
 
 // Checks whether the leak dialog should prompt user to password checkup.
-bool ShouldCheckPasswords(password_manager::CredentialLeakType leak_type);
+bool ShouldCheckPasswords(CredentialLeakType leak_type);
 
 // Checks whether the leak dialog should show change password button.
 bool ShouldShowChangePasswordButton(CredentialLeakType leak_type);
 
 // Checks whether the leak dialog should show cancel button.
-bool ShouldShowCancelButton(password_manager::CredentialLeakType leak_type);
+bool ShouldShowCancelButton(CredentialLeakType leak_type);
 
 // Returns the LeakDialogType corresponding to |leak_type|.
-password_manager::metrics_util::LeakDialogType GetLeakDialogType(
-    password_manager::CredentialLeakType leak_type);
+metrics_util::LeakDialogType GetLeakDialogType(CredentialLeakType leak_type);
 
 // Returns the URL used to launch the password checkup.
 GURL GetPasswordCheckupURL(PasswordCheckupReferrer referrer =
diff --git a/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc b/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc
index f21ea944..fbb9958 100644
--- a/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc
+++ b/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc
@@ -90,7 +90,6 @@
 }
 
 TEST(CredentialLeakDialogUtilsTest, GetCheckPasswordsDescription) {
-  GURL origin("https://example.com");
   for (size_t i = 0; i < base::size(kLeakTypesTestCases); ++i) {
     if (kLeakTypesTestCases[i].leak_message_id ==
         IDS_CREDENTIAL_LEAK_CHECK_PASSWORDS_MESSAGE) {
@@ -98,13 +97,12 @@
       std::u16string expected_message = l10n_util::GetStringUTF16(
           IDS_CREDENTIAL_LEAK_CHECK_PASSWORDS_MESSAGE);
       EXPECT_EQ(expected_message,
-                GetDescription(kLeakTypesTestCases[i].leak_type, origin));
+                GetDescription(kLeakTypesTestCases[i].leak_type));
     }
   }
 }
 
 TEST(CredentialLeakDialogUtilsTest, GetChangeAndCheckPasswordsDescription) {
-  GURL origin("https://example.com");
   for (size_t i = 0; i < base::size(kLeakTypesTestCases); ++i) {
     if (kLeakTypesTestCases[i].leak_message_id ==
         IDS_CREDENTIAL_LEAK_CHANGE_AND_CHECK_PASSWORDS_MESSAGE) {
@@ -112,13 +110,12 @@
       std::u16string expected_message = l10n_util::GetStringUTF16(
           IDS_CREDENTIAL_LEAK_CHANGE_AND_CHECK_PASSWORDS_MESSAGE);
       EXPECT_EQ(expected_message,
-                GetDescription(kLeakTypesTestCases[i].leak_type, origin));
+                GetDescription(kLeakTypesTestCases[i].leak_type));
     }
   }
 }
 
 TEST(CredentialLeakDialogUtilsTest, GetChangePasswordDescription) {
-  GURL origin("https://example.com");
   for (size_t i = 0; i < base::size(kLeakTypesTestCases); ++i) {
     if (kLeakTypesTestCases[i].leak_message_id ==
         IDS_CREDENTIAL_LEAK_CHANGE_PASSWORD_MESSAGE) {
@@ -126,7 +123,7 @@
       std::u16string expected_message = l10n_util::GetStringUTF16(
           IDS_CREDENTIAL_LEAK_CHANGE_PASSWORD_MESSAGE);
       EXPECT_EQ(expected_message,
-                GetDescription(kLeakTypesTestCases[i].leak_type, origin));
+                GetDescription(kLeakTypesTestCases[i].leak_type));
     }
   }
 }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 286ffc5..e439d2a 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -6466,31 +6466,31 @@
       'type': 'int-enum',
       'schema': {
         'type': 'integer',
-        'enum': [ 1, 2 ],
+        'enum': [ 2, 3 ],
       },
       'items': [
         {
-          'name': 'AllowFileHandling',
-          'value': 1,
-          'caption': '''Grant web apps access to file types''',
-        },
-        {
           'name': 'BlockFileHandling',
           'value': 2,
           'caption': '''Do not allow any web app to access file types via the File Handling API''',
         },
+        {
+          'name': 'AskFileHandling',
+          'value': 3,
+          'caption': '''Allow web apps to ask the user to grant access to file types via the File Handling API''',
+        },
       ],
-      'future_on': ['chrome_os', 'chrome.*'],
+      'supported_on': ['chrome_os:91-', 'chrome.*:91-'],
       'features': {
         'dynamic_refresh': True,
         'per_profile': True,
       },
-      'example_value': 1,
+      'example_value': 2,
       'default': None,
       'id': 845,
       'caption': '''Control use of the File Handling API''',
       'tags': ['website-sharing'],
-      'desc': '''Setting the policy to 1 lets web apps access file types. Setting the policy to 2 denies access to file types.
+      'desc': '''Setting the policy to <ph name="ASK_FILE_HANDLING">AskFileHandling</ph> lets web apps ask for access to file types via the File Handling API. Setting the policy to <ph name="BLOCK_FILE_HANDLING">BlockFileHandling</ph> denies access to file types.
 
       Leaving it unset lets web apps ask for access, but users can change this setting.''',
     },
@@ -6502,7 +6502,7 @@
         'type': 'array',
         'items': { 'type': 'string' },
       },
-      'future_on': ['chrome_os', 'chrome.*'],
+      'supported_on': ['chrome_os:91-', 'chrome.*:91-'],
       'features': {
         'dynamic_refresh': True,
         'per_profile': True,
@@ -6529,7 +6529,7 @@
         'type': 'array',
         'items': { 'type': 'string' },
       },
-      'future_on': ['chrome_os', 'chrome.*'],
+      'supported_on': ['chrome_os:91-', 'chrome.*:91-'],
       'features': {
         'dynamic_refresh': True,
         'per_profile': True,
@@ -20685,7 +20685,7 @@
     },
     {
       'name': 'ParentAccessCodeConfig',
-      'owners': ['file://chrome/browser/chromeos/child_accounts/OWNERS', 'agawronska@chromium.org'],
+      'owners': ['file://chrome/browser/ash/child_accounts/OWNERS', 'agawronska@chromium.org'],
       'type': 'dict',
       'schema': {
         'sensitiveValue': True,
diff --git a/components/services/filesystem/OWNERS b/components/services/filesystem/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/components/services/filesystem/OWNERS
+++ /dev/null
diff --git a/components/session_manager/core/OWNERS b/components/session_manager/core/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/components/session_manager/core/OWNERS
+++ /dev/null
diff --git a/components/sessions/content/OWNERS b/components/sessions/content/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/components/sessions/content/OWNERS
+++ /dev/null
diff --git a/components/sessions/ios/OWNERS b/components/sessions/ios/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/components/sessions/ios/OWNERS
+++ /dev/null
diff --git a/components/sync/protocol/autofill_specifics.proto b/components/sync/protocol/autofill_specifics.proto
index 339bc54..88b4fad 100644
--- a/components/sync/protocol/autofill_specifics.proto
+++ b/components/sync/protocol/autofill_specifics.proto
@@ -224,6 +224,12 @@
     UNIONPAY = 9;
   }
 
+  enum VirtualCardEnrollmentState {
+    UNSPECIFIED = 0;
+    UNENROLLED = 1;
+    ENROLLED = 2;
+  }
+
   // Server-generated unique ID string. This is opaque to the client.
   // This is the legacy version of |instrument_id|.
   optional string id = 1;
@@ -265,6 +271,12 @@
   // Server-generated unique ID. This is opaque to the client.
   // |id| is the legacy version of this.
   optional int64 instrument_id = 15;
+
+  // The state of virtual card enrollment.
+  optional VirtualCardEnrollmentState virtual_card_enrollment_state = 16;
+
+  // The URL for the client to fetche the card art image.
+  optional string card_art_url = 17;
 }
 
 // Different than an AutofillProfile because this represents some known address
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc
index a2f6ee73..f45be59 100644
--- a/components/sync/protocol/proto_enum_conversions.cc
+++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -459,6 +459,20 @@
 }
 
 const char* ProtoEnumToString(
+    sync_pb::WalletMaskedCreditCard::VirtualCardEnrollmentState
+        virtual_card_enrollment_state) {
+  ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard,
+                     VirtualCardEnrollmentState, UNSPECIFIED, ENROLLED);
+  switch (virtual_card_enrollment_state) {
+    ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNSPECIFIED);
+    ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNENROLLED);
+    ENUM_CASE(sync_pb::WalletMaskedCreditCard, ENROLLED);
+  }
+  NOTREACHED();
+  return "";
+}
+
+const char* ProtoEnumToString(
     sync_pb::WalletMaskedCreditCard::WalletCardStatus wallet_card_status) {
   ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard, WalletCardStatus, VALID,
                      EXPIRED);
diff --git a/components/sync/protocol/proto_enum_conversions.h b/components/sync/protocol/proto_enum_conversions.h
index c49e54e..1c7c35b1 100644
--- a/components/sync/protocol/proto_enum_conversions.h
+++ b/components/sync/protocol/proto_enum_conversions.h
@@ -94,6 +94,10 @@
     sync_pb::UserEventSpecifics::FlocIdComputed::EventTrigger trigger);
 
 const char* ProtoEnumToString(
+    sync_pb::WalletMaskedCreditCard::VirtualCardEnrollmentState
+        virtual_card_enrollment_state);
+
+const char* ProtoEnumToString(
     sync_pb::WalletMaskedCreditCard::WalletCardStatus wallet_card_status);
 
 const char* ProtoEnumToString(
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index add2fd89..f9884601 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -1090,6 +1090,8 @@
   VISIT(nickname);
   VISIT(card_issuer);
   VISIT(instrument_id);
+  VISIT_ENUM(virtual_card_enrollment_state);
+  VISIT(card_art_url);
 }
 
 VISIT_PROTO_FIELDS(const sync_pb::WalletMetadataSpecifics& proto) {
diff --git a/components/translate/core/browser/translate_pref_names.cc b/components/translate/core/browser/translate_pref_names.cc
index de4c2df0..49c73a6b 100644
--- a/components/translate/core/browser/translate_pref_names.cc
+++ b/components/translate/core/browser/translate_pref_names.cc
@@ -5,7 +5,7 @@
 #include "components/translate/core/browser/translate_pref_names.h"
 
 // These preferences are included in java_pref_names_srcjar for access in
-// Java code.
+// Java code. TODO (https://crbug.com/1197367) add translate namespace.
 namespace prefs {
 
 // Boolean that is true when offering translate (i.e. the automatic translate
@@ -15,4 +15,6 @@
 
 const char kPrefAlwaysTranslateList[] = "translate_whitelists";
 
+const char kPrefTranslateRecentTarget[] = "translate_recent_target";
+
 }  // namespace prefs
diff --git a/components/translate/core/browser/translate_pref_names.h b/components/translate/core/browser/translate_pref_names.h
index 9c4b27c6..6dca8b0 100644
--- a/components/translate/core/browser/translate_pref_names.h
+++ b/components/translate/core/browser/translate_pref_names.h
@@ -9,6 +9,7 @@
 
 extern const char kOfferTranslateEnabled[];
 extern const char kPrefAlwaysTranslateList[];
+extern const char kPrefTranslateRecentTarget[];
 
 }  // namespace prefs
 
diff --git a/components/translate/core/browser/translate_prefs.cc b/components/translate/core/browser/translate_prefs.cc
index 9d68adc..c1da9b7 100644
--- a/components/translate/core/browser/translate_prefs.cc
+++ b/components/translate/core/browser/translate_prefs.cc
@@ -97,8 +97,6 @@
     "translate_last_denied_time_for_language";
 const char TranslatePrefs::kPrefTranslateTooOftenDeniedForLanguage[] =
     "translate_too_often_denied_for_language";
-const char TranslatePrefs::kPrefTranslateRecentTarget[] =
-    "translate_recent_target";
 
 #if defined(OS_ANDROID) || defined(OS_IOS)
 const char TranslatePrefs::kPrefTranslateAutoAlwaysCount[] =
@@ -226,7 +224,7 @@
   prefs_->ClearPref(kPrefTranslateDeniedCount);
   prefs_->ClearPref(kPrefTranslateIgnoredCount);
   prefs_->ClearPref(kPrefTranslateAcceptedCount);
-  prefs_->ClearPref(kPrefTranslateRecentTarget);
+  prefs_->ClearPref(prefs::kPrefTranslateRecentTarget);
 
 #if defined(OS_ANDROID) || defined(OS_IOS)
   prefs_->ClearPref(kPrefTranslateAutoAlwaysCount);
@@ -865,7 +863,7 @@
 
 void TranslatePrefs::SetRecentTargetLanguage(
     const std::string& target_language) {
-  prefs_->SetString(kPrefTranslateRecentTarget, target_language);
+  prefs_->SetString(prefs::kPrefTranslateRecentTarget, target_language);
 }
 
 void TranslatePrefs::ResetRecentTargetLanguage() {
@@ -873,7 +871,7 @@
 }
 
 std::string TranslatePrefs::GetRecentTargetLanguage() const {
-  return prefs_->GetString(kPrefTranslateRecentTarget);
+  return prefs_->GetString(prefs::kPrefTranslateRecentTarget);
 }
 
 int TranslatePrefs::GetForceTriggerOnEnglishPagesCount() const {
@@ -916,7 +914,7 @@
   registry->RegisterDictionaryPref(
       kPrefTranslateTooOftenDeniedForLanguage,
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
-  registry->RegisterStringPref(kPrefTranslateRecentTarget, "",
+  registry->RegisterStringPref(prefs::kPrefTranslateRecentTarget, "",
                                user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
   registry->RegisterIntegerPref(
       kPrefForceTriggerTranslateCount, 0,
diff --git a/components/translate/core/browser/translate_prefs.h b/components/translate/core/browser/translate_prefs.h
index 15f80700..3d4d9328 100644
--- a/components/translate/core/browser/translate_prefs.h
+++ b/components/translate/core/browser/translate_prefs.h
@@ -136,7 +136,6 @@
   static const char kPrefTranslateAcceptedCount[];
   static const char kPrefTranslateLastDeniedTimeForLanguage[];
   static const char kPrefTranslateTooOftenDeniedForLanguage[];
-  static const char kPrefTranslateRecentTarget[];
 #if defined(OS_ANDROID) || defined(OS_IOS)
   static const char kPrefTranslateAutoAlwaysCount[];
   static const char kPrefTranslateAutoNeverCount[];
diff --git a/components/translate/core/browser/translate_ui_delegate.cc b/components/translate/core/browser/translate_ui_delegate.cc
index bc02b82d..001ca783 100644
--- a/components/translate/core/browser/translate_ui_delegate.cc
+++ b/components/translate/core/browser/translate_ui_delegate.cc
@@ -204,8 +204,10 @@
                             TranslateErrors::TRANSLATE_ERROR_MAX);
 }
 
-const LanguageState& TranslateUIDelegate::GetLanguageState() {
-  return *translate_manager_->GetLanguageState();
+const LanguageState* TranslateUIDelegate::GetLanguageState() {
+  if (translate_manager_)
+    return translate_manager_->GetLanguageState();
+  return nullptr;
 }
 
 size_t TranslateUIDelegate::GetNumberOfLanguages() const {
@@ -222,18 +224,21 @@
   std::string language_code = kUnknownLanguageCode;
   if (language_index < GetNumberOfLanguages())
     language_code = GetLanguageCodeAt(language_index);
-  translate_manager_->GetActiveTranslateMetricsLogger()->LogSourceLanguage(
-      language_code);
+  if (translate_manager_) {
+    translate_manager_->GetActiveTranslateMetricsLogger()->LogSourceLanguage(
+        language_code);
+  }
 }
 
 void TranslateUIDelegate::UpdateSourceLanguage(
     const std::string& language_code) {
-  DCHECK(translate_manager_ != nullptr);
   for (size_t i = 0; i < languages_.size(); ++i) {
     if (languages_[i].first.compare(language_code) == 0) {
       UpdateSourceLanguageIndex(i);
-      translate_manager_->mutable_translate_event()
-          ->set_modified_source_language(language_code);
+      if (translate_manager_) {
+        translate_manager_->mutable_translate_event()
+            ->set_modified_source_language(language_code);
+      }
       return;
     }
   }
@@ -247,19 +252,22 @@
   UMA_HISTOGRAM_BOOLEAN(kModifyTargetLang, true);
   target_language_index_ = language_index;
 
-  translate_manager_->GetActiveTranslateMetricsLogger()->LogTargetLanguage(
-      GetLanguageCodeAt(language_index),
-      TranslateBrowserMetrics::TargetLanguageOrigin::kChangedByUser);
+  if (translate_manager_) {
+    translate_manager_->GetActiveTranslateMetricsLogger()->LogTargetLanguage(
+        GetLanguageCodeAt(language_index),
+        TranslateBrowserMetrics::TargetLanguageOrigin::kChangedByUser);
+  }
 }
 
 void TranslateUIDelegate::UpdateTargetLanguage(
     const std::string& language_code) {
-  DCHECK(translate_manager_ != nullptr);
   for (size_t i = 0; i < languages_.size(); ++i) {
     if (languages_[i].first.compare(language_code) == 0) {
       UpdateTargetLanguageIndex(i);
-      translate_manager_->mutable_translate_event()
-          ->set_modified_target_language(language_code);
+      if (translate_manager_) {
+        translate_manager_->mutable_translate_event()
+            ->set_modified_target_language(language_code);
+      }
       return;
     }
   }
diff --git a/components/translate/core/browser/translate_ui_delegate.h b/components/translate/core/browser/translate_ui_delegate.h
index 6e07d8e34..27b5de6 100644
--- a/components/translate/core/browser/translate_ui_delegate.h
+++ b/components/translate/core/browser/translate_ui_delegate.h
@@ -48,7 +48,7 @@
   void OnErrorShown(TranslateErrors::Type error_type);
 
   // Returns the LanguageState associated with this object.
-  const LanguageState& GetLanguageState();
+  const LanguageState* GetLanguageState();
 
   // Returns the number of languages supported.
   size_t GetNumberOfLanguages() const;
diff --git a/components/translate/translate_internals/translate_internals_handler.cc b/components/translate/translate_internals/translate_internals_handler.cc
index 4ce77a4..8daa770 100644
--- a/components/translate/translate_internals/translate_internals_handler.cc
+++ b/components/translate/translate_internals/translate_internals_handler.cc
@@ -242,7 +242,7 @@
   static const char* const keys[] = {
       language::prefs::kFluentLanguages,
       prefs::kOfferTranslateEnabled,
-      translate::TranslatePrefs::kPrefTranslateRecentTarget,
+      prefs::kPrefTranslateRecentTarget,
       translate::TranslatePrefs::kPrefNeverPromptSitesDeprecated,
       translate::TranslatePrefs::kPrefNeverPromptSitesWithTime,
       prefs::kPrefAlwaysTranslateList,
diff --git a/content/app_shim_remote_cocoa/popup_window_mac.mm b/content/app_shim_remote_cocoa/popup_window_mac.mm
index 49ebd76..f75df0e 100644
--- a/content/app_shim_remote_cocoa/popup_window_mac.mm
+++ b/content/app_shim_remote_cocoa/popup_window_mac.mm
@@ -30,6 +30,11 @@
   return self;
 }
 
+- (void)dealloc {
+  [self stopObservingClicks];
+  [super dealloc];
+}
+
 - (void)close {
   [self stopObservingClicks];
   [super close];
diff --git a/content/browser/browser_url_handler_impl.cc b/content/browser/browser_url_handler_impl.cc
index 35a7b788..919d97e 100644
--- a/content/browser/browser_url_handler_impl.cc
+++ b/content/browser/browser_url_handler_impl.cc
@@ -15,6 +15,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -74,7 +75,7 @@
 
 static bool DebugURLHandler(GURL* url, BrowserContext* browser_context) {
   // Circumvent processing URLs that the renderer process will handle.
-  return IsRendererDebugURL(*url);
+  return blink::IsRendererDebugURL(*url);
 }
 
 // static
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index cb5733c7..da10ab7 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -59,6 +59,7 @@
 #include "services/tracing/public/cpp/perfetto/perfetto_config.h"
 #include "services/tracing/public/cpp/tracing_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/layout.h"
@@ -1088,7 +1089,7 @@
 
   {
     content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
-    shell()->LoadURL(GURL(content::kChromeUICrashURL));
+    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
     params = WaitForNotification("Target.targetCrashed", true);
   }
   ClearNotifications();
@@ -1202,7 +1203,7 @@
 
   {
     ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
-    shell()->LoadURL(GURL(content::kChromeUICrashURL));
+    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
     WaitForNotification("Inspector.targetCrashed");
   }
 
@@ -1227,7 +1228,7 @@
 
   {
     ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
-    shell()->LoadURL(GURL(content::kChromeUICrashURL));
+    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
     WaitForNotification("Inspector.targetCrashed");
   }
 
@@ -1251,7 +1252,7 @@
 
   {
     ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
-    shell()->LoadURL(GURL(content::kChromeUICrashURL));
+    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
     WaitForNotification("Inspector.targetCrashed");
   }
 
@@ -2106,7 +2107,7 @@
   {
     ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
     NavigateToURLBlockUntilNavigationsComplete(
-        shell(), GURL(content::kChromeUICrashURL), 1);
+        shell(), GURL(blink::kChromeUICrashURL), 1);
   }
 
   SendCommand("Emulation.clearDeviceMetricsOverride", nullptr);
diff --git a/content/browser/geolocation/OWNERS b/content/browser/geolocation/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/content/browser/geolocation/OWNERS
+++ /dev/null
diff --git a/content/browser/keyboard_lock/OWNERS b/content/browser/keyboard_lock/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/content/browser/keyboard_lock/OWNERS
+++ /dev/null
diff --git a/content/browser/loader/loader_browsertest.cc b/content/browser/loader/loader_browsertest.cc
index caa8e1c..baea7dd 100644
--- a/content/browser/loader/loader_browsertest.cc
+++ b/content/browser/loader/loader_browsertest.cc
@@ -49,6 +49,7 @@
 #include "net/test/url_request/url_request_mock_http_job.h"
 #include "services/network/public/cpp/features.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/loader/previews_state.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "url/gurl.h"
@@ -420,7 +421,7 @@
   RenderProcessHostWatcher crash_observer(
       shell()->web_contents(),
       RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-  EXPECT_FALSE(NavigateToURL(shell(), GURL(kChromeUICrashURL)));
+  EXPECT_FALSE(NavigateToURL(shell(), GURL(blink::kChromeUICrashURL)));
   // Wait for browser to notice the renderer crash.
   crash_observer.Wait();
 
diff --git a/content/browser/loader/navigation_early_hints_manager.cc b/content/browser/loader/navigation_early_hints_manager.cc
index a2badc5..a4968b1 100644
--- a/content/browser/loader/navigation_early_hints_manager.cc
+++ b/content/browser/loader/navigation_early_hints_manager.cc
@@ -303,7 +303,7 @@
   request.destination = LinkAsAttributeToRequestDestination(link->as);
   request.url = link->href;
   request.site_for_cookies = site_for_cookies;
-  request.request_initiator = url::Origin::Create(navigation_request.url);
+  request.request_initiator = top_frame_origin;
   request.referrer = navigation_request.url;
   request.referrer_policy = navigation_request.referrer_policy;
   request.load_flags = net::LOAD_NORMAL;
diff --git a/content/browser/media/capture/content_capture_device_browsertest_base.cc b/content/browser/media/capture/content_capture_device_browsertest_base.cc
index 66a4826..6f40093 100644
--- a/content/browser/media/capture/content_capture_device_browsertest_base.cc
+++ b/content/browser/media/capture/content_capture_device_browsertest_base.cc
@@ -26,6 +26,7 @@
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/display/display_switches.h"
 #include "url/gurl.h"
 
@@ -165,7 +166,8 @@
   RenderProcessHostWatcher crash_observer(
       shell()->web_contents(),
       RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-  ASSERT_TRUE(NavigateToURLAndExpectNoCommit(shell(), GURL(kChromeUICrashURL)));
+  ASSERT_TRUE(
+      NavigateToURLAndExpectNoCommit(shell(), GURL(blink::kChromeUICrashURL)));
   crash_observer.Wait();
   ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
 }
diff --git a/content/browser/renderer_host/debug_urls.cc b/content/browser/renderer_host/debug_urls.cc
index 60b736f..658766e 100644
--- a/content/browser/renderer_host/debug_urls.cc
+++ b/content/browser/renderer_host/debug_urls.cc
@@ -23,6 +23,7 @@
 #include "content/public/common/content_constants.h"
 #include "content/public/common/url_constants.h"
 #include "ppapi/buildflags/buildflags.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "url/gurl.h"
 
 #if BUILDFLAG(ENABLE_PLUGINS)
@@ -56,7 +57,7 @@
 
 void HandlePpapiFlashDebugURL(const GURL& url) {
 #if BUILDFLAG(ENABLE_PLUGINS)
-  bool crash = url == kChromeUIPpapiFlashCrashURL;
+  bool crash = url == blink::kChromeUIPpapiFlashCrashURL;
 
   std::vector<PpapiPluginProcessHost*> hosts;
   PpapiPluginProcessHost::FindByName(base::UTF8ToUTF16(kFlashPluginName),
@@ -143,26 +144,26 @@
   if (IsAsanDebugURL(url))
     return HandleAsanDebugURL(url);
 
-  if (url == kChromeUIBrowserCrashURL) {
+  if (url == blink::kChromeUIBrowserCrashURL) {
     // Induce an intentional crash in the browser process.
     CHECK(false);
     return true;
   }
 
 #if defined(OS_WIN)
-  if (url == kChromeUIBrowserHeapCorruptionURL) {
+  if (url == blink::kChromeUIBrowserHeapCorruptionURL) {
     // Induce an intentional heap corruption in the browser process.
     base::debug::win::TerminateWithHeapCorruption();
     return true;
   }
 #endif
 
-  if (url == kChromeUIBrowserUIHang) {
+  if (url == blink::kChromeUIBrowserUIHang) {
     HangCurrentThread();
     return true;
   }
 
-  if (url == kChromeUIDelayedBrowserUIHang) {
+  if (url == blink::kChromeUIDelayedBrowserUIHang) {
     // Webdriver-safe url to hang the ui thread. Webdriver waits for the onload
     // event in javascript which needs a little more time to fire.
     GetUIThreadTaskRunner({})->PostDelayedTask(
@@ -171,7 +172,7 @@
     return true;
   }
 
-  if (url == kChromeUIGpuCleanURL) {
+  if (url == blink::kChromeUIGpuCleanURL) {
     GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
                              false /* force_create */,
                              base::BindOnce([](GpuProcessHost* host) {
@@ -181,7 +182,7 @@
     return true;
   }
 
-  if (url == kChromeUIGpuCrashURL) {
+  if (url == blink::kChromeUIGpuCrashURL) {
     GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
                              false /* force_create */,
                              base::BindOnce([](GpuProcessHost* host) {
@@ -192,7 +193,7 @@
   }
 
 #if defined(OS_ANDROID)
-  if (url == kChromeUIGpuJavaCrashURL) {
+  if (url == blink::kChromeUIGpuJavaCrashURL) {
     GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
                              false /* force_create */,
                              base::BindOnce([](GpuProcessHost* host) {
@@ -203,7 +204,7 @@
   }
 #endif
 
-  if (url == kChromeUIGpuHangURL) {
+  if (url == blink::kChromeUIGpuHangURL) {
     GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED,
                              false /* force_create */,
                              base::BindOnce([](GpuProcessHost* host) {
@@ -213,19 +214,20 @@
     return true;
   }
 
-  if (url == kChromeUIPpapiFlashCrashURL || url == kChromeUIPpapiFlashHangURL) {
+  if (url == blink::kChromeUIPpapiFlashCrashURL ||
+      url == blink::kChromeUIPpapiFlashHangURL) {
     GetIOThreadTaskRunner({})->PostTask(
         FROM_HERE, base::BindOnce(&HandlePpapiFlashDebugURL, url));
     return true;
   }
 
-  if (url == kChromeUIMemoryPressureCriticalURL) {
+  if (url == blink::kChromeUIMemoryPressureCriticalURL) {
     base::MemoryPressureListener::NotifyMemoryPressure(
         base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
     return true;
   }
 
-  if (url == kChromeUIMemoryPressureModerateURL) {
+  if (url == blink::kChromeUIMemoryPressureModerateURL) {
     base::MemoryPressureListener::NotifyMemoryPressure(
         base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
     return true;
diff --git a/content/browser/renderer_host/frame_tree_browsertest.cc b/content/browser/renderer_host/frame_tree_browsertest.cc
index dd95a28..31646a79 100644
--- a/content/browser/renderer_host/frame_tree_browsertest.cc
+++ b/content/browser/renderer_host/frame_tree_browsertest.cc
@@ -32,6 +32,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/network/public/cpp/web_sandbox_flags.h"
 #include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
 #include "url/url_constants.h"
 
@@ -174,7 +175,7 @@
 
   // Hang the renderer so that it doesn't send any FrameDetached messages.
   // (This navigation will never complete, so don't wait for it.)
-  shell()->LoadURL(GURL(kChromeUIHangURL));
+  shell()->LoadURL(GURL(blink::kChromeUIHangURL));
 
   // Check that the frame tree still has children.
   WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 8f9e7a6..08835ae 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -95,6 +95,7 @@
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/blink/public/common/blob/blob_utils.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/history/session_history_constants.h"
 #include "third_party/blink/public/common/mime_util/mime_util.h"
 #include "third_party/blink/public/common/page_state/page_state_serialization.h"
@@ -293,7 +294,7 @@
   // provides defense-in-depth if a renderer debug URL manages to get here via
   // some other path. We want to reject the navigation here so it doesn't
   // violate assumptions in downstream code.
-  if (IsRendererDebugURL(dest_url)) {
+  if (blink::IsRendererDebugURL(dest_url)) {
     LOG(WARNING) << "Refusing to load renderer debug URL: "
                  << dest_url.possibly_invalid_spec();
     return false;
@@ -2778,7 +2779,7 @@
     DCHECK(pending_entry_ == entries_[pending_entry_index_].get() ||
            pending_entry_ == entry_replaced_by_post_commit_error_.get());
   }
-  DCHECK(!IsRendererDebugURL(pending_entry_->GetURL()));
+  DCHECK(!blink::IsRendererDebugURL(pending_entry_->GetURL()));
   bool is_forced_reload = needs_reload_;
   needs_reload_ = false;
   FrameTreeNode* root = frame_tree_.root();
@@ -3172,7 +3173,7 @@
   // Note: we intentionally leave the pending entry in place for renderer debug
   // URLs, unlike the cases below where we clear it if the navigation doesn't
   // proceed.
-  if (IsRendererDebugURL(params.url)) {
+  if (blink::IsRendererDebugURL(params.url)) {
     // Renderer-debug URLs won't go through NavigationThrottlers so we have to
     // check them explicitly. See bug 913334.
     if (GetContentClient()->browser()->ShouldBlockRendererDebugURL(
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
index badfb3e..689e823 100644
--- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -3021,9 +3021,7 @@
   // This case is not enabled for browser-initiated navigation because the
   // browser-calculated vs renderer-calculated origin doesn't match, leading to
   // a crash.
-  // TODO(https://crbug.com/1190088): Enable this for browser-initiated
-  // navigations too once the bug is fixed.
-  if (renderer_initiated()) {
+  {
     SCOPED_TRACE(testing::Message() << " Testing case 2.");
 
     // Create a new blank window that won't create a NavigationEntry.
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index f9ef5e81..ed39b1c 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -119,6 +119,7 @@
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/public/mojom/web_sandbox_flags.mojom.h"
 #include "third_party/blink/public/common/blob/blob_utils.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/client_hints/client_hints.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/navigation/navigation_policy.h"
@@ -1160,7 +1161,7 @@
       previous_page_ukm_source_id_(
           frame_tree_node_->current_frame_host()->GetPageUkmSourceId()) {
   DCHECK(browser_initiated_ || common_params_->initiator_origin.has_value());
-  DCHECK(!IsRendererDebugURL(common_params_->url));
+  DCHECK(!blink::IsRendererDebugURL(common_params_->url));
   DCHECK(common_params_->method == "POST" || !common_params_->post_data);
   ScopedNavigationRequestCrashKeys crash_keys(this);
 
@@ -1729,7 +1730,7 @@
 
   if (IsInMainFrame()) {
     DCHECK(!common_params_->navigation_start.is_null());
-    DCHECK(!IsRendererDebugURL(common_params_->url));
+    DCHECK(!blink::IsRendererDebugURL(common_params_->url));
     TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
         "navigation", "Navigation StartToCommit",
         TRACE_ID_WITH_SCOPE("StartToCommit", TRACE_ID_LOCAL(this)),
@@ -3779,7 +3780,7 @@
   DCHECK(NeedsUrlLoader() == !!response_head_ ||
          (was_redirected_ && common_params_->url.IsAboutBlank()));
   DCHECK(!common_params_->url.SchemeIs(url::kJavaScriptScheme));
-  DCHECK(!IsRendererDebugURL(common_params_->url));
+  DCHECK(!blink::IsRendererDebugURL(common_params_->url));
   DCHECK(sandbox_flags_to_commit_);
 
   AddOldPageInfoToCommitParamsIfNeeded();
@@ -5084,7 +5085,7 @@
   // ResourceLoader::OnReceivedRedirect.
   // Note: the |common_params_->url| below is the post-redirect URL.
   // See https://crbug.com/728398.
-  CHECK(!IsRendererDebugURL(common_params_->url));
+  CHECK(!blink::IsRendererDebugURL(common_params_->url));
 
   // Update the navigation parameters.
   if (!(common_params_->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT)) {
diff --git a/content/browser/renderer_host/navigation_request_browsertest.cc b/content/browser/renderer_host/navigation_request_browsertest.cc
index ee8c3b8..9d36d2d 100644
--- a/content/browser/renderer_host/navigation_request_browsertest.cc
+++ b/content/browser/renderer_host/navigation_request_browsertest.cc
@@ -42,6 +42,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/url_request/url_request_failed_job.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
 #include "ui/base/page_transition_types.h"
 #include "url/url_constants.h"
@@ -1796,8 +1797,9 @@
   GURL url(embedded_test_server()->GetURL("/title1.html"));
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
-  GURL redirect_url = embedded_test_server()->GetURL(
-      std::string("/server-redirect?") + kChromeUINetworkErrorsListingURL);
+  GURL redirect_url =
+      embedded_test_server()->GetURL(std::string("/server-redirect?") +
+                                     blink::kChromeUINetworkErrorsListingURL);
   NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
   TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
   EXPECT_TRUE(
@@ -2043,13 +2045,13 @@
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
   const GURL kTestUrls[] = {GURL("javascript:window.alert('hello')"),
-                            GURL(kChromeUIBadCastCrashURL),
-                            GURL(kChromeUICrashURL),
-                            GURL(kChromeUIDumpURL),
-                            GURL(kChromeUIKillURL),
-                            GURL(kChromeUIHangURL),
-                            GURL(kChromeUIShorthangURL),
-                            GURL(kChromeUIMemoryExhaustURL)};
+                            GURL(blink::kChromeUIBadCastCrashURL),
+                            GURL(blink::kChromeUICrashURL),
+                            GURL(blink::kChromeUIDumpURL),
+                            GURL(blink::kChromeUIKillURL),
+                            GURL(blink::kChromeUIHangURL),
+                            GURL(blink::kChromeUIShorthangURL),
+                            GURL(blink::kChromeUIMemoryExhaustURL)};
 
   for (const auto& test_url : kTestUrls) {
     SCOPED_TRACE(testing::Message() << "renderer_debug_url = " << test_url);
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 76232fbea..d767944 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -223,6 +223,7 @@
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/blink/public/common/blob/blob_utils.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/frame/frame_policy.h"
 #include "third_party/blink/public/common/loader/inter_process_time_ticks_converter.h"
@@ -837,16 +838,6 @@
   if (renderer_side_origin.opaque() && browser_side_origin.opaque())
     return;
 
-#if defined(OS_ANDROID)
-  // TODO(lukasza): Investigate why about:blank navigations on Android sometimes
-  // have an opaque, unique `browser_side_origin` that doesn't match a regular,
-  // tuple `renderer_side_origin` - see webview_cts_tests,
-  // android.webkit.cts.WebViewTest#testJavascriptInterfaceForClientPopup on
-  // android-pie-arm64-rel.
-  if (navigation_request->GetURL().IsAboutBlank())
-    return;
-#endif
-
   // Navigating to file://localhost/... on windows causes `browser_side_origin`
   // and `renderer_side_origin` to be different (file://localhost/ vs file:///).
   // In particular, without the following block the test
@@ -6057,7 +6048,7 @@
   }
 
   // Renderer-debug URLs can never be committed.
-  if (IsRendererDebugURL(url)) {
+  if (blink::IsRendererDebugURL(url)) {
     LogCanCommitOriginAndUrlFailureReason("is_renderer_debug_url");
     return CanCommitStatus::CANNOT_COMMIT_URL;
   }
@@ -6119,7 +6110,7 @@
     // about:blank, data, and blob URLs.
 
     // Renderer-debug URLs can never be committed.
-    if (IsRendererDebugURL(origin_tuple_or_precursor_tuple.GetURL())) {
+    if (blink::IsRendererDebugURL(origin_tuple_or_precursor_tuple.GetURL())) {
       LogCanCommitOriginAndUrlFailureReason(
           "origin_or_precursor_is_renderer_debug_url");
       return CanCommitStatus::CANNOT_COMMIT_ORIGIN;
@@ -6515,7 +6506,7 @@
   TRACE_EVENT2("navigation", "RenderFrameHostImpl::CommitNavigation",
                "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
                common_params->url.possibly_invalid_spec());
-  DCHECK(!IsRendererDebugURL(common_params->url));
+  DCHECK(!blink::IsRendererDebugURL(common_params->url));
   DCHECK(navigation_request);
 
   bool is_same_document =
@@ -7066,7 +7057,7 @@
 }
 
 void RenderFrameHostImpl::HandleRendererDebugURL(const GURL& url) {
-  DCHECK(IsRendererDebugURL(url));
+  DCHECK(blink::IsRendererDebugURL(url));
 
   // Several tests expect a load of Chrome Debug URLs to send a DidStopLoading
   // notification, so set is loading to true here to properly surface it when
@@ -7078,7 +7069,7 @@
     frame_tree_node()->DidStartLoading(true, was_loading);
   }
 
-  GetMojomFrameInRenderer()->HandleRendererDebugURL(url);
+  GetAssociatedLocalFrame()->HandleRendererDebugURL(url);
 
   // Ensure that the renderer process is marked as used after processing a
   // renderer debug URL, since this process is now unsafe to be reused by sites
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index bbcd3b0..d72c021 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -1070,7 +1070,7 @@
                         int extended_error_code,
                         const base::Optional<std::string>& error_page_content);
 
-  // Seneds a renderer-debug URL to the renderer process for handling.
+  // Sends a renderer-debug URL to the renderer process for handling.
   void HandleRendererDebugURL(const GURL& url);
 
   // Sets up the Mojo connection between this instance and its associated render
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index af497e69..0a89b82 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -63,6 +63,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
 #include "services/network/public/cpp/features.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
@@ -1443,7 +1444,7 @@
       SiteInstanceImpl::GetEffectiveURL(browser_context, destination_url);
   // Don't force a new BrowsingInstance for URLs that are handled in the
   // renderer process, like javascript: or debug URLs like chrome://crash.
-  if (IsRendererDebugURL(destination_effective_url))
+  if (blink::IsRendererDebugURL(destination_effective_url))
     return ShouldSwapBrowsingInstance::kNo_RendererDebugURL;
 
   if (cross_origin_opener_policy_mismatch)
diff --git a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
index db71bcc3..34ee04d 100644
--- a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
@@ -82,6 +82,7 @@
 #include "services/network/public/cpp/features.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "third_party/blink/public/common/action_after_pagehide.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 
 using base::ASCIIToUTF16;
@@ -2447,7 +2448,8 @@
   RenderProcessHostWatcher crash_observer(
       shell()->web_contents(),
       RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-  EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(), GURL(kChromeUICrashURL)));
+  EXPECT_TRUE(
+      NavigateToURLAndExpectNoCommit(shell(), GURL(blink::kChromeUICrashURL)));
   crash_observer.Wait();
 
   // We should not change SiteInstance and BrowsingInstance on navigations to
@@ -2474,12 +2476,13 @@
   RenderProcessHostWatcher crash_observer(
       shell()->web_contents(),
       RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-  EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(), GURL(kChromeUICrashURL)));
+  EXPECT_TRUE(
+      NavigateToURLAndExpectNoCommit(shell(), GURL(blink::kChromeUICrashURL)));
   crash_observer.Wait();
 
   // Load the crash URL again but don't wait for any action.  If it is not
   // ignored this time, we will fail the WebUI CHECK in InitRenderView.
-  shell()->LoadURL(GURL(kChromeUICrashURL));
+  shell()->LoadURL(GURL(blink::kChromeUICrashURL));
 
   // Ensure that such URLs can still work as the initial navigation of a tab.
   // We postpone the initial navigation of the tab using an empty GURL, so that
@@ -2489,7 +2492,8 @@
                              GURL(), nullptr, gfx::Size());
   RenderProcessHostWatcher crash_observer2(
       shell2->web_contents(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
-  EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell2, GURL(kChromeUIKillURL)));
+  EXPECT_TRUE(
+      NavigateToURLAndExpectNoCommit(shell2, GURL(blink::kChromeUIKillURL)));
   crash_observer2.Wait();
 }
 
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index e86b0df6..5a26104 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -48,6 +48,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
@@ -756,8 +757,8 @@
   // We can't use NavigateToURL here since it accesses the shell() after
   // navigating, which the shell_closer deletes.
   ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
-  NavigateToURLBlockUntilNavigationsComplete(
-      shell(), GURL(kChromeUICrashURL), 1);
+  NavigateToURLBlockUntilNavigationsComplete(shell(),
+                                             GURL(blink::kChromeUICrashURL), 1);
 
   // The key here is that all the RenderProcessExited callbacks precede all the
   // RenderProcessHostDestroyed callbacks.
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index a430e5d..b9bc6f2bb 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -2158,7 +2158,7 @@
     bool is_anchor_first) {
   if (view_)
     view_->SelectionBoundsChanged(anchor_rect, anchor_dir, focus_rect,
-                                  focus_dir, is_anchor_first);
+                                  focus_dir, bounding_box, is_anchor_first);
 }
 
 void RenderWidgetHostImpl::OnUpdateDragCursor(
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 9b474bb..92eec14 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1261,6 +1261,19 @@
   return caret_rect;
 }
 
+gfx::Rect RenderWidgetHostViewAura::GetSelectionBoundingBox() const {
+  auto* focused_view = GetFocusedViewForTextSelection();
+  if (!focused_view)
+    return gfx::Rect();
+
+  const gfx::Rect bounding_box =
+      text_input_manager_->GetSelectionRegion(focused_view)->bounding_box;
+  if (bounding_box.IsEmpty())
+    return gfx::Rect();
+
+  return ConvertRectToScreen(bounding_box);
+}
+
 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
     uint32_t index,
     gfx::Rect* rect) const {
@@ -2147,7 +2160,7 @@
 }
 
 RenderWidgetHostViewBase*
-RenderWidgetHostViewAura::GetFocusedViewForTextSelection() {
+RenderWidgetHostViewAura::GetFocusedViewForTextSelection() const {
   // We obtain the TextSelection from focused RWH which is obtained from the
   // frame tree.
   return GetFocusedWidget() ? GetFocusedWidget()->GetView() : nullptr;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index c41cc40..355f66b 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -206,6 +206,7 @@
   int GetTextInputFlags() const override;
   bool CanComposeInline() const override;
   gfx::Rect GetCaretBounds() const override;
+  gfx::Rect GetSelectionBoundingBox() const override;
   bool GetCompositionCharacterBounds(uint32_t index,
                                      gfx::Rect* rect) const override;
   bool HasCompositionText() const override;
@@ -524,7 +525,7 @@
   ui::InputMethod* GetInputMethod() const;
 
   // Get the focused view that should be used for retrieving the text selection.
-  RenderWidgetHostViewBase* GetFocusedViewForTextSelection();
+  RenderWidgetHostViewBase* GetFocusedViewForTextSelection() const;
 
   // Returns whether the widget needs an input grab to work properly.
   bool NeedsInputGrab();
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc
index 6b47dc1..f7ad14f 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc
@@ -363,6 +363,75 @@
   ASSERT_TRUE(ExecuteScript(wc, "noop();"));
 }
 
+// Used to verify features under the environment whose device scale factor is 2.
+class RenderWidgetHostViewAuraDSFBrowserTest
+    : public RenderWidgetHostViewAuraBrowserTest {
+ public:
+  // RenderWidgetHostViewAuraBrowserTest:
+  void SetUp() override {
+    EnablePixelOutput(scale());
+    RenderWidgetHostViewAuraBrowserTest::SetUp();
+  }
+
+  float scale() const { return 2.f; }
+};
+
+// Verifies the bounding box of the selection region.
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraDSFBrowserTest,
+                       SelectionRegionBoundingBox) {
+  GURL page(
+      "data:text/html;charset=utf-8,"
+      "<!DOCTYPE html>"
+      "<html>"
+      "<body>"
+      "<p id=\"text-content\">Gibbons are apes in the family Hylobatidae.</p>"
+      "<script>"
+      "  function selectText() {"
+      "    const input = document.getElementById('text-content');"
+      "    var range = document.createRange();"
+      "    range.selectNodeContents(input);"
+      "    var selection = window.getSelection();  "
+      "    selection.removeAllRanges();"
+      "    selection.addRange(range);"
+      "  }"
+      "  function getSelectionBounds() {"
+      "    var r = "
+      "document.getSelection().getRangeAt(0).getBoundingClientRect();"
+      "    return [r.x, r.right, r.y, r.bottom]; "
+      "  }"
+      "</script>"
+      "</body>"
+      "</html>");
+  EXPECT_TRUE(NavigateToURL(shell(), page));
+
+  // Select text and wait until the bounding box updates.
+  auto* wc = shell()->web_contents();
+  ASSERT_TRUE(ExecuteScript(wc, "selectText();"));
+  WaitForSelectionBoundingBoxUpdate(wc);
+
+  // Verify the device scale factor.
+  const float device_scale_factor =
+      GetRenderWidgetHostView()->GetDeviceScaleFactor();
+  ASSERT_EQ(scale(), device_scale_factor);
+
+  // Calculate the DIP size from the bounds in pixel. Follow exactly what is
+  // done in `WebFrameWidgetImpl`.
+  const base::ListValue eval_result =
+      EvalJs(wc, "getSelectionBounds();").ExtractList();
+  const int x = floor(eval_result.GetList()[0].GetDouble());
+  const int right = ceil(eval_result.GetList()[1].GetDouble());
+  const int y = floor(eval_result.GetList()[2].GetDouble());
+  const int bottom = ceil(eval_result.GetList()[3].GetDouble());
+  const int expected_dip_width = floor(right / scale()) - ceil(x / scale());
+  const int expected_dip_height = floor(bottom / scale()) - ceil(y / scale());
+
+  // Verify the DIP size of the bounding box.
+  const gfx::Rect selection_bounds =
+      GetRenderWidgetHostView()->GetSelectionBoundingBox();
+  EXPECT_EQ(expected_dip_width, selection_bounds.width());
+  EXPECT_EQ(expected_dip_height, selection_bounds.height());
+}
+
 class RenderWidgetHostViewAuraActiveWidgetTest : public ContentBrowserTest {
  public:
   RenderWidgetHostViewAuraActiveWidgetTest() = default;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 3f26c9eb..f8857aa 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -6199,9 +6199,9 @@
     ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
     gfx::Rect anchor_rect = gfx::Rect(0, 0, 10, 10);
     gfx::Rect focus_rect = gfx::Rect(10 + index, 10 + index, 10, 10);
-    views_[index]->SelectionBoundsChanged(anchor_rect,
-                                          base::i18n::LEFT_TO_RIGHT, focus_rect,
-                                          base::i18n::LEFT_TO_RIGHT, true);
+    views_[index]->SelectionBoundsChanged(
+        anchor_rect, base::i18n::LEFT_TO_RIGHT, focus_rect,
+        base::i18n::LEFT_TO_RIGHT, /*bounding_box=*/gfx::Rect(), true);
 
     // Calculate the bounds.
     gfx::SelectionBound anchor_bound = GetSelectionBoundFromRect(
@@ -6529,7 +6529,8 @@
 
   parent_view_->SelectionBoundsChanged(
       gfx::Rect(0, 0, 10, 10), base::i18n::LEFT_TO_RIGHT,
-      gfx::Rect(10, 10, 10, 10), base::i18n::LEFT_TO_RIGHT, true);
+      gfx::Rect(10, 10, 10, 10), base::i18n::LEFT_TO_RIGHT,
+      /*bounding_box=*/gfx::Rect(), true);
   EXPECT_EQ(parent_view_, text_input_client_);
 
   input_method->RemoveObserver(this);
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index cb85ae3..fede8a9 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -124,11 +124,13 @@
     base::i18n::TextDirection anchor_dir,
     const gfx::Rect& focus_rect,
     base::i18n::TextDirection focus_dir,
+    const gfx::Rect& bounding_box,
     bool is_anchor_first) {
 #if !defined(OS_ANDROID)
   if (GetTextInputManager())
     GetTextInputManager()->SelectionBoundsChanged(
-        this, anchor_rect, anchor_dir, focus_rect, focus_dir, is_anchor_first);
+        this, anchor_rect, anchor_dir, focus_rect, focus_dir, bounding_box,
+        is_anchor_first);
 #else
   NOTREACHED() << "Selection bounds should be routed through the compositor.";
 #endif
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index b9d5c2bb..b9fb1f1 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -383,13 +383,15 @@
   // Notifies the view that the renderer selection bounds has changed.
   // Selection bounds are described as a focus bound which is the current
   // position of caret on the screen, as well as the anchor bound which is the
-  // starting position of the selection. The coordinates are with respect to
-  // RenderWidget's window's origin. Focus and anchor bound are represented as
-  // gfx::Rect.
+  // starting position of the selection. `bounding_box` is the bounds of the
+  // rectangle enclosing the selection region. The coordinates are with respect
+  // to RenderWidget's window's origin. Focus and anchor bound are represented
+  // as gfx::Rect.
   virtual void SelectionBoundsChanged(const gfx::Rect& anchor_rect,
                                       base::i18n::TextDirection anchor_dir,
                                       const gfx::Rect& focus_rect,
                                       base::i18n::TextDirection focus_dir,
+                                      const gfx::Rect& bounding_box,
                                       bool is_anchor_first);
 
   // Updates the range of the marked text in an IME composition.
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index ac421e6..d3f8bd7 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -659,7 +659,7 @@
   rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range);
   rwhv_mac_->SelectionBoundsChanged(caret_rect, base::i18n::LEFT_TO_RIGHT,
                                     caret_rect, base::i18n::LEFT_TO_RIGHT,
-                                    false);
+                                    gfx::Rect(), false);
   EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(caret_range, &rect,
                                                              &actual_range));
   EXPECT_EQ(caret_rect, rect);
@@ -678,7 +678,7 @@
   rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range);
   rwhv_mac_->SelectionBoundsChanged(caret_rect, base::i18n::LEFT_TO_RIGHT,
                                     caret_rect, base::i18n::LEFT_TO_RIGHT,
-                                    false);
+                                    gfx::Rect(), false);
   EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(caret_range, &rect,
                                                              &actual_range));
   EXPECT_EQ(caret_rect, rect);
@@ -694,9 +694,9 @@
   // No caret.
   caret_range = gfx::Range(1, 2);
   rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range);
-  rwhv_mac_->SelectionBoundsChanged(caret_rect, base::i18n::LEFT_TO_RIGHT,
-                                    gfx::Rect(30, 11, 0, 10),
-                                    base::i18n::LEFT_TO_RIGHT, false);
+  rwhv_mac_->SelectionBoundsChanged(
+      caret_rect, base::i18n::LEFT_TO_RIGHT, gfx::Rect(30, 11, 0, 10),
+      base::i18n::LEFT_TO_RIGHT, gfx::Rect(), false);
   EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
       gfx::Range(0, 0), &rect, &actual_range));
   EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
diff --git a/content/browser/renderer_host/text_input_manager.cc b/content/browser/renderer_host/text_input_manager.cc
index e593ab5a..ee6e9eb4 100644
--- a/content/browser/renderer_host/text_input_manager.cc
+++ b/content/browser/renderer_host/text_input_manager.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/renderer_host/text_input_manager.h"
 
+#include <algorithm>
+
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "ui/gfx/geometry/rect.h"
@@ -194,6 +196,7 @@
     base::i18n::TextDirection anchor_dir,
     const gfx::Rect& focus_rect,
     base::i18n::TextDirection focus_dir,
+    const gfx::Rect& bounding_box,
     bool is_anchor_first) {
   DCHECK(IsRegistered(view));
   // Converting the anchor point to root's coordinate space (for child frame
@@ -232,12 +235,42 @@
     }
   }
 
+  // Transform `bounding_box` to the top-level frame's coordinate space.
+  std::vector<gfx::Point> bounding_box_vertice = {
+      bounding_box.origin(), bounding_box.top_right(),
+      bounding_box.bottom_left(), bounding_box.bottom_right()};
+  std::vector<int> x_after_transform;
+  std::vector<int> y_after_transform;
+  for (const auto& vertex : bounding_box_vertice) {
+    const gfx::Point vertex_after_transform =
+        view->TransformPointToRootCoordSpace(vertex);
+    x_after_transform.push_back(vertex_after_transform.x());
+    y_after_transform.push_back(vertex_after_transform.y());
+  }
+
+  std::sort(x_after_transform.begin(), x_after_transform.end());
+  std::sort(y_after_transform.begin(), y_after_transform.end());
+
+  const gfx::Point bounding_box_origin_after_transform(x_after_transform[0],
+                                                       y_after_transform[0]);
+  const gfx::Point bounding_box_bottom_right_after_transform(
+      x_after_transform.back(), y_after_transform.back());
+  const gfx::Rect bounding_box_transformed(
+      bounding_box_origin_after_transform,
+      gfx::Size(bounding_box_bottom_right_after_transform.x() -
+                    bounding_box_origin_after_transform.x(),
+                bounding_box_bottom_right_after_transform.y() -
+                    bounding_box_origin_after_transform.y()));
+
   if (anchor_bound == selection_region_map_[view].anchor &&
-      focus_bound == selection_region_map_[view].focus)
+      focus_bound == selection_region_map_[view].focus &&
+      bounding_box_transformed == selection_region_map_[view].bounding_box) {
     return;
+  }
 
   selection_region_map_[view].anchor = anchor_bound;
   selection_region_map_[view].focus = focus_bound;
+  selection_region_map_[view].bounding_box = bounding_box_transformed;
 
   if (anchor_rect == focus_rect) {
     selection_region_map_[view].caret_rect.set_origin(
diff --git a/content/browser/renderer_host/text_input_manager.h b/content/browser/renderer_host/text_input_manager.h
index be8dc1d1..e4a524f 100644
--- a/content/browser/renderer_host/text_input_manager.h
+++ b/content/browser/renderer_host/text_input_manager.h
@@ -74,6 +74,9 @@
     // The end of the selection region (caret position).
     gfx::SelectionBound focus;
 
+    // The bounding box of the selection region.
+    gfx::Rect bounding_box;
+
     // The following variables are only used on Mac platform.
     // The current caret bounds.
     gfx::Rect caret_rect;
@@ -189,6 +192,7 @@
                               base::i18n::TextDirection anchor_dir,
                               const gfx::Rect& focus_rect,
                               base::i18n::TextDirection focus_dir,
+                              const gfx::Rect& bounding_box,
                               bool is_anchor_first);
 
   // Notify observers that the selection bounds have been updated. This is also
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc
index 8013a860..06d60c1f 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -34,6 +34,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
 #include "url/origin.h"
 #include "url/url_constants.h"
@@ -1162,7 +1163,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // If the URL to navigate to can be associated with any site instance,
   // we want to keep it in the same process.
-  if (IsRendererDebugURL(url))
+  if (blink::IsRendererDebugURL(url))
     return true;
 
   // Any process can host an about:blank URL, except the one used for error
@@ -1510,7 +1511,7 @@
   // Some special URLs will match the site instance of any other URL. This is
   // done before checking both of them for validity, since we want these URLs
   // to have the same site instance as even an invalid one.
-  if (IsRendererDebugURL(src_url) || IsRendererDebugURL(dest_url))
+  if (blink::IsRendererDebugURL(src_url) || blink::IsRendererDebugURL(dest_url))
     return true;
 
   // If either URL is invalid, they aren't part of the same site.
diff --git a/content/browser/wake_lock/OWNERS b/content/browser/wake_lock/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/content/browser/wake_lock/OWNERS
+++ /dev/null
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index bff236c..f1130c7 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -68,6 +68,7 @@
 #include "skia/ext/skia_utils_base.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
 #include "third_party/blink/public/common/security/protocol_handler_security_level.h"
 #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
@@ -437,10 +438,10 @@
 // inside a view-source: URL. This verifies that the navigation is not allowed
 // to proceed after the view-source: URL rewriting logic has run.
 TEST_F(WebContentsImplTest, NavigateToViewSourceRendererDebugURL) {
-  const GURL renderer_debug_url(kChromeUIKillURL);
+  const GURL renderer_debug_url(blink::kChromeUIKillURL);
   const GURL view_source_debug_url("view-source:" + renderer_debug_url.spec());
-  EXPECT_TRUE(IsRendererDebugURL(renderer_debug_url));
-  EXPECT_FALSE(IsRendererDebugURL(view_source_debug_url));
+  EXPECT_TRUE(blink::IsRendererDebugURL(renderer_debug_url));
+  EXPECT_FALSE(blink::IsRendererDebugURL(view_source_debug_url));
   controller().LoadURL(view_source_debug_url, Referrer(),
                        ui::PAGE_TRANSITION_GENERATED, std::string());
   EXPECT_EQ(nullptr, controller().GetPendingEntry());
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
index 770dadd..6b6d445 100644
--- a/content/browser/webauth/authenticator_common.cc
+++ b/content/browser/webauth/authenticator_common.cc
@@ -31,12 +31,9 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/device_service.h"
 #include "content/public/browser/is_uvpaa.h"
-#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/common/content_client.h"
-#include "content/public/common/content_features.h"
 #include "crypto/sha2.h"
 #include "device/base/features.h"
 #include "device/fido/attestation_statement.h"
@@ -845,7 +842,9 @@
 }
 
 bool AuthenticatorCommon::IsFocused() const {
-  return GetRenderFrameHost()->IsCurrent() && request_delegate_->IsFocused();
+  return GetRenderFrameHost()->IsCurrent() &&
+         GetWebAuthenticationDelegate()->IsFocused(
+             WebContents::FromRenderFrameHost(GetRenderFrameHost()));
 }
 
 void AuthenticatorCommon::OnLargeBlobCompressed(
@@ -912,7 +911,7 @@
   }
 
   base::Optional<std::string> rp_id =
-      request_delegate_->MaybeGetRelyingPartyIdOverride(
+      GetWebAuthenticationDelegate()->MaybeGetRelyingPartyIdOverride(
           options->relying_party.id, caller_origin);
 
   if (!rp_id) {
@@ -992,7 +991,9 @@
   const bool might_create_resident_key =
       make_credential_options_->resident_key !=
       device::ResidentKeyRequirement::kDiscouraged;
-  if (might_create_resident_key && !request_delegate_->SupportsResidentKeys()) {
+  if (might_create_resident_key &&
+      !GetWebAuthenticationDelegate()->SupportsResidentKeys(
+          GetRenderFrameHost())) {
     if (make_credential_options_->resident_key ==
         device::ResidentKeyRequirement::kRequired) {
       CompleteMakeCredentialRequest(
@@ -1111,7 +1112,8 @@
          device::AttestationConveyancePreference::kEnterpriseApprovedByBrowser);
   if (attestation == device::AttestationConveyancePreference::
                          kEnterpriseIfRPListedOnAuthenticator &&
-      request_delegate_->ShouldPermitIndividualAttestation(relying_party_id_)) {
+      GetWebAuthenticationDelegate()->ShouldPermitIndividualAttestation(
+          GetBrowserContext(), relying_party_id_)) {
     attestation =
         device::AttestationConveyancePreference::kEnterpriseApprovedByBrowser;
   }
@@ -1163,7 +1165,7 @@
   }
 
   base::Optional<std::string> rp_id =
-      request_delegate_->MaybeGetRelyingPartyIdOverride(
+      GetWebAuthenticationDelegate()->MaybeGetRelyingPartyIdOverride(
           options->relying_party_id, caller_origin);
 
   if (!rp_id) {
@@ -1219,7 +1221,8 @@
   request_delegate_->SetConditionalRequest(options->is_conditional);
 
   if (options->allow_credentials.empty()) {
-    if (!request_delegate_->SupportsResidentKeys()) {
+    if (!GetWebAuthenticationDelegate()->SupportsResidentKeys(
+            GetRenderFrameHost())) {
       CompleteGetAssertionRequest(
           blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED);
       return;
@@ -1473,8 +1476,8 @@
       // cryptotoken checks the attestation blocklist itself.
       if (!origin_is_crypto_token_extension &&
           response_data->attestation_should_be_filtered &&
-          !request_delegate_->ShouldPermitIndividualAttestation(
-              relying_party_id_)) {
+          !GetWebAuthenticationDelegate()->ShouldPermitIndividualAttestation(
+              GetBrowserContext(), relying_party_id_)) {
         attestation_erasure =
             AttestationErasureOption::kEraseAttestationAndAaguid;
       } else if (origin_is_crypto_token_extension &&
@@ -1569,8 +1572,8 @@
   // requesting direct attestation then it knows that it was one of the
   // tokens with inappropriate certs.
   if (response_data.IsAttestationCertificateInappropriatelyIdentifying() &&
-      !request_delegate_->ShouldPermitIndividualAttestation(
-          relying_party_id_)) {
+      !GetWebAuthenticationDelegate()->ShouldPermitIndividualAttestation(
+          GetBrowserContext(), relying_party_id_)) {
     // The attestation response is incorrectly individually identifiable, but
     // the consent is for make & model information about a token, not for
     // individually-identifiable information. Erase the attestation to stop it
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index e87560df..77eca27 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -129,7 +129,7 @@
 namespace {
 
 using InterestingFailureReason =
-    ::content::AuthenticatorRequestClientDelegate::InterestingFailureReason;
+    AuthenticatorRequestClientDelegate::InterestingFailureReason;
 using FailureReasonCallbackReceiver =
     ::device::test::TestCallbackReceiver<InterestingFailureReason>;
 
@@ -447,9 +447,26 @@
   return StringToVector(output);
 }
 
+// Convert a blink::mojom::AttestationConveyancePreference to a
+// device::AtttestationConveyancePreference.
+device::AttestationConveyancePreference ConvertAttestationConveyancePreference(
+    AttestationConveyancePreference in) {
+  switch (in) {
+    case AttestationConveyancePreference::NONE:
+      return ::device::AttestationConveyancePreference::kNone;
+    case AttestationConveyancePreference::INDIRECT:
+      return ::device::AttestationConveyancePreference::kIndirect;
+    case AttestationConveyancePreference::DIRECT:
+      return ::device::AttestationConveyancePreference::kDirect;
+    case AttestationConveyancePreference::ENTERPRISE:
+      return ::device::AttestationConveyancePreference::
+          kEnterpriseIfRPListedOnAuthenticator;
+  }
+}
+
 }  // namespace
 
-class AuthenticatorTestBase : public content::RenderViewHostTestHarness {
+class AuthenticatorTestBase : public RenderViewHostTestHarness {
  protected:
   AuthenticatorTestBase()
       : RenderViewHostTestHarness(
@@ -457,7 +474,7 @@
   ~AuthenticatorTestBase() override = default;
 
   void SetUp() override {
-    content::RenderViewHostTestHarness::SetUp();
+    RenderViewHostTestHarness::SetUp();
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::U2FClient::InitializeFake();
@@ -475,7 +492,7 @@
   }
 
   void TearDown() override {
-    content::RenderViewHostTestHarness::TearDown();
+    RenderViewHostTestHarness::TearDown();
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     chromeos::U2FClient::Shutdown();
@@ -518,7 +535,7 @@
   }
 
   void NavigateAndCommit(const GURL& url) {
-    content::RenderViewHostTestHarness::NavigateAndCommit(url);
+    RenderViewHostTestHarness::NavigateAndCommit(url);
   }
 
   mojo::Remote<blink::mojom::Authenticator> ConnectToAuthenticator() {
@@ -1603,86 +1620,65 @@
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-class OverrideRPIDAuthenticatorRequestDelegate
-    : public AuthenticatorRequestClientDelegate {
+// TestWebAuthenticationDelegate is a test fake implementation of the
+// WebAuthentuicationDelegate embedder interface.
+class TestWebAuthenticationDelegate : public WebAuthenticationDelegate {
  public:
-  OverrideRPIDAuthenticatorRequestDelegate() = default;
-  ~OverrideRPIDAuthenticatorRequestDelegate() override = default;
+  base::Optional<bool> IsUserVerifyingPlatformAuthenticatorAvailableOverride(
+      RenderFrameHost*) override {
+    return is_uvpaa_override;
+  }
 
   base::Optional<std::string> MaybeGetRelyingPartyIdOverride(
       const std::string& claimed_rp_id,
       const url::Origin& caller_origin) override {
-    CHECK_EQ(caller_origin.scheme(), "chrome-extension");
-    return caller_origin.Serialize();
+    return rp_id_override;
   }
 
-  bool SupportsResidentKeys() override { return true; }
+  bool ShouldPermitIndividualAttestation(
+      content::BrowserContext* browser_context,
+      const std::string& relying_party_id) override {
+    return permit_individual_attestation;
+  }
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(OverrideRPIDAuthenticatorRequestDelegate);
+  bool SupportsResidentKeys(RenderFrameHost*) override {
+    return supports_resident_keys;
+  }
+
+  bool IsFocused(WebContents* web_contents) override { return is_focused; }
+
+#if defined(OS_MAC)
+  base::Optional<TouchIdAuthenticatorConfig> GetTouchIdAuthenticatorConfig(
+      BrowserContext* browser_context) override {
+    return touch_id_authenticator_config;
+  }
+#endif
+
+  // If set, the return value of IsUVPAA() will be overridden with this value.
+  // Platform-specific implementations will not be invoked.
+  base::Optional<bool> is_uvpaa_override;
+
+  // If set, the delegate will override the RP ID used for WebAuthn requests
+  // with this value.
+  base::Optional<std::string> rp_id_override;
+
+  // Indicates whether individual attestation should be permitted by the
+  // delegate.
+  bool permit_individual_attestation = false;
+
+  // Indicates whether resident key operations should be permitted by the
+  // delegate.
+  bool supports_resident_keys = false;
+
+  // The return value of the focus check issued at the end of a request.
+  bool is_focused = true;
+
+#if defined(OS_MAC)
+  // Configuration data for the macOS platform authenticator.
+  base::Optional<TouchIdAuthenticatorConfig> touch_id_authenticator_config;
+#endif
 };
 
-class OverrideRPIDAuthenticatorContentBrowserClient
-    : public ContentBrowserClient {
- public:
-  std::unique_ptr<AuthenticatorRequestClientDelegate>
-  GetWebAuthenticationRequestDelegate(
-      RenderFrameHost* render_frame_host) override {
-    return std::make_unique<OverrideRPIDAuthenticatorRequestDelegate>();
-  }
-};
-
-static constexpr char kExtensionId[] = "abcdefg";
-
-class ExtensionAuthenticatorTest : public AuthenticatorImplTest {
- public:
-  void SetUp() override {
-    AuthenticatorImplTest::SetUp();
-    old_client_ = SetBrowserClientForTesting(&test_client_);
-
-    const std::string extension_origin =
-        std::string("chrome-extension://") + kExtensionId;
-    const std::string extension_page = extension_origin + "/test.html";
-    NavigateAndCommit(GURL(extension_page));
-  }
-
-  void TearDown() override {
-    SetBrowserClientForTesting(old_client_);
-    AuthenticatorImplTest::TearDown();
-  }
-
- private:
-  OverrideRPIDAuthenticatorContentBrowserClient test_client_;
-  ContentBrowserClient* old_client_ = nullptr;
-};
-
-// Test that credentials can be created and used from an extension origin when
-// permitted by the delegate.
-TEST_F(ExtensionAuthenticatorTest, ChromeExtensions) {
-  std::vector<uint8_t> credential_id;
-  {
-    PublicKeyCredentialCreationOptionsPtr options =
-        GetTestPublicKeyCredentialCreationOptions();
-    options->relying_party.id = kExtensionId;
-
-    MakeCredentialResult result =
-        AuthenticatorMakeCredential(std::move(options));
-    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
-    credential_id = result.response->info->raw_id;
-  }
-
-  {
-    PublicKeyCredentialRequestOptionsPtr options =
-        GetTestPublicKeyCredentialRequestOptions();
-    options->relying_party_id = kExtensionId;
-    options->allow_credentials[0] = device::PublicKeyCredentialDescriptor(
-        device::CredentialType::kPublicKey, std::move(credential_id));
-
-    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
-              AuthenticatorStatus::SUCCESS);
-  }
-}
-
 enum class EnterprisePolicy {
   LISTED,
   NOT_LISTED,
@@ -1706,48 +1702,19 @@
   PACKED,
 };
 
-// Convert a blink::mojom::AttestationConveyancePreference to a
-// device::AtttestationConveyancePreference.
-device::AttestationConveyancePreference ConvertAttestationConveyancePreference(
-    AttestationConveyancePreference in) {
-  switch (in) {
-    case AttestationConveyancePreference::NONE:
-      return ::device::AttestationConveyancePreference::kNone;
-    case AttestationConveyancePreference::INDIRECT:
-      return ::device::AttestationConveyancePreference::kIndirect;
-    case AttestationConveyancePreference::DIRECT:
-      return ::device::AttestationConveyancePreference::kDirect;
-    case AttestationConveyancePreference::ENTERPRISE:
-      return ::device::AttestationConveyancePreference::
-          kEnterpriseIfRPListedOnAuthenticator;
-  }
-}
-
-class TestWebAuthenticationDelegate : public WebAuthenticationDelegate {
- public:
-  base::Optional<bool> IsUserVerifyingPlatformAuthenticatorAvailableOverride(
-      RenderFrameHost*) override {
-    return is_uvpaa;
-  }
-
-  bool is_uvpaa = false;
-};
-
+// TestAuthenticatorRequestDelegate is a test fake implementation of the
+// AuthenticatorRequestClientDelegate embedder interface.
 class TestAuthenticatorRequestDelegate
     : public AuthenticatorRequestClientDelegate {
  public:
   TestAuthenticatorRequestDelegate(
       RenderFrameHost* render_frame_host,
       base::OnceClosure action_callbacks_registered_callback,
-      EnterprisePolicy enterprise_policy,
       AttestationConsent attestation_consent,
-      bool is_focused,
       base::OnceClosure started_over_callback)
       : action_callbacks_registered_callback_(
             std::move(action_callbacks_registered_callback)),
-        enterprise_policy_(enterprise_policy),
         attestation_consent_(attestation_consent),
-        is_focused_(is_focused),
         started_over_callback_(std::move(started_over_callback)) {}
 
   ~TestAuthenticatorRequestDelegate() override {
@@ -1771,11 +1738,6 @@
     }
   }
 
-  bool ShouldPermitIndividualAttestation(
-      const std::string& relying_party_id) override {
-    return enterprise_policy_ == EnterprisePolicy::LISTED;
-  }
-
   void ShouldReturnAttestation(
       const std::string& relying_party_id,
       const device::FidoAuthenticator* authenticator,
@@ -1806,8 +1768,6 @@
     std::move(callback).Run(result);
   }
 
-  bool IsFocused() override { return is_focused_; }
-
   void OnTransportAvailabilityEnumerated(
       device::FidoRequestHandlerBase::TransportAvailabilityInfo transport_info)
       override {
@@ -1821,9 +1781,7 @@
 
   base::OnceClosure action_callbacks_registered_callback_;
   base::Optional<base::OnceClosure> cancel_callback_;
-  const EnterprisePolicy enterprise_policy_;
   const AttestationConsent attestation_consent_;
-  const bool is_focused_;
   base::OnceClosure started_over_callback_;
   bool attestation_consent_queried_ = false;
 
@@ -1831,13 +1789,16 @@
   DISALLOW_COPY_AND_ASSIGN(TestAuthenticatorRequestDelegate);
 };
 
+// TestAuthenticatorContentBrowserClient is a test fake implementation of the
+// ContentBrowserClient interface that injects |TestWebAuthenticationDelegate|
+// and |TestAuthenticatorRequestDelegate| instances into |AuthenticatorImpl|.
 class TestAuthenticatorContentBrowserClient : public ContentBrowserClient {
  public:
   TestWebAuthenticationDelegate* GetTestWebAuthenticationDelegate() {
     return &web_authentication_delegate;
   }
 
-  // ContentBrowserClient
+  // ContentBrowserClient:
   WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
     return &web_authentication_delegate;
   }
@@ -1852,8 +1813,7 @@
         action_callbacks_registered_callback
             ? std::move(action_callbacks_registered_callback)
             : base::DoNothing(),
-        enterprise_policy, attestation_consent, is_focused,
-        std::move(started_over_callback_));
+        attestation_consent, std::move(started_over_callback_));
   }
 
   TestWebAuthenticationDelegate web_authentication_delegate;
@@ -1862,9 +1822,7 @@
   // delegate is informed that the request has started.
   base::OnceClosure action_callbacks_registered_callback;
 
-  EnterprisePolicy enterprise_policy = EnterprisePolicy::NOT_LISTED;
   AttestationConsent attestation_consent = AttestationConsent::NOT_USED;
-  bool is_focused = true;
 
   // This emulates scenarios where a nullptr RequestClientDelegate is returned
   // because a request is already in progress.
@@ -1879,7 +1837,7 @@
 };
 
 // A test class that installs and removes an
-// |AuthenticatorTestContentBrowserClient| automatically and can run tests
+// |TestAuthenticatorContentBrowserClient| automatically and can run tests
 // against simulated attestation results.
 class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
  public:
@@ -1919,7 +1877,9 @@
           AttestationConveyancePreferenceToString(test.attestation_requested));
       SCOPED_TRACE(i);
 
-      test_client_.enterprise_policy = test.enterprise_policy;
+      test_client_.GetTestWebAuthenticationDelegate()
+          ->permit_individual_attestation =
+          test.enterprise_policy == EnterprisePolicy::LISTED;
       test_client_.attestation_consent = test.attestation_consent;
 
       PublicKeyCredentialCreationOptionsPtr options =
@@ -2084,6 +2044,55 @@
   DISALLOW_COPY_AND_ASSIGN(AuthenticatorContentBrowserClientTest);
 };
 
+// Test that credentials can be created and used from an extension origin when
+// permitted by the delegate.
+TEST_F(AuthenticatorContentBrowserClientTest, ChromeExtensions) {
+  static constexpr char kExtensionId[] = "abcdefg";
+  static const std::string kExtensionOrigin =
+      std::string("chrome-extension://") + kExtensionId;
+
+  NavigateAndCommit(GURL(kExtensionOrigin + "/test.html"));
+
+  for (bool permit_rp_id_override : {false, true}) {
+    SCOPED_TRACE(testing::Message() << "permit=" << permit_rp_id_override);
+    if (permit_rp_id_override) {
+      test_client_.GetTestWebAuthenticationDelegate()->rp_id_override =
+          kExtensionOrigin;
+    } else {
+      test_client_.GetTestWebAuthenticationDelegate()->rp_id_override =
+          base::nullopt;
+    }
+
+    std::vector<uint8_t> credential_id;
+    {
+      PublicKeyCredentialCreationOptionsPtr options =
+          GetTestPublicKeyCredentialCreationOptions();
+      options->relying_party.id = kExtensionId;
+
+      MakeCredentialResult result =
+          AuthenticatorMakeCredential(std::move(options));
+      if (permit_rp_id_override) {
+        EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
+        credential_id = result.response->info->raw_id;
+      } else {
+        EXPECT_EQ(result.status, AuthenticatorStatus::INVALID_DOMAIN);
+      }
+    }
+
+    {
+      PublicKeyCredentialRequestOptionsPtr options =
+          GetTestPublicKeyCredentialRequestOptions();
+      options->relying_party_id = kExtensionId;
+      options->allow_credentials[0] = device::PublicKeyCredentialDescriptor(
+          device::CredentialType::kPublicKey, std::move(credential_id));
+
+      EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
+                permit_rp_id_override ? AuthenticatorStatus::SUCCESS
+                                      : AuthenticatorStatus::INVALID_DOMAIN);
+    }
+  }
+}
+
 TEST_F(AuthenticatorContentBrowserClientTest, AttestationBehaviour) {
   const char kStandardCommonName[] = "U2F Attestation";
   const char kIndividualCommonName[] = "Individual Cert";
@@ -2350,7 +2359,7 @@
 // behavior of the Touch ID platform authenticator.
 TEST_F(AuthenticatorContentBrowserClientTest,
        PlatformAuthenticatorAttestation) {
-  test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa = true;
+  test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override = true;
   virtual_device_factory_->SetSupportedProtocol(
       device::ProtocolVersion::kCtap2);
   virtual_device_factory_->SetTransport(
@@ -2922,7 +2931,7 @@
   // When the |ContentBrowserClient| considers the tab to be unfocused,
   // registration requests should fail with a |NOT_FOCUSED| error, but getting
   // assertions should still work.
-  test_client_.is_focused = false;
+  test_client_.GetTestWebAuthenticationDelegate()->is_focused = false;
 
   NavigateAndCommit(GURL(kTestOrigin1));
 
@@ -2988,7 +2997,8 @@
 
   for (const bool is_uvpaa : {false, true}) {
     SCOPED_TRACE(::testing::Message() << "is_uvpaa=" << is_uvpaa);
-    test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa = is_uvpaa;
+    test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override =
+        is_uvpaa;
 
     TestIsUvpaaCallback cb;
     authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(cb.callback());
@@ -3049,9 +3059,7 @@
       : TestAuthenticatorRequestDelegate(
             nullptr /* render_frame_host */,
             base::DoNothing() /* did_start_request_callback */,
-            EnterprisePolicy::NOT_LISTED,
             AttestationConsent::NOT_USED,
-            true /* is_focused */,
             /*started_over_callback=*/base::OnceClosure()),
         failure_reasons_callback_(std::move(failure_reasons_callback)) {}
   ~MockAuthenticatorRequestDelegateObserver() override = default;
@@ -3196,9 +3204,9 @@
   EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
 
   ASSERT_TRUE(failure_reason_receiver.was_called());
-  EXPECT_EQ(content::AuthenticatorRequestClientDelegate::
-                InterestingFailureReason::kTimeout,
-            std::get<0>(*failure_reason_receiver.result()));
+  EXPECT_EQ(
+      AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout,
+      std::get<0>(*failure_reason_receiver.result()));
 }
 
 TEST_F(AuthenticatorImplRequestDelegateTest,
@@ -3226,8 +3234,8 @@
             callback_receiver.status());
 
   ASSERT_TRUE(failure_reason_receiver.was_called());
-  EXPECT_EQ(content::AuthenticatorRequestClientDelegate::
-                InterestingFailureReason::kKeyAlreadyRegistered,
+  EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
+                kKeyAlreadyRegistered,
             std::get<0>(*failure_reason_receiver.result()));
 }
 
@@ -3249,8 +3257,8 @@
   EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
 
   ASSERT_TRUE(failure_reason_receiver.was_called());
-  EXPECT_EQ(content::AuthenticatorRequestClientDelegate::
-                InterestingFailureReason::kKeyNotRegistered,
+  EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
+                kKeyNotRegistered,
             std::get<0>(*failure_reason_receiver.result()));
 }
 
@@ -5368,8 +5376,6 @@
 
   void FinishCollectToken() override {}
 
-  bool SupportsResidentKeys() override { return true; }
-
   void SelectAccount(
       std::vector<device::AuthenticatorGetAssertionResponse> responses,
       base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
@@ -5423,6 +5429,14 @@
 class ResidentKeyTestAuthenticatorContentBrowserClient
     : public ContentBrowserClient {
  public:
+  ResidentKeyTestAuthenticatorContentBrowserClient() {
+    web_authentication_delegate.supports_resident_keys = true;
+  }
+
+  WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
+    return &web_authentication_delegate;
+  }
+
   std::unique_ptr<AuthenticatorRequestClientDelegate>
   GetWebAuthenticationRequestDelegate(
       RenderFrameHost* render_frame_host) override {
@@ -5430,6 +5444,8 @@
         expected_accounts, selected_user_id, &failure_reason, &is_conditional);
   }
 
+  TestWebAuthenticationDelegate web_authentication_delegate;
+
   std::string expected_accounts;
   std::vector<uint8_t> selected_user_id;
   bool is_conditional = false;
@@ -6536,7 +6552,7 @@
   void NavigateAndCommit(const GURL& url) {
     // The |RenderFrameHost| must outlive |AuthenticatorImpl|.
     internal_authenticator_impl_.reset();
-    content::RenderViewHostTestHarness::NavigateAndCommit(url);
+    RenderViewHostTestHarness::NavigateAndCommit(url);
   }
 
   InternalAuthenticatorImpl* GetAuthenticator(
@@ -6655,31 +6671,12 @@
 }
 
 #if defined(OS_MAC)
-class TouchIdConfigWebAuthenticationDelegate
-    : public WebAuthenticationDelegate {
- public:
-  TouchIdConfigWebAuthenticationDelegate() = default;
-  ~TouchIdConfigWebAuthenticationDelegate() override = default;
-
-  base::Optional<TouchIdAuthenticatorConfig> GetTouchIdAuthenticatorConfig(
-      BrowserContext* browser_context) override {
-    return TouchIdAuthenticatorConfig{};
-  }
-};
-
-class TouchIdConfigAuthenticatorContentBrowserClient
-    : public ContentBrowserClient {
- private:
-  WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
-    return &delegate_;
-  }
-  TouchIdConfigWebAuthenticationDelegate delegate_;
-};
-
 class TouchIdAuthenticatorImplTest : public AuthenticatorImplTest {
  public:
   void SetUp() override {
     AuthenticatorImplTest::SetUp();
+    test_client_.GetTestWebAuthenticationDelegate()
+        ->touch_id_authenticator_config.emplace();
     old_client_ = SetBrowserClientForTesting(&test_client_);
   }
 
@@ -6689,7 +6686,7 @@
   }
 
  private:
-  TouchIdConfigAuthenticatorContentBrowserClient test_client_;
+  TestAuthenticatorContentBrowserClient test_client_;
   ContentBrowserClient* old_client_ = nullptr;
 };
 
diff --git a/content/browser/webauth/virtual_authenticator_request_delegate.cc b/content/browser/webauth/virtual_authenticator_request_delegate.cc
index 5f7196b..40e89bf 100644
--- a/content/browser/webauth/virtual_authenticator_request_delegate.cc
+++ b/content/browser/webauth/virtual_authenticator_request_delegate.cc
@@ -19,10 +19,6 @@
 VirtualAuthenticatorRequestDelegate::~VirtualAuthenticatorRequestDelegate() =
     default;
 
-bool VirtualAuthenticatorRequestDelegate::SupportsResidentKeys() {
-  return true;
-}
-
 void VirtualAuthenticatorRequestDelegate::SelectAccount(
     std::vector<device::AuthenticatorGetAssertionResponse> responses,
     base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
diff --git a/content/browser/webauth/virtual_authenticator_request_delegate.h b/content/browser/webauth/virtual_authenticator_request_delegate.h
index b91f812..b44af19 100644
--- a/content/browser/webauth/virtual_authenticator_request_delegate.h
+++ b/content/browser/webauth/virtual_authenticator_request_delegate.h
@@ -20,7 +20,6 @@
   ~VirtualAuthenticatorRequestDelegate() override;
 
   // AuthenticatorRequestClientDelegate:
-  bool SupportsResidentKeys() override;
   void SelectAccount(
       std::vector<device::AuthenticatorGetAssertionResponse> responses,
       base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc
index 48a7681..d0adb60a 100644
--- a/content/browser/webauth/webauth_browsertest.cc
+++ b/content/browser/webauth/webauth_browsertest.cc
@@ -354,6 +354,22 @@
   int delegate_create_count = 0;
 };
 
+class WebAuthBrowserTestWebAuthenticationDelegate
+    : public WebAuthenticationDelegate {
+ public:
+  explicit WebAuthBrowserTestWebAuthenticationDelegate(
+      WebAuthBrowserTestState* test_state)
+      : test_state_(test_state) {}
+
+  bool IsFocused(content::WebContents* web_contents) override {
+    test_state_->focus_checked = true;
+    return WebAuthenticationDelegate::IsFocused(web_contents);
+  }
+
+ private:
+  WebAuthBrowserTestState* const test_state_;
+};
+
 class WebAuthBrowserTestClientDelegate
     : public AuthenticatorRequestClientDelegate {
  public:
@@ -369,11 +385,6 @@
         .Run(std::move(callback));
   }
 
-  bool IsFocused() override {
-    test_state_->focus_checked = true;
-    return AuthenticatorRequestClientDelegate::IsFocused();
-  }
-
  private:
   WebAuthBrowserTestState* const test_state_;
 
@@ -388,6 +399,10 @@
       WebAuthBrowserTestState* test_state)
       : test_state_(test_state) {}
 
+  WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
+    return &web_authentication_delegate_;
+  }
+
   std::unique_ptr<AuthenticatorRequestClientDelegate>
   GetWebAuthenticationRequestDelegate(
       RenderFrameHost* render_frame_host) override {
@@ -397,6 +412,8 @@
 
  private:
   WebAuthBrowserTestState* const test_state_;
+  WebAuthBrowserTestWebAuthenticationDelegate web_authentication_delegate_{
+      test_state_};
 
   DISALLOW_COPY_AND_ASSIGN(WebAuthBrowserTestContentBrowserClient);
 };
diff --git a/content/browser/webui/web_ui_controller_factory_registry.cc b/content/browser/webui/web_ui_controller_factory_registry.cc
index fd75a12..089664f 100644
--- a/content/browser/webui/web_ui_controller_factory_registry.cc
+++ b/content/browser/webui/web_ui_controller_factory_registry.cc
@@ -13,6 +13,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -87,7 +88,7 @@
          // See http://crbug.com/42547
          url.spec() == url::kAboutBlankURL ||
          // javascript: and debug URLs like chrome://kill are allowed.
-         IsRendererDebugURL(url);
+         blink::IsRendererDebugURL(url);
 }
 
 WebUIControllerFactoryRegistry::WebUIControllerFactoryRegistry() = default;
diff --git a/content/browser/webui/web_ui_mojo_browsertest.cc b/content/browser/webui/web_ui_mojo_browsertest.cc
index f0f6be5..08c99f3 100644
--- a/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -44,6 +44,7 @@
 #include "mojo/public/cpp/bindings/binder_map.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 
 namespace content {
 namespace {
@@ -390,7 +391,7 @@
       shell()->web_contents(),
       RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
   shell()->web_contents()->GetController().LoadURL(
-      GURL(content::kChromeUICrashURL), content::Referrer(),
+      GURL(blink::kChromeUICrashURL), content::Referrer(),
       ui::PAGE_TRANSITION_TYPED, std::string());
   crash_observer.Wait();
   EXPECT_FALSE(web_ui->GetRemoteForTest().is_bound());
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn
index bdcf5f6..57d14b4c 100644
--- a/content/child/BUILD.gn
+++ b/content/child/BUILD.gn
@@ -83,7 +83,6 @@
     "//device/gamepad/public/cpp:switches",
     "//gpu/command_buffer/client",
     "//media",
-    "//media/blink",
     "//mojo/core/embedder",
     "//net",
     "//services/device/public/cpp:device_features",
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 5c59e98..930e3a6 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -328,9 +328,6 @@
       CommitNavigationParams request_params)
       => (blink.mojom.CommitResult commit_result);
 
-  // Asks the renderer to handle a renderer-debug URL.
-  HandleRendererDebugURL(url.mojom.Url url);
-
   // Provides the renderer an updated |subresource_loader_factories|.
   //
   // This method is intended to fix broken loaders after a Network Service
diff --git a/content/public/browser/authenticator_request_client_delegate.cc b/content/public/browser/authenticator_request_client_delegate.cc
index 31cee0d..fdf0f533 100644
--- a/content/public/browser/authenticator_request_client_delegate.cc
+++ b/content/public/browser/authenticator_request_client_delegate.cc
@@ -25,6 +25,36 @@
 
 WebAuthenticationDelegate::~WebAuthenticationDelegate() = default;
 
+base::Optional<std::string>
+WebAuthenticationDelegate::MaybeGetRelyingPartyIdOverride(
+    const std::string& claimed_relying_party_id,
+    const url::Origin& caller_origin) {
+  return base::nullopt;
+}
+
+bool WebAuthenticationDelegate::ShouldPermitIndividualAttestation(
+    BrowserContext* browser_context,
+    const std::string& relying_party_id) {
+  return false;
+}
+
+bool WebAuthenticationDelegate::SupportsResidentKeys(
+    RenderFrameHost* render_frame_host) {
+  // The testing API supports resident keys, but for real requests //content
+  // doesn't by default.
+  FrameTreeNode* frame_tree_node =
+      static_cast<RenderFrameHostImpl*>(render_frame_host)->frame_tree_node();
+  if (AuthenticatorEnvironmentImpl::GetInstance()
+          ->IsVirtualAuthenticatorEnabledFor(frame_tree_node)) {
+    return true;
+  }
+  return false;
+}
+
+bool WebAuthenticationDelegate::IsFocused(WebContents* web_contents) {
+  return true;
+}
+
 #if defined(OS_MAC)
 base::Optional<WebAuthenticationDelegate::TouchIdAuthenticatorConfig>
 WebAuthenticationDelegate::GetTouchIdAuthenticatorConfig(
@@ -60,13 +90,6 @@
 AuthenticatorRequestClientDelegate::~AuthenticatorRequestClientDelegate() =
     default;
 
-base::Optional<std::string>
-AuthenticatorRequestClientDelegate::MaybeGetRelyingPartyIdOverride(
-    const std::string& claimed_relying_party_id,
-    const url::Origin& caller_origin) {
-  return base::nullopt;
-}
-
 void AuthenticatorRequestClientDelegate::SetRelyingPartyId(const std::string&) {
 }
 
@@ -81,11 +104,6 @@
     device::FidoRequestHandlerBase::RequestCallback request_callback,
     base::RepeatingClosure bluetooth_adapter_power_on_callback) {}
 
-bool AuthenticatorRequestClientDelegate::ShouldPermitIndividualAttestation(
-    const std::string& relying_party_id) {
-  return false;
-}
-
 void AuthenticatorRequestClientDelegate::ShouldReturnAttestation(
     const std::string& relying_party_id,
     const device::FidoAuthenticator* authenticator,
@@ -94,10 +112,6 @@
   std::move(callback).Run(!is_enterprise_attestation);
 }
 
-bool AuthenticatorRequestClientDelegate::SupportsResidentKeys() {
-  return false;
-}
-
 void AuthenticatorRequestClientDelegate::ConfigureCable(
     const url::Origin& origin,
     base::span<const device::CableDiscoveryData> pairings_from_extension,
@@ -111,10 +125,6 @@
   NOTREACHED();
 }
 
-bool AuthenticatorRequestClientDelegate::IsFocused() {
-  return true;
-}
-
 void AuthenticatorRequestClientDelegate::DisableUI() {}
 
 bool AuthenticatorRequestClientDelegate::IsWebAuthnUIEnabled() {
diff --git a/content/public/browser/authenticator_request_client_delegate.h b/content/public/browser/authenticator_request_client_delegate.h
index b9934e3..713a7b3 100644
--- a/content/public/browser/authenticator_request_client_delegate.h
+++ b/content/public/browser/authenticator_request_client_delegate.h
@@ -34,8 +34,9 @@
 
 namespace content {
 
-class RenderFrameHost;
 class BrowserContext;
+class RenderFrameHost;
+class WebContents;
 
 // WebAuthenticationDelegate is an interface that lets the //content layer
 // provide embedder specific configuration for handling Web Authentication API
@@ -49,6 +50,43 @@
   WebAuthenticationDelegate();
   virtual ~WebAuthenticationDelegate();
 
+  // Permits the embedder to override normal relying party ID processing. Is
+  // given the untrusted, claimed relying party ID from the WebAuthn call, as
+  // well as the origin of the caller, and may return a relying party ID to
+  // override normal validation.
+  //
+  // This is an access-control decision: RP IDs are used to control access to
+  // credentials so thought is required before allowing an origin to assert an
+  // RP ID. RP ID strings may be stored on authenticators and may later appear
+  // in management UI.
+  virtual base::Optional<std::string> MaybeGetRelyingPartyIdOverride(
+      const std::string& claimed_relying_party_id,
+      const url::Origin& caller_origin);
+
+  // Returns true if the given relying party ID is permitted to receive
+  // individual attestation certificates. This:
+  //  a) triggers a signal to the security key that returning individual
+  //     attestation certificates is permitted, and
+  //  b) skips any permission prompt for attestation.
+  virtual bool ShouldPermitIndividualAttestation(
+      BrowserContext* browser_context,
+      const std::string& relying_party_id);
+
+  // SupportsResidentKeys returns true if this implementation of
+  // |AuthenticatorRequestClientDelegate| supports resident keys for WebAuthn
+  // requests originating from |render_frame_host|. If false then requests to
+  // create or get assertions will be immediately rejected.
+  virtual bool SupportsResidentKeys(RenderFrameHost* render_frame_host);
+
+  // Returns whether |web_contents| is the active tab in the focused window. We
+  // do not want to allow authenticatorMakeCredential operations to be triggered
+  // by background tabs.
+  //
+  // Note that the default implementation of this function, and the
+  // implementation in ChromeContentBrowserClient for Android, return |true| so
+  // that testing is possible.
+  virtual bool IsFocused(WebContents* web_contents);
+
 #if defined(OS_MAC)
   using TouchIdAuthenticatorConfig = device::fido::mac::AuthenticatorConfig;
 
@@ -113,23 +151,12 @@
   AuthenticatorRequestClientDelegate();
   ~AuthenticatorRequestClientDelegate() override;
 
-  // Permits the embedder to override normal relying party ID processing. Is
-  // given the untrusted, claimed relying party ID from the WebAuthn call, as
-  // well as the origin of the caller, and may return a relying party ID to
-  // override normal validation.
-  //
-  // This is an access-control decision: RP IDs are used to control access to
-  // credentials so thought is required before allowing an origin to assert an
-  // RP ID. RP ID strings may be stored on authenticators and may later appear
-  // in management UI.
-  virtual base::Optional<std::string> MaybeGetRelyingPartyIdOverride(
-      const std::string& claimed_relying_party_id,
-      const url::Origin& caller_origin);
-
   // SetRelyingPartyId sets the RP ID for this request. This is called after
-  // |MaybeGetRelyingPartyIdOverride| is given the opportunity to affect this
-  // value. For typical origins, the RP ID is just a domain name, but
-  // |MaybeGetRelyingPartyIdOverride| may return other forms of strings.
+  // |WebAuthenticationDelegate::MaybeGetRelyingPartyIdOverride| is given the
+  // opportunity to affect this value. For typical origins, the RP ID is just a
+  // domain name, but
+  // |WebAuthenticationDelegate::MaybeGetRelyingPartyIdOverride| may return
+  // other forms of strings.
   virtual void SetRelyingPartyId(const std::string& rp_id);
 
   // Called when the request fails for the given |reason|.
@@ -152,14 +179,6 @@
       device::FidoRequestHandlerBase::RequestCallback request_callback,
       base::RepeatingClosure bluetooth_adapter_power_on_callback);
 
-  // Returns true if the given relying party ID is permitted to receive
-  // individual attestation certificates. This:
-  //  a) triggers a signal to the security key that returning individual
-  //     attestation certificates is permitted, and
-  //  b) skips any permission prompt for attestation.
-  virtual bool ShouldPermitIndividualAttestation(
-      const std::string& relying_party_id);
-
   // Invokes |callback| with |true| if the given relying party ID is permitted
   // to receive attestation certificates from the provided FidoAuthenticator.
   // Otherwise invokes |callback| with |false|.
@@ -177,12 +196,6 @@
       bool is_enterprise_attestation,
       base::OnceCallback<void(bool)> callback);
 
-  // SupportsResidentKeys returns true if this implementation of
-  // |AuthenticatorRequestClientDelegate| supports resident keys. If false then
-  // requests to create or get assertions will be immediately rejected and
-  // |SelectAccount| will never be called.
-  virtual bool SupportsResidentKeys();
-
   // ConfigureCable optionally configures Cloud-assisted Bluetooth Low Energy
   // transports. |origin| is the origin of the calling site and
   // |pairings_from_extension| are caBLEv1 pairings that have been provided in
@@ -201,21 +214,13 @@
   // use of any specific account before it is returned. The callback takes the
   // selected account, or else |cancel_callback| can be called.
   //
-  // This is only called if |SupportsResidentKeys| returns true.
+  // This is only called if |WebAuthenticationDelegate::SupportsResidentKeys|
+  // returns true.
   virtual void SelectAccount(
       std::vector<device::AuthenticatorGetAssertionResponse> responses,
       base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
           callback);
 
-  // Returns whether the WebContents corresponding to |render_frame_host| is the
-  // active tab in the focused window. We do not want to allow
-  // authenticatorMakeCredential operations to be triggered by background tabs.
-  //
-  // Note that the default implementation of this function, and the
-  // implementation in ChromeContentBrowserClient for Android, return |true| so
-  // that testing is possible.
-  virtual bool IsFocused();
-
   // Disables the UI (needed in cases when called by other components, like
   // cryptotoken).
   virtual void DisableUI();
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index f928bec6..9a8c758 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -41,59 +41,10 @@
 const char kChromeUIUkmHost[] = "ukm";
 const char kChromeUIWebRTCInternalsHost[] = "webrtc-internals";
 
-const char kChromeUIBadCastCrashURL[] = "chrome://badcastcrash/";
-const char kChromeUICheckCrashURL[] = "chrome://checkcrash/";
-const char kChromeUIBrowserCrashURL[] = "chrome://inducebrowsercrashforrealz/";
-const char kChromeUIBrowserUIHang[] = "chrome://uithreadhang/";
-const char kChromeUICrashURL[] = "chrome://crash/";
-const char kChromeUIDelayedBrowserUIHang[] = "chrome://delayeduithreadhang/";
-const char kChromeUIDumpURL[] = "chrome://crashdump/";
-const char kChromeUIGpuCleanURL[] = "chrome://gpuclean/";
-const char kChromeUIGpuCrashURL[] = "chrome://gpucrash/";
-const char kChromeUIGpuHangURL[] = "chrome://gpuhang/";
-const char kChromeUIHangURL[] = "chrome://hang/";
-const char kChromeUIKillURL[] = "chrome://kill/";
-const char kChromeUIMemoryExhaustURL[] = "chrome://memory-exhaust/";
-const char kChromeUIMemoryPressureCriticalURL[] =
-    "chrome://memory-pressure-critical/";
-const char kChromeUIMemoryPressureModerateURL[] =
-    "chrome://memory-pressure-moderate/";
-const char kChromeUINetworkErrorURL[] = "chrome://network-error/";
-const char kChromeUINetworkErrorsListingURL[] = "chrome://network-errors/";
-const char kChromeUIPpapiFlashCrashURL[] = "chrome://ppapiflashcrash/";
-const char kChromeUIPpapiFlashHangURL[] = "chrome://ppapiflashhang/";
-const char kChromeUIProcessInternalsURL[] = "chrome://process-internals";
-#if defined(OS_ANDROID)
-const char kChromeUIGpuJavaCrashURL[] = "chrome://gpu-java-crash/";
-#endif
-#if defined(OS_WIN)
-const char kChromeUIBrowserHeapCorruptionURL[] =
-    "chrome://inducebrowserheapcorruption/";
-const char kChromeUIHeapCorruptionCrashURL[] = "chrome://heapcorruptioncrash/";
-#endif
-#if defined(ADDRESS_SANITIZER)
-const char kChromeUICrashHeapOverflowURL[] = "chrome://crash/heap-overflow";
-const char kChromeUICrashHeapUnderflowURL[] = "chrome://crash/heap-underflow";
-const char kChromeUICrashUseAfterFreeURL[] = "chrome://crash/use-after-free";
-
-#if defined(OS_WIN)
-const char kChromeUICrashCorruptHeapBlockURL[] =
-    "chrome://crash/corrupt-heap-block";
-const char kChromeUICrashCorruptHeapURL[] = "chrome://crash/corrupt-heap";
-#endif  // OS_WIN
-#endif  // ADDRESS_SANITIZER
-
-#if DCHECK_IS_ON()
-const char kChromeUICrashDcheckURL[] = "chrome://crash/dcheck";
-#endif
-
 // This error URL is loaded in normal web renderer processes, so it should not
 // have a chrome:// scheme that might let it be confused with a WebUI page.
 const char kUnreachableWebDataURL[] = "chrome-error://chromewebdata/";
 
 const char kBlockedURL[] = "about:blank#blocked";
 
-const char kChromeUIResourcesURL[] = "chrome://resources/";
-const char kChromeUIShorthangURL[] = "chrome://shorthang/";
-
 }  // namespace content
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index 5bad5bc..ff1e675 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -53,48 +53,6 @@
 CONTENT_EXPORT extern const char kChromeUIUkmHost[];
 CONTENT_EXPORT extern const char kChromeUIWebRTCInternalsHost[];
 
-// Full about URLs (including schemes).
-CONTENT_EXPORT extern const char kChromeUIBadCastCrashURL[];
-CONTENT_EXPORT extern const char kChromeUICheckCrashURL[];
-CONTENT_EXPORT extern const char kChromeUIBrowserCrashURL[];
-CONTENT_EXPORT extern const char kChromeUIBrowserUIHang[];
-CONTENT_EXPORT extern const char kChromeUICrashURL[];
-CONTENT_EXPORT extern const char kChromeUIDelayedBrowserUIHang[];
-CONTENT_EXPORT extern const char kChromeUIDumpURL[];
-CONTENT_EXPORT extern const char kChromeUIGpuCleanURL[];
-CONTENT_EXPORT extern const char kChromeUIGpuCrashURL[];
-CONTENT_EXPORT extern const char kChromeUIGpuHangURL[];
-CONTENT_EXPORT extern const char kChromeUIHangURL[];
-CONTENT_EXPORT extern const char kChromeUIKillURL[];
-CONTENT_EXPORT extern const char kChromeUIMemoryExhaustURL[];
-CONTENT_EXPORT extern const char kChromeUIMemoryPressureCriticalURL[];
-CONTENT_EXPORT extern const char kChromeUIMemoryPressureModerateURL[];
-CONTENT_EXPORT extern const char kChromeUINetworkErrorsListingURL[];
-CONTENT_EXPORT extern const char kChromeUINetworkErrorURL[];
-CONTENT_EXPORT extern const char kChromeUIPpapiFlashCrashURL[];
-CONTENT_EXPORT extern const char kChromeUIPpapiFlashHangURL[];
-CONTENT_EXPORT extern const char kChromeUIProcessInternalsURL[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kChromeUIGpuJavaCrashURL[];
-#endif
-#if defined(OS_WIN)
-CONTENT_EXPORT extern const char kChromeUIBrowserHeapCorruptionURL[];
-CONTENT_EXPORT extern const char kChromeUIHeapCorruptionCrashURL[];
-#endif
-#if defined(ADDRESS_SANITIZER)
-CONTENT_EXPORT extern const char kChromeUICrashHeapOverflowURL[];
-CONTENT_EXPORT extern const char kChromeUICrashHeapUnderflowURL[];
-CONTENT_EXPORT extern const char kChromeUICrashUseAfterFreeURL[];
-#if defined(OS_WIN)
-CONTENT_EXPORT extern const char kChromeUICrashCorruptHeapBlockURL[];
-CONTENT_EXPORT extern const char kChromeUICrashCorruptHeapURL[];
-#endif  // OS_WIN
-#endif  // ADDRESS_SANITIZER
-
-#if DCHECK_IS_ON()
-CONTENT_EXPORT extern const char kChromeUICrashDcheckURL[];
-#endif
-
 // Special URL used to start a navigation to an error page.
 CONTENT_EXPORT extern const char kUnreachableWebDataURL[];
 
@@ -102,11 +60,6 @@
 // source process is not allowed access to the initially requested URL.
 CONTENT_EXPORT extern const char kBlockedURL[];
 
-// Full about URLs (including schemes).
-CONTENT_EXPORT extern const char kChromeUINetworkViewCacheURL[];
-CONTENT_EXPORT extern const char kChromeUIResourcesURL[];
-CONTENT_EXPORT extern const char kChromeUIShorthangURL[];
-
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_COMMON_URL_CONSTANTS_H_
diff --git a/content/public/common/url_utils.cc b/content/public/common/url_utils.cc
index 69fc450..2818573 100644
--- a/content/public/common/url_utils.cc
+++ b/content/public/common/url_utils.cc
@@ -15,6 +15,7 @@
 #include "content/common/url_schemes.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/url_constants.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "url/gurl.h"
 #include "url/url_util.h"
 
@@ -48,7 +49,7 @@
 
   // Renderer debug URLs (e.g. chrome://kill) are handled in the renderer
   // process directly and should not be sent to the network stack.
-  if (IsRendererDebugURL(url))
+  if (blink::IsRendererDebugURL(url))
     return false;
 
   // For you information, even though a "data:" url doesn't generate actual
@@ -63,51 +64,6 @@
   return true;
 }
 
-bool IsRendererDebugURL(const GURL& url) {
-  if (!url.is_valid())
-    return false;
-
-  if (url.SchemeIs(url::kJavaScriptScheme))
-    return true;
-
-  if (!url.SchemeIs(kChromeUIScheme))
-    return false;
-
-  if (url == kChromeUICheckCrashURL || url == kChromeUIBadCastCrashURL ||
-      url == kChromeUICrashURL || url == kChromeUIDumpURL ||
-      url == kChromeUIKillURL || url == kChromeUIHangURL ||
-      url == kChromeUIShorthangURL || url == kChromeUIMemoryExhaustURL) {
-    return true;
-  }
-
-#if defined(ADDRESS_SANITIZER)
-  if (url == kChromeUICrashHeapOverflowURL ||
-      url == kChromeUICrashHeapUnderflowURL ||
-      url == kChromeUICrashUseAfterFreeURL) {
-    return true;
-  }
-#endif
-
-#if defined(OS_WIN)
-  if (url == kChromeUIHeapCorruptionCrashURL)
-    return true;
-#endif
-
-#if DCHECK_IS_ON()
-  if (url == kChromeUICrashDcheckURL)
-    return true;
-#endif
-
-#if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
-  if (url == kChromeUICrashCorruptHeapBlockURL ||
-      url == kChromeUICrashCorruptHeapURL) {
-    return true;
-  }
-#endif
-
-  return false;
-}
-
 bool IsSafeRedirectTarget(const GURL& from_url, const GURL& to_url) {
   static const base::NoDestructor<base::flat_set<base::StringPiece>>
       kUnsafeSchemes(base::flat_set<base::StringPiece>({
diff --git a/content/public/common/url_utils.h b/content/public/common/url_utils.h
index 21c1ef3..6e0c112 100644
--- a/content/public/common/url_utils.h
+++ b/content/public/common/url_utils.h
@@ -23,12 +23,6 @@
 // about:blank. In these cases, no request needs to be sent.
 CONTENT_EXPORT bool IsURLHandledByNetworkStack(const GURL& url);
 
-// Returns whether the given url is either a debugging url handled in the
-// renderer process, such as one that crashes or hangs the renderer, or a
-// javascript: URL that operates on the current page in the renderer.  Such URLs
-// do not represent actual navigations and can be loaded in any SiteInstance.
-CONTENT_EXPORT bool IsRendererDebugURL(const GURL& url);
-
 // Determines whether it is safe to redirect from |from_url| to |to_url|.
 CONTENT_EXPORT bool IsSafeRedirectTarget(const GURL& from_url,
                                          const GURL& to_url);
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 8965de3..a16b3031 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -595,6 +595,43 @@
   base::RepeatingCallback<bool()> is_complete_callback_;
 };
 
+#if defined(USE_AURA)
+
+class BoundingBoxUpdateWaiter : public TextInputManager::Observer {
+ public:
+  explicit BoundingBoxUpdateWaiter(RenderWidgetHostViewAura* rwhva)
+      : text_input_manager_(rwhva->GetTextInputManager()),
+        original_bounding_box_(rwhva->GetSelectionBoundingBox()),
+        rwhva_(rwhva) {
+    text_input_manager_->AddObserver(this);
+  }
+  BoundingBoxUpdateWaiter(const BoundingBoxUpdateWaiter&) = delete;
+  BoundingBoxUpdateWaiter& operator=(const BoundingBoxUpdateWaiter&) = delete;
+  ~BoundingBoxUpdateWaiter() { text_input_manager_->RemoveObserver(this); }
+
+  void Wait() { run_loop_.Run(); }
+
+ private:
+  // TextInputManager::Observer:
+  void OnSelectionBoundsChanged(
+      TextInputManager* text_input_manager,
+      RenderWidgetHostViewBase* updated_view) override {
+    if (rwhva_->GetSelectionBoundingBox() == original_bounding_box_) {
+      return;
+    }
+
+    run_loop_.Quit();
+  }
+
+  TextInputManager* const text_input_manager_;
+  const gfx::Rect original_bounding_box_;
+  RenderWidgetHostViewAura* const rwhva_;
+
+  base::RunLoop run_loop_;
+};
+
+#endif
+
 }  // namespace
 
 bool NavigateToURL(WebContents* web_contents, const GURL& url) {
@@ -1185,6 +1222,13 @@
                             long_tap_details, touch_end.unique_event_id());
   rwhva->OnGestureEvent(&long_tap);
 }
+
+void WaitForSelectionBoundingBoxUpdate(WebContents* web_contents) {
+  RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+      web_contents->GetRenderWidgetHostView());
+  BoundingBoxUpdateWaiter waiter(rwhva);
+  waiter.Wait();
+}
 #endif
 
 void SimulateKeyPress(WebContents* web_contents,
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 0f8874f..8a57947 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -327,6 +327,10 @@
                           const gfx::Point& point);
 
 void SimulateLongTapAt(WebContents* web_contents, const gfx::Point& point);
+
+// Waits for the update in the bounding box (i.e. the rectangle enclosing the
+// selection region) associated with `web_contents`.
+void WaitForSelectionBoundingBoxUpdate(WebContents* web_contents);
 #endif
 
 // Taps the screen with modifires at |point|.
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc
index 65988be..db27753c 100644
--- a/content/public/test/fake_local_frame.cc
+++ b/content/public/test/fake_local_frame.cc
@@ -143,6 +143,8 @@
 }
 #endif
 
+void FakeLocalFrame::HandleRendererDebugURL(const GURL& url) {}
+
 void FakeLocalFrame::BindFrameHostReceiver(
     mojo::ScopedInterfaceEndpointHandle handle) {
   receiver_.Bind(mojo::PendingAssociatedReceiver<blink::mojom::LocalFrame>(
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h
index 6ae7ffab..a3b886dc 100644
--- a/content/public/test/fake_local_frame.h
+++ b/content/public/test/fake_local_frame.h
@@ -109,6 +109,8 @@
   void ExtractSmartClipData(const gfx::Rect& rect,
                             ExtractSmartClipDataCallback callback) override;
 #endif
+  void HandleRendererDebugURL(const GURL& url) override;
+
  private:
   void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
 
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 9793f8c..670d3ad 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -59,8 +59,6 @@
     "compositor/compositor_dependencies.h",
     "content_security_policy_util.cc",
     "content_security_policy_util.h",
-    "crash_helpers.cc",
-    "crash_helpers.h",
     "discardable_memory_utils.cc",
     "discardable_memory_utils.h",
     "dom_automation_controller.cc",
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 2e85f31..0158472 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -85,7 +85,6 @@
 #include "content/renderer/accessibility/render_accessibility_manager.h"
 #include "content/renderer/agent_scheduling_group.h"
 #include "content/renderer/content_security_policy_util.h"
-#include "content/renderer/crash_helpers.h"
 #include "content/renderer/dom_automation_controller.h"
 #include "content/renderer/effective_connection_type_helper.h"
 #include "content/renderer/frame_owner_properties_converter.h"
@@ -136,6 +135,7 @@
 #include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
 #include "third_party/blink/public/common/action_after_pagehide.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/context_menu_data/context_menu_data.h"
 #include "third_party/blink/public/common/context_menu_data/untrustworthy_context_menu_params.h"
 #include "third_party/blink/public/common/features.h"
@@ -231,13 +231,6 @@
 #include "content/renderer/pepper/plugin_module.h"
 #endif
 
-#if defined(OS_WIN)
-#include "base/debug/invalid_access_win.h"
-#include "base/process/kill.h"
-#elif defined(OS_POSIX)
-#include <signal.h>
-#endif
-
 #if defined(OS_ANDROID)
 #include <cpu-features.h>
 
@@ -1333,123 +1326,6 @@
   DISALLOW_COPY_AND_ASSIGN(FrameURLLoaderFactory);
 };
 
-// The following methods are outside of the anonymous namespace to ensure that
-// the corresponding symbols get emmitted even on symbol_level 1.
-NOINLINE void ExhaustMemory() {
-  volatile void* ptr = nullptr;
-  do {
-    ptr = malloc(0x10000000);
-    base::debug::Alias(&ptr);
-  } while (ptr);
-}
-
-#if defined(ADDRESS_SANITIZER)
-NOINLINE void MaybeTriggerAsanError(const GURL& url) {
-  // NOTE(rogerm): We intentionally perform an invalid heap access here in
-  //     order to trigger an Address Sanitizer (ASAN) error report.
-  if (url == kChromeUICrashHeapOverflowURL) {
-    LOG(ERROR) << "Intentionally causing ASAN heap overflow"
-               << " because user navigated to " << url.spec();
-    base::debug::AsanHeapOverflow();
-  } else if (url == kChromeUICrashHeapUnderflowURL) {
-    LOG(ERROR) << "Intentionally causing ASAN heap underflow"
-               << " because user navigated to " << url.spec();
-    base::debug::AsanHeapUnderflow();
-  } else if (url == kChromeUICrashUseAfterFreeURL) {
-    LOG(ERROR) << "Intentionally causing ASAN heap use-after-free"
-               << " because user navigated to " << url.spec();
-    base::debug::AsanHeapUseAfterFree();
-#if defined(OS_WIN)
-  } else if (url == kChromeUICrashCorruptHeapBlockURL) {
-    LOG(ERROR) << "Intentionally causing ASAN corrupt heap block"
-               << " because user navigated to " << url.spec();
-    base::debug::AsanCorruptHeapBlock();
-  } else if (url == kChromeUICrashCorruptHeapURL) {
-    LOG(ERROR) << "Intentionally causing ASAN corrupt heap"
-               << " because user navigated to " << url.spec();
-    base::debug::AsanCorruptHeap();
-#endif  // OS_WIN
-  }
-}
-#endif  // ADDRESS_SANITIZER
-
-// Returns true if the URL is a debug URL, false otherwise. These URLs do not
-// commit, though they are intentionally left in the address bar above the
-// effect they cause (e.g., a sad tab).
-void HandleChromeDebugURL(const GURL& url) {
-  DCHECK(IsRendererDebugURL(url) && !url.SchemeIs(url::kJavaScriptScheme));
-  if (url == kChromeUIBadCastCrashURL) {
-    LOG(ERROR) << "Intentionally crashing (with bad cast)"
-               << " because user navigated to " << url.spec();
-    internal::BadCastCrashIntentionally();
-  } else if (url == kChromeUICrashURL) {
-    LOG(ERROR) << "Intentionally crashing (with null pointer dereference)"
-               << " because user navigated to " << url.spec();
-    internal::CrashIntentionally();
-  } else if (url == kChromeUIDumpURL) {
-    // This URL will only correctly create a crash dump file if content is
-    // hosted in a process that has correctly called
-    // base::debug::SetDumpWithoutCrashingFunction.  Refer to the documentation
-    // of base::debug::DumpWithoutCrashing for more details.
-    base::debug::DumpWithoutCrashing();
-#if defined(OS_WIN) || defined(OS_POSIX)
-  } else if (url == kChromeUIKillURL) {
-    LOG(ERROR) << "Intentionally terminating current process because user"
-                  " navigated to "
-               << url.spec();
-    // Simulate termination such that the base::GetTerminationStatus() API will
-    // return TERMINATION_STATUS_PROCESS_WAS_KILLED.
-#if defined(OS_WIN)
-    base::Process::TerminateCurrentProcessImmediately(
-        base::win::kProcessKilledExitCode);
-#elif defined(OS_POSIX)
-    PCHECK(kill(base::Process::Current().Pid(), SIGTERM) == 0);
-#endif
-#endif  // defined(OS_WIN) || defined(OS_POSIX)
-  } else if (url == kChromeUIHangURL) {
-    LOG(ERROR) << "Intentionally hanging ourselves with sleep infinite loop"
-               << " because user navigated to " << url.spec();
-    for (;;) {
-      base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
-    }
-  } else if (url == kChromeUIShorthangURL) {
-    LOG(ERROR) << "Intentionally sleeping renderer for 20 seconds"
-               << " because user navigated to " << url.spec();
-    base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
-  } else if (url == kChromeUIMemoryExhaustURL) {
-    LOG(ERROR)
-        << "Intentionally exhausting renderer memory because user navigated to "
-        << url.spec();
-    ExhaustMemory();
-  } else if (url == kChromeUICheckCrashURL) {
-    LOG(ERROR) << "Intentionally causing CHECK because user navigated to "
-               << url.spec();
-    CHECK(false);
-  }
-
-#if defined(OS_WIN)
-  if (url == kChromeUIHeapCorruptionCrashURL) {
-    LOG(ERROR)
-        << "Intentionally causing heap corruption because user navigated to "
-        << url.spec();
-    base::debug::win::TerminateWithHeapCorruption();
-  }
-#endif
-
-#if DCHECK_IS_ON()
-  if (url == kChromeUICrashDcheckURL) {
-    LOG(ERROR) << "Intentionally causing DCHECK because user navigated to "
-               << url.spec();
-
-    DCHECK(false) << "Intentional DCHECK.";
-  }
-#endif
-
-#if defined(ADDRESS_SANITIZER)
-  MaybeTriggerAsanError(url);
-#endif  // ADDRESS_SANITIZER
-}
-
 std::string UniqueNameForWebFrame(blink::WebFrame* frame) {
   return frame->IsWebLocalFrame()
              ? RenderFrameImpl::FromWebFrame(frame)->unique_name()
@@ -2870,7 +2746,7 @@
     blink::mojom::PolicyContainerPtr policy_container,
     mojom::NavigationClient::CommitNavigationCallback commit_callback) {
   DCHECK(navigation_client_impl_);
-  DCHECK(!IsRendererDebugURL(common_params->url));
+  DCHECK(!blink::IsRendererDebugURL(common_params->url));
   DCHECK(!NavigationTypeUtils::IsSameDocument(common_params->navigation_type));
 
   AssertNavigationCommits assert_navigation_commits(
@@ -3332,7 +3208,7 @@
     mojom::CommonNavigationParamsPtr common_params,
     mojom::CommitNavigationParamsPtr commit_params,
     CommitSameDocumentNavigationCallback callback) {
-  DCHECK(!IsRendererDebugURL(common_params->url));
+  DCHECK(!blink::IsRendererDebugURL(common_params->url));
   DCHECK(!NavigationTypeUtils::IsReload(common_params->navigation_type));
   DCHECK(!commit_params->is_view_source);
   DCHECK(NavigationTypeUtils::IsSameDocument(common_params->navigation_type));
@@ -3432,24 +3308,6 @@
   }
 }
 
-void RenderFrameImpl::HandleRendererDebugURL(const GURL& url) {
-  DCHECK(IsRendererDebugURL(url));
-  base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
-  if (url.SchemeIs(url::kJavaScriptScheme)) {
-    // Javascript URLs should be sent to Blink for handling.
-    frame_->LoadJavaScriptURL(url);
-  } else {
-    // This is a Chrome Debug URL. Handle it.
-    HandleChromeDebugURL(url);
-  }
-
-  // The browser sets its status as loading before calling this IPC. Inform it
-  // that the load stopped if needed, while leaving the debug URL visible in the
-  // address bar.
-  if (weak_this && frame_ && !frame_->IsLoading())
-    GetFrameHost()->DidStopLoading();
-}
-
 void RenderFrameImpl::UpdateSubresourceLoaderFactories(
     std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
         subresource_loader_factories) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 4b9ab61b..c10ff59 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -804,7 +804,6 @@
       mojom::CommonNavigationParamsPtr common_params,
       mojom::CommitNavigationParamsPtr commit_params,
       CommitSameDocumentNavigationCallback callback) override;
-  void HandleRendererDebugURL(const GURL& url) override;
   void UpdateSubresourceLoaderFactories(
       std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
           subresource_loader_factories) override;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 5eb3a60..0f9121f 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -2310,7 +2310,6 @@
     "//ipc:test_support",
     "//jingle:jingle_glue",
     "//media:test_support",
-    "//media/blink",
     "//media/capture",
     "//media/midi:midi",
     "//media/midi:mojo",
diff --git a/content/test/content_browser_test_test.cc b/content/test/content_browser_test_test.cc
index 8bbf1ad2..251c8ed 100644
--- a/content/test/content_browser_test_test.cc
+++ b/content/test/content_browser_test_test.cc
@@ -134,7 +134,7 @@
   // "#0 0x0000007ea911 (...content_browsertests+0x7ea910)"
   std::string crash_string =
 #if !USE_EXTERNAL_SYMBOLIZER
-      "content::RenderFrameImpl::HandleRendererDebugURL";
+      "blink::LocalFrame::HandleRendererDebugURL";
 #else
       "#0 ";
 #endif
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index 2f2ee0f..d90af32 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -31,6 +31,7 @@
 #include "net/base/load_flags.h"
 #include "net/url_request/redirect_info.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/mojom/loader/mixed_content.mojom.h"
 
 namespace content {
@@ -410,7 +411,7 @@
   state_ = STARTED;
 
   CHECK(request_);
-  if (IsRendererDebugURL(navigation_url_))
+  if (blink::IsRendererDebugURL(navigation_url_))
     return;
 
   if (!NeedsThrottleChecks()) {
@@ -631,7 +632,7 @@
   if (!keep_loading_)
     StopLoading();
 
-  if (!IsRendererDebugURL(navigation_url_))
+  if (!blink::IsRendererDebugURL(navigation_url_))
     CHECK_EQ(1, num_did_finish_navigation_called_);
 }
 
@@ -682,7 +683,7 @@
   CHECK_EQ(0, num_did_finish_navigation_called_)
       << "NavigationSimulatorImpl::Fail cannot be called after the "
          "navigation has finished";
-  CHECK(!IsRendererDebugURL(navigation_url_));
+  CHECK(!blink::IsRendererDebugURL(navigation_url_));
 
   if (state_ == INITIALIZATION)
     Start();
@@ -1135,7 +1136,7 @@
   request =
       web_contents_->GetMainFrame()->frame_tree_node()->navigation_request();
   if (!request) {
-    if (IsRendererDebugURL(navigation_url_)) {
+    if (blink::IsRendererDebugURL(navigation_url_)) {
       // We don't create NavigationRequests nor NavigationHandles for a
       // navigation to a renderer-debug URL. Instead, the URL is passed to the
       // current RenderFrameHost so that the renderer process can handle it.
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 695ec85a..225a4a6 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -310,6 +310,7 @@
         blink::WebNavigationParams::CreateWithHTMLStringForTesting(
             next_navigation_html_override_.value(), info->url_request.Url());
     MockPolicyContainerHost mock_policy_container_host;
+    navigation_params->requestor_origin = info->url_request.RequestorOrigin();
     navigation_params->policy_container =
         std::make_unique<blink::WebPolicyContainer>(
             blink::WebPolicyContainerPolicies(),
diff --git a/docs/android_build_instructions.md b/docs/android_build_instructions.md
index 510e626..191fab88 100644
--- a/docs/android_build_instructions.md
+++ b/docs/android_build_instructions.md
@@ -380,6 +380,27 @@
    * Lint usually takes > 60 seconds to run, so disabling it dramatically
      reduces incremental build times.
 
+#### Running analysis build steps in the background
+Normally analysis build steps like lint and errorprone will run in parallel with
+the rest of the build. The build will then wait for all analysis steps to
+complete successfully. By offloading analysis build steps to a separate build
+server to be run lazily at a low priority when the machine is idle, the actual
+build can complete up to 50-80% faster.
+
+To take advantage of this speedup, run the script at
+[//build/android/fast_local_dev_server.py][fast_local_dev] in a separate
+terminal window. All your local builds will now forward analysis
+steps to this server. Analysis steps include android lint, errorprone, bytecode
+processor, etc. The output of these analysis checks will then be displayed in
+the terminal window running the server.
+
+**Note**: Since the build completes before the analysis checks finish, the build
+will not fail if an analysis check fails. Make sure to check the terminal that
+the server is running in at regular intervals to fix outstanding issues caught
+by these analysis checks.
+
+[fast_local_dev]: https://source.chromium.org/chromium/chromium/src/+/master:build/android/fast_local_dev_server.py
+
 #### Incremental Install
 [Incremental Install](/build/android/incremental_install/README.md) uses
 reflection and sideloading to speed up the edit & deploy cycle (normally < 10
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc
index a4d77ee..718eb624 100644
--- a/extensions/browser/extension_function.cc
+++ b/extensions/browser/extension_function.cc
@@ -256,13 +256,13 @@
 
 class RespondNowAction : public ExtensionFunction::ResponseActionObject {
  public:
-  typedef base::Callback<void(bool)> SendResponseCallback;
+  typedef base::OnceCallback<void(bool)> SendResponseCallback;
   RespondNowAction(ExtensionFunction::ResponseValue result,
-                   const SendResponseCallback& send_response)
-      : result_(std::move(result)), send_response_(send_response) {}
-  ~RespondNowAction() override {}
+                   SendResponseCallback send_response)
+      : result_(std::move(result)), send_response_(std::move(send_response)) {}
+  ~RespondNowAction() override = default;
 
-  void Execute() override { send_response_.Run(result_->Apply()); }
+  void Execute() override { std::move(send_response_).Run(result_->Apply()); }
 
  private:
   ExtensionFunction::ResponseValue result_;
@@ -622,7 +622,7 @@
     ResponseValue result) {
   return ResponseAction(new RespondNowAction(
       std::move(result),
-      base::Bind(&ExtensionFunction::SendResponseImpl, this)));
+      base::BindOnce(&ExtensionFunction::SendResponseImpl, this)));
 }
 
 ExtensionFunction::ResponseAction ExtensionFunction::RespondLater() {
diff --git a/headless/test/headless_browser_browsertest.cc b/headless/test/headless_browser_browsertest.cc
index cee277a..07cd3a2 100644
--- a/headless/test/headless_browser_browsertest.cc
+++ b/headless/test/headless_browser_browsertest.cc
@@ -46,6 +46,7 @@
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/scoped_clipboard_writer.h"
 #include "ui/gfx/geometry/size.h"
@@ -493,7 +494,7 @@
   browser_context_ = browser()->CreateBrowserContextBuilder().Build();
 
   web_contents_ = browser_context_->CreateWebContentsBuilder()
-                      .SetInitialURL(GURL(content::kChromeUICrashURL))
+                      .SetInitialURL(GURL(blink::kChromeUICrashURL))
                       .Build();
 
   web_contents_->AddObserver(this);
diff --git a/headless/test/headless_devtools_client_browsertest.cc b/headless/test/headless_devtools_client_browsertest.cc
index 7610122..1f8753b5 100644
--- a/headless/test/headless_devtools_client_browsertest.cc
+++ b/headless/test/headless_devtools_client_browsertest.cc
@@ -36,6 +36,7 @@
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "url/gurl.h"
 
 #define EXPECT_SIZE_EQ(expected, actual)               \
@@ -494,7 +495,7 @@
     devtools_client_->GetInspector()->GetExperimental()->AddObserver(this);
     devtools_client_->GetInspector()->GetExperimental()->Enable(
         inspector::EnableParams::Builder().Build());
-    devtools_client_->GetPage()->Navigate(content::kChromeUICrashURL);
+    devtools_client_->GetPage()->Navigate(blink::kChromeUICrashURL);
   }
 
   void OnTargetCrashed(const inspector::TargetCrashedParams& params) override {
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 4c42427..0321e30dc 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -350,8 +350,7 @@
 
 - (void)showPasswordBreachForLeakType:(CredentialLeakType)leakType
                                   URL:(const GURL&)URL {
-  [self.passwordBreachDispatcher showPasswordBreachForLeakType:leakType
-                                                           URL:URL];
+  [self.passwordBreachDispatcher showPasswordBreachForLeakType:leakType];
 }
 
 - (void)showPasswordProtectionWarning:(NSString*)warningText
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_navigation_controller.h b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_navigation_controller.h
index a24a68a..b0a94c62 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_navigation_controller.h
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_navigation_controller.h
@@ -7,18 +7,6 @@
 
 #import <UIKit/UIKit.h>
 
-@class BottomSheetNavigationController;
-
-// Delegate protocol for presentation events of BottomSheetNavigationController.
-@protocol BottomSheetNavigationControllerPresentationDelegate <NSObject>
-
-// Called when BottomSheetNavigationController disappears. Related to:
-// -[UIViewController viewDidDisappear:].
-- (void)bottomSheetNavigationControllerDidDisappear:
-    (BottomSheetNavigationController*)viewController;
-
-@end
-
 // Navigation controller presented from the bottom. The pushed view controllers
 // view have to be UIScrollView. This is required to support high font size
 // (related to accessibility) with small devices (like iPhone SE).
@@ -29,11 +17,6 @@
 // ChildBottomSheetViewController protocol.
 @interface BottomSheetNavigationController : UINavigationController
 
-// Presentation delegate.
-@property(nonatomic, weak)
-    id<BottomSheetNavigationControllerPresentationDelegate>
-        presentationDelegate;
-
 // Returns the desired size related to the current view controller shown by
 // |BottomSheetNavigationController|.
 - (CGSize)layoutFittingSize;
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_navigation_controller.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_navigation_controller.mm
index da41196..320bb146 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_navigation_controller.mm
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_navigation_controller.mm
@@ -29,11 +29,6 @@
   self.view.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor];
 }
 
-- (void)viewDidDisappear:(BOOL)animated {
-  [super viewDidDisappear:animated];
-  [self.presentationDelegate bottomSheetNavigationControllerDidDisappear:self];
-}
-
 - (void)pushViewController:(UIViewController*)viewController
                   animated:(BOOL)animated {
   // |viewController.view| has to be a UIScrollView.
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_presentation_controller.h b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_presentation_controller.h
index 8a2f200..462100a 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_presentation_controller.h
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_presentation_controller.h
@@ -8,12 +8,27 @@
 #import <UIKit/UIKit.h>
 
 @class BottomSheetNavigationController;
+@class BottomSheetPresentationController;
+
+// Presentation protocol for BottomSheetPresentationController.
+@protocol BottomSheetPresentationControllerPresentationDelegate <NSObject>
+
+// Called when the bottom sheet view controller needs to be dismissed.
+- (void)bottomSheetPresentationControllerDismissViewController:
+    (BottomSheetPresentationController*)controller;
+
+@end
 
 // Presentation controller to present BottomSheetNavigationController from the
 // bottom of the screen.
 // Related to BottomSheetNavigationController.
 @interface BottomSheetPresentationController : UIPresentationController
 
+// Presentation delegate.
+@property(nonatomic, weak)
+    id<BottomSheetPresentationControllerPresentationDelegate>
+        presentationDelegate;
+
 - (instancetype)initWithBottomSheetNavigationController:
                     (BottomSheetNavigationController*)viewcontroller
                                presentingViewController:
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_presentation_controller.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_presentation_controller.mm
index b2b1302..a8132232 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_presentation_controller.mm
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/bottom_sheet_presentation_controller.mm
@@ -112,8 +112,8 @@
 
 // Closes the bottom sheet.
 - (void)closeButtonAction:(id)sender {
-  [self.presentedViewController dismissViewControllerAnimated:YES
-                                                   completion:nil];
+  [self.presentationDelegate
+      bottomSheetPresentationControllerDismissViewController:self];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm
index 1a1b4ae..c39085fa 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm
@@ -19,7 +19,7 @@
 #endif
 
 @interface ConsistencyPromoSigninCoordinator () <
-    BottomSheetNavigationControllerPresentationDelegate,
+    BottomSheetPresentationControllerPresentationDelegate,
     UINavigationControllerDelegate,
     UIViewControllerTransitioningDelegate>
 
@@ -46,7 +46,6 @@
   self.navigationController = [[BottomSheetNavigationController alloc]
       initWithRootViewController:[self firstViewController]];
   self.navigationController.delegate = self;
-  self.navigationController.presentationDelegate = self;
   UIScreenEdgePanGestureRecognizer* edgeSwipeGesture =
       [[UIScreenEdgePanGestureRecognizer alloc]
           initWithTarget:self
@@ -69,6 +68,26 @@
   return nil;
 }
 
+// Dismisses the bottom sheet view controller.
+- (void)dismissNavigationViewController {
+  __weak __typeof(self) weakSelf = self;
+  [self.navigationController
+      dismissViewControllerAnimated:YES
+                         completion:^() {
+                           [weakSelf finishedWithResult:
+                                         SigninCoordinatorResultCanceledByUser
+                                               identity:nil];
+                         }];
+}
+
+// Calls the sign-in completion block.
+- (void)finishedWithResult:(SigninCoordinatorResult)signinResult
+                  identity:(ChromeIdentity*)identity {
+  [self runCompletionCallbackWithSigninResult:signinResult
+                                     identity:identity
+                   showAdvancedSettingsSignin:NO];
+}
+
 #pragma mark - SwipeGesture
 
 // Called when the swipe gesture is active. This method controls the sliding
@@ -107,17 +126,14 @@
   }
 }
 
-#pragma mark - BottomSheetNavigationControllerPresentationDelegate
+#pragma mark - BottomSheetPresentationControllerPresentationDelegate
 
-- (void)bottomSheetNavigationControllerDidDisappear:
-    (UIViewController*)viewController {
-  [self runCompletionCallbackWithSigninResult:
-            SigninCoordinatorResultCanceledByUser
-                                     identity:nil
-                   showAdvancedSettingsSignin:NO];
+- (void)bottomSheetPresentationControllerDismissViewController:
+    (BottomSheetPresentationController*)controller {
+  [self dismissNavigationViewController];
 }
 
-#pragma mark - UIViewControllerAnimatedTransitioning
+#pragma mark - UINavigationControllerDelegate
 
 - (id<UIViewControllerAnimatedTransitioning>)
                navigationController:
@@ -159,9 +175,12 @@
                                 (UIViewController*)presentingViewController
                                 sourceViewController:(UIViewController*)source {
   DCHECK_EQ(self.navigationController, presentedViewController);
-  return [[BottomSheetPresentationController alloc]
-      initWithBottomSheetNavigationController:self.navigationController
-                     presentingViewController:presentingViewController];
+  BottomSheetPresentationController* controller =
+      [[BottomSheetPresentationController alloc]
+          initWithBottomSheetNavigationController:self.navigationController
+                         presentingViewController:presentingViewController];
+  controller.presentationDelegate = self;
+  return controller;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
index 80efb9c..76a65837 100644
--- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -993,13 +993,11 @@
 
 #pragma mark - PasswordBreachCommands
 
-- (void)showPasswordBreachForLeakType:(CredentialLeakType)leakType
-                                  URL:(const GURL&)URL {
+- (void)showPasswordBreachForLeakType:(CredentialLeakType)leakType {
   self.passwordBreachCoordinator = [[PasswordBreachCoordinator alloc]
       initWithBaseViewController:self.viewController
                          browser:self.browser
-                        leakType:leakType
-                             URL:URL];
+                        leakType:leakType];
   [self.passwordBreachCoordinator start];
 }
 
diff --git a/ios/chrome/browser/ui/commands/password_breach_commands.h b/ios/chrome/browser/ui/commands/password_breach_commands.h
index 62b5273..04fe0f0 100644
--- a/ios/chrome/browser/ui/commands/password_breach_commands.h
+++ b/ios/chrome/browser/ui/commands/password_breach_commands.h
@@ -9,16 +9,13 @@
 
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 
-class GURL;
-
 using password_manager::CredentialLeakType;
 
 // Commands related to Password Breach.
 @protocol PasswordBreachCommands
 
 // Shows Password Breach for |leakType| and |URL|.
-- (void)showPasswordBreachForLeakType:(CredentialLeakType)leakType
-                                  URL:(const GURL&)URL;
+- (void)showPasswordBreachForLeakType:(CredentialLeakType)leakType;
 
 @end
 
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index 3fa5c6f12..40d18881 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -546,25 +546,23 @@
 // TODO(crbug.com/1173160): Split and move to the StartSurfaceSceneAgent after
 // refactoring the scene states.
 - (void)handleShowStartSurfaceIfNecessary {
-  if (!ShouldShowStartSurfaceForSceneState(self.sceneState)) {
-    return;
-  }
-
   // Do not show the Start Surface no matter whether it is enabled or not when
   // the Tab grid is active by design.
   if (self.mainCoordinator.isTabGridActive) {
     return;
   }
 
-  // If there is no active tab, a NTP will be added, and since there is no
-  // recent tab, there is not need to mark |modifytVisibleNTPForStartSurface|.
   // Keep showing the last active NTP tab no matter whether the Start Surface is
   // enabled or not by design.
   // Note that currentWebState could only be nullptr when the Tab grid is active
   // for now.
   web::WebState* currentWebState =
-      self.mainInterface.browser->GetWebStateList()->GetActiveWebState();
-  if (!currentWebState || IsURLNtp(currentWebState->GetVisibleURL())) {
+      self.currentInterface.browser->GetWebStateList()->GetActiveWebState();
+  if (IsURLNtp(currentWebState->GetVisibleURL())) {
+    return;
+  }
+
+  if (!ShouldShowStartSurfaceForSceneState(self.sceneState)) {
     return;
   }
 
@@ -882,12 +880,6 @@
     [self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
   }
 
-  // Call this right after |setCurrentInterfaceForMode:| to ensure the
-  // currentInterface is set in case a new tab needs to be opened. Since this is
-  // synchronous with |setActivePage:| above, then the user should not see the
-  // last tab if the Start Surface is opened.
-  [self handleShowStartSurfaceIfNecessary];
-
   // Figure out what UI to show initially.
 
   if (self.mainCoordinator.isTabGridActive) {
diff --git a/ios/chrome/browser/ui/passwords/password_breach_app_interface.mm b/ios/chrome/browser/ui/passwords/password_breach_app_interface.mm
index d10dfbb..b71a423 100644
--- a/ios/chrome/browser/ui/passwords/password_breach_app_interface.mm
+++ b/ios/chrome/browser/ui/passwords/password_breach_app_interface.mm
@@ -19,9 +19,7 @@
       password_manager::IsSaved(true),
       password_manager::IsReused(checkButtonPresent),
       password_manager::IsSyncing(true));
-  [(id<PasswordBreachCommands>)handler
-      showPasswordBreachForLeakType:leakType
-                                URL:GURL("example.com")];
+  [(id<PasswordBreachCommands>)handler showPasswordBreachForLeakType:leakType];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/passwords/password_breach_coordinator.h b/ios/chrome/browser/ui/passwords/password_breach_coordinator.h
index 729694f..4b594fe 100644
--- a/ios/chrome/browser/ui/passwords/password_breach_coordinator.h
+++ b/ios/chrome/browser/ui/passwords/password_breach_coordinator.h
@@ -8,8 +8,6 @@
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
 
-class GURL;
-
 // Presents and stops the Password Breach feature, which consists in alerting
 // the user that Chrome detected a leaked credential. In some scenarios it
 // prompts for a checkup of the stored passwords.
@@ -19,7 +17,7 @@
     initWithBaseViewController:(UIViewController*)baseViewController
                        browser:(Browser*)browser
                       leakType:(password_manager::CredentialLeakType)leakType
-                           URL:(const GURL&)URL NS_DESIGNATED_INITIALIZER;
+    NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)initWithBaseViewController:(UIViewController*)viewController
                                    browser:(Browser*)browser NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/passwords/password_breach_coordinator.mm b/ios/chrome/browser/ui/passwords/password_breach_coordinator.mm
index 9e5a6e4..31d1a69 100644
--- a/ios/chrome/browser/ui/passwords/password_breach_coordinator.mm
+++ b/ios/chrome/browser/ui/passwords/password_breach_coordinator.mm
@@ -49,11 +49,9 @@
 
 - (instancetype)initWithBaseViewController:(UIViewController*)baseViewController
                                    browser:(Browser*)browser
-                                  leakType:(CredentialLeakType)leakType
-                                       URL:(const GURL&)URL {
+                                  leakType:(CredentialLeakType)leakType {
   self = [super initWithBaseViewController:baseViewController browser:browser];
   if (self) {
-    _url = URL;
     _leakType = leakType;
   }
   return self;
@@ -68,7 +66,6 @@
   self.mediator =
       [[PasswordBreachMediator alloc] initWithConsumer:self.viewController
                                              presenter:self
-                                                   URL:_url
                                               leakType:self.leakType];
   self.viewController.actionHandler = self.mediator;
 
diff --git a/ios/chrome/browser/ui/passwords/password_breach_mediator.h b/ios/chrome/browser/ui/passwords/password_breach_mediator.h
index 71172c3..e216004a 100644
--- a/ios/chrome/browser/ui/passwords/password_breach_mediator.h
+++ b/ios/chrome/browser/ui/passwords/password_breach_mediator.h
@@ -10,8 +10,6 @@
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 #import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h"
 
-class GURL;
-
 @protocol ApplicationCommands;
 @protocol PasswordBreachConsumer;
 @protocol PasswordBreachPresenter;
@@ -21,7 +19,6 @@
 
 - (instancetype)initWithConsumer:(id<PasswordBreachConsumer>)consumer
                        presenter:(id<PasswordBreachPresenter>)presenter
-                             URL:(const GURL&)URL
                         leakType:(password_manager::CredentialLeakType)leakType;
 
 - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/passwords/password_breach_mediator.mm b/ios/chrome/browser/ui/passwords/password_breach_mediator.mm
index d9f74e9..e82a998 100644
--- a/ios/chrome/browser/ui/passwords/password_breach_mediator.mm
+++ b/ios/chrome/browser/ui/passwords/password_breach_mediator.mm
@@ -48,7 +48,6 @@
 
 - (instancetype)initWithConsumer:(id<PasswordBreachConsumer>)consumer
                        presenter:(id<PasswordBreachPresenter>)presenter
-                             URL:(const GURL&)URL
                         leakType:(CredentialLeakType)leakType {
   self = [super init];
   if (self) {
@@ -56,7 +55,7 @@
     _leakType = GetLeakDialogType(leakType);
     _dismissReason = LeakDialogDismissalReason::kNoDirectInteraction;
 
-    NSString* subtitle = SysUTF16ToNSString(GetDescription(leakType, URL));
+    NSString* subtitle = SysUTF16ToNSString(GetDescription(leakType));
     NSString* primaryActionString =
         SysUTF16ToNSString(GetAcceptButtonLabel(leakType));
     [consumer setTitleString:SysUTF16ToNSString(GetTitle(leakType))
diff --git a/ios/chrome/browser/ui/start_surface/BUILD.gn b/ios/chrome/browser/ui/start_surface/BUILD.gn
index ec545b75..2103ac22 100644
--- a/ios/chrome/browser/ui/start_surface/BUILD.gn
+++ b/ios/chrome/browser/ui/start_surface/BUILD.gn
@@ -44,24 +44,3 @@
     "//ui/base",
   ]
 }
-
-source_set("eg2_tests") {
-  defines = [ "CHROME_EARL_GREY_2" ]
-  configs += [
-    "//build/config/compiler:enable_arc",
-    "//build/config/ios:xctest_config",
-  ]
-  testonly = true
-
-  sources = [ "start_surface_egtest.mm" ]
-
-  deps = [
-    ":feature_flags",
-    "//ios/chrome/test/earl_grey:eg_test_support+eg2",
-    "//ios/testing/earl_grey:eg_test_support+eg2",
-    "//ios/third_party/earl_grey2:test_lib",
-    "//net:test_support",
-  ]
-
-  frameworks = [ "UIKit.framework" ]
-}
diff --git a/ios/chrome/browser/ui/start_surface/start_surface_egtest.mm b/ios/chrome/browser/ui/start_surface/start_surface_egtest.mm
deleted file mode 100644
index e1f1fe93..0000000
--- a/ios/chrome/browser/ui/start_surface/start_surface_egtest.mm
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <XCTest/XCTest.h>
-
-#import "ios/chrome/browser/ui/start_surface/start_surface_features.h"
-#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_matchers.h"
-#import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/testing/earl_grey/app_launch_manager.h"
-#include "ios/testing/earl_grey/earl_grey_test.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-// Integration tests for the Start Surface user flows.
-@interface StartSurfaceTestCase : ChromeTestCase
-@end
-
-@implementation StartSurfaceTestCase
-
-- (AppLaunchConfiguration)appConfigurationForTestCase {
-  AppLaunchConfiguration config;
-  config.additional_args.push_back(
-      std::string("--enable-features=StartSurface:"
-                  "ReturnToStartSurfaceInactiveDurationInSeconds/0"));
-  config.relaunch_policy = ForceRelaunchByCleanShutdown;
-  return config;
-}
-
-// Tests that navigating to a page and restarting upon cold start, an NTP page
-// is opened.
-- (void)testColdStartOpenStartSurface {
-  // TODO(crbug.com/1198227): Reenable this test when the session saving issue
-  // is resolved.
-  if ([ChromeEarlGrey isIPadIdiom]) {
-    EARL_GREY_TEST_SKIPPED(@"Skipped for iPad (Session saving issue)");
-  }
-
-  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
-  const GURL destinationUrl = self.testServer->GetURL("/pony.html");
-  [ChromeEarlGrey loadURL:destinationUrl];
-
-  [[AppLaunchManager sharedManager]
-      ensureAppLaunchedWithConfiguration:self.appConfigurationForTestCase];
-
-  [ChromeTestCase removeAnyOpenMenusAndInfoBars];
-  // Assert NTP is visible by checking that the fake omnibox is here.
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()]
-      assertWithMatcher:grey_sufficientlyVisible()];
-  GREYAssertEqual([ChromeEarlGrey mainTabCount], 2,
-                  @"Two tabs were expected to be open");
-}
-
-@end
diff --git a/ios/chrome/browser/ui/start_surface/start_surface_scene_agent.mm b/ios/chrome/browser/ui/start_surface/start_surface_scene_agent.mm
index c613cc24..cb611e03 100644
--- a/ios/chrome/browser/ui/start_surface/start_surface_scene_agent.mm
+++ b/ios/chrome/browser/ui/start_surface/start_surface_scene_agent.mm
@@ -19,7 +19,6 @@
     // TODO(crbug.com/1173160): Consider when to clear the session object since
     // Chrome may be closed without transiting to background, e.g. device power
     // off, then the previous session object is staled.
-    NSLog(@"%@", [NSThread callStackSymbols]);
     SetStartSurfaceSessionObjectForSceneState(sceneState);
   }
 }
diff --git a/ios/chrome/browser/web/resources/OWNERS b/ios/chrome/browser/web/resources/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/ios/chrome/browser/web/resources/OWNERS
+++ /dev/null
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn
index 905ab4c..91343c1 100644
--- a/ios/chrome/test/earl_grey2/BUILD.gn
+++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -168,7 +168,6 @@
     "//ios/chrome/browser/ui/safe_mode:eg2_tests",
     "//ios/chrome/browser/ui/settings/sync/utils:eg2_tests",
     "//ios/chrome/browser/ui/side_swipe:eg2_tests",
-    "//ios/chrome/browser/ui/start_surface:eg2_tests",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid:eg2_tests",
     "//ios/chrome/browser/ui/tabs:eg2_tests",
     "//ios/chrome/browser/ui/thumb_strip:eg2_tests",
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
index 6f985af..3a30a33 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-16a96700d4374bef4d160afc01e00010958f7eb8
\ No newline at end of file
+3881df9e63927dabb99bc8b9a11165abcc52b43e
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
index 060dea1..78f8478 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-eeca3064a806fd67f76d272e6729312dac79103d
\ No newline at end of file
+7f181c8a207978586fa406d0f15ffa5b5e5f095b
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
index 1c774708..a31d1b2 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-3ee562dcfda7bfd876c5c31f1e960aca2dd1efed
\ No newline at end of file
+a0ccbc990a57926f44337ea4246b2150b068b749
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
index f5e6d1b2..7d629b4 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-7d13bc661fb14c3d358b035986642820742deded
\ No newline at end of file
+c239c8910f8c7d8262b123875464287b9c96a8e2
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
index 877b1ea5..6dfc1e2 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-e4538bf9afd86c96fc91b7f2c21587a307c6b104
\ No newline at end of file
+2a68627a0d63167c2daf8eeb90cea570a2dd0e4c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
index 1726a62..c2abce5 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-2577a5e01d50f6a33ada0597117e2d4078542545
\ No newline at end of file
+4f1f86ceb0c4c8e2cf846458c9da3a7d1db4a00f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
index e759a47..ea3dac43 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-834f4de5eda202e99be7526d4ba87b145060fd5f
\ No newline at end of file
+26e0e2c969a1eee3bb5c7275568101760fcec71b
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
index 7664441..0d2509b 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-b5579f3c42d3a6f33f161b3ee907f68a19fa2eab
\ No newline at end of file
+87dc7143e28e70ef9c89e8c6c151ba375560a48a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
index 2251242c..6e79036 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-f05253b84bde01b80b781e4239f605dc7ab423dc
\ No newline at end of file
+6022a98679c35fe46951ce95f9dd18fe03c7f9b4
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
index 1aa6b012..5e0ca38 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-e604253ddcd4c3e6c1e6d6652f7758b805e839e1
\ No newline at end of file
+c2a549644941b8037513b2221171bcbe6fb0796c
\ No newline at end of file
diff --git a/ios/web_view/internal/translate/cwv_translation_controller_unittest.mm b/ios/web_view/internal/translate/cwv_translation_controller_unittest.mm
index 7d7ef8f3..3ef7e70 100644
--- a/ios/web_view/internal/translate/cwv_translation_controller_unittest.mm
+++ b/ios/web_view/internal/translate/cwv_translation_controller_unittest.mm
@@ -119,7 +119,7 @@
     pref_service_.registry()->RegisterDictionaryPref(
         translate::TranslatePrefs::kPrefTranslateTooOftenDeniedForLanguage);
     pref_service_.registry()->RegisterStringPref(
-        translate::TranslatePrefs::kPrefTranslateRecentTarget, "");
+        prefs::kPrefTranslateRecentTarget, "");
     // Using string literal here because kForceTriggerTranslateCount is private
     // in translate::TranslatePrefs.
     pref_service_.registry()->RegisterIntegerPref(
diff --git a/media/audio/audio_opus_encoder.cc b/media/audio/audio_opus_encoder.cc
index 4b830ae..03bcef1 100644
--- a/media/audio/audio_opus_encoder.cc
+++ b/media/audio/audio_opus_encoder.cc
@@ -101,6 +101,9 @@
 
 }  // namespace
 
+// TODO: Remove after switching to C++17
+constexpr int AudioOpusEncoder::kMinBitrate;
+
 AudioOpusEncoder::AudioOpusEncoder()
     : opus_encoder_(nullptr, OpusEncoderDeleter) {}
 
diff --git a/media/audio/audio_opus_encoder.h b/media/audio/audio_opus_encoder.h
index e37dd15..0c1f45a4 100644
--- a/media/audio/audio_opus_encoder.h
+++ b/media/audio/audio_opus_encoder.h
@@ -42,6 +42,8 @@
 
   void Flush(StatusCB done_cb) override;
 
+  static constexpr int kMinBitrate = 6000;
+
  private:
   // Called synchronously by |fifo_| once enough audio frames have been
   // buffered. Calls libopus to do actual encoding.
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 828b043..1502642 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -585,6 +585,20 @@
                                     base::TimeDelta::FromMicroseconds(1));
   }
 
+  // Fixup negative timestamps where the before-zero portion is completely
+  // discarded after decoding.
+  if (buffer->timestamp() < base::TimeDelta()) {
+    // Discard padding may also remove samples after zero.
+    auto fixed_ts = buffer->discard_padding().first + buffer->timestamp();
+
+    // Allow for rounding error in the discard padding calculations.
+    if (fixed_ts == base::TimeDelta::FromMicroseconds(-1))
+      fixed_ts = base::TimeDelta();
+
+    if (fixed_ts >= base::TimeDelta())
+      buffer->set_timestamp(fixed_ts);
+  }
+
   // Only allow negative timestamps past if we know they'll be fixed up by the
   // code paths below; otherwise they should be treated as a parse error.
   if ((!fixup_chained_ogg_ || last_packet_timestamp_ == kNoTimestamp) &&
diff --git a/media/gpu/gpu_video_encode_accelerator_factory.cc b/media/gpu/gpu_video_encode_accelerator_factory.cc
index 3ddcd3c..9469934b 100644
--- a/media/gpu/gpu_video_encode_accelerator_factory.cc
+++ b/media/gpu/gpu_video_encode_accelerator_factory.cc
@@ -197,6 +197,11 @@
     });
   }
 
+  base::EraseIf(profiles, [](const auto& vea_profile) {
+    return vea_profile.profile >= HEVCPROFILE_MIN &&
+           vea_profile.profile <= HEVCPROFILE_MAX;
+  });
+
   return profiles;
 }
 
diff --git a/media/gpu/vaapi/test/av1_decoder.cc b/media/gpu/vaapi/test/av1_decoder.cc
index 0ccced8c..cbe666e 100644
--- a/media/gpu/vaapi/test/av1_decoder.cc
+++ b/media/gpu/vaapi/test/av1_decoder.cc
@@ -617,7 +617,11 @@
   }
 
   libgav1::ObuFrameHeader current_frame_header = obu_parser_->frame_header();
-  last_decoded_frame_visible_ = current_frame_header.show_frame;
+  if (current_frame_header.show_existing_frame) {
+    last_decoded_frame_visible_ = true;
+  } else {
+    last_decoded_frame_visible_ = current_frame_header.show_frame;
+  }
 
   if (obu_parser_->sequence_header_changed()) {
     if (current_frame_header.frame_type != libgav1::kFrameKey ||
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index df500d8b..694ce8a0 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -2549,7 +2549,10 @@
   base::AutoLock auto_lock(*va_lock_);
   TRACE_EVENT0("media,gpu", "VaapiWrapper::DownloadFromVABufferLocked");
 
-  {
+  // vaSyncSurface() is not necessary on Intel platforms as long as there is a
+  // vaMapBuffer() like in ScopedVABufferMapping below, see b/184312032.
+  if (GetImplementationType() != VAImplementation::kIntelI965 ||
+      GetImplementationType() != VAImplementation::kIntelIHD) {
     TRACE_EVENT0("media,gpu", "VaapiWrapper::DownloadFromVABuffer_SyncSurface");
     const VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id);
     VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, false);
diff --git a/net/base/schemeful_site_fuzzer.cc b/net/base/schemeful_site_fuzzer.cc
index 4d62f2c..0bf4709 100644
--- a/net/base/schemeful_site_fuzzer.cc
+++ b/net/base/schemeful_site_fuzzer.cc
@@ -23,6 +23,12 @@
 
   url::Origin origin = url::Origin::Create((GURL(native_input)));
 
+  // We don't run the fuzzer on inputs whose hosts will contain "..". The ".."
+  // causes SchemefulSite to consider the registrable domain to start with the
+  // second ".".
+  if (origin.host().find("..") != std::string::npos)
+    return;
+
   net::SchemefulSite site(origin);
 
   base::Optional<net::SchemefulSite> site_with_registrable_domain =
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index b986097..30df2fa 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -281,6 +281,8 @@
     "register_support_host_request.h",
     "remote_input_filter.cc",
     "remote_input_filter.h",
+    "remote_open_url_message_handler.cc",
+    "remote_open_url_message_handler.h",
     "remoting_register_support_host_request.cc",
     "remoting_register_support_host_request.h",
     "resizing_host_observer.cc",
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index ece63ec4..b45dec99 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -29,6 +29,7 @@
 #include "remoting/host/input_injector.h"
 #include "remoting/host/keyboard_layout_monitor.h"
 #include "remoting/host/mouse_shape_pump.h"
+#include "remoting/host/remote_open_url_message_handler.h"
 #include "remoting/host/screen_controls.h"
 #include "remoting/host/screen_resolution.h"
 #include "remoting/proto/control.pb.h"
@@ -199,6 +200,13 @@
                             base::Unretained(this)));
   }
 
+  if (HasCapability(capabilities_, protocol::kRemoteOpenUrlCapability)) {
+    data_channel_manager_.RegisterCreateHandlerCallback(
+        RemoteOpenUrlMessageHandler::kChannelName,
+        base::BindRepeating(&ClientSession::CreateRemoteOpenUrlMessageHandler,
+                            base::Unretained(this)));
+  }
+
   std::vector<ActionRequest::Action> supported_actions;
   if (HasCapability(capabilities_, protocol::kSendAttentionSequenceAction))
     supported_actions.push_back(ActionRequest::SEND_ATTENTION_SEQUENCE);
@@ -385,6 +393,8 @@
   host_capabilities_.append(protocol::kRtcLogTransferCapability);
   host_capabilities_.append(" ");
   host_capabilities_.append(protocol::kWebrtcIceSdpRestartAction);
+  host_capabilities_.append(" ");
+  host_capabilities_.append(protocol::kRemoteOpenUrlCapability);
 
   // Create the object that controls the screen resolution.
   screen_controls_ = desktop_environment_->CreateScreenControls();
@@ -875,4 +885,13 @@
                            std::move(action_executor));
 }
 
+void ClientSession::CreateRemoteOpenUrlMessageHandler(
+    const std::string& channel_name,
+    std::unique_ptr<protocol::MessagePipe> pipe) {
+  // RemoteOpenUrlMessageHandler manages its own lifetime and is tied to the
+  // lifetime of |pipe|. Once |pipe| is closed, this instance will be cleaned
+  // up.
+  new RemoteOpenUrlMessageHandler(channel_name, std::move(pipe));
+}
+
 }  // namespace remoting
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h
index f5c50f980..7211825 100644
--- a/remoting/host/client_session.h
+++ b/remoting/host/client_session.h
@@ -207,6 +207,10 @@
       const std::string& channel_name,
       std::unique_ptr<protocol::MessagePipe> pipe);
 
+  void CreateRemoteOpenUrlMessageHandler(
+      const std::string& channel_name,
+      std::unique_ptr<protocol::MessagePipe> pipe);
+
   EventHandler* event_handler_;
 
   // Used to create a DesktopEnvironment instance for this session.
diff --git a/remoting/host/remote_open_url_message_handler.cc b/remoting/host/remote_open_url_message_handler.cc
new file mode 100644
index 0000000..5e371c8c5
--- /dev/null
+++ b/remoting/host/remote_open_url_message_handler.cc
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/remote_open_url_message_handler.h"
+
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "remoting/base/compound_buffer.h"
+#include "remoting/proto/remote_open_url.pb.h"
+
+namespace remoting {
+
+// static
+constexpr char RemoteOpenUrlMessageHandler::kChannelName[];
+
+RemoteOpenUrlMessageHandler::RemoteOpenUrlMessageHandler(
+    const std::string& name,
+    std::unique_ptr<protocol::MessagePipe> pipe)
+    : protocol::NamedMessagePipeHandler(name, std::move(pipe)) {}
+
+RemoteOpenUrlMessageHandler::~RemoteOpenUrlMessageHandler() = default;
+
+void RemoteOpenUrlMessageHandler::OnConnected() {
+  NOTIMPLEMENTED();
+  // To send a request: Send(remote_open_url, base::DoNothing())
+}
+
+void RemoteOpenUrlMessageHandler::OnIncomingMessage(
+    std::unique_ptr<CompoundBuffer> message) {
+  NOTIMPLEMENTED();
+}
+
+void RemoteOpenUrlMessageHandler::OnDisconnecting() {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace remoting
\ No newline at end of file
diff --git a/remoting/host/remote_open_url_message_handler.h b/remoting/host/remote_open_url_message_handler.h
new file mode 100644
index 0000000..a9f57a4
--- /dev/null
+++ b/remoting/host/remote_open_url_message_handler.h
@@ -0,0 +1,33 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_REMOTE_OPEN_URL_MESSAGE_HANDLER_H_
+#define REMOTING_HOST_REMOTE_OPEN_URL_MESSAGE_HANDLER_H_
+
+#include "remoting/protocol/named_message_pipe_handler.h"
+
+namespace remoting {
+
+class RemoteOpenUrlMessageHandler final
+    : public protocol::NamedMessagePipeHandler {
+ public:
+  static constexpr char kChannelName[] = "remote-open-url";
+
+  RemoteOpenUrlMessageHandler(const std::string& name,
+                              std::unique_ptr<protocol::MessagePipe> pipe);
+  ~RemoteOpenUrlMessageHandler() override;
+
+  // protocol::NamedMessagePipeHandler implementation.
+  void OnConnected() override;
+  void OnIncomingMessage(std::unique_ptr<CompoundBuffer> message) override;
+  void OnDisconnecting() override;
+
+  RemoteOpenUrlMessageHandler(const RemoteOpenUrlMessageHandler&) = delete;
+  RemoteOpenUrlMessageHandler& operator=(const RemoteOpenUrlMessageHandler&) =
+      delete;
+};
+
+}  // namespace remoting
+
+#endif  // REMOTING_HOST_REMOTE_OPEN_URL_MESSAGE_HANDLER_H_
diff --git a/remoting/proto/BUILD.gn b/remoting/proto/BUILD.gn
index b905e5c..c96282e 100644
--- a/remoting/proto/BUILD.gn
+++ b/remoting/proto/BUILD.gn
@@ -22,6 +22,7 @@
     "layout_key_function.proto",
     "mux.proto",
     "process_stats.proto",
+    "remote_open_url.proto",
     "test_data_channel_manager.proto",
     "video.proto",
     "video_stats.proto",
diff --git a/remoting/proto/remote_open_url.proto b/remoting/proto/remote_open_url.proto
new file mode 100644
index 0000000..91cff6e9
--- /dev/null
+++ b/remoting/proto/remote_open_url.proto
@@ -0,0 +1,56 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package remoting.protocol;
+
+// Composite message type for messages sent over the remote-open-url data
+// channel.
+// Next ID: 3
+message RemoteOpenUrl {
+  // Message sent requesting the remote end to open |url|.
+  // Next ID: 3
+  message OpenUrlRequest {
+    // An ID used to associate the request with the response.
+    optional uint32 id = 1;
+
+    // The URL to be opened by the remote end.
+    optional string url = 2;
+  }
+
+  // Message sent from the remote end to the requester.
+  // Next ID: 3
+  message OpenUrlResponse {
+    // An ID used to associate the request with the response.
+    optional uint32 id = 1;
+
+    // The outcome of opening the URL remotely.
+    // Next ID: 4
+    enum Result {
+      UNSPECIFIED_OPEN_URL_RESULT = 0;
+
+      // The URL was successfully opened.
+      SUCCESS = 1;
+
+      // The URL failed to open, and the requester should not try to open the
+      // URL locally.
+      FAILURE = 2;
+
+      // The remote end has decided that the URL should be opened locally by the
+      // requester.
+      LOCAL_FALLBACK = 3;
+    }
+
+    // The result of opening the URL remotely.
+    optional Result result = 2;
+  }
+
+  oneof message {
+    OpenUrlRequest open_url_request = 1;
+    OpenUrlResponse open_url_response = 2;
+  }
+}
diff --git a/remoting/protocol/capability_names.h b/remoting/protocol/capability_names.h
index 740874a..0e71ddc 100644
--- a/remoting/protocol/capability_names.h
+++ b/remoting/protocol/capability_names.h
@@ -17,6 +17,8 @@
 constexpr char kFileTransferCapability[] = "fileTransfer";
 constexpr char kRtcLogTransferCapability[] = "rtcLogTransfer";
 
+constexpr char kRemoteOpenUrlCapability[] = "remoteOpenUrl";
+
 // TODO(joedow): Ideally these would be dynamically created via the
 // DataChannelManager, we should consider moving them there if we begin using
 // WebRTC data channels for individual features more frequently.
diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc
index 7b47970..b8e76745 100644
--- a/sandbox/linux/services/credentials_unittest.cc
+++ b/sandbox/linux/services/credentials_unittest.cc
@@ -47,8 +47,22 @@
 bool WorkingDirectoryIsRoot() {
   char current_dir[PATH_MAX];
   char* cwd = getcwd(current_dir, sizeof(current_dir));
-  PCHECK(cwd);
-  if (strcmp("/", cwd)) return false;
+
+  // Kernel commit 7bc3e6e55acf ("proc: Use a list of inodes to flush from
+  // proc"), present in 5.6 and later, changed how procfs inodes are cleaned up
+  // when a process exits. Credentials::DropFileSystemAccess() relies forking a
+  // child process which shares the same file system information (using
+  // clone(CLONE_FS)), and chroot()'ing to /proc/self/fdinfo/ in that process.
+  // However, when that child process exits, its procfs directories are
+  // unlinked, causing getcwd() to return ENOENT. getcwd() has been documented
+  // as returning ENOENT when the directory has been unlinked since at least
+  // 2004 (man-pages commit fea681daf).
+  if (cwd) {
+    if (strcmp("/", cwd))
+      return false;
+  } else {
+    PCHECK(errno == ENOENT);
+  }
 
   // The current directory is the root. Add a few paranoid checks.
   struct stat current;
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn
index 12faff2e..e26758c 100644
--- a/sandbox/win/BUILD.gn
+++ b/sandbox/win/BUILD.gn
@@ -95,8 +95,6 @@
     "src/restricted_token_utils.h",
     "src/sandbox.cc",
     "src/sandbox.h",
-    "src/sandbox_constants.cc",
-    "src/sandbox_constants.h",
     "src/sandbox_factory.h",
     "src/sandbox_globals.cc",
     "src/sandbox_nt_types.h",
diff --git a/sandbox/win/src/sandbox_constants.cc b/sandbox/win/src/sandbox_constants.cc
deleted file mode 100644
index 81723f9..0000000
--- a/sandbox/win/src/sandbox_constants.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/win/src/sandbox_constants.h"
-
-namespace sandbox {
-// Strings used as keys in base::Value snapshots of Policies for WebUI.
-extern const char kAppContainerCapabilities[] = "appContainerCapabilities";
-extern const char kAppContainerInitialCapabilities[] =
-    "appContainerInitialCapabilities";
-extern const char kAppContainerSid[] = "appContainerSid";
-extern const char kDesiredIntegrityLevel[] = "desiredIntegrityLevel";
-extern const char kDesiredMitigations[] = "desiredMitigations";
-extern const char kDisconnectCsrss[] = "disconnectCsrss";
-extern const char kHandlesToClose[] = "handlesToClose";
-extern const char kJobLevel[] = "jobLevel";
-extern const char kLockdownLevel[] = "lockdownLevel";
-extern const char kLowboxSid[] = "lowboxSid";
-extern const char kPlatformMitigations[] = "platformMitigations";
-extern const char kPolicyRules[] = "policyRules";
-extern const char kProcessIds[] = "processIds";
-
-// Strings used as values in snapshots of Policies.
-extern const char kDisabled[] = "disabled";
-extern const char kEnabled[] = "enabled";
-}  // namespace sandbox
diff --git a/sandbox/win/src/sandbox_constants.h b/sandbox/win/src/sandbox_constants.h
deleted file mode 100644
index 65718ef..0000000
--- a/sandbox/win/src/sandbox_constants.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_WIN_SRC_SANDBOX_CONSTANTS_H_
-#define SANDBOX_WIN_SRC_SANDBOX_CONSTANTS_H_
-
-namespace sandbox {
-// Strings used as keys in base::Value snapshots of Policies.
-extern const char kAppContainerCapabilities[];
-extern const char kAppContainerInitialCapabilities[];
-extern const char kAppContainerSid[];
-extern const char kDesiredIntegrityLevel[];
-extern const char kDesiredMitigations[];
-extern const char kDisconnectCsrss[];
-extern const char kHandlesToClose[];
-extern const char kJobLevel[];
-extern const char kLockdownLevel[];
-extern const char kLowboxSid[];
-extern const char kPlatformMitigations[];
-extern const char kPolicyRules[];
-extern const char kProcessIds[];
-
-// Strings used as values in snapshots of Policies.
-extern const char kDisabled[];
-extern const char kEnabled[];
-}  // namespace sandbox
-
-#endif  // SANDBOX_WIN_SRC_SANDBOX_CONSTANTS_H_
diff --git a/sandbox/win/src/sandbox_policy_diagnostic.cc b/sandbox/win/src/sandbox_policy_diagnostic.cc
index 5195ac5..4ffbc999 100644
--- a/sandbox/win/src/sandbox_policy_diagnostic.cc
+++ b/sandbox/win/src/sandbox_policy_diagnostic.cc
@@ -21,7 +21,6 @@
 #include "base/values.h"
 #include "sandbox/win/src/ipc_tags.h"
 #include "sandbox/win/src/policy_engine_opcodes.h"
-#include "sandbox/win/src/sandbox_constants.h"
 #include "sandbox/win/src/sandbox_policy_base.h"
 #include "sandbox/win/src/target_process.h"
 #include "sandbox/win/src/win_utils.h"
@@ -30,6 +29,26 @@
 
 namespace {
 
+// Keys in base::Value snapshots of Policies for chrome://sandbox.
+const char kAppContainerCapabilities[] = "appContainerCapabilities";
+const char kAppContainerInitialCapabilities[] =
+    "appContainerInitialCapabilities";
+const char kAppContainerSid[] = "appContainerSid";
+const char kDesiredIntegrityLevel[] = "desiredIntegrityLevel";
+const char kDesiredMitigations[] = "desiredMitigations";
+const char kDisconnectCsrss[] = "disconnectCsrss";
+const char kHandlesToClose[] = "handlesToClose";
+const char kJobLevel[] = "jobLevel";
+const char kLockdownLevel[] = "lockdownLevel";
+const char kLowboxSid[] = "lowboxSid";
+const char kPlatformMitigations[] = "platformMitigations";
+const char kPolicyRules[] = "policyRules";
+const char kProcessIds[] = "processIds";
+
+// Values in snapshots of Policies.
+const char kDisabled[] = "disabled";
+const char kEnabled[] = "enabled";
+
 base::Value ProcessIdList(std::vector<uint32_t> process_ids) {
   base::Value results(base::Value::Type::LIST);
   for (const auto pid : process_ids) {
diff --git a/services/device/geolocation/win/location_provider_winrt_unittest.cc b/services/device/geolocation/win/location_provider_winrt_unittest.cc
index 0061d5d4..a9397661 100644
--- a/services/device/geolocation/win/location_provider_winrt_unittest.cc
+++ b/services/device/geolocation/win/location_provider_winrt_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "base/win/core_winrt_util.h"
+#include "base/win/scoped_winrt_initializer.h"
 #include "services/device/geolocation/win/fake_geocoordinate_winrt.h"
 #include "services/device/geolocation/win/fake_geolocator_winrt.h"
 #include "services/device/public/cpp/geolocation/geoposition.h"
@@ -80,17 +80,15 @@
 };
 
 class LocationProviderWinrtTest : public testing::Test {
- public:
-  static void SetUpTestSuite() {
-    base::win::RoInitialize(RO_INIT_TYPE::RO_INIT_MULTITHREADED);
-  }
-
  protected:
   LocationProviderWinrtTest()
       : observer_(
             std::make_unique<MockLocationObserver>(run_loop_.QuitClosure())),
         callback_(base::BindRepeating(&MockLocationObserver::OnLocationUpdate,
-                                      base::Unretained(observer_.get()))) {}
+                                      base::Unretained(observer_.get()))) {
+    if (!winrt_initializer_.Succeeded())
+      ADD_FAILURE() << "WinRT initialization failed.";
+  }
 
   void InitializeProvider(
       PositionStatus position_status = PositionStatus::PositionStatus_Ready) {
@@ -110,6 +108,7 @@
     provider_->SetUpdateCallback(callback_);
   }
 
+  base::win::ScopedWinrtInitializer winrt_initializer_;
   base::test::TaskEnvironment task_environment_;
   base::RunLoop run_loop_;
   const std::unique_ptr<MockLocationObserver> observer_;
diff --git a/services/device/usb/usb_device_handle_win.cc b/services/device/usb/usb_device_handle_win.cc
index dd5fc6d..8fb3515c 100644
--- a/services/device/usb/usb_device_handle_win.cc
+++ b/services/device/usb/usb_device_handle_win.cc
@@ -335,10 +335,12 @@
   }
 
   bool found_alternate = false;
-  for (const auto& alternate : interface.info->alternates) {
-    if (alternate->alternate_setting == alternate_setting) {
-      found_alternate = true;
-      break;
+  if (interface.info) {
+    for (const auto& alternate : interface.info->alternates) {
+      if (alternate->alternate_setting == alternate_setting) {
+        found_alternate = true;
+        break;
+      }
     }
   }
 
@@ -413,7 +415,7 @@
       base::BindOnce(&ResetPipeBlocking, interface.handle.Get(),
                      endpoint_address),
       base::BindOnce(&UsbDeviceHandleWin::OnClearHalt, this,
-                     interface.info->interface_number, std::move(callback)));
+                     interface.interface_number, std::move(callback)));
 }
 
 void UsbDeviceHandleWin::ControlTransfer(
@@ -597,6 +599,8 @@
 
       Interface& interface_info = interfaces_[interface->interface_number];
       interface_info.info = interface.get();
+      interface_info.interface_number = interface->interface_number;
+      interface_info.first_interface = interface->first_interface;
       RegisterEndpoints(interface.get(), *alternate);
 
       if (device_->driver_type() == UsbDeviceWin::DriverType::kComposite) {
@@ -619,7 +623,8 @@
     DCHECK(base::Contains(device_->functions(), 0));
     const UsbDeviceWin::FunctionInfo& function_info =
         device_->functions().find(0)->second;
-    DCHECK(base::Contains(interfaces_, 0));
+    // This may create a fake interface 0 (for internal bookkeeping purposes) if
+    // the device doesn't have any interfaces.
     Interface& interface_info = interfaces_[0];
     interface_info.function_driver = function_info.driver;
     interface_info.function_path = function_info.path;
@@ -693,8 +698,8 @@
     OpenInterfaceHandle(
         first_interface,
         base::BindOnce(&UsbDeviceHandleWin::OnFirstInterfaceOpened,
-                       weak_factory_.GetWeakPtr(),
-                       interface->info->interface_number, std::move(callback)));
+                       weak_factory_.GetWeakPtr(), interface->interface_number,
+                       std::move(callback)));
     return;
   }
 
@@ -720,10 +725,10 @@
       DCHECK(base::Contains(interfaces_, 0));
       return &interfaces_[0];
     case UsbDeviceWin::DriverType::kComposite: {
-      if (interface->info->interface_number == interface->info->first_interface)
+      if (interface->interface_number == interface->first_interface)
         return interface;
 
-      auto it = interfaces_.find(interface->info->first_interface);
+      auto it = interfaces_.find(interface->first_interface);
       DCHECK(it != interfaces_.end());
       return &it->second;
     }
@@ -740,14 +745,14 @@
 
   if (!base::EqualsCaseInsensitiveASCII(interface->function_driver,
                                         kWinUsbDriverName)) {
-    USB_LOG(ERROR) << "Interface " << int{interface->info->interface_number}
+    USB_LOG(ERROR) << "Interface " << int{interface->interface_number}
                    << " uses driver \"" << interface->function_driver
                    << "\" instead of WinUSB.";
     return;
   }
 
   if (interface->function_path.empty()) {
-    USB_LOG(ERROR) << "Interface " << int{interface->info->interface_number}
+    USB_LOG(ERROR) << "Interface " << int{interface->interface_number}
                    << " has no device path.";
     return;
   }
@@ -777,10 +782,8 @@
   DCHECK(interface_it != interfaces_.end());
   Interface* interface = &interface_it->second;
   if (device_->driver_type() == UsbDeviceWin::DriverType::kComposite) {
-    DCHECK_NE(interface->info->first_interface,
-              interface->info->interface_number);
-    DCHECK_EQ(interface->info->first_interface,
-              first_interface->info->interface_number);
+    DCHECK_NE(interface->first_interface, interface->interface_number);
+    DCHECK_EQ(interface->first_interface, first_interface->interface_number);
   }
 
   base::ScopedClosureRunner run_callback(
@@ -791,8 +794,8 @@
 
   first_interface->reference_count++;
 
-  int index = interface->info->interface_number -
-              first_interface->info->interface_number - 1;
+  int index =
+      interface->interface_number - first_interface->interface_number - 1;
   WINUSB_INTERFACE_HANDLE handle;
   if (WinUsb_GetAssociatedInterface(first_interface->handle.Get(), index,
                                     &handle)) {
@@ -800,7 +803,7 @@
   } else {
     USB_PLOG(ERROR) << "Failed to get associated interface " << index
                     << " from interface "
-                    << int{first_interface->info->interface_number};
+                    << int{first_interface->interface_number};
     ReleaseInterfaceReference(first_interface);
   }
 }
@@ -830,6 +833,7 @@
   }
 
   // Unregister endpoints from the previously selected alternate setting.
+  DCHECK(interface.info);
   for (const auto& alternate : interface.info->alternates) {
     if (alternate->alternate_setting == interface.alternate_setting) {
       UnregisterEndpoints(*alternate);
@@ -999,7 +1003,7 @@
   interface->reference_count++;
 
   auto request = std::make_unique<Request>(interface->handle.Get(),
-                                           interface->info->interface_number);
+                                           interface->interface_number);
   Request* request_ptr = request.get();
   requests_.push_back(std::move(request));
   return request_ptr;
@@ -1136,7 +1140,7 @@
         const Interface& interface = map_entry.second;
 
         // Iterate over functions, rather than interfaces.
-        if (interface.info->first_interface != interface.info->interface_number)
+        if (interface.first_interface != interface.interface_number)
           continue;
 
         if (interface.function_driver.empty())
diff --git a/services/device/usb/usb_device_handle_win.h b/services/device/usb/usb_device_handle_win.h
index 11694d98..722ced7 100644
--- a/services/device/usb/usb_device_handle_win.h
+++ b/services/device/usb/usb_device_handle_win.h
@@ -100,7 +100,16 @@
     Interface();
     ~Interface();
 
-    const mojom::UsbInterfaceInfo* info;
+    // This may be nullptr in the rare case of a device which doesn't have any
+    // interfaces. In that case the Windows API still considers the device to
+    // have a single function which is represented here by initializing
+    // |interface_number| and |first_interface| to create a fake interface 0.
+    const mojom::UsbInterfaceInfo* info = nullptr;
+
+    // These fields are copied from |info| and initialized to 0 in case it is
+    // nullptr.
+    uint8_t interface_number = 0;
+    uint8_t first_interface = 0;
 
     // In a composite device each function has its own driver and path to open.
     std::wstring function_driver;
diff --git a/storage/common/database/OWNERS b/storage/common/database/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/storage/common/database/OWNERS
+++ /dev/null
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 022264b..3ab1095 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -4452,8 +4452,6 @@
     "gtest_tests": [
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android29.textpb",
@@ -4518,8 +4516,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -4539,11 +4535,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.71"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.73"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.71",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.73",
         "resultdb": {
           "enable": true
         },
@@ -4553,7 +4549,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.71"
+              "revision": "version:90.0.4430.73"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -4599,8 +4595,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -4680,8 +4674,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -4761,8 +4753,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -4782,11 +4772,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.71"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.73"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.71",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.73",
         "resultdb": {
           "enable": true
         },
@@ -4796,7 +4786,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.71"
+              "revision": "version:90.0.4430.73"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -4842,8 +4832,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -4923,8 +4911,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -5008,8 +4994,6 @@
     "gtest_tests": [
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android23.textpb",
@@ -5074,8 +5058,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -5095,11 +5077,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.71"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.73"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.71",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.73",
         "resultdb": {
           "enable": true
         },
@@ -5109,7 +5091,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.71"
+              "revision": "version:90.0.4430.73"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5155,8 +5137,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -5236,8 +5216,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -5317,8 +5295,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -5338,11 +5314,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.71"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.73"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.71",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.73",
         "resultdb": {
           "enable": true
         },
@@ -5352,7 +5328,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.71"
+              "revision": "version:90.0.4430.73"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5398,8 +5374,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -5479,8 +5453,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index bb6a33f2..74b32b40 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -49000,8 +49000,6 @@
     "gtest_tests": [
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
@@ -49065,8 +49063,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49086,11 +49082,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.71"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.73"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.71",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.73",
         "resultdb": {
           "enable": true
         },
@@ -49100,7 +49096,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.71"
+              "revision": "version:90.0.4430.73"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49146,8 +49142,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49227,8 +49221,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49308,8 +49300,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49329,11 +49319,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.71"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.73"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.71",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.73",
         "resultdb": {
           "enable": true
         },
@@ -49343,7 +49333,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.71"
+              "revision": "version:90.0.4430.73"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49389,8 +49379,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49470,8 +49458,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49555,8 +49541,6 @@
     "gtest_tests": [
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
@@ -49620,8 +49604,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49641,11 +49623,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.71"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.73"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.71",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.73",
         "resultdb": {
           "enable": true
         },
@@ -49655,7 +49637,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.71"
+              "revision": "version:90.0.4430.73"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49701,8 +49683,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49782,8 +49762,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49863,8 +49841,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -49884,11 +49860,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.71"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.73"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.71",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.73",
         "resultdb": {
           "enable": true
         },
@@ -49898,7 +49874,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.71"
+              "revision": "version:90.0.4430.73"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49944,8 +49920,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
@@ -50025,8 +49999,6 @@
       },
       {
         "args": [
-          "--timeout-scale",
-          "2.0",
           "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index b18d97f..d0f7f76a 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -2516,29 +2516,6 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.headless_browsertests.filter",
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "headless_browsertests",
-        "test_id_prefix": "ninja://headless:headless_browsertests/"
-      },
-      {
-        "args": [
           "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
         ],
         "merge": {
@@ -3733,28 +3710,6 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.headless_browsertests.filter",
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "headless_browsertests",
-        "test_id_prefix": "ninja://headless:headless_browsertests/"
-      },
-      {
-        "args": [
           "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
         ],
         "merge": {
diff --git a/testing/buildbot/filters/ozone-linux.interactive_ui_tests_wayland.filter b/testing/buildbot/filters/ozone-linux.interactive_ui_tests_wayland.filter
index 5d38f45..f0de130 100644
--- a/testing/buildbot/filters/ozone-linux.interactive_ui_tests_wayland.filter
+++ b/testing/buildbot/filters/ozone-linux.interactive_ui_tests_wayland.filter
@@ -68,3 +68,6 @@
 -MenuItemViewTestInsert20.InsertItem20
 -MenuItemViewTestInsert00.InsertItem00
 -BookmarkBarViewTest18.BookmarkBarViewTest18_SiblingMenu
+
+# TODO(crbug.com/1195324): flaky fullscreen notification test
+-NotificationsTest.TestShouldDisplayMultiFullscreen
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index e899561..bd78f1e 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1584,6 +1584,8 @@
     },
     'remove_from': [
       'CrWinAsan(dll)', # https://crbug.com/935598
+      'Fuchsia x64', # https://crbug.com/1198259
+      'Fuchsia ARM64', # https://crbug.com/1198259
     ],
   },
   'info_collection_tests': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index d5ed6cc8..fa8d84a 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -6839,13 +6839,7 @@
     'android_weblayer_x86_marshmallow_10_gtests': {
       'weblayer_instrumentation_tests': {
         'variants': [
-          {
-            'identifier': 'ToT_Tests',
-            'args': [
-              '--timeout-scale',
-              '2.0',
-            ]
-          }
+          {'identifier': 'ToT_Tests'}
         ]
       },
       'weblayer_instrumentation_version_tests': {
@@ -6863,13 +6857,7 @@
     'android_weblayer_x86_pie_oreo_gtests': {
       'weblayer_instrumentation_tests': {
         'variants': [
-          {
-            'identifier': 'ToT_Tests',
-            'args': [
-              '--timeout-scale',
-              '2.0',
-            ]
-          }
+          {'identifier': 'ToT_Tests'}
         ]
       },
       'weblayer_instrumentation_version_tests': {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index c10f3c55..f1c136e2 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -312,8 +312,6 @@
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -338,8 +336,6 @@
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -351,21 +347,19 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--impl-version=90',
     ],
-    'identifier': 'Implementation Library Skew Tests For 90.0.4430.71',
+    'identifier': 'Implementation Library Skew Tests For 90.0.4430.73',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M90',
-          'revision': 'version:90.0.4430.71',
+          'revision': 'version:90.0.4430.73',
         }
       ],
     },
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -390,8 +384,6 @@
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -416,8 +408,6 @@
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -429,21 +419,19 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--impl-version=90',
     ],
-    'identifier': 'Implementation Library Skew Tests For 90.0.4430.71',
+    'identifier': 'Implementation Library Skew Tests For 90.0.4430.73',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M90',
-          'revision': 'version:90.0.4430.71',
+          'revision': 'version:90.0.4430.73',
         }
       ],
     },
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -468,8 +456,6 @@
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -494,8 +480,6 @@
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -507,21 +491,19 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--client-version=90',
     ],
-    'identifier': 'Client Library Skew Tests For 90.0.4430.71',
+    'identifier': 'Client Library Skew Tests For 90.0.4430.73',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M90',
-          'revision': 'version:90.0.4430.71',
+          'revision': 'version:90.0.4430.73',
         }
       ],
     },
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
-      '--timeout-scale',
-      '2.0',
       '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
@@ -593,4 +575,4 @@
     },
     'identifier': 'SNAPPY_TOT',
   },
-}
+}
\ No newline at end of file
diff --git a/testing/scripts/representative_perf_test_data/platform_specific_tags.json b/testing/scripts/representative_perf_test_data/platform_specific_tags.json
index c43512c..fd4ebbb 100644
--- a/testing/scripts/representative_perf_test_data/platform_specific_tags.json
+++ b/testing/scripts/representative_perf_test_data/platform_specific_tags.json
@@ -4,12 +4,12 @@
     "tags": [
       {
         "buildername": "Mac Release (Intel)",
-        "master": "chromium.gpu",
-        "os": "Mac-10.14.6"
+        "builder_group": "chromium.gpu",
+        "os": "Mac-10.15.5"
       },
       {
         "buildername": "Mac Retina Release (AMD)",
-        "master": "chromium.gpu",
+        "builder_group": "chromium.gpu",
         "os": "Mac-10.14.6"
       }
     ]
@@ -19,8 +19,8 @@
     "tags": [
       {
         "buildername": "Win10 x64 Release (NVIDIA)",
-        "master": "chromium.gpu",
-        "os": "Windows-10"
+        "builder_group": "chromium.gpu",
+        "os": "Windows-10-18363"
       }
     ]
   },
@@ -29,7 +29,7 @@
     "tags": [
       {
         "buildername": "Android FYI Release (Nexus 5X)",
-        "master": "chromium.gpu.fyi",
+        "builder_group": "chromium.gpu.fyi",
         "os": "Android"
       }
     ]
diff --git a/testing/test.gni b/testing/test.gni
index 2950167..a4eed34 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -169,6 +169,9 @@
         "use_native_activity",
       ]
 
+      _use_default_launcher =
+          !defined(invoker.use_default_launcher) || invoker.use_default_launcher
+
       # Adds the unwind tables from unstripped binary as an asset file in the
       # apk, if |add_unwind_tables_in_apk| is specified by the test.
       if (defined(invoker.add_unwind_tables_in_apk) &&
@@ -204,8 +207,7 @@
           }
         }
 
-        if (!defined(invoker.use_default_launcher) ||
-            invoker.use_default_launcher) {
+        if (_use_default_launcher) {
           deps += [ "//testing/android/native_test:native_test_native_code" ]
         }
       }
@@ -225,7 +227,9 @@
         }
 
         # Add the Java classes so that each target does not have to do it.
-        deps += [ "//base/test:test_support_java" ]
+        if (_use_default_launcher) {
+          deps += [ "//base/test:test_support_java" ]
+        }
 
         if (defined(_unwind_table_asset_name)) {
           deps += [ ":${_unwind_table_asset_name}" ]
diff --git a/third_party/android_crazy_linker/src/OWNERS b/third_party/android_crazy_linker/src/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/android_crazy_linker/src/OWNERS
+++ /dev/null
diff --git a/third_party/android_swipe_refresh/java/OWNERS b/third_party/android_swipe_refresh/java/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/android_swipe_refresh/java/OWNERS
+++ /dev/null
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index c373c2cf..b4496f666 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -76,10 +76,13 @@
     "bluetooth/web_bluetooth_device_id.cc",
     "browser_interface_broker_proxy.cc",
     "cache_storage/cache_storage_utils.cc",
+    "chrome_debug_urls.cc",
     "client_hints/client_hints.cc",
     "context_menu_data/context_menu_mojom_traits.cc",
     "context_menu_data/context_menu_params_builder.cc",
     "context_menu_data/untrustworthy_context_menu_params.cc",
+    "crash_helpers.cc",
+    "crash_helpers.h",
     "custom_handlers/protocol_handler_utils.cc",
     "device_memory/approximated_device_memory.cc",
     "dom_storage/session_storage_namespace_id.cc",
diff --git a/third_party/blink/common/chrome_debug_urls.cc b/third_party/blink/common/chrome_debug_urls.cc
new file mode 100644
index 0000000..d26ee1e
--- /dev/null
+++ b/third_party/blink/common/chrome_debug_urls.cc
@@ -0,0 +1,240 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/chrome_debug_urls.h"
+
+#include "base/debug/asan_invalid_access.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/logging.h"
+#include "base/process/process.h"
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+#include "third_party/blink/common/crash_helpers.h"
+#include "url/gurl.h"
+
+#if defined(OS_WIN)
+#include "base/debug/invalid_access_win.h"
+#include "base/process/kill.h"
+#elif defined(OS_POSIX)
+#include <signal.h>
+#endif
+
+namespace blink {
+
+// See the comment in chrome_debug_urls.h about why these exist here.
+// https://crbug.com/1197375.
+const char kChromeUIBadCastCrashURL[] = "chrome://badcastcrash/";
+const char kChromeUICheckCrashURL[] = "chrome://checkcrash/";
+const char kChromeUIBrowserCrashURL[] = "chrome://inducebrowsercrashforrealz/";
+const char kChromeUIBrowserUIHang[] = "chrome://uithreadhang/";
+const char kChromeUICrashURL[] = "chrome://crash/";
+const char kChromeUIDelayedBrowserUIHang[] = "chrome://delayeduithreadhang/";
+const char kChromeUIDumpURL[] = "chrome://crashdump/";
+const char kChromeUIGpuCleanURL[] = "chrome://gpuclean/";
+const char kChromeUIGpuCrashURL[] = "chrome://gpucrash/";
+const char kChromeUIGpuHangURL[] = "chrome://gpuhang/";
+const char kChromeUIHangURL[] = "chrome://hang/";
+const char kChromeUIKillURL[] = "chrome://kill/";
+const char kChromeUIMemoryExhaustURL[] = "chrome://memory-exhaust/";
+const char kChromeUIMemoryPressureCriticalURL[] =
+    "chrome://memory-pressure-critical/";
+const char kChromeUIMemoryPressureModerateURL[] =
+    "chrome://memory-pressure-moderate/";
+const char kChromeUINetworkErrorURL[] = "chrome://network-error/";
+const char kChromeUINetworkErrorsListingURL[] = "chrome://network-errors/";
+const char kChromeUIPpapiFlashCrashURL[] = "chrome://ppapiflashcrash/";
+const char kChromeUIPpapiFlashHangURL[] = "chrome://ppapiflashhang/";
+const char kChromeUIProcessInternalsURL[] = "chrome://process-internals";
+#if defined(OS_ANDROID)
+const char kChromeUIGpuJavaCrashURL[] = "chrome://gpu-java-crash/";
+#endif
+#if defined(OS_WIN)
+const char kChromeUIBrowserHeapCorruptionURL[] =
+    "chrome://inducebrowserheapcorruption/";
+const char kChromeUIHeapCorruptionCrashURL[] = "chrome://heapcorruptioncrash/";
+#endif
+
+#if defined(ADDRESS_SANITIZER)
+const char kChromeUICrashHeapOverflowURL[] = "chrome://crash/heap-overflow";
+const char kChromeUICrashHeapUnderflowURL[] = "chrome://crash/heap-underflow";
+const char kChromeUICrashUseAfterFreeURL[] = "chrome://crash/use-after-free";
+
+#if defined(OS_WIN)
+const char kChromeUICrashCorruptHeapBlockURL[] =
+    "chrome://crash/corrupt-heap-block";
+const char kChromeUICrashCorruptHeapURL[] = "chrome://crash/corrupt-heap";
+#endif  // OS_WIN
+#endif  // ADDRESS_SANITIZER
+
+#if DCHECK_IS_ON()
+const char kChromeUICrashDcheckURL[] = "chrome://crash/dcheck";
+#endif
+
+const char kChromeUIResourcesURL[] = "chrome://resources/";
+const char kChromeUIShorthangURL[] = "chrome://shorthang/";
+
+bool IsRendererDebugURL(const GURL& url) {
+  if (!url.is_valid())
+    return false;
+
+  if (url.SchemeIs(url::kJavaScriptScheme))
+    return true;
+
+  if (!url.SchemeIs("chrome"))
+    return false;
+
+  if (url == kChromeUICheckCrashURL || url == kChromeUIBadCastCrashURL ||
+      url == kChromeUICrashURL || url == kChromeUIDumpURL ||
+      url == kChromeUIKillURL || url == kChromeUIHangURL ||
+      url == kChromeUIShorthangURL || url == kChromeUIMemoryExhaustURL) {
+    return true;
+  }
+
+#if defined(ADDRESS_SANITIZER)
+  if (url == kChromeUICrashHeapOverflowURL ||
+      url == kChromeUICrashHeapUnderflowURL ||
+      url == kChromeUICrashUseAfterFreeURL) {
+    return true;
+  }
+#endif
+
+#if defined(OS_WIN)
+  if (url == kChromeUIHeapCorruptionCrashURL)
+    return true;
+#endif
+
+#if DCHECK_IS_ON()
+  if (url == kChromeUICrashDcheckURL)
+    return true;
+#endif
+
+#if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
+  if (url == kChromeUICrashCorruptHeapBlockURL ||
+      url == kChromeUICrashCorruptHeapURL) {
+    return true;
+  }
+#endif
+
+  return false;
+}
+
+namespace {
+
+// The following methods are outside of the anonymous namespace to ensure that
+// the corresponding symbols get emitted even on symbol_level 1.
+NOINLINE void ExhaustMemory() {
+  volatile void* ptr = nullptr;
+  do {
+    ptr = malloc(0x10000000);
+    base::debug::Alias(&ptr);
+  } while (ptr);
+}
+
+#if defined(ADDRESS_SANITIZER)
+NOINLINE void MaybeTriggerAsanError(const GURL& url) {
+  // NOTE(rogerm): We intentionally perform an invalid heap access here in
+  //     order to trigger an Address Sanitizer (ASAN) error report.
+  if (url == kChromeUICrashHeapOverflowURL) {
+    LOG(ERROR) << "Intentionally causing ASAN heap overflow"
+               << " because user navigated to " << url.spec();
+    base::debug::AsanHeapOverflow();
+  } else if (url == kChromeUICrashHeapUnderflowURL) {
+    LOG(ERROR) << "Intentionally causing ASAN heap underflow"
+               << " because user navigated to " << url.spec();
+    base::debug::AsanHeapUnderflow();
+  } else if (url == kChromeUICrashUseAfterFreeURL) {
+    LOG(ERROR) << "Intentionally causing ASAN heap use-after-free"
+               << " because user navigated to " << url.spec();
+    base::debug::AsanHeapUseAfterFree();
+#if defined(OS_WIN)
+  } else if (url == kChromeUICrashCorruptHeapBlockURL) {
+    LOG(ERROR) << "Intentionally causing ASAN corrupt heap block"
+               << " because user navigated to " << url.spec();
+    base::debug::AsanCorruptHeapBlock();
+  } else if (url == kChromeUICrashCorruptHeapURL) {
+    LOG(ERROR) << "Intentionally causing ASAN corrupt heap"
+               << " because user navigated to " << url.spec();
+    base::debug::AsanCorruptHeap();
+#endif  // OS_WIN
+  }
+}
+#endif  // ADDRESS_SANITIZER
+
+}  // namespace
+
+void HandleChromeDebugURL(const GURL& url) {
+  DCHECK(IsRendererDebugURL(url) && !url.SchemeIs("javascript"));
+  if (url == kChromeUIBadCastCrashURL) {
+    LOG(ERROR) << "Intentionally crashing (with bad cast)"
+               << " because user navigated to " << url.spec();
+    internal::BadCastCrashIntentionally();
+  } else if (url == kChromeUICrashURL) {
+    LOG(ERROR) << "Intentionally crashing (with null pointer dereference)"
+               << " because user navigated to " << url.spec();
+    internal::CrashIntentionally();
+  } else if (url == kChromeUIDumpURL) {
+    // This URL will only correctly create a crash dump file if content is
+    // hosted in a process that has correctly called
+    // base::debug::SetDumpWithoutCrashingFunction.  Refer to the documentation
+    // of base::debug::DumpWithoutCrashing for more details.
+    base::debug::DumpWithoutCrashing();
+#if defined(OS_WIN) || defined(OS_POSIX)
+  } else if (url == kChromeUIKillURL) {
+    LOG(ERROR) << "Intentionally terminating current process because user"
+                  " navigated to "
+               << url.spec();
+    // Simulate termination such that the base::GetTerminationStatus() API will
+    // return TERMINATION_STATUS_PROCESS_WAS_KILLED.
+#if defined(OS_WIN)
+    base::Process::TerminateCurrentProcessImmediately(
+        base::win::kProcessKilledExitCode);
+#elif defined(OS_POSIX)
+    PCHECK(kill(base::Process::Current().Pid(), SIGTERM) == 0);
+#endif
+#endif  // defined(OS_WIN) || defined(OS_POSIX)
+  } else if (url == kChromeUIHangURL) {
+    LOG(ERROR) << "Intentionally hanging ourselves with sleep infinite loop"
+               << " because user navigated to " << url.spec();
+    for (;;) {
+      base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
+    }
+  } else if (url == kChromeUIShorthangURL) {
+    LOG(ERROR) << "Intentionally sleeping renderer for 20 seconds"
+               << " because user navigated to " << url.spec();
+    base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
+  } else if (url == kChromeUIMemoryExhaustURL) {
+    LOG(ERROR)
+        << "Intentionally exhausting renderer memory because user navigated to "
+        << url.spec();
+    ExhaustMemory();
+  } else if (url == kChromeUICheckCrashURL) {
+    LOG(ERROR) << "Intentionally causing CHECK because user navigated to "
+               << url.spec();
+    CHECK(false);
+  }
+
+#if defined(OS_WIN)
+  if (url == kChromeUIHeapCorruptionCrashURL) {
+    LOG(ERROR)
+        << "Intentionally causing heap corruption because user navigated to "
+        << url.spec();
+    base::debug::win::TerminateWithHeapCorruption();
+  }
+#endif
+
+#if DCHECK_IS_ON()
+  if (url == kChromeUICrashDcheckURL) {
+    LOG(ERROR) << "Intentionally causing DCHECK because user navigated to "
+               << url.spec();
+
+    DCHECK(false) << "Intentional DCHECK.";
+  }
+#endif
+
+#if defined(ADDRESS_SANITIZER)
+  MaybeTriggerAsanError(url);
+#endif  // ADDRESS_SANITIZER
+}
+
+}  // namespace blink
diff --git a/content/renderer/crash_helpers.cc b/third_party/blink/common/crash_helpers.cc
similarity index 90%
rename from content/renderer/crash_helpers.cc
rename to third_party/blink/common/crash_helpers.cc
index ed610b3b..4d162dc 100644
--- a/content/renderer/crash_helpers.cc
+++ b/third_party/blink/common/crash_helpers.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/crash_helpers.h"
+#include "third_party/blink/common/crash_helpers.h"
 
 #include "base/debug/alias.h"
 
-namespace content {
+namespace blink {
 
 namespace internal {
 
@@ -38,4 +38,4 @@
 
 }  // namespace internal
 
-}  // namespace content
+}  // namespace blink
diff --git a/content/renderer/crash_helpers.h b/third_party/blink/common/crash_helpers.h
similarity index 74%
rename from content/renderer/crash_helpers.h
rename to third_party/blink/common/crash_helpers.h
index 30bbb9e..c4f234d3 100644
--- a/content/renderer/crash_helpers.h
+++ b/third_party/blink/common/crash_helpers.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_CRASH_HELPERS_H_
-#define CONTENT_RENDERER_CRASH_HELPERS_H_
+#ifndef THIRD_PARTY_BLINK_COMMON_CRASH_HELPERS_H_
+#define THIRD_PARTY_BLINK_COMMON_CRASH_HELPERS_H_
 
 #include "base/compiler_specific.h"
 
-namespace content {
+namespace blink {
 
 namespace internal {
 
@@ -21,6 +21,6 @@
 
 }  // namespace internal
 
-}  // namespace content
+}  // namespace blink
 
-#endif  // CONTENT_RENDERER_CRASH_HELPERS_H_
+#endif  // THIRD_PARTY_BLINK_COMMON_CRASH_HELPERS_H_
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index e726b2d..891b598 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -71,6 +71,7 @@
     "bluetooth/web_bluetooth_device_id_mojom_traits.h",
     "browser_interface_broker_proxy.h",
     "cache_storage/cache_storage_utils.h",
+    "chrome_debug_urls.h",
     "client_hints/client_hints.h",
     "context_menu_data/context_menu_data.h",
     "context_menu_data/context_menu_params_builder.h",
diff --git a/third_party/blink/public/common/chrome_debug_urls.h b/third_party/blink/public/common/chrome_debug_urls.h
new file mode 100644
index 0000000..9a0318e
--- /dev/null
+++ b/third_party/blink/public/common/chrome_debug_urls.h
@@ -0,0 +1,82 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_CHROME_DEBUG_URLS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_CHROME_DEBUG_URLS_H_
+
+#include "base/check_op.h"
+#include "build/build_config.h"
+#include "third_party/blink/public/common/common_export.h"
+
+class GURL;
+
+namespace blink {
+
+// TODO(https://crbug.com/1197375): This file defines ChromeUI URLs that support
+// triggering debug functionalities. These functionalities do not need to be
+// Chrome-specific, and therefore defined in Blink, while they use ChromeUI
+// specific URLs. Revisit to see if these URLs (and therefore functionalities
+// too) should rather be implemented by embedders.
+
+// Full about URLs (including schemes).
+BLINK_COMMON_EXPORT extern const char kChromeUIBadCastCrashURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUICheckCrashURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIBrowserCrashURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIBrowserUIHang[];
+BLINK_COMMON_EXPORT extern const char kChromeUICrashURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIDelayedBrowserUIHang[];
+BLINK_COMMON_EXPORT extern const char kChromeUIDumpURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIGpuCleanURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIGpuCrashURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIGpuHangURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIHangURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIKillURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIMemoryExhaustURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIMemoryPressureCriticalURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIMemoryPressureModerateURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUINetworkErrorsListingURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUINetworkErrorURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIPpapiFlashCrashURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIPpapiFlashHangURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIProcessInternalsURL[];
+#if defined(OS_ANDROID)
+BLINK_COMMON_EXPORT extern const char kChromeUIGpuJavaCrashURL[];
+#endif
+#if defined(OS_WIN)
+BLINK_COMMON_EXPORT extern const char kChromeUIBrowserHeapCorruptionURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIHeapCorruptionCrashURL[];
+#endif
+
+#if defined(ADDRESS_SANITIZER)
+BLINK_COMMON_EXPORT extern const char kChromeUICrashHeapOverflowURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUICrashHeapUnderflowURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUICrashUseAfterFreeURL[];
+#if defined(OS_WIN)
+BLINK_COMMON_EXPORT extern const char kChromeUICrashCorruptHeapBlockURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUICrashCorruptHeapURL[];
+#endif  // OS_WIN
+#endif  // ADDRESS_SANITIZER
+
+#if DCHECK_IS_ON()
+BLINK_COMMON_EXPORT extern const char kChromeUICrashDcheckURL[];
+#endif
+
+// Full about URLs (including schemes).
+BLINK_COMMON_EXPORT extern const char kChromeUIResourcesURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUIShorthangURL[];
+
+// Returns whether the given url is either a debugging url handled in the
+// renderer process, such as one that crashes or hangs the renderer, or a
+// javascript: URL that operates on the current page in the renderer.  Such URLs
+// do not represent actual navigations and can be loaded in any SiteInstance.
+BLINK_COMMON_EXPORT bool IsRendererDebugURL(const GURL& url);
+
+// Handles the given debug URL. These URLs do not commit, though they are
+// intentionally left in the address bar above the effect they cause
+// (e.g., a sad tab).
+BLINK_COMMON_EXPORT void HandleChromeDebugURL(const GURL& url);
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_CHROME_DEBUG_URLS_H_
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index 6f7898a..1d30844 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -763,6 +763,9 @@
   ExtractSmartClipData(gfx.mojom.Rect rect)
       => (mojo_base.mojom.String16 text, mojo_base.mojom.String16 html,
               gfx.mojom.Rect clip_rect);
+
+  // Asks the renderer to handle a renderer-debug URL.
+  HandleRendererDebugURL(url.mojom.Url url);
 };
 
 // Also implemented in Blink, this interface defines frame-specific methods
diff --git a/third_party/blink/public/web/web_navigation_control.h b/third_party/blink/public/web/web_navigation_control.h
index 7f0af42..dacadc3e 100644
--- a/third_party/blink/public/web/web_navigation_control.h
+++ b/third_party/blink/public/web/web_navigation_control.h
@@ -54,11 +54,6 @@
       bool has_transient_user_activation,
       std::unique_ptr<WebDocumentLoader::ExtraData> extra_data) = 0;
 
-  // Loads a JavaScript URL in the frame.
-  // TODO(dgozman): this may replace the document, so perhaps we should
-  // return something meaningful?
-  virtual void LoadJavaScriptURL(const WebURL&) = 0;
-
   enum FallbackContentResult {
     // An error page should be shown instead of fallback.
     NoFallbackContent,
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h
index 763b1f0..6fd031d 100644
--- a/third_party/blink/public/web/web_navigation_params.h
+++ b/third_party/blink/public/web/web_navigation_params.h
@@ -235,7 +235,9 @@
   // The http status code of the request used to load the main resource, if any.
   int http_status_code = 0;
   // The origin of the request used to load the main resource, specified at
-  // https://fetch.spec.whatwg.org/#concept-request-origin. Can be null.
+  // https://fetch.spec.whatwg.org/#concept-request-origin. This is never null
+  // for renderer-initiated navigations, but can be null for 1)
+  // browser-initiated navigations and 2) loading of initial empty documents.
   // TODO(dgozman,nasko): we shouldn't need both this and |origin_to_commit|.
   WebSecurityOrigin requestor_origin;
   // If non-null, used as a URL which we weren't able to load. For example,
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc b/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc
index 797bcab..d5b1fd8 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc
@@ -61,7 +61,7 @@
 Node* V8GCController::OpaqueRootForGC(v8::Isolate*, Node* node) {
   DCHECK(node);
   if (node->isConnected())
-    return &node->GetDocument().TreeRootDocument();
+    return &node->GetDocument();
 
   if (auto* attr = DynamicTo<Attr>(node)) {
     Node* owner_element = attr->ownerElement();
diff --git a/third_party/blink/renderer/core/css/media_values_cached.cc b/third_party/blink/renderer/core/css/media_values_cached.cc
index 16c91688..f95a988 100644
--- a/third_party/blink/renderer/core/css/media_values_cached.cc
+++ b/third_party/blink/renderer/core/css/media_values_cached.cc
@@ -47,7 +47,7 @@
     Document& document)
     : MediaValuesCached::MediaValuesCachedData() {
   DCHECK(IsMainThread());
-  LocalFrame* frame = document.GetFrameOfTreeRootDocument();
+  LocalFrame* frame = document.GetFrame();
   // TODO(hiroshige): Clean up |frame->view()| conditions.
   DCHECK(!frame || frame->View());
   if (frame && frame->View()) {
diff --git a/third_party/blink/renderer/core/css/media_values_dynamic.cc b/third_party/blink/renderer/core/css/media_values_dynamic.cc
index 9561a883..312bf87 100644
--- a/third_party/blink/renderer/core/css/media_values_dynamic.cc
+++ b/third_party/blink/renderer/core/css/media_values_dynamic.cc
@@ -16,7 +16,7 @@
 namespace blink {
 
 MediaValues* MediaValuesDynamic::Create(Document& document) {
-  return MediaValuesDynamic::Create(document.GetFrameOfTreeRootDocument());
+  return MediaValuesDynamic::Create(document.GetFrame());
 }
 
 MediaValues* MediaValuesDynamic::Create(LocalFrame* frame) {
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 4bfd738..1efbbfda 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -1197,16 +1197,6 @@
                                                              flags, is);
 }
 
-Document& Document::TreeRootDocument() const {
-  return *const_cast<Document*>(this);
-}
-
-LocalDOMWindow* Document::ExecutingWindow() const {
-  if (LocalDOMWindow* owning_window = domWindow())
-    return owning_window;
-  return nullptr;
-}
-
 DocumentFragment* Document::createDocumentFragment() {
   return DocumentFragment::Create(*this);
 }
@@ -1822,12 +1812,6 @@
   return GetFrame() ? GetFrame()->GetPage() : nullptr;
 }
 
-LocalFrame* Document::GetFrameOfTreeRootDocument() const {
-  if (GetFrame())
-    return GetFrame();
-  return nullptr;
-}
-
 Settings* Document::GetSettings() const {
   return GetFrame() ? GetFrame()->GetSettings() : nullptr;
 }
@@ -6450,13 +6434,11 @@
 bool Document::ShouldInheritSecurityOriginFromOwner(const KURL& url) {
   // https://html.spec.whatwg.org/C/#origin
   //
-  // If a Document is the initial "about:blank" document The origin and
-  // effective script origin of the Document are those it was assigned when its
-  // browsing context was created.
-  //
-  // Note: We generalize this to all "blank" URLs and invalid URLs because we
-  // treat all of these URLs as about:blank.
-  return url.IsEmpty() || url.ProtocolIsAbout();
+  // In some cases, the Document's origin might be inherited from the owner
+  // document (the creator of the document for the initial empty documents, the
+  // initiator of the navigation for "about:blank", or the parent for
+  // "about:srcdoc".
+  return url.IsEmpty() || url.IsAboutBlankURL() || url.IsAboutSrcdocURL();
 }
 
 KURL Document::OpenSearchDescriptionURL() {
@@ -7090,7 +7072,7 @@
   // Also, if the listening node came from other document, which happens on
   // context-less event dispatching, we also need to ask the owner document of
   // the node.
-  LocalDOMWindow* window = ExecutingWindow();
+  LocalDOMWindow* window = domWindow();
   if (!window)
     return false;
 
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index d3a124b..98124a5 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -322,8 +322,6 @@
 
   bool IsPrerendering() const { return is_prerendering_; }
 
-  LocalDOMWindow* ExecutingWindow() const;
-
   network::mojom::ReferrerPolicy GetReferrerPolicy() const;
 
   bool DocumentPolicyFeatureObserved(
@@ -543,9 +541,6 @@
 
   LocalFrameView* View() const;  // can be null
   LocalFrame* GetFrame() const;  // can be null
-  // Returns frame_ for current document.  Can be null.
-  // TODO(kochi): Audit usage of this interface (crbug.com/746150).
-  LocalFrame* GetFrameOfTreeRootDocument() const;
   Page* GetPage() const;          // can be null
   Settings* GetSettings() const;  // can be null
 
@@ -1323,8 +1318,6 @@
                               const ElementRegistrationOptions*,
                               ExceptionState&);
 
-  Document& TreeRootDocument() const;
-
   void AdjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad>&,
                                                 const LayoutObject&) const;
   void AdjustFloatRectForScrollAndAbsoluteZoom(FloatRect&,
diff --git a/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc b/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc
index 9628c5b..8ccf309a 100644
--- a/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc
+++ b/third_party/blink/renderer/core/frame/child_frame_compositing_helper.cc
@@ -46,7 +46,6 @@
 
 void ChildFrameCompositingHelper::SetSurfaceId(
     const viz::SurfaceId& surface_id,
-    const gfx::Size& frame_size_in_dip,
     bool capture_sequence_number_changed) {
   if (surface_id_ == surface_id)
     return;
@@ -71,8 +70,6 @@
                                       true /* is_surface_layer */);
 
   UpdateVisibility(true);
-
-  surface_layer_->SetBounds(frame_size_in_dip);
 }
 
 void ChildFrameCompositingHelper::UpdateVisibility(bool visible) {
diff --git a/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h b/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h
index 1f3b6633..c7c49374 100644
--- a/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h
+++ b/third_party/blink/renderer/core/frame/child_frame_compositing_helper.h
@@ -21,10 +21,6 @@
 class PictureLayer;
 }
 
-namespace gfx {
-class Size;
-}
-
 namespace blink {
 
 class ChildFrameCompositor;
@@ -36,7 +32,6 @@
   ~ChildFrameCompositingHelper() override;
 
   void SetSurfaceId(const viz::SurfaceId& surface_id,
-                    const gfx::Size& frame_size_in_dip,
                     bool capture_sequence_number_changed);
   void UpdateVisibility(bool visible);
   void ChildFrameGone(float device_scale_factor);
diff --git a/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc b/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
index 3e9550e4..a88021e 100644
--- a/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
+++ b/third_party/blink/renderer/core/frame/child_frame_compositing_helper_test.cc
@@ -70,8 +70,7 @@
   EXPECT_FALSE(compositing_helper()->surface_id().is_valid());
 
   const viz::SurfaceId surface_id = MakeSurfaceId(viz::FrameSinkId(1, 1), 1);
-  const gfx::Size frame_size_in_dip(100, 100);
-  compositing_helper()->SetSurfaceId(surface_id, frame_size_in_dip, false);
+  compositing_helper()->SetSurfaceId(surface_id, false);
   EXPECT_EQ(surface_id, compositing_helper()->surface_id());
 
   // Reporting that the child frame is gone should clear the surface id.
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index 6664272..d944f04 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -157,7 +157,7 @@
 void LoadFrameDontWait(WebLocalFrame* frame, const WebURL& url) {
   auto* impl = To<WebLocalFrameImpl>(frame);
   if (url.ProtocolIs("javascript")) {
-    impl->LoadJavaScriptURL(url);
+    impl->GetFrame()->LoadJavaScriptURL(url);
   } else {
     auto params = std::make_unique<WebNavigationParams>();
     params->url = url;
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index c589243..c6d20ff 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -45,6 +45,7 @@
 #include "skia/public/mojom/skcolor.mojom-blink.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/input/web_input_event_attribution.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
@@ -192,6 +193,7 @@
 #include "third_party/blink/renderer/platform/network/network_utils.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -2544,6 +2546,22 @@
   GetLocalFrameHostRemote().DidActivateForPrerendering();
 }
 
+void LocalFrame::LoadJavaScriptURL(const KURL& url) {
+  // Protect privileged pages against bookmarklets and other JavaScript
+  // manipulations.
+  if (SchemeRegistry::ShouldTreatURLSchemeAsNotAllowingJavascriptURLs(
+          GetDocument()->Url().Protocol()))
+    return;
+
+  // TODO(mustaq): This is called only through the user typing a javascript URL
+  // into the omnibox.  See https://crbug.com/1082900
+  NotifyUserActivation(
+      mojom::blink::UserActivationNotificationType::kInteraction, false);
+  DomWindow()->GetScriptController().ExecuteJavaScriptURL(
+      url, network::mojom::CSPDisposition::DO_NOT_CHECK,
+      &DOMWrapperWorld::MainWorld());
+}
+
 WebURLLoader::DeferType LocalFrame::GetLoadDeferType() {
   if (GetPage()->GetPageScheduler()->IsInBackForwardCache() &&
       IsInflightNetworkRequestBackForwardCacheSupportEnabled()) {
@@ -3303,7 +3321,7 @@
       media_element->SetLoop(enable);
       break;
     case blink::mojom::blink::MediaPlayerActionType::kControls:
-      media_element->SetBooleanAttribute(html_names::kControlsAttr, enable);
+      media_element->SetUserWantsControlsVisible(enable);
       break;
     case blink::mojom::blink::MediaPlayerActionType::kPictureInPicture:
       DCHECK(IsA<HTMLVideoElement>(media_element));
@@ -3594,6 +3612,23 @@
 }
 #endif  // defined(OS_ANDROID)
 
+void LocalFrame::HandleRendererDebugURL(const KURL& url) {
+  DCHECK(IsRendererDebugURL(url));
+  if (url.ProtocolIs("javascript")) {
+    // JavaScript URLs should be sent to Blink for handling.
+    LoadJavaScriptURL(url);
+  } else {
+    // This is a Chrome Debug URL. Handle it.
+    HandleChromeDebugURL(url);
+  }
+
+  // The browser sets its status as loading before calling this IPC. Inform it
+  // that the load stopped if needed, while leaving the debug URL visible in the
+  // address bar.
+  if (!IsLoading())
+    Client()->DidStopLoading();
+}
+
 bool LocalFrame::ShouldThrottleDownload() {
   const auto now = base::TimeTicks::Now();
   if (num_burst_download_requests_ == 0) {
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 33a4304d..6aea471a 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -699,6 +699,7 @@
   void ExtractSmartClipData(const gfx::Rect& rect,
                             ExtractSmartClipDataCallback callback) final;
 #endif
+  void HandleRendererDebugURL(const KURL& url) final;
 
   // blink::mojom::LocalMainFrame overrides:
   void AnimateDoubleTapZoom(const gfx::Point& point,
@@ -800,6 +801,8 @@
   // event.
   void DidActivateForPrerendering();
 
+  void LoadJavaScriptURL(const KURL& url);
+
  private:
   friend class FrameNavigationDisabler;
   FRIEND_TEST_ALL_PREFIXES(LocalFrameTest, CharacterIndexAtPointWithPinchZoom);
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index 439af01..1d7c2d0 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -1004,9 +1004,12 @@
   DCHECK(surface_id.is_valid());
   DCHECK(!remote_process_gone_);
 
-  compositing_helper_->SetSurfaceId(
-      surface_id, pending_visual_properties_.compositor_viewport.size(),
-      capture_sequence_number_changed);
+  compositing_helper_->SetSurfaceId(surface_id,
+                                    capture_sequence_number_changed);
+  DCHECK(cc_layer_);
+  // Note that in pre-CompositeAfterPaint, CompositedLayerMapping/GraphicsLayer
+  // will set the bounds again with the same value.
+  cc_layer_->SetBounds(pending_visual_properties_.local_frame_size);
 
   bool rect_changed = !sent_visual_properties_ ||
                       sent_visual_properties_->screen_space_rect !=
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc
index c8c42cf..ae0bf1f 100644
--- a/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -11591,7 +11591,7 @@
   KURL javascript_url = ToKURL("javascript:location='" + redirect_url + "'");
   url_test_helpers::RegisterMockedURLLoad(ToKURL(redirect_url),
                                           test::CoreTestDataPath("foo.html"));
-  helper.LocalMainFrame()->LoadJavaScriptURL(javascript_url);
+  helper.LocalMainFrame()->GetFrame()->LoadJavaScriptURL(javascript_url);
   RunPendingTasks();
 
   // The result of the JS url replaces the existing contents on the
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 306ef76..2bec823 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -2349,23 +2349,6 @@
       mojom::blink::TriggeringEventInfo::kNotFromEvent, std::move(extra_data));
 }
 
-void WebLocalFrameImpl::LoadJavaScriptURL(const WebURL& url) {
-  DCHECK(GetFrame());
-  // Protect privileged pages against bookmarklets and other javascript
-  // manipulations.
-  if (SchemeRegistry::ShouldTreatURLSchemeAsNotAllowingJavascriptURLs(
-          GetFrame()->GetDocument()->Url().Protocol()))
-    return;
-
-  // TODO(mustaq): This is called only through the user typing a javascript URL
-  // into the omnibox.  See https://crbug.com/1082900
-  LocalFrame::NotifyUserActivation(
-      GetFrame(), mojom::blink::UserActivationNotificationType::kInteraction);
-  GetFrame()->DomWindow()->GetScriptController().ExecuteJavaScriptURL(
-      url, network::mojom::CSPDisposition::DO_NOT_CHECK,
-      &DOMWrapperWorld::MainWorld());
-}
-
 WebNavigationControl::FallbackContentResult
 WebLocalFrameImpl::MaybeRenderFallbackContent(const WebURLError& error) const {
   DCHECK(GetFrame());
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 40ba864d..d071850 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -337,7 +337,6 @@
       bool is_client_redirect,
       bool has_transient_user_activation,
       std::unique_ptr<WebDocumentLoader::ExtraData> extra_data) override;
-  void LoadJavaScriptURL(const WebURL&) override;
   FallbackContentResult MaybeRenderFallbackContent(
       const WebURLError&) const override;
   void SetCommittedFirstRealLoad() override;
diff --git a/third_party/blink/renderer/core/html/OWNERS b/third_party/blink/renderer/core/html/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/renderer/core/html/OWNERS
+++ /dev/null
diff --git a/third_party/blink/renderer/core/html/custom/custom_element.cc b/third_party/blink/renderer/core/html/custom/custom_element.cc
index 88c244e..a80dd58 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element.cc
+++ b/third_party/blink/renderer/core/html/custom/custom_element.cc
@@ -27,7 +27,7 @@
 }
 
 CustomElementRegistry* CustomElement::Registry(const Document& document) {
-  if (LocalDOMWindow* window = document.ExecutingWindow())
+  if (LocalDOMWindow* window = document.domWindow())
     return window->customElements();
   return nullptr;
 }
diff --git a/third_party/blink/renderer/core/html/link_resource.cc b/third_party/blink/renderer/core/html/link_resource.cc
index 4e7be39..7df24ba7 100644
--- a/third_party/blink/renderer/core/html/link_resource.cc
+++ b/third_party/blink/renderer/core/html/link_resource.cc
@@ -47,7 +47,7 @@
 }
 
 LocalFrame* LinkResource::LoadingFrame() const {
-  return owner_->GetDocument().TreeRootDocument().GetFrame();
+  return owner_->GetDocument().GetFrame();
 }
 
 Document& LinkResource::GetDocument() {
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index 18a89bf..7cf205df 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -153,7 +153,9 @@
   kNoScript,
   kNotShown,
   kDisabledSettings,
-  kMaxValue = kDisabledSettings,
+  kUserExplicitlyEnabled,
+  kUserExplicitlyDisabled,
+  kMaxValue = kUserExplicitlyDisabled,
 };
 
 // These values are used for the Media.MediaElement.ContentTypeResult histogram.
@@ -2740,6 +2742,18 @@
     return false;
   }
 
+  // If the user has explicitly shown or hidden the controls, then force that
+  // choice.
+  if (user_wants_controls_visible_.has_value()) {
+    if (record_metrics == RecordMetricsBehavior::kDoRecord) {
+      RecordShowControlsUsage(this,
+                              *user_wants_controls_visible_
+                                  ? MediaControlsShow::kUserExplicitlyEnabled
+                                  : MediaControlsShow::kUserExplicitlyDisabled);
+    }
+    return *user_wants_controls_visible_;
+  }
+
   if (FastHasAttribute(html_names::kControlsAttr)) {
     if (record_metrics == RecordMetricsBehavior::kDoRecord)
       RecordShowControlsUsage(this, MediaControlsShow::kAttribute);
@@ -2850,6 +2864,11 @@
   autoplay_policy_->StopAutoplayMutedWhenVisible();
 }
 
+void HTMLMediaElement::SetUserWantsControlsVisible(bool visible) {
+  user_wants_controls_visible_ = visible;
+  UpdateControlsVisibility();
+}
+
 double HTMLMediaElement::EffectiveMediaVolume() const {
   if (muted_)
     return 0;
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h
index 26f54fe..18ec6e6 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.h
+++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -250,6 +250,7 @@
   bool muted() const;
   void setMuted(bool);
   virtual bool SupportsPictureInPicture() const { return false; }
+  void SetUserWantsControlsVisible(bool visible);
 
   void TogglePlayState();
 
@@ -750,6 +751,10 @@
 
   bool was_always_muted_ : 1;
 
+  // Set if the user has used the context menu to set the visibility of the
+  // controls.
+  base::Optional<bool> user_wants_controls_visible_;
+
   // Whether or not |web_media_player_| should apply pitch adjustments at
   // playback raters other than 1.0.
   bool preserves_pitch_ = true;
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
index c3a381a..f41966c36 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element_test.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
@@ -324,6 +324,8 @@
     return !!Media()->lazy_load_intersection_observer_;
   }
 
+  bool ControlsVisible() const { return Media()->ShouldShowControls(); }
+
   ExecutionContext* GetExecutionContext() const {
     return dummy_page_holder_->GetFrame().DomWindow();
   }
@@ -1068,4 +1070,36 @@
   EXPECT_TRUE(ReceivedMessageBufferUnderflowEvent());
 }
 
+TEST_P(HTMLMediaElementTest,
+       ControlsVisibilityUserChoiceOverridesControlsAttr) {
+  // Enable scripts to prevent controls being shown due to no scripts.
+  Media()->GetDocument().GetSettings()->SetScriptEnabled(true);
+
+  // Setting the controls attribute to true should show the controls.
+  Media()->SetBooleanAttribute(html_names::kControlsAttr, true);
+  EXPECT_TRUE(ControlsVisible());
+
+  // Setting it to false should hide them.
+  Media()->SetBooleanAttribute(html_names::kControlsAttr, false);
+  EXPECT_FALSE(ControlsVisible());
+
+  // If the user explicitly shows them, that should override the controls
+  // attribute.
+  Media()->SetUserWantsControlsVisible(true);
+  EXPECT_TRUE(ControlsVisible());
+
+  // Setting the controls attribute to false again should do nothing.
+  Media()->SetBooleanAttribute(html_names::kControlsAttr, false);
+  EXPECT_TRUE(ControlsVisible());
+
+  // If the user explicitly hides the controls, that should also override any
+  // controls attribute setting.
+  Media()->SetUserWantsControlsVisible(false);
+  EXPECT_FALSE(ControlsVisible());
+
+  // So setting the controls attribute to true should not show the controls.
+  Media()->SetBooleanAttribute(html_names::kControlsAttr, true);
+  EXPECT_FALSE(ControlsVisible());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index 83d2a5a..e82d18719 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -1230,7 +1230,7 @@
     if (worker_global_scope_) {
       context = worker_global_scope_.Get();
     } else if (loader && loader->GetFrame()) {
-      context = loader->GetFrame()->GetDocument()->ExecutingWindow();
+      context = loader->GetFrame()->GetDocument()->domWindow();
     }
     String stack_id =
         RequestDebugHeaderScope::CaptureStackIdForCurrentLocation(context);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index 185a4d75..c7529c94 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -99,21 +99,25 @@
     const ComputedStyle& style,
     const NGBoxStrut& border_padding,
     const base::Optional<MinMaxSizes>& min_max_sizes,
-    const Length& length) {
+    const Length& length,
+    LayoutUnit available_inline_size_adjustment) {
   DCHECK_EQ(constraint_space.GetWritingMode(), style.GetWritingMode());
 
   switch (length.GetType()) {
     case Length::kFillAvailable: {
       DCHECK_GE(constraint_space.AvailableSize().inline_size, LayoutUnit());
-      LayoutUnit content_size = constraint_space.AvailableSize().inline_size;
-      NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
+      const LayoutUnit available_size =
+          (constraint_space.AvailableSize().inline_size -
+           available_inline_size_adjustment)
+              .ClampNegativeToZero();
+      const NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
       return std::max(border_padding.InlineSum(),
-                      content_size - margins.InlineSum());
+                      available_size - margins.InlineSum());
     }
     case Length::kPercent:
     case Length::kFixed:
     case Length::kCalculated: {
-      LayoutUnit percentage_resolution_size =
+      const LayoutUnit percentage_resolution_size =
           constraint_space.PercentageResolutionInlineSize();
       DCHECK(length.IsFixed() || percentage_resolution_size != kIndefiniteSize);
       LayoutUnit value =
@@ -141,9 +145,11 @@
         value = min_max_sizes->max_size;
       } else {
         DCHECK_GE(available_size, LayoutUnit());
+        available_size = (available_size - available_inline_size_adjustment)
+                             .ClampNegativeToZero();
         NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
         LayoutUnit fill_available =
-            std::max(LayoutUnit(), available_size - margins.InlineSum());
+            (available_size - margins.InlineSum()).ClampNegativeToZero();
         value = min_max_sizes->ShrinkToFit(fill_available);
       }
       return value;
@@ -174,17 +180,18 @@
   switch (length.GetType()) {
     case Length::kFillAvailable: {
       DCHECK_GE(constraint_space.AvailableSize().block_size, LayoutUnit());
-      LayoutUnit available_size = (constraint_space.AvailableSize().block_size -
-                                   available_block_size_adjustment)
-                                      .ClampNegativeToZero();
-      NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
+      const LayoutUnit available_size =
+          (constraint_space.AvailableSize().block_size -
+           available_block_size_adjustment)
+              .ClampNegativeToZero();
+      const NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
       return std::max(border_padding.BlockSum(),
                       available_size - margins.BlockSum());
     }
     case Length::kPercent:
     case Length::kFixed:
     case Length::kCalculated: {
-      LayoutUnit percentage_resolution_size =
+      const LayoutUnit percentage_resolution_size =
           opt_percentage_resolution_block_size_for_min_max
               ? *opt_percentage_resolution_block_size_for_min_max
               : constraint_space.PercentageResolutionBlockSize();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
index 09c6af6..da5de37 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
@@ -68,12 +68,13 @@
 //  - |border_padding| the resolved border, and padding of the node.
 //  - |MinMaxSizes| is only used when the length is intrinsic (fit-content).
 //  - |Length| is the length to resolve.
-CORE_EXPORT LayoutUnit
-ResolveInlineLengthInternal(const NGConstraintSpace&,
-                            const ComputedStyle&,
-                            const NGBoxStrut& border_padding,
-                            const base::Optional<MinMaxSizes>&,
-                            const Length&);
+CORE_EXPORT LayoutUnit ResolveInlineLengthInternal(
+    const NGConstraintSpace&,
+    const ComputedStyle&,
+    const NGBoxStrut& border_padding,
+    const base::Optional<MinMaxSizes>&,
+    const Length&,
+    LayoutUnit available_inline_size_adjustment = LayoutUnit());
 
 // Same as ResolveInlineLengthInternal, except here |intrinsic_size| roughly
 // plays the part of |MinMaxSizes|.
@@ -94,7 +95,8 @@
     const ComputedStyle& style,
     const NGBoxStrut& border_padding,
     const MinMaxSizesFunc& min_max_sizes_func,
-    const Length& length) {
+    const Length& length,
+    LayoutUnit available_inline_size_adjustment = LayoutUnit()) {
   if (LIKELY(length.IsAuto() ||
              InlineLengthUnresolvable(constraint_space, length)))
     return border_padding.InlineSum();
@@ -108,7 +110,8 @@
   }
 
   return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length);
+                                     min_max_sizes, length,
+                                     available_inline_size_adjustment);
 }
 
 template <>
@@ -117,13 +120,15 @@
     const ComputedStyle& style,
     const NGBoxStrut& border_padding,
     const base::Optional<MinMaxSizes>& min_max_sizes,
-    const Length& length) {
+    const Length& length,
+    LayoutUnit available_inline_size_adjustment) {
   if (LIKELY(length.IsAuto() ||
              InlineLengthUnresolvable(constraint_space, length)))
     return border_padding.InlineSum();
 
   return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length);
+                                     min_max_sizes, length,
+                                     available_inline_size_adjustment);
 }
 
 // Used for resolving max inline lengths, (|ComputedStyle::MaxLogicalWidth|).
@@ -133,7 +138,8 @@
     const ComputedStyle& style,
     const NGBoxStrut& border_padding,
     const MinMaxSizesFunc& min_max_sizes_func,
-    const Length& length) {
+    const Length& length,
+    LayoutUnit available_inline_size_adjustment = LayoutUnit()) {
   if (LIKELY(length.IsNone() ||
              InlineLengthUnresolvable(constraint_space, length)))
     return LayoutUnit::Max();
@@ -147,7 +153,8 @@
   }
 
   return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length);
+                                     min_max_sizes, length,
+                                     available_inline_size_adjustment);
 }
 
 template <>
@@ -156,13 +163,15 @@
     const ComputedStyle& style,
     const NGBoxStrut& border_padding,
     const base::Optional<MinMaxSizes>& min_max_sizes,
-    const Length& length) {
+    const Length& length,
+    LayoutUnit available_inline_size_adjustment) {
   if (LIKELY(length.IsNone() ||
              InlineLengthUnresolvable(constraint_space, length)))
     return LayoutUnit::Max();
 
   return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length);
+                                     min_max_sizes, length,
+                                     available_inline_size_adjustment);
 }
 
 // Used for resolving main inline lengths, (|ComputedStyle::LogicalWidth|).
@@ -172,7 +181,8 @@
     const ComputedStyle& style,
     const NGBoxStrut& border_padding,
     const MinMaxSizesFunc& min_max_sizes_func,
-    const Length& length) {
+    const Length& length,
+    LayoutUnit available_inline_size_adjustment = LayoutUnit()) {
   DCHECK(!length.IsAuto());
   base::Optional<MinMaxSizes> min_max_sizes;
   if (length.IsContentOrIntrinsic()) {
@@ -183,7 +193,8 @@
   }
 
   return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length);
+                                     min_max_sizes, length,
+                                     available_inline_size_adjustment);
 }
 
 template <>
@@ -192,10 +203,12 @@
     const ComputedStyle& style,
     const NGBoxStrut& border_padding,
     const base::Optional<MinMaxSizes>& min_max_sizes,
-    const Length& length) {
+    const Length& length,
+    LayoutUnit available_inline_size_adjustment) {
   DCHECK(!length.IsAuto());
   return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length);
+                                     min_max_sizes, length,
+                                     available_inline_size_adjustment);
 }
 
 // Used for resolving min block lengths, (|ComputedStyle::MinLogicalHeight|).
diff --git a/third_party/blink/renderer/core/layout/svg/OWNERS b/third_party/blink/renderer/core/layout/svg/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/renderer/core/layout/svg/OWNERS
+++ /dev/null
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 8b5105b..4518bd22 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -126,6 +126,7 @@
 namespace blink {
 
 namespace {
+
 Vector<OriginTrialFeature> CopyInitiatorOriginTrials(
     const WebVector<int>& initiator_origin_trial_features) {
   Vector<OriginTrialFeature> result;
@@ -1724,6 +1725,52 @@
   }
 }
 
+Frame* DocumentLoader::CalculateOwnerFrame() {
+  // For "about:srcdoc", the parent is the owner frame.
+  if (url_.IsAboutSrcdocURL())
+    return frame_->Tree().Parent();
+
+  // Consider the parent or the opener for 1) about:blank" and 2) the initial
+  // empty document.
+  DCHECK(url_.IsAboutBlankURL() || url_.IsEmpty()) << "url_ = " << url_;
+  Frame* owner_frame = frame_->Tree().Parent();
+  if (!owner_frame)
+    owner_frame = frame_->Loader().Opener();
+
+  // No other checks are needed for the initial empty document.
+  if (url_.IsEmpty())
+    return owner_frame;
+
+  // For about:blank the owner frame should be the actual initiator/requestor of
+  // the navigation - see:
+  // https://html.spec.whatwg.org/multipage/browsers.html#determining-the-origin
+  //
+  // This requires a few extra checks below.
+  DCHECK(url_.IsAboutBlankURL());
+
+  // Browser-initiated navigations to about:blank should always commit with an
+  // opaque origin (i.e. they should not inherit the origin and other properties
+  // of the `owner_frame`).
+  if (!requestor_origin_)
+    return nullptr;
+
+  // The parent-or-owner heuristic above might not find the actual initiator of
+  // the navigation (e.g. see the SameSiteSiblingToAboutBlank_CrossSiteTop
+  // testcase).  To limit (but not eliminate :-/) incorrect cases we require
+  // that `owner_frame`'s origin is same origin with `requestor_origin_`.
+  //
+  // TODO(https://crbug.com/1176291): Improve heuristics for finding the
+  // correct initiator, to properly inherit/alias `document.domain` in more
+  // cases.
+  if (owner_frame &&
+      owner_frame->GetSecurityContext()->GetSecurityOrigin()->IsSameOriginWith(
+          requestor_origin_.get())) {
+    return owner_frame;
+  } else {
+    return nullptr;
+  }
+}
+
 scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
     Document* owner_document) {
   scoped_refptr<SecurityOrigin> origin;
@@ -2037,33 +2084,9 @@
   // Calculate `owner_document` from which the committing navigation should
   // inherit the cookie URL and inherit/alias the SecurityOrigin.
   if (Document::ShouldInheritSecurityOriginFromOwner(Url())) {
-    // Base `owner_frame` on parent-or-opener heuristic.
-    Frame* owner_frame = frame_->Tree().Parent();
-    if (!owner_frame && !url_.IsAboutSrcdocURL())
-      owner_frame = frame_->Loader().Opener();
-
-    // `owner_document` has to come from a local frame and
-    // 1) for "about:srcdoc" has to be the parent
-    // 2) for other cases ("about:blank" and initial empty document) has to be
-    //    the initiator/requestor of the navigation - see:
-    //    https://html.spec.whatwg.org/multipage/browsers.html#determining-the-origin
-    // The parent-or-owner heuristic above might not find the actual initiator
-    // of the navigation in the 2nd case (e.g. see the
-    // SameSiteSiblingToAboutBlank_CrossSiteTop testcase).  To limit (but not
-    // eliminate :-/) incorrect cases we require that `owner_document`'s origin
-    // is same origin with `requestor_origin`.
-    //
-    // TODO(https://crbug.com/1176291): Improve heuristics for finding the
-    // correct initiator, to properly inherit/alias `document.domain` in more
-    // cases.
-    auto* owner_local_frame = DynamicTo<LocalFrame>(owner_frame);
-    if (owner_local_frame &&
-        (url_.IsAboutSrcdocURL() || !requestor_origin_ ||
-         owner_local_frame->GetSecurityContext()
-             ->GetSecurityOrigin()
-             ->IsSameOriginWith(requestor_origin_.get()))) {
+    Frame* owner_frame = CalculateOwnerFrame();
+    if (auto* owner_local_frame = DynamicTo<LocalFrame>(owner_frame))
       owner_document = owner_local_frame->GetDocument();
-    }
   }
 
   LocalDOMWindow* previous_window = frame_->DomWindow();
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h
index d901201..aa20a07 100644
--- a/third_party/blink/renderer/core/loader/document_loader.h
+++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -86,6 +86,7 @@
 class ContentSecurityPolicy;
 class Document;
 class DocumentParser;
+class Frame;
 class FrameLoader;
 class HistoryItem;
 class LocalDOMWindow;
@@ -368,6 +369,7 @@
   Member<MHTMLArchive> archive_;
 
  private:
+  Frame* CalculateOwnerFrame();
   scoped_refptr<SecurityOrigin> CalculateOrigin(Document* owner_document);
   void InitializeWindow(Document* owner_document);
   void DidInstallNewDocument(Document*);
diff --git a/third_party/blink/renderer/core/mojo/OWNERS b/third_party/blink/renderer/core/mojo/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/renderer/core/mojo/OWNERS
+++ /dev/null
diff --git a/third_party/blink/renderer/core/paint/compositing/OWNERS b/third_party/blink/renderer/core/paint/compositing/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/renderer/core/paint/compositing/OWNERS
+++ /dev/null
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc
index e5792f3..6c67597 100644
--- a/third_party/blink/renderer/core/script/script_loader.cc
+++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -338,7 +338,7 @@
     return false;
 
   Document& element_document = element_->GetDocument();
-  LocalDOMWindow* context_window = element_document.ExecutingWindow();
+  LocalDOMWindow* context_window = element_document.domWindow();
 
   // <spec step="7">... Determine the script's type as follows: ...</spec>
   script_type_ = GetScriptTypeAtPrepare(element_->TypeAttributeValue(),
diff --git a/third_party/blink/renderer/core/svg/OWNERS b/third_party/blink/renderer/core/svg/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/renderer/core/svg/OWNERS
+++ /dev/null
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index 3cfe52f5..3bcdf6c 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -174,6 +174,9 @@
   // A list item is presentational if its parent is a native list but
   // it has an explicit ARIA role set on it that's anything other than "list".
   Element* parent = FlatTreeTraversal::ParentElement(*node);
+  if (!parent)
+    return false;
+
   if (IsA<HTMLMenuElement>(*parent) || IsA<HTMLUListElement>(*parent) ||
       IsA<HTMLOListElement>(*parent)) {
     AtomicString role = AccessibleNode::GetPropertyOrARIAAttribute(
diff --git a/third_party/blink/renderer/modules/crypto/OWNERS b/third_party/blink/renderer/modules/crypto/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/renderer/modules/crypto/OWNERS
+++ /dev/null
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser.cc b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
index 4e28f5b..4d0e9dc 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
@@ -32,6 +32,9 @@
 namespace {
 
 static constexpr char kUrlHandlerWildcardPrefix[] = "%2A.";
+// Keep in sync with web_app_origin_association_task.cc.
+static wtf_size_t kMaxUrlHandlersSize = 10;
+static wtf_size_t kMaxOriginLength = 2000;
 
 bool IsValidMimeType(const String& mime_type) {
   if (mime_type.StartsWith('.'))
@@ -1074,6 +1077,14 @@
     return url_handlers;
   }
   for (wtf_size_t i = 0; i < handlers_list->size(); ++i) {
+    if (i == kMaxUrlHandlersSize) {
+      AddErrorInfo("property 'url_handlers' contains more than " +
+                   String::Number(kMaxUrlHandlersSize) +
+                   " valid elements, only the first " +
+                   String::Number(kMaxUrlHandlersSize) + " are parsed.");
+      break;
+    }
+
     const JSONObject* handler_object = JSONObject::Cast(handlers_list->at(i));
     if (!handler_object) {
       AddErrorInfo("url_handlers entry ignored, type object expected.");
@@ -1112,6 +1123,14 @@
   // assume the use of https for URL handling. Remove this TODO if we decide
   // to require fully specified https scheme in this origin input.
 
+  if (origin_string->length() > kMaxOriginLength) {
+    AddErrorInfo(
+        "url_handlers entry ignored, 'origin' exceeds maximum character length "
+        "of " +
+        String::Number(kMaxOriginLength) + " .");
+    return base::nullopt;
+  }
+
   auto origin = SecurityOrigin::CreateFromString(*origin_string);
   if (!origin || origin->IsOpaque()) {
     AddErrorInfo(
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
index 8af7f34..b458421 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
@@ -2711,6 +2711,60 @@
             ->IsSameOriginWith(url_handlers[0]->origin.get()));
     ASSERT_FALSE(url_handlers[0]->has_origin_wildcard);
   }
+
+  // Validate only the first 10 handlers are parsed.
+  {
+    auto& manifest = ParseManifest(
+        "{"
+        "  \"url_handlers\": ["
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8001\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8002\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8003\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8004\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8005\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8006\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8007\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8008\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8009\""
+        "    },"
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8010\""
+        "    },"
+        // 10 handlers above, this one should not be in the result.
+        "    {"
+        "      \"origin\": \"https://192.168.0.1:8011\""
+        "    }"
+        "  ]"
+        "}");
+    auto& url_handlers = manifest->url_handlers;
+
+    ASSERT_EQ(1u, GetErrorCount());
+    EXPECT_EQ(
+        "property 'url_handlers' contains more than 10 valid elements, "
+        "only the first 10 are parsed.",
+        errors()[0]);
+    ASSERT_EQ(10u, url_handlers.size());
+    ASSERT_TRUE(
+        blink::SecurityOrigin::CreateFromString("https://192.168.0.1:8010")
+            ->IsSameOriginWith(url_handlers[9]->origin.get()));
+  }
 }
 
 TEST_F(ManifestParserTest, ShareTargetParseRules) {
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc b/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
index 12643b4..9529996 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
+++ b/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
@@ -4,10 +4,13 @@
 
 #include "third_party/blink/renderer/modules/webcodecs/audio_encoder.h"
 
+#include <limits>
+
 #include "base/numerics/safe_conversions.h"
 #include "media/audio/audio_opus_encoder.h"
 #include "media/base/audio_parameters.h"
 #include "media/base/limits.h"
+#include "media/base/mime_util.h"
 #include "media/base/offloading_audio_encoder.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_decoder_config.h"
@@ -22,41 +25,105 @@
 namespace blink {
 
 namespace {
+
 AudioEncoderTraits::ParsedConfig* ParseConfigStatic(
-    const AudioEncoderConfig* opts,
+    const AudioEncoderConfig* config,
     ExceptionState& exception_state) {
+  if (!config) {
+    exception_state.ThrowTypeError("No config provided");
+    return nullptr;
+  }
   auto* result = MakeGarbageCollected<AudioEncoderTraits::ParsedConfig>();
-  if (opts->codec().Utf8() == "opus") {
-    result->codec = media::kCodecOpus;
-  } else {
+
+  result->codec = media::kUnknownAudioCodec;
+  bool is_codec_ambiguous = true;
+  bool parse_succeeded = ParseAudioCodecString(
+      "", config->codec().Utf8(), &is_codec_ambiguous, &result->codec);
+
+  if (!parse_succeeded || is_codec_ambiguous) {
     exception_state.ThrowTypeError("Unknown codec.");
     return nullptr;
   }
-  result->options.channels = opts->numberOfChannels();
-  if (result->options.channels > media::limits::kMaxChannels) {
-    exception_state.ThrowTypeError("Too many channels.");
+
+  result->options.channels = config->numberOfChannels();
+  if (result->options.channels < 1 ||
+      result->options.channels > media::limits::kMaxChannels) {
+    exception_state.ThrowTypeError(String::Format(
+        "Invalid channel number; expected range from %d to %d, received %d.", 1,
+        media::limits::kMaxChannels, result->options.channels));
     return nullptr;
   }
 
-  result->options.sample_rate = opts->sampleRate();
-  result->codec_string = opts->codec();
-  if (opts->hasBitrate()) {
-    if (!base::IsValueInRangeForNumericType<int>(opts->bitrate())) {
-      exception_state.ThrowTypeError("Invalid bitrate.");
+  result->options.sample_rate = config->sampleRate();
+  if (result->options.sample_rate < media::limits::kMinSampleRate ||
+      result->options.sample_rate > media::limits::kMaxSampleRate) {
+    exception_state.ThrowTypeError(String::Format(
+        "Invalid sample rate; expected range from %d to %d, received %d.",
+        media::limits::kMinSampleRate, media::limits::kMaxSampleRate,
+        result->options.sample_rate));
+    return nullptr;
+  }
+
+  result->codec_string = config->codec();
+  if (config->hasBitrate()) {
+    if (config->bitrate() > std::numeric_limits<int>::max()) {
+      exception_state.ThrowTypeError(String::Format(
+          "Bitrate is too large; expected at most %d, received %" PRIu64,
+          std::numeric_limits<int>::max(), config->bitrate()));
       return nullptr;
     }
-    result->options.bitrate = static_cast<int>(opts->bitrate());
+    result->options.bitrate = static_cast<int>(config->bitrate());
   }
 
-  if (result->options.channels == 0) {
-    exception_state.ThrowTypeError("Invalid channel number.");
-    return nullptr;
-  }
+  return result;
+}
 
-  if (result->options.sample_rate == 0) {
-    exception_state.ThrowTypeError("Invalid sample rate.");
-    return nullptr;
+bool VerifyCodecSupportStatic(AudioEncoderTraits::ParsedConfig* config,
+                              ExceptionState* exception_state) {
+  switch (config->codec) {
+    case media::kCodecOpus: {
+      if (config->options.channels > 2) {
+        // Our Opus implementation only supports up to 2 channels
+        if (exception_state) {
+          exception_state->ThrowDOMException(
+              DOMExceptionCode::kNotSupportedError,
+              String::Format("Too many channels for Opus encoder; "
+                             "expected at most 2, received %d.",
+                             config->options.channels));
+        }
+        return false;
+      }
+      if (config->options.bitrate.has_value() &&
+          config->options.bitrate.value() <
+              media::AudioOpusEncoder::kMinBitrate) {
+        if (exception_state) {
+          exception_state->ThrowDOMException(
+              DOMExceptionCode::kNotSupportedError,
+              String::Format(
+                  "Opus bitrate is too low; expected at least %d, received %d.",
+                  media::AudioOpusEncoder::kMinBitrate,
+                  config->options.bitrate.value()));
+        }
+        return false;
+      }
+      return true;
+    }
+    default:
+      if (exception_state) {
+        exception_state->ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+                                           "Unsupported codec type.");
+      }
+      return false;
   }
+}
+
+AudioEncoderConfig* CopyConfig(const AudioEncoderConfig& config) {
+  auto* result = AudioEncoderConfig::Create();
+  result->setCodec(config.codec());
+  result->setSampleRate(config.sampleRate());
+  result->setNumberOfChannels(config.numberOfChannels());
+  if (config.hasBitrate())
+    result->setBitrate(config.bitrate());
   return result;
 }
 
@@ -229,12 +296,7 @@
 
 bool AudioEncoder::VerifyCodecSupport(ParsedConfig* config,
                                       ExceptionState& exception_state) {
-  if (config->codec != media::kCodecOpus) {
-    exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
-                                      "Unsupported codec type.");
-    return false;
-  }
-  return true;
+  return VerifyCodecSupportStatic(config, &exception_state);
 }
 
 void AudioEncoder::CallOutputCallback(
@@ -283,12 +345,15 @@
 ScriptPromise AudioEncoder::isConfigSupported(ScriptState* script_state,
                                               const AudioEncoderConfig* config,
                                               ExceptionState& exception_state) {
-  if (!ParseConfigStatic(config, exception_state))
+  auto* parsed_config = ParseConfigStatic(config, exception_state);
+  if (!parsed_config) {
+    DCHECK(exception_state.HadException());
     return ScriptPromise();
+  }
 
   auto* support = AudioEncoderSupport::Create();
-  support->setSupported(false);
-  support->setConfig(MakeGarbageCollected<AudioEncoderConfig>());
+  support->setSupported(VerifyCodecSupportStatic(parsed_config, nullptr));
+  support->setConfig(CopyConfig(*config));
   return ScriptPromise::Cast(script_state, ToV8(support, script_state));
 }
 
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl b/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl
index 78ef4c67..ab29c94 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl
+++ b/third_party/blink/renderer/modules/webcodecs/audio_encoder_config.idl
@@ -4,6 +4,8 @@
 
 // https://github.com/WICG/web-codecs
 
+// NOTE: Keep this structure in sync with CopyConfig() defined in
+// audio_encoder.cc.
 dictionary AudioEncoderConfig {
   // TODO(chcunningham): reference spec registry.
   required DOMString codec;
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer.py b/third_party/blink/tools/blinkpy/w3c/test_importer.py
index 2cccdc2..6d1c0679 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -71,8 +71,14 @@
         self.new_test_expectations = {}
         self.verbose = False
 
-        args = ['--clean-up-affected-tests-only',
-                '--clean-up-test-expectations']
+        args = [
+            '--clean-up-affected-tests-only',
+            '--clean-up-test-expectations',
+            # TODO(crbug.com/1196713): Result download needs to migrate away
+            # from test-results.appspot.com before we can resume using
+            # results from CQ builders.
+            '--rebaseline-blink-try-bots-only'
+        ]
         self._expectations_updater = WPTExpectationsUpdater(
             self.host, args, wpt_manifests)
 
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
index 9aa24b9..7a36190 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
@@ -146,6 +146,12 @@
             help='Adds Pass to tests with failure expectations. '
                  'This command line argument can be used to mark tests '
                  'as flaky.')
+        parser.add_argument(
+            '--rebaseline-blink-try-bots-only',
+            action='store_true',
+            help='When set, only rebaselines using the results from blink-rel '
+            'trybots, and ignores CQ bots. By default, both CQ and blink '
+            'bots are used.')
 
     def update_expectations(self):
         """Downloads text new baselines and adds test expectations lines.
@@ -905,6 +911,9 @@
             '--no-trigger-jobs',
             '--fill-missing',
         ]
+        if self.options.rebaseline_blink_try_bots_only:
+            command.append('--use-blink-try-bots-only')
+
         if self.patchset:
             command.append('--patchset=' + str(self.patchset))
         command += tests_to_rebaseline
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 3794958..bc051a9 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -6789,3 +6789,5 @@
 crbug.com/1198098 storage/indexeddb/dispatch-events.html [ Pass Timeout ]
 crbug.com/1198098 storage/indexeddb/key-generator.html [ Pass Timeout ]
 crbug.com/1198103 virtual/scroll-unification/fast/events/drag-and-drop-autoscroll.html [ Pass Timeout ]
+
+crbug.com/1193979 [ Mac ] fast/events/tabindex-focus-blur-all.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/WebGPUExpectations b/third_party/blink/web_tests/WebGPUExpectations
index cfd6cfef..8b03d0e 100644
--- a/third_party/blink/web_tests/WebGPUExpectations
+++ b/third_party/blink/web_tests/WebGPUExpectations
@@ -244,6 +244,7 @@
 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:dimension="3d";* [ Failure ]
 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:format="depth16unorm";* [ Failure ]
 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:format="stencil8";* [ Failure ]
+wpt_internal/webgpu/cts.html?q=webgpu:api,operation,rendering,depth:depth_compare_func:format="depth16unorm";* [ Failure ]
 
 crbug.com/dawn/730 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:texture_usage:dimension="1d";format="depth24plus";* [ Skip ]
 crbug.com/dawn/730 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:texture_usage:dimension="1d";format="depth24plus-stencil8";* [ Skip ]
diff --git a/third_party/blink/web_tests/external/wpt/cors/OWNERS b/third_party/blink/web_tests/external/wpt/cors/OWNERS
deleted file mode 100644
index 8b13789..0000000
--- a/third_party/blink/web_tests/external/wpt/cors/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/third_party/blink/web_tests/external/wpt/css/OWNERS b/third_party/blink/web_tests/external/wpt/css/OWNERS
deleted file mode 100644
index 8b13789..0000000
--- a/third_party/blink/web_tests/external/wpt/css/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/resources/tall.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/resources/tall.html
new file mode 100644
index 0000000..3de84d0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/resources/tall.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<body style="background: blue">
+  <div style="position: fixed; left: 0; top: 0; width: 100%; height: 100px; background: yellow"></div>
+  <div style="position: fixed; left: 0; bottom: 0; width: 100%; height: 100px; background: green"></div>
+  <div style="height: 2000px"></div>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub-ref.html
new file mode 100644
index 0000000..01c1e2f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<html class="reftest-wait">
+<iframe id=myframe style="width: 300px; height: 1000px" src="resources/tall.html"></iframe>
+<div style="height: 2000px"></div>
+<script>
+  window.scrollTo(0, 700);
+  myframe.onload = () => document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub.html
new file mode 100644
index 0000000..43b9d7a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Rendering of tall cross-domain iframe element in a scrolled window</title>
+<link rel="match" href="tall-cross-domain-iframe-in-scrolled.sub-ref.html">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules">
+<meta name="assert" content="Checks that tall cross-domain iframe in a scrolled window is correctly rendered">
+<iframe id=myframe style="width: 300px; height: 1000px"
+    src="http://{{domains[www1]}}:{{ports[http][0]}}/html/rendering/replaced-elements/embedded-content/resources/tall.html"></iframe>
+<div style="height: 2000px"></div>
+<script>
+  window.scrollTo(0, 700);
+  myframe.onload = () => document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/audio-encoder-config.any.js b/third_party/blink/web_tests/external/wpt/webcodecs/audio-encoder-config.any.js
index b7ea8fb..a847473 100644
--- a/third_party/blink/web_tests/external/wpt/webcodecs/audio-encoder-config.any.js
+++ b/third_party/blink/web_tests/external/wpt/webcodecs/audio-encoder-config.any.js
@@ -4,16 +4,126 @@
 const invalidConfigs = [
   {
     comment: 'Emtpy codec',
-    config: {codec: ''},
+    config: { codec: '' },
   },
   {
     comment: 'Unrecognized codec',
-    config: {codec: 'bogus'},
+    config: { codec: 'bogus' },
+  },
+  {
+    comment: 'Sample rate is too small',
+    config: {
+      codec: 'opus',
+      sampleRate: 100,
+      numberOfChannels: 2,
+    },
+  },
+  {
+    comment: 'Sample rate is too large',
+    config: {
+      codec: 'opus',
+      sampleRate: 1e6,
+      numberOfChannels: 2,
+    },
+  },
+  {
+    comment: 'Too few channels',
+    config: {
+      codec: 'opus',
+      sampleRate: 8000,
+      numberOfChannels: 0,
+    },
+  },
+  {
+    comment: 'Way too many channels',
+    config: {
+      codec: 'opus',
+      sampleRate: 8000,
+      numberOfChannels: 100,
+      bitrate: 128000
+    },
+  },
+  {
+    comment: 'Bit rate too big',
+    config: {
+      codec: 'opus',
+      sampleRate: 8000,
+      numberOfChannels: 2,
+      bitrate: 6e9
+    },
   },
 ];
 
 invalidConfigs.forEach(entry => {
   promise_test(t => {
     return promise_rejects_js(t, TypeError, AudioEncoder.isConfigSupported(entry.config));
-  }, 'Test that AudioDecoder.isConfigSupported() rejects invalid config:' + entry.comment);
-});
\ No newline at end of file
+  }, 'Test that AudioEncoder.isConfigSupported() rejects invalid config:' + entry.comment);
+});
+
+const validButUnsupportedConfigs = [
+  {
+    comment: 'Too many channels',
+    config: {
+      codec: 'opus',
+      sampleRate: 48000,
+      numberOfChannels: 30,
+    },
+  },
+  {
+    comment: 'Bitrate is too low',
+    config: {
+      codec: 'opus',
+      sampleRate: 48000,
+      numberOfChannels: 2,
+      bitrate: 1
+    },
+  }
+];
+
+validButUnsupportedConfigs.forEach(entry => {
+  promise_test(async t => {
+    let support = await AudioEncoder.isConfigSupported(entry.config);
+    assert_false(support.supported);
+
+    let config = support.config;
+    assert_equals(config.codec, entry.config.codec);
+    assert_equals(config.sampleRate, entry.config.sampleRate);
+    assert_equals(config.numberOfChannels, entry.config.numberOfChannels);
+
+  }, "Test that AudioEncoder.isConfigSupported() doesn't support config:" + entry.comment);
+});
+
+const validConfigs = [
+  {
+    codec: 'opus',
+    sampleRate: 8000,
+    numberOfChannels: 1,
+  },
+  {
+    codec: 'opus',
+    sampleRate: 48000,
+    numberOfChannels: 2,
+  },
+  {
+    codec: 'opus',
+    sampleRate: 48000,
+    numberOfChannels: 2,
+    bitrate: 128000,
+    bogus: 123
+  },
+];
+
+validConfigs.forEach(config => {
+  promise_test(async t => {
+    let support = await AudioEncoder.isConfigSupported(config);
+    assert_true(support.supported);
+
+    let new_config = support.config;
+    assert_equals(new_config.codec, config.codec);
+    assert_equals(new_config.sampleRate, config.sampleRate);
+    assert_equals(new_config.numberOfChannels, config.numberOfChannels);
+    if (config.bitrate)
+      assert_equals(new_config.bitrate, config.bitrate);
+    assert_false(new_config.hasOwnProperty('bogus'));
+  }, "AudioEncoder.isConfigSupported() supports:" + JSON.stringify(config));
+});
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/audio-encoder.any.js b/third_party/blink/web_tests/external/wpt/webcodecs/audio-encoder.any.js
index 610c2b7d..2aece5d0 100644
--- a/third_party/blink/web_tests/external/wpt/webcodecs/audio-encoder.any.js
+++ b/third_party/blink/web_tests/external/wpt/webcodecs/audio-encoder.any.js
@@ -90,9 +90,13 @@
       outputs++;
     }
   };
-
   let encoder = new AudioEncoder(init);
 
+
+  let support = await AudioEncoder.isConfigSupported(config);
+  assert_true(support.supported)
+  config = support.config;
+
   encoder.configure(config);
   for (let frame of good_frames) {
     encoder.encode(frame);
@@ -111,7 +115,7 @@
 
 function channelNumberVariationTests() {
   let sample_rate = 48000;
-  for (let channels = 1; channels < 12; channels++) {
+  for (let channels = 1; channels <= 2; channels++) {
     let config = {
       codec: 'opus',
       sampleRate: sample_rate,
diff --git a/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl b/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl
new file mode 100644
index 0000000..f6ffae1
--- /dev/null
+++ b/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl
@@ -0,0 +1,48 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is a .pyl, or "Python Literal", file. You can treat it just like a
+# .json file, with the following exceptions:
+# * all keys must be quoted (use single quotes, please);
+# * comments are allowed, using '#' syntax; and
+# * trailing commas are allowed.
+
+# This is a list of manual test splits for the WebGPU CTS. They are added to workaround timeouts in the CTS due to
+# large combinatoric tests with many parameterizations.
+# Specifying a query will cause the parent of the the specified subtree to the expanded into separate WPT variants.
+# For example, 'webgpu:some,path,to,file:foo:bar=2;*' will generate a variant for all values of bar.
+
+[
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,validation,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_format,*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc1-rgba-unorm";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc1-rgba-unorm";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8unorm";*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="CopyToBuffer";format="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="CopyToTexture";format="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="Sample";format="rgba8unorm";*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:shader,execution,robust_access_vertex:vertexAccess:indexed=false;indirect=false;*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:shader,execution,robust_access_vertex:vertexAccess:indexed=true;indirect=false;*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0033:variableOrConstant="var";lhsContainerType="_undef_";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0033:variableOrConstant="const";lhsContainerType="_undef_";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0038:storageClass="in";containerType="_undef_";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0038:storageClass="out";containerType="_undef_";*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0038:storageClass="private";containerType="_undef_";*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:dimension="1d";*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:texture_size,default_value_and_smallest_size,*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:texture_usage:dimension="1d";*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=0;*',
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=0;*',
+
+  'wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="DepthTest";format="depth32float";*',
+]
diff --git a/third_party/blink/web_tests/webgpu/internal_cts_test_splits.txt b/third_party/blink/web_tests/webgpu/internal_cts_test_splits.txt
deleted file mode 100644
index a4f1c5e5..0000000
--- a/third_party/blink/web_tests/webgpu/internal_cts_test_splits.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm";*
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_format,*
-
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc1-rgba-unorm";*
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc1-rgba-unorm";*
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8unorm";*
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8unorm";*
-
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="CopyToBuffer";format="rgba8unorm";*
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="CopyToTexture";format="rgba8unorm";*
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="Sample";format="rgba8unorm";*
-
-wpt_internal/webgpu/cts.html?q=webgpu:shader,execution,robust_access_vertex:vertexAccess:indexed=false;indirect=false;*
-wpt_internal/webgpu/cts.html?q=webgpu:shader,execution,robust_access_vertex:vertexAccess:indexed=true;indirect=false;*
-
-wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0033:variableOrConstant="var";lhsContainerType="_undef_";*
-wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0033:variableOrConstant="const";lhsContainerType="_undef_";*
-wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0038:storageClass="in";containerType="_undef_";*
-wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0038:storageClass="out";containerType="_undef_";*
-wpt_internal/webgpu/cts.html?q=webgpu:shader,validation,variable_and_const:v_0038:storageClass="private";containerType="_undef_";*
-
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:dimension="1d";*
-
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:texture_size,default_value_and_smallest_size,*
-
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createTexture:texture_usage:dimension="1d";*
-
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=0;*
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,rendering,draw:arguments:first=3;count=0;*
-
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="DepthTest";format="depth32float";*
diff --git a/third_party/blink/web_tests/webgpu/regenerate_internal_cts_html.sh b/third_party/blink/web_tests/webgpu/regenerate_internal_cts_html.sh
deleted file mode 100755
index 3d63932c..0000000
--- a/third_party/blink/web_tests/webgpu/regenerate_internal_cts_html.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/bash
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This tool regenerates `wpt_internal/webgpu/cts.html` using the currently
-# checked-out version of the WebGPU CTS. It does the following:
-#
-#   - Extracts the "name" part of every expectation from WebGPUExpectations.
-#   - Transpiles the WebGPU checkout into a tmp directory to run the
-#     gen_wpt_cts_html tool.
-#   - Runs gen_wpt_cts_html with the appropriate metadata and the extracted
-#     expectations names. This generates a cts.html file with the necessary
-#     variants to cover the expectations in WebGPUExpectations.
-#
-# Note: If it fails, it's likely that updates are needed to make
-# WebGPUExpectations match the latest CTS (e.g. perhaps test/case names or
-# parameters have changed). Consult the error message for details.
-
-set -e
-
-cd "$(dirname "$0")"/../../../..  # cd to [chromium]/src/
-
-expectations=$(mktemp)
-out_dir=$(mktemp -d)
-out_cts_html=$(realpath $(dirname "$0")/../wpt_internal/webgpu/cts.html)
-
-echo "Expectations names: $expectations"
-echo "JS output dir: $out_dir"
-echo "Output CTS html: $out_cts_html"
-
-function check_output() {
-  if [ ! -f $out_cts_html ]; then
-    echo "Failed to generate $out_cts_html"
-    exit 1
-  fi
-}
-
-function cleanup() {
-  rm -f $expectations
-  rm -rf $out_dir
-  check_output
-}
-
-trap cleanup EXIT
-
-rm -f $out_cts_html
-
-echo 'Extracting expectation names...'
-third_party/webgpu-cts/scripts/extract_expectation_names_for_variant_generation.py \
-    third_party/blink/web_tests/WebGPUExpectations > $expectations
-
-cat third_party/blink/web_tests/webgpu/internal_cts_test_splits.txt >> $expectations
-
-pushd third_party/webgpu-cts/src > /dev/null
-
-  echo 'Transpiling WebGPU CTS...'
-  ../scripts/tsc_ignore_errors.py \
-    --project node.tsconfig.json \
-    --outDir $out_dir \
-    --noEmit false \
-    --declaration false \
-    --sourceMap false
-
-  echo 'Regenerating cts.html...'
-  ../../node/node.py $out_dir/common/tools/gen_wpt_cts_html.js \
-    $out_cts_html \
-    ../../blink/web_tests/webgpu/ctshtml-template.txt \
-    ../../blink/web_tests/webgpu/argsprefixes.txt \
-    $expectations \
-    'wpt_internal/webgpu/cts.html' webgpu
-
-popd > /dev/null
-
-check_output
diff --git a/third_party/blink/web_tests/webgpu/roll_webgpu_cts.sh b/third_party/blink/web_tests/webgpu/roll_webgpu_cts.sh
index 26df1527..99d91747d 100755
--- a/third_party/blink/web_tests/webgpu/roll_webgpu_cts.sh
+++ b/third_party/blink/web_tests/webgpu/roll_webgpu_cts.sh
@@ -54,7 +54,7 @@
 ********************************************************************
 Roll complete!
 
-Remember to run ./regenerate_internal_cts_html.sh.
+Remember to run regenerate_internal_cts_html.py.
 Updates to WebGPUExpectations may be necessary to make it succeed.
 
 Further updates to WebGPUExpectations may be needed to pass the
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/cts.html b/third_party/blink/web_tests/wpt_internal/webgpu/cts.html
index 826c4fcf..cfc31c1 100644
--- a/third_party/blink/web_tests/wpt_internal/webgpu/cts.html
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/cts.html
@@ -159,6 +159,7 @@
 <meta name=variant content='?q=webgpu:api,operation,render_pipeline,culling_tests:*'>
 <meta name=variant content='?q=webgpu:api,operation,render_pipeline,primitive_topology:*'>
 <meta name=variant content='?q=webgpu:api,operation,rendering,basic:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth:*'>
 <meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=0;*'>
 <meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=3;*'>
 <meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:first=0;count=6;*'>
diff --git a/third_party/closure_compiler/externs/activity_log_private.js b/third_party/closure_compiler/externs/activity_log_private.js
index 669ee0df..eb1441f 100644
--- a/third_party/closure_compiler/externs/activity_log_private.js
+++ b/third_party/closure_compiler/externs/activity_log_private.js
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -128,7 +128,7 @@
 
 /**
  * Delete URLs in the ActivityLog database.
- * @param {!Array<string>=} urls Erases only the URLs listed; if empty, erases
+ * @param {!Array<string>} urls Erases only the URLs listed; if empty, erases
  *     all URLs.
  */
 chrome.activityLogPrivate.deleteUrls = function(urls) {};
diff --git a/third_party/libjingle_xmpp/task_runner/OWNERS b/third_party/libjingle_xmpp/task_runner/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/libjingle_xmpp/task_runner/OWNERS
+++ /dev/null
diff --git a/third_party/libjingle_xmpp/xmllite/OWNERS b/third_party/libjingle_xmpp/xmllite/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/libjingle_xmpp/xmllite/OWNERS
+++ /dev/null
diff --git a/third_party/libjingle_xmpp/xmpp/OWNERS b/third_party/libjingle_xmpp/xmpp/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/third_party/libjingle_xmpp/xmpp/OWNERS
+++ /dev/null
diff --git a/third_party/webgpu-cts/PRESUBMIT.py b/third_party/webgpu-cts/PRESUBMIT.py
index 0af3d155..fca19ab 100644
--- a/third_party/webgpu-cts/PRESUBMIT.py
+++ b/third_party/webgpu-cts/PRESUBMIT.py
@@ -6,18 +6,25 @@
 
 import sys
 
-
 def CheckChangeOnUpload(input_api, output_api):
+    results = []
     old_sys_path = sys.path
     try:
         sys.path = [
             input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')
         ] + sys.path
-        from gen_ts_dep_lists import get_ts_sources
-        expected_ts_sources = get_ts_sources()
+
+        results.extend(_CheckTsSources(input_api, output_api))
+        results.extend(_CheckCTSHtml(input_api, output_api))
     finally:
         sys.path = old_sys_path
 
+    return results
+
+def _CheckTsSources(input_api, output_api):
+    from gen_ts_dep_lists import get_ts_sources
+    expected_ts_sources = get_ts_sources()
+
     ts_sources = input_api.ReadFile(
         input_api.os_path.join(input_api.PresubmitLocalPath(),
                                'ts_sources.txt')).split()
@@ -30,3 +37,21 @@
         ]
 
     return []
+
+
+def _CheckCTSHtml(input_api, output_api):
+    from regenerate_internal_cts_html import generate_internal_cts_html
+    expected_contents = generate_internal_cts_html()
+
+    cts_html = input_api.os_path.join(input_api.change.RepositoryRoot(),
+                                      'third_party', 'blink', 'web_tests',
+                                      'wpt_internal', 'webgpu', 'cts.html')
+    with open(cts_html, 'rb') as f:
+        if f.read() != expected_contents:
+            return [
+                output_api.PresubmitError(
+                    '%s out of date. Please run //third_party/webgpu-cts/scripts/regenerate_internal_cts_html.py.'
+                    % cts_html)
+            ]
+    return []
+
diff --git a/third_party/webgpu-cts/scripts/extract_expectation_names_for_variant_generation.py b/third_party/webgpu-cts/scripts/extract_expectation_names_for_variant_generation.py
deleted file mode 100755
index 6c861f0d..0000000
--- a/third_party/webgpu-cts/scripts/extract_expectation_names_for_variant_generation.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env vpython
-#
-# 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.
-#
-# Given an expectations file (e.g. web_tests/WebGPUExpectations), extracts only
-# the test name from each expectation (e.g. wpt_internal/webgpu/cts.html?...).
-
-from os import path as os_path
-import sys
-
-try:
-    old_sys_path = sys.path
-    third_party_dir = os_path.dirname(
-        os_path.dirname(os_path.dirname(os_path.abspath(__file__))))
-    sys.path = old_sys_path + [os_path.join(third_party_dir, 'blink', 'tools')]
-
-    from run_webgpu_cts import split_cts_expectations_and_web_test_expectations
-finally:
-    sys.path = old_sys_path
-
-filename = sys.argv[1]
-with open(filename) as f:
-    expectations = split_cts_expectations_and_web_test_expectations(
-        f.read())['web_test_expectations']['expectations']
-    for expectation in expectations:
-        if expectation.test:
-            print(expectation.test)
diff --git a/third_party/webgpu-cts/scripts/regenerate_internal_cts_html.py b/third_party/webgpu-cts/scripts/regenerate_internal_cts_html.py
new file mode 100755
index 0000000..26cb332
--- /dev/null
+++ b/third_party/webgpu-cts/scripts/regenerate_internal_cts_html.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env vpython
+# Copyright 2021 The Chromium Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import ast
+import tempfile
+import os
+import shutil
+import subprocess
+import sys
+
+third_party_dir = os.path.dirname(
+    os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+
+def generate_internal_cts_html():
+    split_list_fd, split_list_fname = tempfile.mkstemp()
+    cts_html_fd, cts_html_fname = tempfile.mkstemp()
+    js_out_dir = tempfile.mkdtemp()
+    try:
+        print('WebGPU CTS: Extracting expectation names...')
+        old_sys_path = sys.path
+        try:
+            sys.path = old_sys_path + [
+                os.path.join(third_party_dir, 'blink', 'tools')
+            ]
+
+            from run_webgpu_cts import split_cts_expectations_and_web_test_expectations
+        finally:
+            sys.path = old_sys_path
+
+        with open(
+                os.path.join(third_party_dir, 'blink', 'web_tests',
+                             'WebGPUExpectations')) as f:
+            web_test_expectations = split_cts_expectations_and_web_test_expectations(
+                f.read())['web_test_expectations']['expectations']
+
+        print('WebGPU CTS: Reading manual test splits...')
+        with open(
+                os.path.join(third_party_dir, 'blink', 'web_tests', 'webgpu',
+                             'internal_cts_test_splits.pyl')) as f:
+            manual_splits = ast.literal_eval(f.read())
+
+        with open(split_list_fname, 'w') as split_list_out:
+            for expectation in web_test_expectations:
+                if expectation.test:
+                    split_list_out.write('%s\n' % expectation.test)
+            for test in manual_splits:
+                split_list_out.write('%s\n' % test)
+
+        print('WebGPU CTS: Transpiling tools...')
+        cmd = [
+            '../scripts/tsc_ignore_errors.py',
+            '--project',
+            'node.tsconfig.json',
+            '--outDir',
+            js_out_dir,
+            '--noEmit',
+            'false',
+            '--declaration',
+            'false',
+            '--sourceMap',
+            'false',
+        ]
+        process = subprocess.Popen(cmd,
+                                   cwd=os.path.join(third_party_dir,
+                                                    'webgpu-cts', 'src'))
+        process.communicate()
+
+        print('WebGPU CTS: Generating cts.html contents...')
+        cmd = [
+            os.path.join(third_party_dir, 'node', 'node.py'),
+            os.path.join(js_out_dir,
+                         'common/tools/gen_wpt_cts_html.js'), cts_html_fname,
+            os.path.join(third_party_dir, 'blink', 'web_tests', 'webgpu',
+                         'ctshtml-template.txt'),
+            os.path.join(third_party_dir, 'blink', 'web_tests', 'webgpu',
+                         'argsprefixes.txt'), split_list_fname,
+            'wpt_internal/webgpu/cts.html', 'webgpu'
+        ]
+        process = subprocess.Popen(cmd)
+        process.communicate()
+
+        with open(cts_html_fname) as f:
+            return f.read()
+
+    finally:
+        os.close(split_list_fd)
+        os.close(cts_html_fd)
+        shutil.rmtree(js_out_dir)
+
+
+if __name__ == '__main__':
+    out_cts_html = os.path.join(third_party_dir, 'blink', 'web_tests',
+                                'wpt_internal', 'webgpu', 'cts.html')
+    contents = generate_internal_cts_html()
+    if not contents:
+        print('Failed to generate %s' % out_cts_html)
+        sys.exit(1)
+
+    with open(out_cts_html, 'wb') as f:
+        f.write(contents)
diff --git a/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt b/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
index fc6f25d..9509c79 100644
--- a/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
+++ b/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
@@ -39,6 +39,7 @@
 # Exclude directories that don't depend on //base, because nothing there uses
 # anything from /base.
 sandbox/linux/system_headers/
+components/history_clusters/core/
 
 # The folder holds headers that are duplicated in the Android source and need to
 # provide a stable C ABI. Can't depend on //base.
diff --git a/tools/ipc_fuzzer/fuzzer/OWNERS b/tools/ipc_fuzzer/fuzzer/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/tools/ipc_fuzzer/fuzzer/OWNERS
+++ /dev/null
diff --git a/tools/ipc_fuzzer/message_dump/OWNERS b/tools/ipc_fuzzer/message_dump/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/tools/ipc_fuzzer/message_dump/OWNERS
+++ /dev/null
diff --git a/tools/ipc_fuzzer/message_replay/OWNERS b/tools/ipc_fuzzer/message_replay/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/tools/ipc_fuzzer/message_replay/OWNERS
+++ /dev/null
diff --git a/tools/ipc_fuzzer/message_tools/OWNERS b/tools/ipc_fuzzer/message_tools/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/tools/ipc_fuzzer/message_tools/OWNERS
+++ /dev/null
diff --git a/tools/ipc_fuzzer/scripts/OWNERS b/tools/ipc_fuzzer/scripts/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/tools/ipc_fuzzer/scripts/OWNERS
+++ /dev/null
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b7eeaa7..2aa2aa62 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -21672,6 +21672,7 @@
   <int value="8" label="NO_CHROME_ACCOUNT"/>
   <int value="9" label="LOW_END_DEVICE"/>
   <int value="10" label="MULTIPLE_ACCOUNTS_ON_DEVICE"/>
+  <int value="11" label="AGSA_NOT_INSTALLED"/>
 </enum>
 
 <enum name="EmbeddedWorkerStartingPhase">
@@ -47880,6 +47881,7 @@
   <int value="1369649674" label="ChromeShareScreenshot:enabled"/>
   <int value="1370797930" label="ShowBluetoothDeviceBattery:enabled"/>
   <int value="1371092708" label="disable-desktop-capture-picker-old-ui"/>
+  <int value="1371344350" label="MediaSessionWebRTC:disabled"/>
   <int value="1371907429" label="enable-wallet-card-import"/>
   <int value="1372680885" label="enable-mtp-write-support"/>
   <int value="1373777956" label="disable-threaded-gpu-rasterization"/>
@@ -48745,6 +48747,7 @@
   <int value="2137347307" label="enable-drive-apps-in-app-list"/>
   <int value="2137554806"
       label="enable-experimental-accessibility-dictation-listening"/>
+  <int value="2137571271" label="MediaSessionWebRTC:enabled"/>
   <int value="2137599770" label="enable-win32k-renderer-lockdown"/>
   <int value="2138146331" label="OmniboxVoiceSearchAlwaysVisible:enabled"/>
   <int value="2139048614" label="UseSurfaceLayerForVideo:enabled"/>
@@ -50568,6 +50571,8 @@
   <int value="2" label="No scripts allowed"/>
   <int value="3" label="Not shown"/>
   <int value="4" label="Disabled by settings"/>
+  <int value="5" label="User explicitly enabled"/>
+  <int value="6" label="User explicitly disabled"/>
 </enum>
 
 <enum name="MediaDocumentDownloadButtonType">
diff --git a/tools/metrics/histograms/histograms_xml/ash/histograms.xml b/tools/metrics/histograms/histograms_xml/ash/histograms.xml
index 7910f58..6a45dfe8 100644
--- a/tools/metrics/histograms/histograms_xml/ash/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/ash/histograms.xml
@@ -1557,6 +1557,51 @@
   </summary>
 </histogram>
 
+<histogram name="Ash.Overview.ArrowKeyPresses" units="units"
+    expires_after="2022-04-08">
+  <owner>chinsenj@chromium.org</owner>
+  <owner>nupurjain@chromium.org</owner>
+  <owner>sammiequon@chromium.org</owner>
+  <summary>
+    The number of times the arrow keys are pressed in overview mode per session,
+    i.e. between bringing up overview mode and ending it. This is only measured
+    for the sessions that end by selecting a window with the enter key.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Overview.Items" units="units" expires_after="2022-04-08">
+  <owner>chinsenj@chromium.org</owner>
+  <owner>nupurjain@chromium.org</owner>
+  <owner>sammiequon@chromium.org</owner>
+  <summary>
+    The number of items (single windows or groups of windows such as panels) in
+    the overview mode, present at the start of each session.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Overview.KeyPressesOverItemsRatio" units="%"
+    expires_after="2022-04-08">
+  <owner>chinsenj@chromium.org</owner>
+  <owner>nupurjain@chromium.org</owner>
+  <owner>sammiequon@chromium.org</owner>
+  <summary>
+    The ratio between the arrow key presses and the number of overview items,
+    expressed as a percentage for a single session. Recorded when an overview
+    session is exited after selecting a highlighted overview item.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Overview.OverviewClosedItems" units="units"
+    expires_after="2022-04-08">
+  <owner>chinsenj@chromium.org</owner>
+  <owner>nupurjain@chromium.org</owner>
+  <owner>sammiequon@chromium.org</owner>
+  <summary>
+    The number of items closed from the window overview for a single session.
+    Recorded when exiting an overview session.
+  </summary>
+</histogram>
+
 <histogram name="Ash.Overview.Scroll.PresentationTime.MaxLatency.TabletMode"
     units="ms" expires_after="2021-12-31">
   <owner>sammiequon@chromium.org</owner>
@@ -1578,6 +1623,59 @@
   </summary>
 </histogram>
 
+<histogram name="Ash.Overview.SelectionDepth" units="items"
+    expires_after="2022-04-08">
+  <owner>chinsenj@chromium.org</owner>
+  <owner>nupurjain@chromium.org</owner>
+  <owner>sammiequon@chromium.org</owner>
+  <owner>tclaiborne@chromium.org</owner>
+  <summary>
+    When a window is selected in overview mode, records that window's position
+    in the global MRU ordering. 1 represents the most-recently used window, 2
+    represents the next most-recently used window, and so on.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Overview.TimeBetweenActiveWindowChanges" units="seconds"
+    expires_after="2022-04-08">
+  <owner>chinsenj@chromium.org</owner>
+  <owner>nupurjain@chromium.org</owner>
+  <owner>sammiequon@chromium.org</owner>
+  <summary>
+    The amount of time between endings of overview mode sessions which were
+    caused by the user selecting a window which was not previously active. Only
+    recorded on the second and later times after startup that the user selected
+    a window which was not previously active.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Overview.TimeBetweenUse" units="ms"
+    expires_after="2022-04-08">
+  <owner>chinsenj@chromium.org</owner>
+  <owner>nupurjain@chromium.org</owner>
+  <owner>sammiequon@chromium.org</owner>
+  <summary>
+    The amount of time between uses of overview mode, recorded when overview
+    mode is entered. Only recorded on the second and later times after startup
+    that the user entered overview mode.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Overview.TimeInOverview" units="ms"
+    expires_after="2022-04-08">
+  <owner>chinsenj@chromium.org</owner>
+  <owner>nupurjain@chromium.org</owner>
+  <owner>sammiequon@chromium.org</owner>
+  <summary>
+    The amount of time spent in overview mode. Overview mode is engaged by
+    pressing the overview accelerator, overview button tray or swiping up from
+    the shelf in tablet mode. The time is measured from the moment the windows
+    begin animating to a thumbnail size preview to when a window is selected or
+    selection is canceled. Recorded when an overview session is exited, before
+    the exit animation starts.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Ash.Overview.WindowDrag.PresentationTime"
     units="ms" expires_after="2021-12-31">
 <!-- Name completed by histogram_suffixes
@@ -2324,7 +2422,8 @@
 </histogram>
 
 <histogram name="Ash.TimeBetweenTaskSwitches" units="seconds"
-    expires_after="M81">
+    expires_after="2022-04-08">
+  <owner>nupurjain@chromium.org</owner>
   <owner>tbuckley@google.com</owner>
   <summary>
     The number of seconds between contiguous task switch user actions triggered
@@ -2333,10 +2432,12 @@
     Ash.Tab.TimeBetweenSwitchToExistingTabUserActions,
     Ash.WindowCycleController.TimeBetweenTaskSwitches,
     Ash.AppList.TimeBetweenTaskSwitches,
-    Ash.WindowSelector.TimeBetweenActiveWindowChanges, etc). Note the
+    Ash.Overview.TimeBetweenActiveWindowChanges, etc). Note the
     Ash.AppList.TimeBetweenTaskSwitches and
     Ash.Tab.TimeBetweenSwitchToExistingTabUserActions histograms were deprecated
-    and removed in 10/2016.
+    and removed in 10/2016. Note that
+    Ash.Overview.TimeBetweenActiveWindowChanges was renamed from
+    Ash.WindowSelector.TimeBetweenActiveWindowChanges on 04/2021.
   </summary>
 </histogram>
 
@@ -2661,6 +2762,9 @@
 
 <histogram name="Ash.WindowSelector.ArrowKeyPresses" units="units"
     expires_after="M81">
+  <obsolete>
+    Replaced 04/2021 by Ash.Overview.ArrowKeyPresses.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <summary>
     The number of times the arrow keys are pressed in overview mode per session,
@@ -2671,6 +2775,9 @@
 
 <histogram name="Ash.WindowSelector.Items" units="units"
     expires_after="2020-10-04">
+  <obsolete>
+    Replaced 04/2021 by Ash.Overview.Items.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <owner>kuscher@google.com</owner>
   <summary>
@@ -2681,6 +2788,10 @@
 
 <histogram name="Ash.WindowSelector.ItemsWhenTextFilteringUsed" units="items"
     expires_after="M77">
+  <obsolete>
+    Removed 04/2021 as of https://crrev.com/c/2816339. The text filtering
+    feature has been removed.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <summary>
     The number of items showing in overview mode at the moment when an item is
@@ -2691,6 +2802,9 @@
 
 <histogram name="Ash.WindowSelector.KeyPressesOverItemsRatio" units="%"
     expires_after="2020-03-01">
+  <obsolete>
+    Replaced 04/2021 by Ash.Overview.KeyPressesOverItemsRatio.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <summary>
     The ratio between the arrow key presses and the number of overview items,
@@ -2700,6 +2814,9 @@
 
 <histogram name="Ash.WindowSelector.OverviewClosedItems" units="units"
     expires_after="2020-01-26">
+  <obsolete>
+    Replaced 04/2021 by Ash.Overview.OverviewClosedItems.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <summary>
     The number of items closed from the window overview for a single session.
@@ -2708,6 +2825,9 @@
 
 <histogram name="Ash.WindowSelector.SelectionDepth" units="items"
     expires_after="2021-09-29">
+  <obsolete>
+    Replaced 04/2021 by Ash.Overview.SelectionDepth.
+  </obsolete>
   <owner>sammiequon@chromium.org</owner>
   <owner>tclaiborne@chromium.org</owner>
   <summary>
@@ -2719,6 +2839,10 @@
 
 <histogram name="Ash.WindowSelector.TextFilteringStringLength"
     units="characters" expires_after="M77">
+  <obsolete>
+    Removed 04/2021 as of https://crrev.com/c/2816339. The text filtering
+    feature has been removed.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <summary>
     The length of the string entered into the text filtering textfield at the
@@ -2728,6 +2852,10 @@
 
 <histogram name="Ash.WindowSelector.TextFilteringTextfieldCleared"
     units="units" expires_after="M77">
+  <obsolete>
+    Removed 04/2021 as of https://crrev.com/c/2816339. The text filtering
+    feature has been removed.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <summary>
     The number of times the text filtering textfield has had all of its text
@@ -2739,6 +2867,9 @@
 
 <histogram name="Ash.WindowSelector.TimeBetweenActiveWindowChanges"
     units="seconds" expires_after="M81">
+  <obsolete>
+    Replaced 04/2021 by Ash.Overview.TimeBetweenActiveWindowChanges.
+  </obsolete>
   <owner>tbuckley@chromium.org</owner>
   <summary>
     The amount of time between endings of overview mode sessions which were
@@ -2750,6 +2881,9 @@
 
 <histogram name="Ash.WindowSelector.TimeBetweenUse" units="ms"
     expires_after="M82">
+  <obsolete>
+    Replaced 04/2021 by Ash.Overview.TimeBetweenUse.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <owner>kuscher@google.com</owner>
   <summary>
@@ -2761,6 +2895,9 @@
 
 <histogram name="Ash.WindowSelector.TimeInOverview" units="ms"
     expires_after="2020-10-18">
+  <obsolete>
+    Replaced 04/2021 by Ash.Overview.TimeInOverview.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <owner>kuscher@google.com</owner>
   <summary>
@@ -2773,6 +2910,10 @@
 
 <histogram name="Ash.WindowSelector.TimeInOverviewWithTextFiltering" units="ms"
     expires_after="M85">
+  <obsolete>
+    Removed 04/2021 as of https://crrev.com/c/2816339. The text filtering
+    feature has been removed.
+  </obsolete>
   <owner>flackr@chromium.org</owner>
   <summary>
     The amount of time spent in overview mode when text filtering is used. The
diff --git a/tools/metrics/histograms/histograms_xml/mobile/histograms.xml b/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
index 294ca88f..babf349 100644
--- a/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
@@ -81,7 +81,7 @@
 </histogram>
 
 <histogram name="Mobile.ContextMenu.EntryPoints" enum="IOSMenuScenario"
-    expires_after="2021-09-05">
+    expires_after="2022-06-01">
   <owner>seblalancette@chromium.org</owner>
   <owner>gambard@chromium.org</owner>
   <summary>
@@ -92,7 +92,7 @@
 </histogram>
 
 <histogram name="Mobile.ContextMenu.{EntryPoint}.Actions" enum="IOSMenuAction"
-    expires_after="2021-07-01">
+    expires_after="2022-06-01">
   <owner>seblalancette@chromium.org</owner>
   <owner>gambard@chromium.org</owner>
   <summary>
@@ -338,7 +338,7 @@
 </histogram>
 
 <histogram name="Mobile.Share.EntryPoints" enum="IOSActivityScenario"
-    expires_after="2021-10-04">
+    expires_after="2022-06-01">
   <owner>seblalancette@chromium.org</owner>
   <owner>chrome-sharing-core@google.com</owner>
   <summary>
@@ -349,7 +349,7 @@
 </histogram>
 
 <histogram name="Mobile.Share.{EntryPoint}.Actions" enum="IOSShareAction"
-    expires_after="2021-06-01">
+    expires_after="2022-06-01">
   <owner>seblalancette@chromium.org</owner>
   <owner>chrome-sharing-core@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 2e2314fe..9ed16b27 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -4976,7 +4976,7 @@
 </histogram>
 
 <histogram name="DriveCommon.Lifecycle.Mount" enum="DriveMountStatus"
-    expires_after="2021-08-22">
+    expires_after="M102">
   <owner>simmonsjosh@google.com</owner>
   <owner>src/ui/file_manager/OWNERS</owner>
   <summary>Records outcomes of attempts to mount Google Drive.</summary>
@@ -4990,7 +4990,7 @@
 </histogram>
 
 <histogram name="DriveCommon.Lifecycle.Unmount" enum="DriveMountStatus"
-    expires_after="2021-04-19">
+    expires_after="M102">
   <owner>simmonsjosh@google.com</owner>
   <owner>src/ui/file_manager/OWNERS</owner>
   <summary>Records outcomes of attempts to unmount Google Drive.</summary>
@@ -5026,7 +5026,7 @@
 </histogram>
 
 <histogram name="DriveCommon.RemoteSearch.SharedSearchTime" units="ms"
-    expires_after="2021-04-19">
+    expires_after="M102">
   <owner>simmonsjosh@google.com</owner>
   <owner>src/ui/file_manager/OWNERS</owner>
   <summary>
@@ -5036,7 +5036,7 @@
 </histogram>
 
 <histogram name="DriveCommon.RemoteSearch.TextSearchTime" units="ms"
-    expires_after="2021-04-19">
+    expires_after="M102">
   <owner>simmonsjosh@google.com</owner>
   <owner>src/ui/file_manager/OWNERS</owner>
   <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index aa4c8363..3425516e 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": "fe4d07829c74610e4ea8455a540d602ebdd8e2b1",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/e2af31e5ad285a2d89143f65cfc8f41a56dba5e0/trace_processor_shell.exe"
+            "hash": "ca9434e1de09fdd5a6bb20fb4f6cd7115bdcd3d7",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/1b78913ea7b1a4c3a3447f6b183e4be62a01e7e3/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "4969720d5c4c63ab4f99abd3da2e3d8a862f30d2",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/507ccb8542d8915bcc88f0bec545ac9e8a464af6/trace_processor_shell"
+            "hash": "a35e5e173c0444596d24ee8d8101cb512e7e354b",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/31ac7832bfcaabb8389a8d04a321d459917da176/trace_processor_shell"
         },
         "linux": {
-            "hash": "d4236cf2970714db8496eb09e5f0405ac34ca977",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/7dceb880165b7ba5b85f3f8d095e5262407b5fad/trace_processor_shell"
+            "hash": "e84b3daa166591d4239a11c230c9ad622c50a629",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/31ac7832bfcaabb8389a8d04a321d459917da176/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/perf/experimental/representative_perf_test_limit_adjuster/adjust_upper_limits.py b/tools/perf/experimental/representative_perf_test_limit_adjuster/adjust_upper_limits.py
index 462a22bd..989bfa8c 100644
--- a/tools/perf/experimental/representative_perf_test_limit_adjuster/adjust_upper_limits.py
+++ b/tools/perf/experimental/representative_perf_test_limit_adjuster/adjust_upper_limits.py
@@ -29,7 +29,7 @@
   """Fetches the item id of tasks described by the tags.
 
   Args:
-    tags: The tags which describe the task such as OS, master and buildername.
+    tags: The tags which describe the task such as OS, builder_group and buildername.
     limit: The number of runs to look at.
 
   Returns:
@@ -39,8 +39,9 @@
   query = [
       SWARMING_PATH, 'tasks', '-S', 'chromium-swarm.appspot.com', '-limit',
       str(limit), '-state=COMPLETED', '-field', 'items(task_id)', '-tag',
-      'master:{master}'.format(**tags), '-tag', 'os:{os}'.format(**tags),
-      '-tag', 'name:rendering_representative_perf_tests', '-tag',
+      'builder_group:{builder_group}'.format(**tags), '-tag',
+      'os:{os}'.format(**tags), '-tag',
+      'name:rendering_representative_perf_tests', '-tag',
       'buildername:{buildername}'.format(**tags)
   ]
   return json.loads(subprocess.check_output(query))
diff --git a/tools/perf/measurements/rasterize_and_record_micro_unittest.py b/tools/perf/measurements/rasterize_and_record_micro_unittest.py
index ef292fe9..44ccf6c4 100644
--- a/tools/perf/measurements/rasterize_and_record_micro_unittest.py
+++ b/tools/perf/measurements/rasterize_and_record_micro_unittest.py
@@ -17,7 +17,7 @@
   """
 
   # Fails or flaky on some bots.  See http://crbug.com/956798
-  @decorators.Disabled('win', 'chromeos', 'linux', 'win7', 'mac')
+  @decorators.Disabled('win', 'chromeos', 'linux', 'win7')
   def testRasterizeAndRecordMicro(self):
     pate_test = rasterize_and_record_micro.RasterizeAndRecordMicro(
         rasterize_repeat=1, record_repeat=1, start_wait_time=0.0,
@@ -41,8 +41,8 @@
     ]
     for name in expected_positve_scalar:
       samples = measurements[name]['samples']
-      self.assertEqual(len(samples), 1)
-      self.assertGreater(samples[0], 0)
+      self.assertEqual(len(samples), 1, '%s did not have 1 sample' % name)
+      self.assertGreater(samples[0], 0, 'Sample from %s was not > 0' % name)
 
     samples = measurements['total_picture_layers_off_screen']['samples']
     self.assertEqual(len(samples), 1)
diff --git a/ui/base/accelerators/accelerator_manager.cc b/ui/base/accelerators/accelerator_manager.cc
index 01d842d..ec6bffed 100644
--- a/ui/base/accelerators/accelerator_manager.cc
+++ b/ui/base/accelerators/accelerator_manager.cc
@@ -7,9 +7,18 @@
 #include "base/check.h"
 #include "base/containers/contains.h"
 
+#if defined(OS_CHROMEOS)
+#include "ui/base/ui_base_features.h"
+#endif
+
 namespace ui {
 
-AcceleratorManager::AcceleratorManager() = default;
+AcceleratorManager::AcceleratorManager() {
+#if defined(OS_CHROMEOS)
+  accelerators_.set_use_positional_lookup(
+      ::features::IsImprovedKeyboardShortcutsEnabled());
+#endif
+}
 
 AcceleratorManager::~AcceleratorManager() = default;
 
diff --git a/ui/base/accelerators/accelerator_manager_unittest.cc b/ui/base/accelerators/accelerator_manager_unittest.cc
index 502d45aa..2778775 100644
--- a/ui/base/accelerators/accelerator_manager_unittest.cc
+++ b/ui/base/accelerators/accelerator_manager_unittest.cc
@@ -202,7 +202,123 @@
     EXPECT_TRUE(manager_.Process(trigger));
   }
 }
-#endif
+
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+#if defined(OS_CHROMEOS)
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_AllEqual) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      features::kImprovedKeyboardShortcuts);
+
+  // Use a local instance so that the feature is enabled during construction.
+  AcceleratorManager manager;
+
+  // Test what would be ctrl + ']' (VKEY_OEM_6) on a US keyboard. This
+  // should match.
+  TestAcceleratorTarget target;
+  const Accelerator accelerator(VKEY_OEM_6, EF_CONTROL_DOWN);
+  manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+  KeyEvent event(ui::ET_KEY_PRESSED, VKEY_OEM_6, ui::DomCode::BRACKET_RIGHT,
+                 ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+                 base::TimeTicks());
+  const Accelerator trigger(event);
+  EXPECT_TRUE(manager.IsRegistered(trigger));
+  EXPECT_TRUE(manager.Process(trigger));
+}
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_MatchingDomCode) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      features::kImprovedKeyboardShortcuts);
+
+  // Use a local instance so that the feature is enabled during construction.
+  AcceleratorManager manager;
+
+  // Test what would be ctrl + ']' on a US keyboard with matching DomCode
+  // and different VKEY (eg. '+'). This is the use case of a positional key
+  // on the German keyboard. Since the DomCode matches, this should match.
+  TestAcceleratorTarget target;
+  const Accelerator accelerator(VKEY_OEM_6, EF_CONTROL_DOWN);
+  manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+  KeyEvent event(ui::ET_KEY_PRESSED, VKEY_OEM_PLUS, ui::DomCode::BRACKET_RIGHT,
+                 ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+                 base::TimeTicks());
+  const Accelerator trigger(event);
+  EXPECT_TRUE(manager.IsRegistered(trigger));
+  EXPECT_TRUE(manager.Process(trigger));
+}
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_NotMatchingDomCode) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      features::kImprovedKeyboardShortcuts);
+
+  // Use a local instance so that the feature is enabled during construction.
+  AcceleratorManager manager;
+
+  // Test what would be ctrl + ']' on a US keyboard using positional mapping
+  // for a German layout. The accelerator is registered using the US VKEY and
+  // triggered with a KeyEvent with the US VKEY but a mismatched DomCode. This
+  // should not match. This prevents ghost shortcuts on non-US layouts.
+  TestAcceleratorTarget target;
+  const Accelerator accelerator(VKEY_OEM_6, EF_CONTROL_DOWN);
+  manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+  KeyEvent event(ui::ET_KEY_PRESSED, VKEY_OEM_6, ui::DomCode::BRACKET_LEFT,
+                 ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+                 base::TimeTicks());
+  const Accelerator trigger(event);
+  EXPECT_FALSE(manager.IsRegistered(trigger));
+  EXPECT_FALSE(manager.Process(trigger));
+}
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_NonPositionalMatch) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      features::kImprovedKeyboardShortcuts);
+
+  // Use a local instance so that the feature is enabled during construction.
+  AcceleratorManager manager;
+
+  // Test ctrl + 'Z' for the German layout. Since 'Z' is not a positional
+  // key it should match based on the VKEY, regardless of the DomCode. In this
+  // case the 'Z' has DomCode US_Y (ie. QWERTZ keyboard), but it should still
+  // match.
+  TestAcceleratorTarget target;
+  const Accelerator accelerator(VKEY_Z, EF_CONTROL_DOWN);
+  manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+  KeyEvent event(ui::ET_KEY_PRESSED, VKEY_Z, ui::DomCode::US_Y,
+                 ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+                 base::TimeTicks());
+  const Accelerator trigger(event);
+  EXPECT_TRUE(manager.IsRegistered(trigger));
+  EXPECT_TRUE(manager.Process(trigger));
+}
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_NonPositionalNonMatch) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      features::kImprovedKeyboardShortcuts);
+
+  // Use a local instance so that the feature is enabled during construction.
+  AcceleratorManager manager;
+
+  // Test ctrl + 'Z' for the German layout. The 'Y' key (in the US_Z position),
+  // should not match. Alphanumeric keys are not positional, and pressing the
+  // key with DomCode::US_Z should not match when it's mapped to VKEY_Y.
+  TestAcceleratorTarget target;
+  const Accelerator accelerator(VKEY_Z, EF_CONTROL_DOWN);
+  manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+  KeyEvent event(ui::ET_KEY_PRESSED, VKEY_Y, ui::DomCode::US_Z,
+                 ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+                 base::TimeTicks());
+  const Accelerator trigger(event);
+  EXPECT_FALSE(manager.IsRegistered(trigger));
+  EXPECT_FALSE(manager.Process(trigger));
+}
+
+#endif  // defined(OS_CHROMEOS)
 
 }  // namespace
 }  // namespace test
diff --git a/ui/base/ime/dummy_text_input_client.cc b/ui/base/ime/dummy_text_input_client.cc
index d063f39d..c68324c 100644
--- a/ui/base/ime/dummy_text_input_client.cc
+++ b/ui/base/ime/dummy_text_input_client.cc
@@ -8,6 +8,7 @@
 #include <vector>
 #endif
 
+#include "base/notreached.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -79,6 +80,11 @@
   return gfx::Rect();
 }
 
+gfx::Rect DummyTextInputClient::GetSelectionBoundingBox() const {
+  NOTIMPLEMENTED_LOG_ONCE();
+  return gfx::Rect();
+}
+
 bool DummyTextInputClient::GetCompositionCharacterBounds(
     uint32_t index,
     gfx::Rect* rect) const {
diff --git a/ui/base/ime/dummy_text_input_client.h b/ui/base/ime/dummy_text_input_client.h
index 7908a32..ab322f5a 100644
--- a/ui/base/ime/dummy_text_input_client.h
+++ b/ui/base/ime/dummy_text_input_client.h
@@ -38,6 +38,7 @@
   int GetTextInputFlags() const override;
   bool CanComposeInline() const override;
   gfx::Rect GetCaretBounds() const override;
+  gfx::Rect GetSelectionBoundingBox() const override;
   bool GetCompositionCharacterBounds(uint32_t index,
                                      gfx::Rect* rect) const override;
   bool HasCompositionText() const override;
diff --git a/ui/base/ime/fake_text_input_client.cc b/ui/base/ime/fake_text_input_client.cc
index e5593e9..2ccd397c 100644
--- a/ui/base/ime/fake_text_input_client.cc
+++ b/ui/base/ime/fake_text_input_client.cc
@@ -74,6 +74,10 @@
   return {};
 }
 
+gfx::Rect FakeTextInputClient::GetSelectionBoundingBox() const {
+  return {};
+}
+
 bool FakeTextInputClient::GetCompositionCharacterBounds(uint32_t index,
                                                         gfx::Rect* rect) const {
   return false;
diff --git a/ui/base/ime/fake_text_input_client.h b/ui/base/ime/fake_text_input_client.h
index 39597c6..c060b25 100644
--- a/ui/base/ime/fake_text_input_client.h
+++ b/ui/base/ime/fake_text_input_client.h
@@ -48,6 +48,7 @@
   int GetTextInputFlags() const override;
   bool CanComposeInline() const override;
   gfx::Rect GetCaretBounds() const override;
+  gfx::Rect GetSelectionBoundingBox() const override;
   bool GetCompositionCharacterBounds(uint32_t index,
                                      gfx::Rect* rect) const override;
   bool HasCompositionText() const override;
diff --git a/ui/base/ime/text_input_client.h b/ui/base/ime/text_input_client.h
index e9a5e37..4f8f661 100644
--- a/ui/base/ime/text_input_client.h
+++ b/ui/base/ime/text_input_client.h
@@ -136,6 +136,11 @@
   // If there is selection, then the selection bounds will be returned.
   virtual gfx::Rect GetCaretBounds() const = 0;
 
+  // Returns the bounds of the rectangle which encloses the selection region.
+  // Bounds are in the screen coordinates. An empty value should be returned if
+  // there is not any selection or this function is not implemented.
+  virtual gfx::Rect GetSelectionBoundingBox() const = 0;
+
   // Retrieves the composition character boundary rectangle in the universal
   // screen coordinates in DIP (Density Independent Pixel).
   // The |index| is zero-based index of character position in composition text.
diff --git a/ui/base/ime/win/tsf_text_store_unittest.cc b/ui/base/ime/win/tsf_text_store_unittest.cc
index 2c97dfa..e282507 100644
--- a/ui/base/ime/win/tsf_text_store_unittest.cc
+++ b/ui/base/ime/win/tsf_text_store_unittest.cc
@@ -48,6 +48,7 @@
   MOCK_CONST_METHOD0(GetTextInputFlags, int());
   MOCK_CONST_METHOD0(CanComposeInline, bool());
   MOCK_CONST_METHOD0(GetCaretBounds, gfx::Rect());
+  MOCK_CONST_METHOD0(GetSelectionBoundingBox, gfx::Rect());
   MOCK_CONST_METHOD2(GetCompositionCharacterBounds, bool(uint32_t, gfx::Rect*));
   MOCK_CONST_METHOD0(HasCompositionText, bool());
   MOCK_CONST_METHOD0(GetFocusReason, ui::TextInputClient::FocusReason());
diff --git a/ui/color/color_provider_manager.cc b/ui/color/color_provider_manager.cc
index 0d18cd2..73772bd 100644
--- a/ui/color/color_provider_manager.cc
+++ b/ui/color/color_provider_manager.cc
@@ -56,7 +56,8 @@
 #if !defined(OS_ANDROID)
     manager.value().AppendColorProviderInitializer(base::BindRepeating(
         [](ColorProvider* provider, ColorProviderManager::ColorMode color_mode,
-           ColorProviderManager::ContrastMode contrast_mode) {
+           ColorProviderManager::ContrastMode contrast_mode,
+           ColorProviderManager::ThemeName theme_name) {
           const bool dark_mode =
               color_mode == ColorProviderManager::ColorMode::kDark;
           const bool high_contrast =
@@ -112,9 +113,11 @@
       DVLOG(2) << "ColorProviderManager: Initializing Color Provider"
                << " - ColorMode: " << ColorModeName(std::get<ColorMode>(key))
                << " - ContrastMode: "
-               << ContrastModeName(std::get<ContrastMode>(key));
+               << ContrastModeName(std::get<ContrastMode>(key))
+               << " - ThemeName: " << std::get<ThemeName>(key);
       initializer_list_->Notify(provider.get(), std::get<ColorMode>(key),
-                                std::get<ContrastMode>(key));
+                                std::get<ContrastMode>(key),
+                                std::get<ThemeName>(key));
     }
 
     iter = color_providers_.emplace(key, std::move(provider)).first;
diff --git a/ui/color/color_provider_manager.h b/ui/color/color_provider_manager.h
index 26c1257..d70fc14 100644
--- a/ui/color/color_provider_manager.h
+++ b/ui/color/color_provider_manager.h
@@ -32,9 +32,10 @@
     kNormal,
     kHigh,
   };
-  using ColorProviderKey = std::tuple<ColorMode, ContrastMode>;
+  using ThemeName = std::string;
+  using ColorProviderKey = std::tuple<ColorMode, ContrastMode, ThemeName>;
   using ColorProviderInitializerList = base::RepeatingCallbackList<
-      void(ColorProvider*, ColorMode, ContrastMode)>;
+      void(ColorProvider*, ColorMode, ContrastMode, ThemeName)>;
 
   ColorProviderManager(const ColorProviderManager&) = delete;
   ColorProviderManager& operator=(const ColorProviderManager&) = delete;
diff --git a/ui/color/color_provider_manager_unittest.cc b/ui/color/color_provider_manager_unittest.cc
index 46a007e..e28ddec 100644
--- a/ui/color/color_provider_manager_unittest.cc
+++ b/ui/color/color_provider_manager_unittest.cc
@@ -29,7 +29,7 @@
 ColorProvider* GetLightNormalColorProvider() {
   return ColorProviderManager::GetForTesting().GetColorProviderFor(
       {ColorProviderManager::ColorMode::kLight,
-       ColorProviderManager::ContrastMode::kNormal});
+       ColorProviderManager::ContrastMode::kNormal, std::string()});
 }
 
 }  // namespace
@@ -50,7 +50,8 @@
   ColorProviderManager::GetForTesting().AppendColorProviderInitializer(
       base::BindRepeating([](ColorProvider* provider,
                              ColorProviderManager::ColorMode,
-                             ColorProviderManager::ContrastMode) {
+                             ColorProviderManager::ContrastMode,
+                             ColorProviderManager::ThemeName) {
         provider->AddMixer().AddSet(
             {kColorSetTest0, {{kColorTest0, SK_ColorBLUE}}});
       }));
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index ccedbb8b..d84ff09 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -744,27 +744,49 @@
   NOTREACHED();
 }
 
+Compositor::TrackerState::TrackerState() = default;
+Compositor::TrackerState::TrackerState(TrackerState&&) = default;
+Compositor::TrackerState& Compositor::TrackerState::operator=(TrackerState&&) =
+    default;
+Compositor::TrackerState::~TrackerState() = default;
+
 void Compositor::StartThroughputTracker(
     TrackerId tracker_id,
     ThroughputTrackerHost::ReportCallback callback) {
   DCHECK(!base::Contains(throughput_tracker_map_, tracker_id));
-  throughput_tracker_map_[tracker_id] = std::move(callback);
+
+  auto& tracker_state = throughput_tracker_map_[tracker_id];
+  tracker_state.report_callback = std::move(callback);
+
   animation_host_->StartThroughputTracking(tracker_id);
 }
 
-void Compositor::StopThroughtputTracker(TrackerId tracker_id) {
-  // TODO(crbug.com/1183374): DCHECKs are disabled during automated testing on
-  // CrOS and this check failed when tested on an experimental builder. Revert
-  // https://crrev.com/c/2727841 (or uncomment) to enable it. See
-  // go/chrome-dcheck-on-cros or http://crbug.com/1113456 for more details.
-  // DCHECK(base::Contains(throughput_tracker_map_, tracker_id));
+bool Compositor::StopThroughtputTracker(TrackerId tracker_id) {
+  auto it = throughput_tracker_map_.find(tracker_id);
+  DCHECK(it != throughput_tracker_map_.end());
+
+  // Clean up if report has happened since StopThroughputTracking would
+  // not trigger report in this case.
+  if (it->second.report_attempted) {
+    throughput_tracker_map_.erase(it);
+    return false;
+  }
+
+  it->second.should_report = true;
   animation_host_->StopThroughputTracking(tracker_id);
+  return true;
 }
 
 void Compositor::CancelThroughtputTracker(TrackerId tracker_id) {
-  DCHECK(base::Contains(throughput_tracker_map_, tracker_id));
-  StopThroughtputTracker(tracker_id);
-  throughput_tracker_map_.erase(tracker_id);
+  auto it = throughput_tracker_map_.find(tracker_id);
+  DCHECK(it != throughput_tracker_map_.end());
+
+  const bool should_stop = !it->second.report_attempted;
+
+  throughput_tracker_map_.erase(it);
+
+  if (should_stop)
+    animation_host_->StopThroughputTracking(tracker_id);
 }
 
 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
@@ -803,9 +825,16 @@
   if (it == throughput_tracker_map_.end())
     return;
 
+  // Set `report_attempted` but not reporting if relevant ThroughputTrackers
+  // are not stopped and waiting for reports.
+  if (!it->second.should_report) {
+    it->second.report_attempted = true;
+    return;
+  }
+
   // Callback may modify `throughput_tracker_map_` so update the map first.
   // See https://crbug.com/1193382.
-  auto callback = std::move(it->second);
+  auto callback = std::move(it->second.report_callback);
   throughput_tracker_map_.erase(it);
   std::move(callback).Run(data);
 }
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 65467f7..fe4e33a 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -372,7 +372,7 @@
   void StartThroughputTracker(
       TrackerId tracker_id,
       ThroughputTrackerHost::ReportCallback callback) override;
-  void StopThroughtputTracker(TrackerId tracker_id) override;
+  bool StopThroughtputTracker(TrackerId tracker_id) override;
   void CancelThroughtputTracker(TrackerId tracker_id) override;
 
 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
@@ -504,8 +504,23 @@
   bool disabled_swap_until_resize_ = false;
 
   TrackerId next_throughput_tracker_id_ = 1u;
-  using ThroughputTrackerMap =
-      base::flat_map<TrackerId, ThroughputTrackerHost::ReportCallback>;
+  struct TrackerState {
+    TrackerState();
+    TrackerState(TrackerState&&);
+    TrackerState& operator=(TrackerState&&);
+    ~TrackerState();
+
+    // Whether a tracker is waiting for report and `report_callback` should be
+    // invoked. This is set to true when a tracker is stopped.
+    bool should_report = false;
+    // Whether the report for a tracker has happened. This is set when an
+    // involuntary report happens before the tracker is stopped and set
+    // `should_report` field above.
+    bool report_attempted = false;
+    // Invoked to send report to the owner of a tracker.
+    ThroughputTrackerHost::ReportCallback report_callback;
+  };
+  using ThroughputTrackerMap = base::flat_map<TrackerId, TrackerState>;
   ThroughputTrackerMap throughput_tracker_map_;
 
   base::WeakPtrFactory<Compositor> context_creation_weak_ptr_factory_{this};
diff --git a/ui/compositor/compositor_unittest.cc b/ui/compositor/compositor_unittest.cc
index 7eaa8bbe..7e3faff7 100644
--- a/ui/compositor/compositor_unittest.cc
+++ b/ui/compositor/compositor_unittest.cc
@@ -192,7 +192,7 @@
           // May be called since Stop() is called.
         }));
     auto moved_tracker = std::move(tracker);
-    moved_tracker.Stop();
+    EXPECT_TRUE(moved_tracker.Stop());
   }
 
   // Move a started instance and cancel.
@@ -214,7 +214,7 @@
         [&](const cc::FrameSequenceMetrics::CustomReportData& data) {
           // May be called since Stop() is called.
         }));
-    tracker.Stop();
+    EXPECT_TRUE(tracker.Stop());
     auto moved_tracker = std::move(tracker);
   }
 
@@ -257,7 +257,7 @@
     DrawWaiterForTest::WaitForCompositingEnded(compositor());
   }
 
-  tracker.Stop();
+  EXPECT_TRUE(tracker.Stop());
 
   // Generates a few frames after tracker stops. Note the number of frames
   // must be at least two: one to trigger underlying cc::FrameSequenceTracker to
@@ -279,8 +279,8 @@
 
   DestroyCompositor();
 
-  // No crash, no use-after-free and no report.
-  tracker.Stop();
+  // Stop() fails but no crash, no use-after-free and no report.
+  EXPECT_FALSE(tracker.Stop());
 }
 
 TEST_F(CompositorTestWithMessageLoop, ThroughputTrackerCallbackStateChange) {
@@ -315,7 +315,7 @@
     DrawWaiterForTest::WaitForCompositingEnded(compositor());
   }
 
-  tracker.Stop();
+  EXPECT_TRUE(tracker.Stop());
 
   // Generates a few frames after tracker stops. Note the number of frames
   // must be at least two: one to trigger underlying cc::FrameSequenceTracker to
@@ -328,6 +328,38 @@
   run_loop.Run();
 }
 
+TEST_F(CompositorTestWithMessageLoop, ThroughputTrackerInvoluntaryReport) {
+  auto root_layer = std::make_unique<Layer>(ui::LAYER_SOLID_COLOR);
+  viz::ParentLocalSurfaceIdAllocator allocator;
+  allocator.GenerateId();
+  root_layer->SetBounds(gfx::Rect(10, 10));
+  compositor()->SetRootLayer(root_layer.get());
+  compositor()->SetScaleAndSize(1.0f, gfx::Size(10, 10),
+                                allocator.GetCurrentLocalSurfaceId());
+  ASSERT_TRUE(compositor()->IsVisible());
+
+  ThroughputTracker tracker = compositor()->RequestNewThroughputTracker();
+
+  tracker.Start(base::BindLambdaForTesting(
+      [&](const cc::FrameSequenceMetrics::CustomReportData& data) {
+        ADD_FAILURE() << "No report should happen";
+      }));
+
+  // Generates a few frames after tracker starts to have some data collected.
+  for (int i = 0; i < 5; ++i) {
+    compositor()->ScheduleFullRedraw();
+    DrawWaiterForTest::WaitForCompositingEnded(compositor());
+  }
+
+  // ReleaseAcceleratedWidget() destroys underlying cc::FrameSequenceTracker
+  // and triggers reports before Stop(). Such reports are dropped.
+  compositor()->SetVisible(false);
+  compositor()->ReleaseAcceleratedWidget();
+
+  // Stop() fails but no DCHECK or crash.
+  EXPECT_FALSE(tracker.Stop());
+}
+
 #if defined(OS_WIN)
 // TODO(crbug.com/608436): Flaky on windows trybots
 #define MAYBE_CreateAndReleaseOutputSurface \
diff --git a/ui/compositor/throughput_tracker.cc b/ui/compositor/throughput_tracker.cc
index 95bcb01..f0a819d 100644
--- a/ui/compositor/throughput_tracker.cc
+++ b/ui/compositor/throughput_tracker.cc
@@ -46,12 +46,14 @@
   host_->StartThroughputTracker(id_, std::move(callback));
 }
 
-void ThroughputTracker::Stop() {
+bool ThroughputTracker::Stop() {
   DCHECK(started_);
 
   started_ = false;
   if (host_)
-    host_->StopThroughtputTracker(id_);
+    return host_->StopThroughtputTracker(id_);
+
+  return false;
 }
 
 void ThroughputTracker::Cancel() {
diff --git a/ui/compositor/throughput_tracker.h b/ui/compositor/throughput_tracker.h
index ae18af42..e536423 100644
--- a/ui/compositor/throughput_tracker.h
+++ b/ui/compositor/throughput_tracker.h
@@ -35,10 +35,11 @@
   // throughput data collection starts after the next commit.
   void Start(ThroughputTrackerHost::ReportCallback callback);
 
-  // Stops tracking. The supplied callback will be invoked when the data
-  // collection finishes after the next frame presentation. Note that no data
-  // will be reported if Stop() is not called,
-  void Stop();
+  // Stops tracking. Returns true when the supplied callback will be invoked
+  // when the data collection finishes. Returns false when the data collection
+  // is finished before Stop() is called, e.g. when gpu process crashes.
+  // Note that no data will be reported if Stop() is not called,
+  bool Stop();
 
   // Cancels tracking. The supplied callback will not be invoked.
   void Cancel();
diff --git a/ui/compositor/throughput_tracker_host.h b/ui/compositor/throughput_tracker_host.h
index d763516..6c694e0 100644
--- a/ui/compositor/throughput_tracker_host.h
+++ b/ui/compositor/throughput_tracker_host.h
@@ -25,8 +25,9 @@
   virtual void StartThroughputTracker(TrackerId tracker_id,
                                       ReportCallback callback) = 0;
 
-  // Stops the tracking for the given tracker id.
-  virtual void StopThroughtputTracker(TrackerId tracker_id) = 0;
+  // Stops the tracking for the given tracker id. Returns true if tracking
+  // is stopped successfully. Otherwise, returns false.
+  virtual bool StopThroughtputTracker(TrackerId tracker_id) = 0;
 
   // Cancels the tracking for the given tracker id.
   virtual void CancelThroughtputTracker(TrackerId tracker_id) = 0;
diff --git a/ui/gl/swap_chain_presenter.cc b/ui/gl/swap_chain_presenter.cc
index 6889bc6f..cefbf6b 100644
--- a/ui/gl/swap_chain_presenter.cc
+++ b/ui/gl/swap_chain_presenter.cc
@@ -30,6 +30,11 @@
 namespace gl {
 namespace {
 
+// When in BGRA888 overlay format, wait for this time delta before retrying
+// YUV format.
+constexpr base::TimeDelta kDelayForRetryingYUVFormat =
+    base::TimeDelta::FromMinutes(10);
+
 // Some drivers fail to correctly handle BT.709 video in overlays. This flag
 // converts them to BT.601 in the video processor.
 const base::Feature kFallbackBT709VideoToBT601{
@@ -235,6 +240,7 @@
     Microsoft::WRL::ComPtr<IDCompositionDevice2> dcomp_device)
     : layer_tree_(layer_tree),
       window_(window),
+      switched_to_BGRA8888_time_tick_(base::TimeTicks::Now()),
       d3d11_device_(d3d11_device),
       dcomp_device_(dcomp_device),
       is_on_battery_power_(
@@ -274,12 +280,21 @@
 
   if (swap_chain_format_ == yuv_overlay_format) {
     // Switch to BGRA once 3/4 of presents are composed.
-    if (composition_count >= (PresentationHistory::kPresentsToStore * 3 / 4))
+    if (composition_count >= (PresentationHistory::kPresentsToStore * 3 / 4)) {
+      switched_to_BGRA8888_time_tick_ = base::TimeTicks::Now();
       return DXGI_FORMAT_B8G8R8A8_UNORM;
+    }
   } else {
-    // Switch to YUV once 3/4 are using overlays (or unknown).
-    if (composition_count < (PresentationHistory::kPresentsToStore / 4))
+    // To prevent it from switching back and forth between YUV and BGRA8888,
+    // Wait for at least 10 minutes before we re-try YUV. On a system that
+    // can promote BGRA8888 but not YUV, the format change might cause
+    // flickers.
+    base::TimeDelta time_delta =
+        base::TimeTicks::Now() - switched_to_BGRA8888_time_tick_;
+    if (time_delta >= kDelayForRetryingYUVFormat) {
+      presentation_history_.Clear();
       return yuv_overlay_format;
+    }
   }
   return swap_chain_format_;
 }
diff --git a/ui/gl/swap_chain_presenter.h b/ui/gl/swap_chain_presenter.h
index c93bbca..afc17b0 100644
--- a/ui/gl/swap_chain_presenter.h
+++ b/ui/gl/swap_chain_presenter.h
@@ -12,6 +12,7 @@
 
 #include "base/containers/circular_deque.h"
 #include "base/power_monitor/power_monitor.h"
+#include "base/time/time.h"
 #include "base/win/scoped_handle.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gl/dc_renderer_layer_params.h"
@@ -202,6 +203,9 @@
   // Current swap chain format.
   DXGI_FORMAT swap_chain_format_ = DXGI_FORMAT_B8G8R8A8_UNORM;
 
+  // Last time tick when switching to BGRA8888 format.
+  base::TimeTicks switched_to_BGRA8888_time_tick_;
+
   // Whether the swap chain was reallocated, and next present will be the first.
   bool first_present_ = false;
 
diff --git a/ui/gtk/BUILD.gn b/ui/gtk/BUILD.gn
index 47ec07c..5afb864 100644
--- a/ui/gtk/BUILD.gn
+++ b/ui/gtk/BUILD.gn
@@ -44,14 +44,31 @@
   logging_include = "ui/gtk/log_noop.h"
 }
 
+source_set("gtk_compat") {
+  sources = [
+    "gtk_compat.cc",
+    "gtk_compat.h",
+  ]
+  defines = [ "IS_GTK_IMPL" ]
+  deps = [
+    ":gtk_buildflags",
+    ":gtk_stubs",
+    ":gtk_types",
+    "//base",
+    "//build/config/linux/gtk",
+    "//ui/base",
+    "//ui/gfx",
+  ]
+}
+
 component("gtk_ui_delegate") {
   public = [ "gtk_ui_delegate.h" ]
   sources = [ "gtk_ui_delegate.cc" ]
   deps = [
+    ":gtk_buildflags",
     "//base",
     "//ui/gfx",
   ]
-  public_deps = [ ":gtk_buildflags" ]
   defines = [ "IS_GTK_IMPL" ]
 }
 
@@ -63,8 +80,6 @@
   sources = [
     "gtk_color_mixers.cc",
     "gtk_color_mixers.h",
-    "gtk_compat.cc",
-    "gtk_compat.h",
     "gtk_key_bindings_handler.cc",
     "gtk_key_bindings_handler.h",
     "gtk_ui.cc",
@@ -104,9 +119,9 @@
   }
 
   deps = [
-    ":gtk_stubs",
-    ":gtk_types",
+    ":gtk_compat",
     "//base",
+    "//build/config/linux/gtk",
     "//build/config/linux/gtk:gtkprint",
     "//printing",
     "//skia",
@@ -114,7 +129,6 @@
     # GTK pulls pangoft2, which requires HarfBuzz symbols. When linking
     # our own HarfBuzz avoid mixing symbols from system HarfBuzz and
     # our own through the indirect dependency to harfbuzz-ng here.
-    "//build/config/linux/gtk",
     "//third_party:freetype_harfbuzz",
     "//ui/aura",
     "//ui/base",
diff --git a/ui/gtk/gtk_color_mixers.cc b/ui/gtk/gtk_color_mixers.cc
index 044ddd43..82085bda 100644
--- a/ui/gtk/gtk_color_mixers.cc
+++ b/ui/gtk/gtk_color_mixers.cc
@@ -21,7 +21,13 @@
 void AddGtkNativeCoreColorMixer(
     ui::ColorProvider* provider,
     ui::ColorProviderManager::ColorMode color_mode,
-    ui::ColorProviderManager::ContrastMode contrast_mode) {
+    ui::ColorProviderManager::ContrastMode contrast_mode,
+    ui::ColorProviderManager::ThemeName theme_name) {
+  // `theme_name` is empty when using the system theme. We do not initialize the
+  // GTK mixer in this case.
+  if (theme_name.empty())
+    return;
+
   ui::ColorMixer& mixer = provider->AddMixer();
 
   ui::ColorSet::ColorMap color_map;
diff --git a/ui/gtk/gtk_color_mixers.h b/ui/gtk/gtk_color_mixers.h
index 3b4edb5..eb7b92bc 100644
--- a/ui/gtk/gtk_color_mixers.h
+++ b/ui/gtk/gtk_color_mixers.h
@@ -16,7 +16,8 @@
 void AddGtkNativeCoreColorMixer(
     ui::ColorProvider* provider,
     ui::ColorProviderManager::ColorMode color_mode,
-    ui::ColorProviderManager::ContrastMode contrast_mode);
+    ui::ColorProviderManager::ContrastMode contrast_mode,
+    ui::ColorProviderManager::ThemeName theme_name);
 
 }  // namespace gtk
 
diff --git a/ui/gtk/gtk_compat.cc b/ui/gtk/gtk_compat.cc
index 7434830..614a9492 100644
--- a/ui/gtk/gtk_compat.cc
+++ b/ui/gtk/gtk_compat.cc
@@ -10,6 +10,7 @@
 #include "base/compiler_specific.h"
 #include "base/debug/leak_annotations.h"
 #include "base/no_destructor.h"
+#include "ui/gtk/gtk_buildflags.h"
 #include "ui/gtk/gtk_stubs.h"
 
 namespace gtk {
@@ -67,13 +68,7 @@
   return GetLibGtk3();
 }
 
-gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
-  return gfx::Insets(border.top, border.left, border.bottom, border.right);
-}
-
-}  // namespace
-
-bool LoadGtk(int gtk_version) {
+bool LoadGtkImpl(int gtk_version) {
   if (gtk_version < 4) {
     ui_gtk::InitializeGdk_pixbuf(GetLibGdkPixbuf());
     ui_gtk::InitializeGdk(GetLibGdk3());
@@ -92,6 +87,17 @@
   return true;
 }
 
+gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
+  return gfx::Insets(border.top, border.left, border.bottom, border.right);
+}
+
+}  // namespace
+
+bool LoadGtk() {
+  static bool loaded = LoadGtkImpl(BUILDFLAG(GTK_VERSION));
+  return loaded;
+}
+
 const base::Version& GtkVersion() {
   static base::NoDestructor<base::Version> gtk_version(
       std::vector<uint32_t>{gtk_get_major_version(), gtk_get_minor_version(),
diff --git a/ui/gtk/gtk_compat.h b/ui/gtk/gtk_compat.h
index ed6fb86..86bcf487 100644
--- a/ui/gtk/gtk_compat.h
+++ b/ui/gtk/gtk_compat.h
@@ -31,7 +31,7 @@
 namespace gtk {
 
 // Loads libgtk and related libraries and returns true on success.
-COMPONENT_EXPORT(GTK) bool LoadGtk(int gtk_version);
+COMPONENT_EXPORT(GTK) bool LoadGtk();
 
 const base::Version& GtkVersion();
 
diff --git a/ui/gtk/gtk_key_bindings_handler.h b/ui/gtk/gtk_key_bindings_handler.h
index afd795a..7ff77b4c 100644
--- a/ui/gtk/gtk_key_bindings_handler.h
+++ b/ui/gtk/gtk_key_bindings_handler.h
@@ -12,7 +12,7 @@
 
 #include "ui/base/ime/linux/text_edit_command_auralinux.h"
 #include "ui/events/platform_event.h"
-#include "ui/gtk/gtk_types.h"
+#include "ui/gtk/gtk_compat.h"
 
 namespace ui {
 class Event;
diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc
index 9f32b40..477af96 100644
--- a/ui/gtk/gtk_ui.cc
+++ b/ui/gtk/gtk_ui.cc
@@ -290,7 +290,6 @@
   using Action = views::LinuxUI::WindowFrameAction;
   using ActionSource = views::LinuxUI::WindowFrameActionSource;
 
-  DCHECK(delegate_);
   DCHECK(!g_gtk_ui);
   g_gtk_ui = this;
 
@@ -299,8 +298,7 @@
       {ActionSource::kMiddleClick, GetDefaultMiddleClickAction()},
       {ActionSource::kRightClick, Action::kMenu}};
 
-  static bool loaded = LoadGtk(BUILDFLAG(GTK_VERSION));
-  CHECK(loaded);
+  CHECK(LoadGtk());
 
   // Avoid GTK initializing atk-bridge, and let AuraLinux implementation
   // do it once it is ready.
diff --git a/ui/gtk/gtk_util.h b/ui/gtk/gtk_util.h
index 36d8846b..62e60881 100644
--- a/ui/gtk/gtk_util.h
+++ b/ui/gtk/gtk_util.h
@@ -14,7 +14,6 @@
 #include "base/component_export.h"
 #include "ui/base/glib/scoped_gobject.h"
 #include "ui/color/color_id.h"
-#include "ui/gtk/gtk_buildflags.h"
 #include "ui/gtk/gtk_compat.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/views/window/frame_buttons.h"
diff --git a/ui/gtk/input_method_context_impl_gtk.h b/ui/gtk/input_method_context_impl_gtk.h
index 2fb3356..c5f21cde 100644
--- a/ui/gtk/input_method_context_impl_gtk.h
+++ b/ui/gtk/input_method_context_impl_gtk.h
@@ -12,7 +12,6 @@
 #include "ui/base/glib/glib_signal.h"
 #include "ui/base/ime/linux/linux_input_method_context.h"
 #include "ui/gfx/geometry/rect.h"
-#include "ui/gtk/gtk_buildflags.h"
 
 using GtkIMContext = struct _GtkIMContext;
 using GdkWindow = struct _GdkWindow;
diff --git a/ui/gtk/native_theme_gtk.cc b/ui/gtk/native_theme_gtk.cc
index 171e3edb4..5cdbb71 100644
--- a/ui/gtk/native_theme_gtk.cc
+++ b/ui/gtk/native_theme_gtk.cc
@@ -164,6 +164,17 @@
   native_theme->NotifyOnNativeThemeUpdated();
 }
 
+std::string NativeThemeGtk::GetNativeThemeName() const {
+  gchar* theme = nullptr;
+  g_object_get(gtk_settings_get_default(), "gtk-theme-name", &theme, nullptr);
+  std::string theme_string;
+  if (theme) {
+    theme_string = theme;
+    g_free(theme);
+  }
+  return theme_string;
+}
+
 void NativeThemeGtk::OnThemeChanged(GtkSettings* settings,
                                     GtkParamSpec* param) {
   SetThemeCssOverride(ScopedCssProvider());
@@ -212,9 +223,7 @@
 
 bool NativeThemeGtk::AllowColorPipelineRedirection(
     ColorScheme color_scheme) const {
-  // TODO(crbug.com/1186781): Remove this override once we support NativeTheme
-  // changes for GTK in Color Pipeline.
-  return false;
+  return true;
 }
 
 SkColor NativeThemeGtk::GetSystemColorDeprecated(ColorId color_id,
diff --git a/ui/gtk/native_theme_gtk.h b/ui/gtk/native_theme_gtk.h
index 0d9366a..bcef1705 100644
--- a/ui/gtk/native_theme_gtk.h
+++ b/ui/gtk/native_theme_gtk.h
@@ -71,6 +71,7 @@
                          const FrameTopAreaExtraParams& frame_top_area,
                          ColorScheme color_scheme) const override;
   void NotifyOnNativeThemeUpdated() override;
+  std::string GetNativeThemeName() const override;
 
   void OnThemeChanged(GtkSettings* settings, GtkParamSpec* param);
 
diff --git a/ui/gtk/native_theme_gtk_unittest.cc b/ui/gtk/native_theme_gtk_unittest.cc
index a19d79f5..7ecc432 100644
--- a/ui/gtk/native_theme_gtk_unittest.cc
+++ b/ui/gtk/native_theme_gtk_unittest.cc
@@ -4,15 +4,16 @@
 
 #include "ui/gtk/native_theme_gtk.h"
 
+#include <memory>
 #include <tuple>
 
 #include "base/check.h"
 #include "base/command_line.h"
+#include "base/memory/ptr_util.h"
 #include "base/test/scoped_feature_list.h"
-#include "build/buildflag.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ui_base_features.h"
-#include "ui/gtk/gtk_compat.h"
+#include "ui/gtk/gtk_ui.h"
 #include "ui/gtk/gtk_util.h"
 #include "ui/native_theme/native_theme_color_id.h"
 #include "ui/native_theme/test/color_utils.h"
@@ -26,8 +27,7 @@
           std::tuple<ui::NativeTheme::ColorScheme, ui::NativeTheme::ColorId>> {
  public:
   NativeThemeGtkRedirectedEquivalenceTest() {
-    static bool loaded = LoadGtk(BUILDFLAG(GTK_VERSION));
-    CHECK(loaded);
+    gtk_ui_ = base::WrapUnique(BuildGtkUi(nullptr));
     GtkInitFromCommandLine(base::CommandLine(base::CommandLine::NO_PROGRAM));
   }
 
@@ -58,6 +58,8 @@
         return "kPlatformHighContrast";
     }
   }
+
+  std::unique_ptr<views::LinuxUI> gtk_ui_;
 };
 
 }  // namespace
diff --git a/ui/gtk/wayland/BUILD.gn b/ui/gtk/wayland/BUILD.gn
index 599af20..25943e4 100644
--- a/ui/gtk/wayland/BUILD.gn
+++ b/ui/gtk/wayland/BUILD.gn
@@ -15,6 +15,7 @@
   deps = [
     "//base",
     "//build/config/linux/gtk",
+    "//ui/gtk:gtk_compat",
   ]
   public_deps = [ "//ui/gtk:gtk_ui_delegate" ]
   defines = [ "IS_GTK_WAYLAND_IMPL" ]
diff --git a/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc b/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc
index f075333..81378647e 100644
--- a/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc
+++ b/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/environment.h"
 #include "base/logging.h"
+#include "ui/gtk/gtk_compat.h"
 
 #if BUILDFLAG(GTK_VERSION) >= 4
 #include <gdk/wayland/gdkwayland.h>
@@ -24,6 +25,8 @@
 namespace ui {
 
 GtkUiDelegateWaylandBase::GtkUiDelegateWaylandBase() {
+  CHECK(gtk::LoadGtk());
+
   gdk_set_allowed_backends("wayland");
   // GDK_BACKEND takes precedence over gdk_set_allowed_backends(), so override
   // it to ensure we get the wayland backend.
diff --git a/ui/gtk/x/BUILD.gn b/ui/gtk/x/BUILD.gn
index 6046a39..082178ef 100644
--- a/ui/gtk/x/BUILD.gn
+++ b/ui/gtk/x/BUILD.gn
@@ -21,6 +21,7 @@
     "//ui/base",
     "//ui/events/platform/x11",
     "//ui/gfx/x",
+    "//ui/gtk:gtk_compat",
     "//ui/platform_window/x11",
   ]
   public_deps = [ "//ui/gtk:gtk_ui_delegate" ]
diff --git a/ui/gtk/x/gtk_event_loop_x11.h b/ui/gtk/x/gtk_event_loop_x11.h
index 91cbe124..89ec463 100644
--- a/ui/gtk/x/gtk_event_loop_x11.h
+++ b/ui/gtk/x/gtk_event_loop_x11.h
@@ -10,7 +10,7 @@
 
 #include "ui/base/glib/glib_integers.h"
 #include "ui/base/glib/glib_signal.h"
-#include "ui/gtk/gtk_buildflags.h"
+#include "ui/gtk/gtk_compat.h"
 
 namespace ui {
 
diff --git a/ui/gtk/x/gtk_ui_delegate_x11.cc b/ui/gtk/x/gtk_ui_delegate_x11.cc
index 618d0865..9e1410b3 100644
--- a/ui/gtk/x/gtk_ui_delegate_x11.cc
+++ b/ui/gtk/x/gtk_ui_delegate_x11.cc
@@ -15,6 +15,7 @@
 #include "ui/gfx/x/xlib_support.h"
 #include "ui/gfx/x/xproto.h"
 #include "ui/gfx/x/xproto_util.h"
+#include "ui/gtk/gtk_compat.h"
 #include "ui/gtk/x/gtk_event_loop_x11.h"
 #include "ui/platform_window/x11/x11_window.h"
 #include "ui/platform_window/x11/x11_window_manager.h"
@@ -38,6 +39,8 @@
 GtkUiDelegateX11::GtkUiDelegateX11(x11::Connection* connection)
     : connection_(connection) {
   DCHECK(connection_);
+  CHECK(gtk::LoadGtk());
+
   gdk_set_allowed_backends("x11");
   // GDK_BACKEND takes precedence over gdk_set_allowed_backends(), so override
   // it to ensure we get the x11 backend.
diff --git a/ui/native_theme/native_theme.cc b/ui/native_theme/native_theme.cc
index 998e819..b58740ea 100644
--- a/ui/native_theme/native_theme.cc
+++ b/ui/native_theme/native_theme.cc
@@ -113,7 +113,8 @@
 
 base::Optional<SkColor> NativeTheme::GetColorProviderColor(
     ColorId color_id,
-    ColorScheme color_scheme) const {
+    ColorScheme color_scheme,
+    std::string theme_name) const {
   if (base::FeatureList::IsEnabled(features::kColorProviderRedirection) &&
       AllowColorPipelineRedirection(color_scheme)) {
     if (auto provider_color_id = NativeThemeColorIdToColorId(color_id)) {
@@ -123,7 +124,8 @@
                : ColorProviderManager::ColorMode::kLight,
            (color_scheme == NativeTheme::ColorScheme::kPlatformHighContrast)
                ? ColorProviderManager::ContrastMode::kHigh
-               : ColorProviderManager::ContrastMode::kNormal});
+               : ColorProviderManager::ContrastMode::kNormal,
+           std::move(theme_name)});
       ReportHistogramBooleanUsesColorProvider(true);
       return color_provider->GetColor(provider_color_id.value());
     }
@@ -154,6 +156,10 @@
              : PlatformHighContrastColorScheme::kLight;
 }
 
+std::string NativeTheme::GetNativeThemeName() const {
+  return std::string();
+}
+
 NativeTheme::PreferredColorScheme NativeTheme::GetPreferredColorScheme() const {
   return preferred_color_scheme_;
 }
@@ -307,8 +313,10 @@
   if (color_scheme == NativeTheme::ColorScheme::kDefault)
     color_scheme = GetDefaultSystemColorScheme();
 
-  if (auto color = GetColorProviderColor(color_id, color_scheme))
+  if (auto color =
+          GetColorProviderColor(color_id, color_scheme, GetNativeThemeName())) {
     return color.value();
+  }
 
   ReportHistogramBooleanUsesColorProvider(false);
   return GetSystemColorDeprecated(color_id, color_scheme, apply_processing);
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
index b4f22b9..177818c 100644
--- a/ui/native_theme/native_theme.h
+++ b/ui/native_theme/native_theme.h
@@ -449,6 +449,10 @@
   // colors, you probably shouldn't. Instead, use GetSystemColor().
   virtual bool ShouldUseDarkColors() const;
 
+  // Returns the name that uniquely identifies the current NativeTheme. Default
+  // implementation returns an empty string.
+  virtual std::string GetNativeThemeName() const;
+
   // Returns the OS-level user preferred color scheme. See the comment for
   // CalculatePreferredColorScheme() for details on how preferred color scheme
   // is calculated.
@@ -503,7 +507,8 @@
 
   // Gets the color from the color provider if using a color provider is enable.
   base::Optional<SkColor> GetColorProviderColor(ColorId color_id,
-                                                ColorScheme color_scheme) const;
+                                                ColorScheme color_scheme,
+                                                std::string theme_name) const;
 
   // Whether high contrast is forced via command-line flag.
   bool IsForcedHighContrast() const;
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index d5dd6609..ae3efba 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -922,6 +922,8 @@
     "animation/test/test_ink_drop_host.h",
     "animation/test/test_ink_drop_ripple_observer.cc",
     "animation/test/test_ink_drop_ripple_observer.h",
+    "controls/table/test_table_model.cc",
+    "controls/table/test_table_model.h",
     "controls/textfield/textfield_test_api.cc",
     "controls/textfield/textfield_test_api.h",
     "layout/animating_layout_manager_test_util.cc",
@@ -1149,8 +1151,6 @@
     "controls/tabbed_pane/tabbed_pane_unittest.cc",
     "controls/table/table_utils_unittest.cc",
     "controls/table/table_view_unittest.cc",
-    "controls/table/test_table_model.cc",
-    "controls/table/test_table_model.h",
     "controls/textarea/textarea_unittest.cc",
     "controls/textfield/textfield_model_unittest.cc",
     "controls/textfield/textfield_unittest.cc",
diff --git a/ui/views/accessibility/ax_event_manager.cc b/ui/views/accessibility/ax_event_manager.cc
index 7e1fd0f..d46d12e 100644
--- a/ui/views/accessibility/ax_event_manager.cc
+++ b/ui/views/accessibility/ax_event_manager.cc
@@ -33,4 +33,10 @@
     observer.OnViewEvent(view, event_type);
 }
 
+void AXEventManager::NotifyVirtualViewEvent(views::AXVirtualView* virtual_view,
+                                            ax::mojom::Event event_type) {
+  for (AXEventObserver& observer : observers_)
+    observer.OnVirtualViewEvent(virtual_view, event_type);
+}
+
 }  // namespace views
diff --git a/ui/views/accessibility/ax_event_manager.h b/ui/views/accessibility/ax_event_manager.h
index 0e734520..c491ee0 100644
--- a/ui/views/accessibility/ax_event_manager.h
+++ b/ui/views/accessibility/ax_event_manager.h
@@ -12,6 +12,7 @@
 namespace views {
 
 class AXEventObserver;
+class AXVirtualView;
 class View;
 
 // AXEventManager allows observation of accessibility events for all views.
@@ -30,6 +31,8 @@
 
   // Notifies observers of an accessibility event. |view| must not be null.
   void NotifyViewEvent(views::View* view, ax::mojom::Event event_type);
+  void NotifyVirtualViewEvent(views::AXVirtualView* virtual_view,
+                              ax::mojom::Event event_type);
 
  private:
   base::ObserverList<AXEventObserver> observers_;
diff --git a/ui/views/accessibility/ax_event_observer.h b/ui/views/accessibility/ax_event_observer.h
index 9dfd0a2..9658479 100644
--- a/ui/views/accessibility/ax_event_observer.h
+++ b/ui/views/accessibility/ax_event_observer.h
@@ -11,12 +11,15 @@
 
 namespace views {
 
+class AXVirtualView;
 class View;
 
 // AXEventObserver is notified for accessibility events on all views.
 class VIEWS_EXPORT AXEventObserver : public base::CheckedObserver {
  public:
   virtual void OnViewEvent(views::View* view, ax::mojom::Event event_type) = 0;
+  virtual void OnVirtualViewEvent(views::AXVirtualView* virtual_view,
+                                  ax::mojom::Event event_type) {}
 
  protected:
   AXEventObserver();
diff --git a/ui/views/accessibility/ax_virtual_view.cc b/ui/views/accessibility/ax_virtual_view.cc
index 5a6cdd44..c0900a5ab 100644
--- a/ui/views/accessibility/ax_virtual_view.cc
+++ b/ui/views/accessibility/ax_virtual_view.cc
@@ -20,6 +20,7 @@
 #include "ui/base/layout.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/views/accessibility/ax_event_manager.h"
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/accessibility/view_ax_platform_node_delegate.h"
 #include "ui/views/view.h"
@@ -202,7 +203,12 @@
     if (events_callback)
       events_callback.Run(this, event_type);
   }
+
+  // This is used on platforms that have a native accessibility API.
   ax_platform_node_->NotifyAccessibilityEvent(event_type);
+
+  // This is used on platforms that don't have a native accessibility API.
+  AXEventManager::Get()->NotifyVirtualViewEvent(this, event_type);
 }
 
 ui::AXNodeData& AXVirtualView::GetCustomData() {
diff --git a/ui/views/accessibility/ax_virtual_view_wrapper.cc b/ui/views/accessibility/ax_virtual_view_wrapper.cc
index bfdc3d66..cda91fe8 100644
--- a/ui/views/accessibility/ax_virtual_view_wrapper.cc
+++ b/ui/views/accessibility/ax_virtual_view_wrapper.cc
@@ -38,6 +38,12 @@
 
 void AXVirtualViewWrapper::Serialize(ui::AXNodeData* out_node_data) {
   *out_node_data = virtual_view_->GetData();
+  View* owner_view = virtual_view_->GetOwnerView();
+  if (owner_view && owner_view->GetWidget()) {
+    gfx::Point offset;
+    View::ConvertPointToScreen(owner_view, &offset);
+    out_node_data->relative_bounds.bounds.Offset(offset.x(), offset.y());
+  }
 }
 
 ui::AXNodeID AXVirtualViewWrapper::GetUniqueId() const {
diff --git a/ui/views/accessibility/view_accessibility.cc b/ui/views/accessibility/view_accessibility.cc
index 8cfb389a..c0e020c 100644
--- a/ui/views/accessibility/view_accessibility.cc
+++ b/ui/views/accessibility/view_accessibility.cc
@@ -458,8 +458,7 @@
 }
 
 void ViewAccessibility::NotifyAccessibilityEvent(ax::mojom::Event event_type) {
-  // On certain platforms, e.g. Chrome OS, we don't create any
-  // AXPlatformDelegates, so the base method in this file would be called.
+  // Used for unit testing.
   if (accessibility_events_callback_)
     accessibility_events_callback_.Run(nullptr, event_type);
 }
diff --git a/ui/views/controls/prefix_selector.cc b/ui/views/controls/prefix_selector.cc
index 014e9fd..541eb4b 100644
--- a/ui/views/controls/prefix_selector.cc
+++ b/ui/views/controls/prefix_selector.cc
@@ -87,6 +87,11 @@
   return rect;
 }
 
+gfx::Rect PrefixSelector::GetSelectionBoundingBox() const {
+  NOTIMPLEMENTED_LOG_ONCE();
+  return gfx::Rect();
+}
+
 bool PrefixSelector::GetCompositionCharacterBounds(uint32_t index,
                                                    gfx::Rect* rect) const {
   // TextInputClient::GetCompositionCharacterBounds is expected to fill |rect|
diff --git a/ui/views/controls/prefix_selector.h b/ui/views/controls/prefix_selector.h
index 390b23f..99c1353 100644
--- a/ui/views/controls/prefix_selector.h
+++ b/ui/views/controls/prefix_selector.h
@@ -56,6 +56,7 @@
   int GetTextInputFlags() const override;
   bool CanComposeInline() const override;
   gfx::Rect GetCaretBounds() const override;
+  gfx::Rect GetSelectionBoundingBox() const override;
   bool GetCompositionCharacterBounds(uint32_t index,
                                      gfx::Rect* rect) const override;
   bool HasCompositionText() const override;
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 39d6db7..0d6e91d 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1504,6 +1504,11 @@
   return rect;
 }
 
+gfx::Rect Textfield::GetSelectionBoundingBox() const {
+  NOTIMPLEMENTED_LOG_ONCE();
+  return gfx::Rect();
+}
+
 bool Textfield::GetCompositionCharacterBounds(uint32_t index,
                                               gfx::Rect* rect) const {
   DCHECK(rect);
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index 126dace..5e3a9f1 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -416,6 +416,7 @@
   int GetTextInputFlags() const override;
   bool CanComposeInline() const override;
   gfx::Rect GetCaretBounds() const override;
+  gfx::Rect GetSelectionBoundingBox() const override;
   bool GetCompositionCharacterBounds(uint32_t index,
                                      gfx::Rect* rect) const override;
   bool HasCompositionText() const override;
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc
index 685410d..ac73a84 100644
--- a/ui/views/controls/tree/tree_view.cc
+++ b/ui/views/controls/tree/tree_view.cc
@@ -699,8 +699,9 @@
 
     case ui::VKEY_UP:
     case ui::VKEY_DOWN:
-      IncrementSelection(event.key_code() == ui::VKEY_UP ? INCREMENT_PREVIOUS
-                                                         : INCREMENT_NEXT);
+      IncrementSelection(event.key_code() == ui::VKEY_UP
+                             ? IncrementType::kPrevious
+                             : IncrementType::kNext);
       return true;
 
     case ui::VKEY_LEFT:
@@ -1323,7 +1324,7 @@
     // If nothing is selected select the first or last node.
     if (root_.children().empty())
       return;
-    if (type == INCREMENT_PREVIOUS) {
+    if (type == IncrementType::kPrevious) {
       int row_count = GetRowCount();
       int depth = 0;
       DCHECK(row_count);
@@ -1338,7 +1339,7 @@
   }
 
   int depth = 0;
-  int delta = type == INCREMENT_PREVIOUS ? -1 : 1;
+  int delta = type == IncrementType::kPrevious ? -1 : 1;
   int row = GetRowForInternalNode(active_node_, &depth);
   int new_row = base::ClampToRange(row + delta, 0, GetRowCount() - 1);
   if (new_row == row)
diff --git a/ui/views/controls/tree/tree_view.h b/ui/views/controls/tree/tree_view.h
index 15dd3e6..9b3cbf4 100644
--- a/ui/views/controls/tree/tree_view.h
+++ b/ui/views/controls/tree/tree_view.h
@@ -307,12 +307,12 @@
   };
 
   // Used by IncrementSelection.
-  enum IncrementType {
+  enum class IncrementType {
     // Selects the next node.
-    INCREMENT_NEXT,
+    kNext,
 
     // Selects the previous node.
-    INCREMENT_PREVIOUS
+    kPrevious
   };
 
   // Row of the root node. This varies depending upon whether the root is
diff --git a/ui/views/controls/tree/tree_view_unittest.cc b/ui/views/controls/tree/tree_view_unittest.cc
index df91103..891495bf 100644
--- a/ui/views/controls/tree/tree_view_unittest.cc
+++ b/ui/views/controls/tree/tree_view_unittest.cc
@@ -329,8 +329,8 @@
 }
 
 void TreeViewTest::IncrementSelection(bool next) {
-  tree_->IncrementSelection(next ? TreeView::INCREMENT_NEXT
-                                 : TreeView::INCREMENT_PREVIOUS);
+  tree_->IncrementSelection(next ? TreeView::IncrementType::kNext
+                                 : TreeView::IncrementType::kPrevious);
 }
 
 void TreeViewTest::CollapseOrSelectParent() {
diff --git a/ui/views/corewm/tooltip_controller.cc b/ui/views/corewm/tooltip_controller.cc
index 284cb8d..54c0e6ff 100644
--- a/ui/views/corewm/tooltip_controller.cc
+++ b/ui/views/corewm/tooltip_controller.cc
@@ -127,11 +127,18 @@
 void TooltipController::UpdateTooltip(aura::Window* target) {
   // The |tooltip_parent_window_| is only set when the tooltip is visible or
   // its |will_show_tooltip_timer_| is running.
-  if (observed_window_ == target && state_manager_->tooltip_parent_window()) {
-    // Since this is an update on an already (or about to be) visible tooltip,
-    // assume that the trigger is the same as the one that initiated the current
-    // tooltip and reuse it.
-    UpdateIfRequired(state_manager_->tooltip_trigger());
+  if (target && observed_window_ == target) {
+    // This is either an update on an already (or about to be) visible tooltip
+    // or a call to UpdateIfRequired that will potentially trigger a tooltip
+    // caused by a tooltip text update.
+    //
+    // If there's no active tooltip, it's appropriate to assume that the trigger
+    // is kCursor because a tooltip text update triggered from the keyboard
+    // would always happen in UpdateTooltipFromKeyboard, not from here.
+    if (state_manager_->tooltip_parent_window())
+      UpdateIfRequired(state_manager_->tooltip_trigger());
+    else if (IsTooltipTextUpdateNeeded())
+      UpdateIfRequired(TooltipTrigger::kCursor);
   }
 
   ResetWindowAtMousePressedIfNeeded(target, /* force_reset */ false);
diff --git a/ui/views/corewm/tooltip_controller_unittest.cc b/ui/views/corewm/tooltip_controller_unittest.cc
index 9ab8a56a..b0da6f5 100644
--- a/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/ui/views/corewm/tooltip_controller_unittest.cc
@@ -752,6 +752,43 @@
   widget2.reset();
 }
 
+TEST_F(TooltipControllerTest, ShowTooltipOnTooltipTextUpdate) {
+  std::u16string expected_tooltip;
+
+  wm::SetTooltipText(GetWindow(), &expected_tooltip);
+
+  // Create a mouse event. This event shouldn't trigger the tooltip to show
+  // since the tooltip text is empty, but should set the |observed_window_|
+  // correctly.
+  gfx::Point point(1, 1);
+  View::ConvertPointToWidget(view_, &point);
+  generator_->MoveMouseRelativeTo(GetWindow(), point);
+
+  EXPECT_EQ(std::u16string(), helper_->GetTooltipText());
+  EXPECT_EQ(nullptr, helper_->GetTooltipParentWindow());
+  EXPECT_EQ(GetWindow(), helper_->GetObservedWindow());
+  EXPECT_FALSE(helper_->IsTooltipVisible());
+
+  // This is the heart of the test: we update the tooltip text and call
+  // UpdateTooltip. It should trigger the tooltip to show up because the
+  // |observed_window_| will be set to GetWindow() and the tooltip text on the
+  // window will be different than it previously was.
+  expected_tooltip = u"Tooltip text";
+  helper_->controller()->UpdateTooltip(GetWindow());
+
+  EXPECT_EQ(expected_tooltip, wm::GetTooltipText(GetWindow()));
+  EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+  EXPECT_EQ(GetWindow(), helper_->GetTooltipParentWindow());
+  EXPECT_TRUE(helper_->IsTooltipVisible());
+  EXPECT_EQ(helper_->state_manager()->tooltip_trigger(),
+            TooltipTrigger::kCursor);
+
+  helper_->HideAndReset();
+
+  EXPECT_FALSE(helper_->IsTooltipVisible());
+  EXPECT_EQ(nullptr, helper_->GetTooltipParentWindow());
+}
+
 namespace {
 
 class TestTooltip : public Tooltip {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
index 1493ae7..32a9410 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
@@ -18,6 +18,7 @@
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/events/event.h"
+#include "ui/platform_window/extensions/wayland_extension.h"
 #include "ui/platform_window/extensions/x11_extension.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 #include "ui/platform_window/wm/wm_move_resize_handler.h"
@@ -103,6 +104,23 @@
   open_windows_ = nullptr;
 }
 
+// static
+DesktopWindowTreeHostLinux* DesktopWindowTreeHostLinux::From(
+    WindowTreeHost* wth) {
+  DCHECK(open_windows_) << "Calling this method from non-Linux based "
+                           "platform.";
+
+  for (auto widget : *open_windows_) {
+    DesktopWindowTreeHostPlatform* wth_platform =
+        DesktopWindowTreeHostPlatform::GetHostForWidget(widget);
+    if (wth_platform != wth)
+      continue;
+
+    return static_cast<views::DesktopWindowTreeHostLinux*>(wth_platform);
+  }
+  return nullptr;
+}
+
 gfx::Rect DesktopWindowTreeHostLinux::GetXRootWindowOuterBounds() const {
   // TODO(msisov): must be removed as soon as all X11 low-level bits are moved
   // to Ozone.
@@ -139,6 +157,15 @@
                         weak_factory_.GetWeakPtr());
 }
 
+ui::WaylandExtension* DesktopWindowTreeHostLinux::GetWaylandExtension() {
+  return ui::GetWaylandExtension(*(platform_window()));
+}
+
+const ui::WaylandExtension* DesktopWindowTreeHostLinux::GetWaylandExtension()
+    const {
+  return ui::GetWaylandExtension(*(platform_window()));
+}
+
 void DesktopWindowTreeHostLinux::Init(const Widget::InitParams& params) {
   DesktopWindowTreeHostPlatform::Init(params);
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
index e033937..49c27768 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
@@ -25,6 +25,7 @@
 
 namespace ui {
 class X11Extension;
+class WaylandExtension;
 }  // namespace ui
 
 namespace views {
@@ -50,6 +51,9 @@
   // internal list of open windows.
   static void CleanUpWindowList(void (*func)(aura::Window* window));
 
+  // Casts from a base WindowTreeHost instance.
+  static DesktopWindowTreeHostLinux* From(WindowTreeHost* wth);
+
   // Returns the current bounds in terms of the X11 Root Window including the
   // borders provided by the window manager (if any). Not in use for Wayland.
   gfx::Rect GetXRootWindowOuterBounds() const;
@@ -66,6 +70,9 @@
   // Disables event listening to make |dialog| modal.
   base::OnceClosure DisableEventListening();
 
+  ui::WaylandExtension* GetWaylandExtension();
+  const ui::WaylandExtension* GetWaylandExtension() const;
+
  protected:
   // Overridden from DesktopWindowTreeHost:
   void Init(const Widget::InitParams& params) override;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 6418459f..0af4dfa5 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/feature_list.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
@@ -42,7 +41,6 @@
 #include "ui/views/buildflags.h"
 #include "ui/views/drag_utils.h"
 #include "ui/views/views_delegate.h"
-#include "ui/views/views_features.h"
 #include "ui/views/widget/drop_helper.h"
 #include "ui/views/widget/focus_manager_event_handler.h"
 #include "ui/views/widget/native_widget_delegate.h"
@@ -71,7 +69,6 @@
 
 #if BUILDFLAG(ENABLE_DESKTOP_AURA) && \
     (defined(OS_LINUX) || defined(OS_CHROMEOS))
-#include "ui/views/linux_ui/linux_ui.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
 #endif
 
@@ -1160,27 +1157,6 @@
 #endif
 }
 
-const ui::NativeTheme* Widget::GetNativeTheme() const {
-  if (base::FeatureList::IsEnabled(
-          features::kInheritNativeThemeFromParentWidget) &&
-      parent_) {
-    return parent_->GetNativeTheme();
-  }
-
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) && \
-    (defined(OS_LINUX) || defined(OS_CHROMEOS))
-  const LinuxUI* linux_ui = LinuxUI::instance();
-  if (linux_ui) {
-    ui::NativeTheme* native_theme =
-        linux_ui->GetNativeTheme(native_widget_->GetNativeWindow());
-    if (native_theme)
-      return native_theme;
-  }
-#endif
-
-  return ui::NativeTheme::GetInstanceForNativeUi();
-}
-
 namespace internal {
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm
index 77fa016..bbfae3e 100644
--- a/ui/views/widget/native_widget_mac.mm
+++ b/ui/views/widget/native_widget_mac.mm
@@ -12,7 +12,6 @@
 
 #include "base/base64.h"
 #include "base/bind.h"
-#include "base/feature_list.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/no_destructor.h"
 #include "base/strings/sys_string_conversions.h"
@@ -36,7 +35,6 @@
 #import "ui/views/cocoa/drag_drop_client_mac.h"
 #import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
 #include "ui/views/cocoa/text_input_host.h"
-#include "ui/views/views_features.h"
 #include "ui/views/widget/drop_helper.h"
 #include "ui/views/widget/widget_aura_utils.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -939,16 +937,6 @@
   }
 }
 
-const ui::NativeTheme* Widget::GetNativeTheme() const {
-  if (base::FeatureList::IsEnabled(
-          features::kInheritNativeThemeFromParentWidget) &&
-      parent_) {
-    return parent_->GetNativeTheme();
-  }
-
-  return ui::NativeTheme::GetInstanceForNativeUi();
-}
-
 namespace internal {
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 59f7da0..4f4282e 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -10,6 +10,7 @@
 #include "base/auto_reset.h"
 #include "base/check_op.h"
 #include "base/containers/adapters.h"
+#include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
@@ -33,6 +34,7 @@
 #include "ui/views/focus/focus_manager_factory.h"
 #include "ui/views/focus/widget_focus_manager.h"
 #include "ui/views/views_delegate.h"
+#include "ui/views/views_features.h"
 #include "ui/views/widget/any_widget_observer_singleton.h"
 #include "ui/views/widget/native_widget_private.h"
 #include "ui/views/widget/root_view.h"
@@ -399,7 +401,7 @@
     SetInitialBoundsForFramelessWindow(bounds);
   }
 
-  observation_.Observe(GetNativeTheme());
+  native_theme_observation_.Observe(GetNativeTheme());
   native_widget_initialized_ = true;
   native_widget_->OnWidgetInitDone();
 
@@ -806,13 +808,15 @@
 
 const ui::ColorProvider* Widget::GetColorProvider() const {
   auto color_scheme = GetNativeTheme()->GetDefaultSystemColorScheme();
+  auto theme_name = GetNativeTheme()->GetNativeThemeName();
   return ui::ColorProviderManager::Get().GetColorProviderFor(
       {(color_scheme == ui::NativeTheme::ColorScheme::kDark)
            ? ui::ColorProviderManager::ColorMode::kDark
            : ui::ColorProviderManager::ColorMode::kLight,
        (color_scheme == ui::NativeTheme::ColorScheme::kPlatformHighContrast)
            ? ui::ColorProviderManager::ContrastMode::kHigh
-           : ui::ColorProviderManager::ContrastMode::kNormal});
+           : ui::ColorProviderManager::ContrastMode::kNormal,
+       std::move(theme_name)});
 }
 
 FocusManager* Widget::GetFocusManager() {
@@ -1102,6 +1106,13 @@
   return native_widget_active_ || paint_as_active_refcount_;
 }
 
+void Widget::SetNativeTheme(ui::NativeTheme* native_theme) {
+  native_theme_ = native_theme;
+  native_theme_observation_.Reset();
+  if (native_theme)
+    native_theme_observation_.Observe(native_theme);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Widget, NativeWidgetDelegate implementation:
 
@@ -1528,19 +1539,6 @@
 
 void Widget::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
   TRACE_EVENT0("ui", "Widget::OnNativeThemeUpdated");
-
-  DCHECK(observation_.IsObservingSource(observed_theme));
-
-#if defined(OS_APPLE) || defined(OS_WIN)
-  ui::NativeTheme* current_native_theme = observed_theme;
-#else
-  ui::NativeTheme* current_native_theme = GetNativeTheme();
-#endif
-  if (!observation_.IsObservingSource(current_native_theme)) {
-    observation_.Reset();
-    observation_.Observe(current_native_theme);
-  }
-
   PropagateNativeThemeChanged();
 }
 
@@ -1570,6 +1568,18 @@
 
 void Widget::OnDragComplete() {}
 
+const ui::NativeTheme* Widget::GetNativeTheme() const {
+  if (native_theme_)
+    return native_theme_;
+
+  if (base::FeatureList::IsEnabled(
+          features::kInheritNativeThemeFromParentWidget) &&
+      parent_)
+    return parent_->GetNativeTheme();
+
+  return ui::NativeTheme::GetInstanceForNativeUi();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Widget, private:
 
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
index dde160f1a..5da6f1f 100644
--- a/ui/views/widget/widget.h
+++ b/ui/views/widget/widget.h
@@ -1007,6 +1007,11 @@
   // Overridden from ui::NativeThemeObserver:
   void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
 
+  // Set the native theme from which this widget gets color from.
+  void SetNativeThemeForTest(ui::NativeTheme* native_theme) {
+    SetNativeTheme(native_theme);
+  }
+
  protected:
   // Call this to propagate native theme changes to the root view. Subclasses
   // may override this to customize how native theme updates are propagated.
@@ -1028,6 +1033,9 @@
   // Notification that the drag performed by RunShellDrag() has completed.
   virtual void OnDragComplete();
 
+  // Set the native theme from which this widget gets color from.
+  void SetNativeTheme(ui::NativeTheme* native_theme);
+
  private:
   // Type of ways to ignore activation changes.
   enum class DisableActivationChangeHandlingType {
@@ -1204,8 +1212,12 @@
   // Block the widget from closing.
   bool block_close_ = false;
 
+  // The native theme this widget is using.
+  // If nullptr, defaults to use the regular native theme.
+  ui::NativeTheme* native_theme_ = nullptr;
+
   base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver>
-      observation_{this};
+      native_theme_observation_{this};
 
   base::WeakPtrFactory<Widget> weak_ptr_factory_{this};
 
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_list_item.js b/ui/webui/resources/cr_components/chromeos/network/network_list_item.js
index 92240ee..a6d2071 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_list_item.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_list_item.js
@@ -734,12 +734,19 @@
     if (!this.isUpdatedCellularUiEnabled_) {
       return false;
     }
-    if (!managedProperties || !managedProperties.typeProperties.cellular) {
+    if (!managedProperties) {
       return false;
     }
-    const paymentPortal =
-        managedProperties.typeProperties.cellular.paymentPortal;
-    if (paymentPortal && paymentPortal.url) {
+    const cellularProperties = managedProperties.typeProperties.cellular;
+    if (!cellularProperties || cellularProperties.eid) {
+      return false;
+    }
+    if (cellularProperties.activationState !==
+        chromeos.networkConfig.mojom.ActivationStateType.kNotActivated) {
+      return false;
+    }
+    if (cellularProperties.paymentPortal &&
+        cellularProperties.paymentPortal.url) {
       return true;
     }
     return false;
diff --git a/url/android/OWNERS b/url/android/OWNERS
deleted file mode 100644
index e69de29..0000000
--- a/url/android/OWNERS
+++ /dev/null
diff --git a/weblayer/browser/android/javatests/skew/expectations.txt b/weblayer/browser/android/javatests/skew/expectations.txt
index 6058b348..448b7a3 100644
--- a/weblayer/browser/android/javatests/skew/expectations.txt
+++ b/weblayer/browser/android/javatests/skew/expectations.txt
@@ -4,7 +4,9 @@
 # Lines tagged with "impl_lte_$VERSION" will be active when testing trunk client
 # with versions less than or equal to $VERSION of the implementation.
 #
-# tags: [ client_lte_87 client_lte_88 client_lte_89 ]
+# These lines are not comments! They define the set of known tags and other information.
+# tags: [ client_lte_87 client_lte_88 client_lte_89 client_lte_91 ]
+# tags: [ impl_lte_91 ]
 # results: [ Skip ]
 # conflicts_allowed: True
 
@@ -16,3 +18,53 @@
 
 # The test was changed in the main branch in crrev.com/c/2377987 and the changes won't be merged into M88
 crbug.com/1155565 [ client_lte_88 ] org.chromium.weblayer.test.CookieManagerTest#testSetCookieNotSet [ Skip ]
+
+# Bulk disable to get bot green.
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.FullscreenCallbackTest* [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.MediaSessionTest#basic [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.InputTypesTest* [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.NavigationTest#testDestroyTabWithModalDialog [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.NavigationTest#testRepostConfirmation [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.NewTabCallbackTest#testDestroyTabInOnNewTab [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testScrollNotificationDirectionChange [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testTabModalOverlay [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabListCallbackTest#testMoveToDifferentFragment [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabListCallbackTest#testDestroyTab [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabListCallbackTest#testActiveTabChanged [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabTest#testRotationDoesntChangeVisibility [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabTest#testBeforeUnload [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.NewTabCallbackTest#testNewBrowser [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.DownloadCallbackTest#testBasic [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.NewTabCallbackTest#testNewTabHasFocus [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.FindInPageTest#testHideOnNewTab [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testTabModalOverlayOnBackgroundTab [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.CookieManagerTest#testCookieChanged [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testDismissTransientUi [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.NavigationTest#testIsFormSubmission [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testOnRenderProcessGone [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.ScrollOffsetCallbackTest#testBasic [ Skip ]
+crbug.com/1191751 [ impl_lte_91 ] org.chromium.weblayer.test.TabListCallbackTest#testCallbackInvokedWhenTabClosedViaWebContents [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.FullscreenCallbackTest* [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.MediaSessionTest#basic [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.InputTypesTest* [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.NavigationTest#testDestroyTabWithModalDialog [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.NavigationTest#testRepostConfirmation [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.NewTabCallbackTest#testDestroyTabInOnNewTab [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testScrollNotificationDirectionChange [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testTabModalOverlay [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabListCallbackTest#testMoveToDifferentFragment [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabListCallbackTest#testDestroyTab [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabListCallbackTest#testActiveTabChanged [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabTest#testRotationDoesntChangeVisibility [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabTest#testBeforeUnload [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.NewTabCallbackTest#testNewBrowser [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.DownloadCallbackTest#testBasic [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.NewTabCallbackTest#testNewTabHasFocus [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.FindInPageTest#testHideOnNewTab [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testTabModalOverlayOnBackgroundTab [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.CookieManagerTest#testCookieChanged [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testDismissTransientUi [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.NavigationTest#testIsFormSubmission [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabCallbackTest#testOnRenderProcessGone [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.ScrollOffsetCallbackTest#testBasic [ Skip ]
+crbug.com/1191751 [ client_lte_91 ] org.chromium.weblayer.test.TabListCallbackTest#testCallbackInvokedWhenTabClosedViaWebContents [ Skip ]