diff --git a/DEPS b/DEPS
index 7ba5d28..ca8e5ac 100644
--- a/DEPS
+++ b/DEPS
@@ -111,11 +111,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': '1de48d8040aa263d4f79c023f9c31445310432a9',
+  'skia_revision': 'c09dc8ac723f81554581562f5cef3f302ae17f31',
   # 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': 'd2036a9f91efb2fa671c4b9c328ccfe5f569de31',
+  'v8_revision': 'bb933756abe4cb9d3a94bca336db3a38b707ab0f',
   # 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.
@@ -123,7 +123,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': '4a22f4b04619fd92138f4b37f861eebc2b0bfc6b',
+  'angle_revision': '0da64b5e1009a8d1b011fbb3c31ca52cecc71899',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -135,7 +135,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'b7c4a0243e82f6c4ff91cd90b5bae336100c3c70',
+  'pdfium_revision': 'ea08d171755bd4088d01261c55d1bfe0ff0f9f39',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -171,7 +171,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '00755b36f6d2dcf7228d6f6bb7f851f82ee5d21e',
+  'catapult_revision': '25da2e8be18d819ef6b5223a8b9dbf2223344cda',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -650,7 +650,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9201a4e1a9369d1618bc8737a97d9f6ded6d6e3e',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9ab423a548ac7085671685a355af5fd251a1b070',
       'condition': 'checkout_linux',
   },
 
@@ -670,7 +670,7 @@
   },
 
   'src/third_party/custom_tabs_client/src': {
-      'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + '873e69c103480c501fafdacf06e90febadeeff9c',
+      'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + 'c813ed8fcc4ece1838dba8dddf6d8ca39d6c6785',
       'condition': 'checkout_android',
   },
 
@@ -1004,7 +1004,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'a56061dd6c202a9497843d72604934135bff55c6',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'acda68b0292e8c8283b45f999eb8e7d95281cac5',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1156,7 +1156,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '0d55c887e92b645f6effe753528323ab2ffd94c2',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '72864963fe626e0971d7725b878a49d3784b6f87',
+    Var('webrtc_git') + '/src.git' + '@' + '12048c71501a2b62225e65ba270cdcd0dcd691ee',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1187,7 +1187,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0a47db54fa15928f891e86d0c2637b222bd391a6',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b0874f87a68d71e21e7b926ff2d17cf004ff8eb8',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 1a66c20f..a7187be 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -997,6 +997,11 @@
                   'content/renderer/indexed_db|'\
                   'content/test/data/indexeddb',
     },
+    'infra': {
+      'filepath': 'infra/config|'\
+                  'testing/buildbot|'\
+                  'tools/mb',
+    },
     'ink_drop': {
       'filepath': 'ui/views/animation/test/.*ink_drop.*|' \
                   'ui/views/animation/.*ink_drop.*'
@@ -2191,6 +2196,7 @@
     'incident_reporting': ['grt+watch@chromium.org'],
     'indexed_db': ['cmumford@chromium.org',
                    'jsbell+idb@chromium.org'],
+    'infra': ['jbudorick+watch@chromium.org'],
     'ink_drop': ['bruthig+ink_drop@chromium.org'],
     'input': ['dtapuska+chromiumwatch@chromium.org'],
     'input_devices': ['spang+watch@chromium.org'],
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 5644931..7bc95f1 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -1603,11 +1603,18 @@
 
 TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_NextTrack) {
   EXPECT_EQ(0, client()->handle_media_next_track_count());
+  EXPECT_EQ(0, controller()->next_track_count());
 
   ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_NEXT_TRACK, ui::EF_NONE));
   Shell::Get()->media_controller()->FlushForTesting();
 
-  EXPECT_EQ(1, client()->handle_media_next_track_count());
+  if (service_enabled()) {
+    EXPECT_EQ(0, client()->handle_media_next_track_count());
+    EXPECT_EQ(1, controller()->next_track_count());
+  } else {
+    EXPECT_EQ(1, client()->handle_media_next_track_count());
+    EXPECT_EQ(0, controller()->next_track_count());
+  }
 }
 
 TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_PlayPause) {
@@ -1628,11 +1635,18 @@
 
 TEST_P(MediaSessionAcceleratorTest, MediaGlobalAccelerators_PrevTrack) {
   EXPECT_EQ(0, client()->handle_media_prev_track_count());
+  EXPECT_EQ(0, controller()->previous_track_count());
 
   ProcessInController(ui::Accelerator(ui::VKEY_MEDIA_PREV_TRACK, ui::EF_NONE));
   Shell::Get()->media_controller()->FlushForTesting();
 
-  EXPECT_EQ(1, client()->handle_media_prev_track_count());
+  if (service_enabled()) {
+    EXPECT_EQ(0, client()->handle_media_prev_track_count());
+    EXPECT_EQ(1, controller()->previous_track_count());
+  } else {
+    EXPECT_EQ(1, client()->handle_media_prev_track_count());
+    EXPECT_EQ(0, controller()->previous_track_count());
+  }
 }
 
 }  // namespace ash
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc
index 6c43a60d..04e4b88 100644
--- a/ash/app_list/app_list_presenter_delegate_unittest.cc
+++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -1188,9 +1188,9 @@
       GetAppListView()->GetAppListBackgroundShieldForTest()->layer();
   EXPECT_EQ(0.7f, background_layer->opacity());
 
-  // Turn on tablet mode. The background sheild opacity should be 10%.
+  // Turn on tablet mode. The background shield should be transparent.
   EnableTabletMode(true);
-  EXPECT_EQ(0.4f, background_layer->opacity());
+  EXPECT_EQ(0.f, background_layer->opacity());
 }
 
 // Tests that the background blur is disabled for the app list.
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc
index 824adc9..3f31b4f1 100644
--- a/ash/app_list/views/app_list_view.cc
+++ b/ash/app_list/views/app_list_view.cc
@@ -89,9 +89,6 @@
 constexpr float kAppListAnimationDurationMs = 200;
 constexpr float kAppListAnimationDurationFromFullscreenMs = 250;
 
-// The app list opacity when the tablet mode is enabled.
-constexpr float kAppListOpacityInTabletMode = 0.4;
-
 // The background corner radius in peeking and fullscreen state.
 constexpr int kAppListBackgroundRadius = 28;
 
@@ -289,8 +286,6 @@
           std::make_unique<HideViewAnimationObserver>()),
       transition_animation_observer_(
           std::make_unique<TransitionAnimationObserver>(this)),
-      previous_arrow_key_traversal_enabled_(
-          views::FocusManager::arrow_key_traversal_enabled()),
       state_animation_metrics_reporter_(
           std::make_unique<StateAnimationMetricsReporter>()),
       is_home_launcher_enabled_(app_list_features::IsHomeLauncherEnabled()),
@@ -298,18 +293,12 @@
           app_list_features::IsNewStyleLauncherEnabled()),
       weak_ptr_factory_(this) {
   CHECK(delegate);
-
-  // Enable arrow key in FocusManager. Arrow left/right and up/down triggers
-  // the same focus movement as tab/shift+tab.
-  views::FocusManager::set_arrow_key_traversal_enabled(true);
 }
 
 AppListView::~AppListView() {
   hide_view_animation_observer_.reset();
   // Remove child views first to ensure no remaining dependencies on delegate_.
   RemoveAllChildViews(true);
-  views::FocusManager::set_arrow_key_traversal_enabled(
-      previous_arrow_key_traversal_enabled_);
 }
 
 // static
@@ -592,6 +581,11 @@
   fullscreen_widget_->GetNativeView()->SetBounds(
       GetPreferredWidgetBoundsForState(AppListViewState::CLOSED));
 
+  // Enable arrow key in FocusManager. Arrow left/right and up/down triggers
+  // the same focus movement as tab/shift+tab.
+  fullscreen_widget_->GetFocusManager()
+      ->set_arrow_key_traversal_enabled_for_widget(true);
+
   widget_observer_ = std::make_unique<FullscreenWidgetObserver>(this);
 }
 
@@ -1123,8 +1117,7 @@
       parent_window->AddChild(window);
 
     // Update background opacity.
-    app_list_background_shield_->layer()->SetOpacity(
-        kAppListOpacityInTabletMode);
+    app_list_background_shield_->layer()->SetOpacity(0.f);
 
     // Update background blur.
     if (is_background_blur_enabled_)
diff --git a/ash/app_list/views/app_list_view.h b/ash/app_list/views/app_list_view.h
index d456966..454f4d2 100644
--- a/ash/app_list/views/app_list_view.h
+++ b/ash/app_list/views/app_list_view.h
@@ -409,9 +409,6 @@
   // Accessibility announcement dialogue.
   base::string16 state_announcement_;
 
-  // Whether FocusManager can handle arrow key before this class is constructed.
-  const bool previous_arrow_key_traversal_enabled_;
-
   // Metric reporter for state change animations.
   const std::unique_ptr<ui::AnimationMetricsReporter>
       state_animation_metrics_reporter_;
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 344bbf7f..3a08e49 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -181,12 +181,6 @@
   login_screen_client_->HardlockPod(account_id);
 }
 
-void LoginScreenController::RecordClickOnLockIcon(const AccountId& account_id) {
-  if (!login_screen_client_)
-    return;
-  login_screen_client_->RecordClickOnLockIcon(account_id);
-}
-
 void LoginScreenController::OnFocusPod(const AccountId& account_id) {
   if (!login_screen_client_)
     return;
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index 7082f9f..738741e 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -66,7 +66,6 @@
   void EnrollUserWithExternalBinary(OnAuthenticateCallback callback);
   void AuthenticateUserWithEasyUnlock(const AccountId& account_id);
   void HardlockPod(const AccountId& account_id);
-  void RecordClickOnLockIcon(const AccountId& account_id);
   void OnFocusPod(const AccountId& account_id);
   void OnNoPodFocused();
   void LoadWallpaper(const AccountId& account_id);
diff --git a/ash/login/login_screen_controller_unittest.cc b/ash/login/login_screen_controller_unittest.cc
index ec4a93a..7c73d94 100644
--- a/ash/login/login_screen_controller_unittest.cc
+++ b/ash/login/login_screen_controller_unittest.cc
@@ -99,11 +99,6 @@
   EXPECT_CALL(*client, HardlockPod(id));
   controller->HardlockPod(id);
   base::RunLoop().RunUntilIdle();
-
-  // Verify RecordClickOnLockIcon mojo call is run with the same account id.
-  EXPECT_CALL(*client, RecordClickOnLockIcon(id));
-  controller->RecordClickOnLockIcon(id);
-  base::RunLoop().RunUntilIdle();
 }
 
 TEST_F(LoginScreenControllerTest, RequestUserPodFocus) {
diff --git a/ash/login/mock_login_screen_client.h b/ash/login/mock_login_screen_client.h
index 00cfd90..d2bc8f3 100644
--- a/ash/login/mock_login_screen_client.h
+++ b/ash/login/mock_login_screen_client.h
@@ -67,7 +67,6 @@
   MOCK_METHOD1(AuthenticateUserWithEasyUnlock,
                void(const AccountId& account_id));
   MOCK_METHOD1(HardlockPod, void(const AccountId& account_id));
-  MOCK_METHOD1(RecordClickOnLockIcon, void(const AccountId& account_id));
   MOCK_METHOD1(OnFocusPod, void(const AccountId& account_id));
   MOCK_METHOD0(OnNoPodFocused, void());
   MOCK_METHOD1(LoadWallpaper, void(const AccountId& account_id));
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index c6d54e5..ef99069 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -27,6 +27,7 @@
 #include "ash/wallpaper/wallpaper_controller.h"
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/user_manager/user.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -459,6 +460,15 @@
   return view_->disabled_auth_message_;
 }
 
+views::Button* LoginAuthUserView::TestApi::external_binary_auth_button() const {
+  return view_->external_binary_auth_button_;
+}
+
+views::Button* LoginAuthUserView::TestApi::external_binary_enrollment_button()
+    const {
+  return view_->external_binary_enrollment_button_;
+}
+
 LoginAuthUserView::Callbacks::Callbacks() = default;
 
 LoginAuthUserView::Callbacks::Callbacks(const Callbacks& other) = default;
@@ -640,6 +650,11 @@
   external_binary_auth_button_->SetVisible(has_external_binary);
   external_binary_enrollment_button_->SetVisible(has_external_binary);
 
+  if (has_external_binary) {
+    power_manager_client_observer_.Add(
+        chromeos::DBusThreadManager::Get()->GetPowerManagerClient());
+  }
+
   int padding_view_height = kDistanceBetweenPasswordFieldAndPinKeyboardDp;
   if (has_fingerprint && !has_pin) {
     padding_view_height = kDistanceBetweenPasswordFieldAndFingerprintViewDp;
@@ -853,13 +868,7 @@
   if (sender == online_sign_in_message_) {
     OnOnlineSignInMessageTap();
   } else if (sender == external_binary_auth_button_) {
-    password_view_->SetReadOnly(true);
-    external_binary_auth_button_->SetEnabled(false);
-    external_binary_enrollment_button_->SetEnabled(false);
-    Shell::Get()->login_screen_controller()->AuthenticateUserWithExternalBinary(
-        current_user()->basic_user_info->account_id,
-        base::BindOnce(&LoginAuthUserView::OnAuthComplete,
-                       weak_factory_.GetWeakPtr()));
+    AttemptAuthenticateWithExternalBinary();
   } else if (sender == external_binary_enrollment_button_) {
     password_view_->SetReadOnly(true);
     external_binary_auth_button_->SetEnabled(false);
@@ -870,6 +879,13 @@
   }
 }
 
+void LoginAuthUserView::LidEventReceived(
+    chromeos::PowerManagerClient::LidState state,
+    const base::TimeTicks& timestamp) {
+  if (state == chromeos::PowerManagerClient::LidState::OPEN)
+    AttemptAuthenticateWithExternalBinary();
+}
+
 void LoginAuthUserView::OnAuthSubmit(const base::string16& password) {
   // Pressing enter when the password field is empty and tap-to-unlock is
   // enabled should attempt unlock.
@@ -942,4 +958,14 @@
   return (auth_methods_ & auth_method) != 0;
 }
 
+void LoginAuthUserView::AttemptAuthenticateWithExternalBinary() {
+  password_view_->SetReadOnly(true);
+  external_binary_auth_button_->SetEnabled(false);
+  external_binary_enrollment_button_->SetEnabled(false);
+  Shell::Get()->login_screen_controller()->AuthenticateUserWithExternalBinary(
+      current_user()->basic_user_info->account_id,
+      base::BindOnce(&LoginAuthUserView::OnAuthComplete,
+                     weak_factory_.GetWeakPtr()));
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/login_auth_user_view.h b/ash/login/ui/login_auth_user_view.h
index d728a93..6db9cb6e 100644
--- a/ash/login/ui/login_auth_user_view.h
+++ b/ash/login/ui/login_auth_user_view.h
@@ -16,6 +16,8 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/scoped_observer.h"
+#include "base/time/time.h"
+#include "chromeos/dbus/power_manager_client.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
 
@@ -34,8 +36,10 @@
 // This class will make call mojo authentication APIs directly. The embedder can
 // receive some events about the results of those mojo
 // authentication attempts (ie, success/failure).
-class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
-                                     public views::ButtonListener {
+class ASH_EXPORT LoginAuthUserView
+    : public NonAccessibleView,
+      public views::ButtonListener,
+      public chromeos::PowerManagerClient::Observer {
  public:
   // TestApi is used for tests to get internal implementation details.
   class ASH_EXPORT TestApi {
@@ -48,6 +52,8 @@
     LoginPinView* pin_view() const;
     views::Button* online_sign_in_message() const;
     views::View* disabled_auth_message() const;
+    views::Button* external_binary_auth_button() const;
+    views::Button* external_binary_enrollment_button() const;
 
    private:
     LoginAuthUserView* const view_;
@@ -137,6 +143,10 @@
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
+  // chromeos::PowerManagerClient::Observer:
+  void LidEventReceived(chromeos::PowerManagerClient::LidState state,
+                        const base::TimeTicks& timestamp) override;
+
  private:
   struct AnimationState;
   class FingerprintView;
@@ -161,6 +171,10 @@
   // bool has_tap = HasAuthMethod(AUTH_TAP).
   bool HasAuthMethod(AuthMethods auth_method) const;
 
+  // TODO(crbug/899812): remove this and pass a handler in via the Callbacks
+  // struct instead.
+  void AttemptAuthenticateWithExternalBinary();
+
   AuthMethods auth_methods_ = AUTH_NONE;
   // True if the user's password might be a PIN. PIN is hashed differently from
   // password. The PIN keyboard may not always be visible even when the user
@@ -188,6 +202,10 @@
   // |ApplyAnimationPostLayout|.
   std::unique_ptr<AnimationState> cached_animation_state_;
 
+  ScopedObserver<chromeos::PowerManagerClient,
+                 chromeos::PowerManagerClient::Observer>
+      power_manager_client_observer_{this};
+
   base::WeakPtrFactory<LoginAuthUserView> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(LoginAuthUserView);
diff --git a/ash/login/ui/login_auth_user_view_unittest.cc b/ash/login/ui/login_auth_user_view_unittest.cc
index 532c5055..b2b5b90 100644
--- a/ash/login/ui/login_auth_user_view_unittest.cc
+++ b/ash/login/ui/login_auth_user_view_unittest.cc
@@ -12,13 +12,19 @@
 #include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/controls/textfield/textfield_test_api.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/widget/widget.h"
 
+using testing::_;
+
 namespace ash {
 
 namespace {
@@ -30,6 +36,9 @@
 
   // LoginTestBase:
   void SetUp() override {
+    power_manager_ = new chromeos::FakePowerManagerClient();
+    chromeos::DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient(
+        base::WrapUnique(power_manager_));
     LoginTestBase::SetUp();
 
     user_ = CreateUser("user@domain.com");
@@ -59,6 +68,8 @@
   mojom::LoginUserInfoPtr user_;
   views::View* container_ = nullptr;   // Owned by test widget view hierarchy.
   LoginAuthUserView* view_ = nullptr;  // Owned by test widget view hierarchy.
+  chromeos::FakePowerManagerClient* power_manager_ =
+      nullptr;  // Owned by DBusThreadmanager
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LoginAuthUserViewUnittest);
@@ -187,4 +198,31 @@
   EXPECT_FALSE(has_password());
 }
 
+TEST_F(LoginAuthUserViewUnittest, AttemptsUnlockOnLidOpen) {
+  LoginAuthUserView::TestApi test_auth_user_view(view_);
+  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+
+  SetAuthMethods(LoginAuthUserView::AUTH_EXTERNAL_BINARY);
+
+  client->set_authenticate_user_callback_result(false);
+
+  EXPECT_CALL(*client, AuthenticateUserWithExternalBinary_(
+                           test_auth_user_view.user_view()
+                               ->current_user()
+                               ->basic_user_info->account_id,
+                           _));
+  power_manager_->SetLidState(chromeos::PowerManagerClient::LidState::OPEN,
+                              base::TimeTicks::Now());
+
+  base::RunLoop().RunUntilIdle();
+
+  LoginPasswordView::TestApi password_test(test_auth_user_view.password_view());
+  EXPECT_FALSE(password_test.textfield()->read_only());
+  EXPECT_TRUE(test_auth_user_view.external_binary_auth_button()->state() ==
+              views::Button::STATE_NORMAL);
+  EXPECT_TRUE(
+      test_auth_user_view.external_binary_enrollment_button()->state() ==
+      views::Button::STATE_NORMAL);
+}
+
 }  // namespace ash
diff --git a/ash/media_controller.cc b/ash/media_controller.cc
index 7f0d5835..5e943f1 100644
--- a/ash/media_controller.cc
+++ b/ash/media_controller.cc
@@ -52,14 +52,26 @@
 }
 
 void MediaController::HandleMediaNextTrack() {
-  // TODO(beccahughes): Add media session service integration.
+  // If media session media key handling is enabled. Fire next track using the
+  // media session service.
+  if (base::FeatureList::IsEnabled(features::kMediaSessionAccelerators)) {
+    if (GetMediaSessionController())
+      GetMediaSessionController()->NextTrack();
+    return;
+  }
 
   if (client_)
     client_->HandleMediaNextTrack();
 }
 
 void MediaController::HandleMediaPrevTrack() {
-  // TODO(beccahughes): Add media session service integration.
+  // If media session media key handling is enabled. Fire previous track using
+  // the media session service.
+  if (base::FeatureList::IsEnabled(features::kMediaSessionAccelerators)) {
+    if (GetMediaSessionController())
+      GetMediaSessionController()->PreviousTrack();
+    return;
+  }
 
   if (client_)
     client_->HandleMediaPrevTrack();
diff --git a/ash/media_controller.h b/ash/media_controller.h
index 5c82620..45c818a 100644
--- a/ash/media_controller.h
+++ b/ash/media_controller.h
@@ -52,14 +52,14 @@
       const base::flat_map<AccountId, mojom::MediaCaptureState>& capture_states)
       override;
 
-  // If media session accelerators are enabled then this method will use the
+  // If media session accelerators are enabled then these methods will use the
   // media session service to control playback. Otherwise it will forward to
   // |client_|.
   void HandleMediaPlayPause();
-
-  // Methods that forward to |client_|.
   void HandleMediaNextTrack();
   void HandleMediaPrevTrack();
+
+  // Methods that forward to |client_|.
   void RequestCaptureState();
   void SuspendMediaSessions();
 
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc
index b625ad6..5dcc9a2 100644
--- a/ash/public/cpp/app_list/app_list_features.cc
+++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -18,6 +18,8 @@
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kEnablePlayStoreAppSearch{
     "EnablePlayStoreAppSearch", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kEnableAppDataSearch{"EnableAppDataSearch",
+                                         base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kEnableHomeLauncher{"EnableHomeLauncher",
                                         base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableHomeLauncherGestures{
@@ -55,6 +57,10 @@
   return base::FeatureList::IsEnabled(kEnablePlayStoreAppSearch);
 }
 
+bool IsAppDataSearchEnabled() {
+  return base::FeatureList::IsEnabled(kEnableAppDataSearch);
+}
+
 bool IsHomeLauncherEnabled() {
   return base::FeatureList::IsEnabled(kEnableHomeLauncher);
 }
diff --git a/ash/public/cpp/app_list/app_list_features.h b/ash/public/cpp/app_list/app_list_features.h
index c5d4ba10..00b059c 100644
--- a/ash/public/cpp/app_list/app_list_features.h
+++ b/ash/public/cpp/app_list/app_list_features.h
@@ -32,6 +32,9 @@
 // Enables the Play Store app search.
 ASH_PUBLIC_EXPORT extern const base::Feature kEnablePlayStoreAppSearch;
 
+// Enables in-app data search.
+ASH_PUBLIC_EXPORT extern const base::Feature kEnableAppDataSearch;
+
 // Enables the home launcher in tablet mode. In this mode, the launcher will be
 // always shown right on top of the wallpaper. Home button will minimize all
 // windows instead of toggling the launcher.
@@ -67,6 +70,7 @@
 bool ASH_PUBLIC_EXPORT IsAppShortcutSearchEnabled();
 bool ASH_PUBLIC_EXPORT IsBackgroundBlurEnabled();
 bool ASH_PUBLIC_EXPORT IsPlayStoreAppSearchEnabled();
+bool ASH_PUBLIC_EXPORT IsAppDataSearchEnabled();
 bool ASH_PUBLIC_EXPORT IsHomeLauncherEnabled();
 bool ASH_PUBLIC_EXPORT IsHomeLauncherGesturesEnabled();
 bool ASH_PUBLIC_EXPORT IsSettingsShortcutSearchEnabled();
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom
index 750482f..3dc408c 100644
--- a/ash/public/interfaces/login_screen.mojom
+++ b/ash/public/interfaces/login_screen.mojom
@@ -251,10 +251,6 @@
   // |account_id|:    The account id of the user in the user pod.
   HardlockPod(signin.mojom.AccountId account_id);
 
-  // Record clicks on the lock icon in the user pod.
-  // |account_id|:    The account id of the user in the user pod.
-  RecordClickOnLockIcon(signin.mojom.AccountId account_id);
-
   // Focus user pod of user with |account_id|.
   OnFocusPod(signin.mojom.AccountId account_id);
 
diff --git a/ash/public/interfaces/login_user_info.mojom b/ash/public/interfaces/login_user_info.mojom
index 89b6532..a58732b 100644
--- a/ash/public/interfaces/login_user_info.mojom
+++ b/ash/public/interfaces/login_user_info.mojom
@@ -75,11 +75,6 @@
   // display via a separate EasyUnlockIconsOption update. See
   // login_screen.mojom::HardlockPod.
   bool hardlock_on_click;
-  // If true, the lock screen is being demoed so the user can test out easy
-  // unlock. The flow operates as normal. Hardlocking is disabled in this
-  // scenario.
-  // TODO(jdufault): This should be removed, as it does not change UI.
-  bool is_trial_run;
 };
 
 // Infomation of each input method. This is used to populate keyboard layouts
diff --git a/ash/system/power/power_button_controller.cc b/ash/system/power/power_button_controller.cc
index bb58387..b28e342 100644
--- a/ash/system/power/power_button_controller.cc
+++ b/ash/system/power/power_button_controller.cc
@@ -76,6 +76,11 @@
   gfx::Rect widget_bounds =
       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
   menu_widget->SetBounds(widget_bounds);
+
+  // Enable arrow key in FocusManager. Arrow right/left and down/up triggers
+  // the same focus movement as tab/shift+tab.
+  menu_widget->GetFocusManager()->set_arrow_key_traversal_enabled_for_widget(
+      true);
   return menu_widget;
 }
 
@@ -143,9 +148,7 @@
 
 PowerButtonController::PowerButtonController(
     BacklightsForcedOffSetter* backlights_forced_off_setter)
-    : arrow_key_traversal_initially_enabled_(
-          views::FocusManager::arrow_key_traversal_enabled()),
-      backlights_forced_off_setter_(backlights_forced_off_setter),
+    : backlights_forced_off_setter_(backlights_forced_off_setter),
       lock_state_controller_(Shell::Get()->lock_state_controller()),
       tick_clock_(base::DefaultTickClock::GetInstance()),
       backlights_forced_off_observer_(this),
@@ -347,8 +350,6 @@
 
   show_menu_animation_done_ = false;
   active_window_widget_controller_.reset();
-  views::FocusManager::set_arrow_key_traversal_enabled(
-      arrow_key_traversal_initially_enabled_);
 }
 
 void PowerButtonController::StopForcingBacklightsOff() {
@@ -521,9 +522,6 @@
 
 void PowerButtonController::SetShowMenuAnimationDone() {
   show_menu_animation_done_ = true;
-  // Enable arrow key in FocusManager. Arrow right/left and down/up triggers
-  // the same focus movement as tab/shift+tab.
-  views::FocusManager::set_arrow_key_traversal_enabled(true);
   pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this,
                             &PowerButtonController::OnPreShutdownTimeout);
 }
diff --git a/ash/system/power/power_button_controller.h b/ash/system/power/power_button_controller.h
index ef452b0..31f66ff 100644
--- a/ash/system/power/power_button_controller.h
+++ b/ash/system/power/power_button_controller.h
@@ -237,9 +237,6 @@
   // True if the next button release event should force the display off.
   bool force_off_on_button_up_ = false;
 
-  // Whether FocusManager can handle arrow key before showing the power menu.
-  const bool arrow_key_traversal_initially_enabled_;
-
   // Used to force backlights off, when needed.
   BacklightsForcedOffSetter* backlights_forced_off_setter_;  // Not owned.
 
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc
index 2a25267..b1a321b1 100644
--- a/ash/wallpaper/wallpaper_view.cc
+++ b/ash/wallpaper/wallpaper_view.cc
@@ -31,6 +31,10 @@
 namespace ash {
 namespace {
 
+// The value used for alpha to apply a dark filter to the wallpaper in tablet
+// mode. A higher number up to 255 results in a darker wallpaper.
+constexpr int kWallpaperDimnessInTabletMode = 102;
+
 // A view that controls the child view's layer so that the layer always has the
 // same size as the display's original, un-scaled size in DIP. The layer is then
 // transformed to fit to the virtual screen size when laid-out. This is to avoid
@@ -85,6 +89,10 @@
   return SkColorSetA(darken_color, login_constants::kTranslucentAlpha);
 }
 
+SkColor GetWallpaperDarkenColorForTabletMode() {
+  return SkColorSetA(GetWallpaperDarkenColor(), kWallpaperDimnessInTabletMode);
+}
+
 }  // namespace
 
 // This event handler receives events in the pre-target phase and takes care of
@@ -131,12 +139,30 @@
     : pre_dispatch_handler_(new PreEventDispatchHandler()) {
   set_context_menu_controller(this);
   AddPreTargetHandler(pre_dispatch_handler_.get());
+  tablet_mode_observer_.Add(Shell::Get()->tablet_mode_controller());
+  is_tablet_mode_ = Shell::Get()
+                        ->tablet_mode_controller()
+                        ->IsTabletModeWindowManagerEnabled();
 }
 
 WallpaperView::~WallpaperView() {
   RemovePreTargetHandler(pre_dispatch_handler_.get());
 }
 
+void WallpaperView::OnTabletModeStarted() {
+  is_tablet_mode_ = true;
+  SchedulePaint();
+}
+
+void WallpaperView::OnTabletModeEnded() {
+  is_tablet_mode_ = false;
+  SchedulePaint();
+}
+
+void WallpaperView::OnTabletControllerDestroyed() {
+  tablet_mode_observer_.RemoveAll();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WallpaperView, views::View overrides:
 
@@ -160,6 +186,9 @@
   if (controller->ShouldApplyDimming()) {
     flags.setColorFilter(SkColorFilter::MakeModeFilter(
         GetWallpaperDarkenColor(), SkBlendMode::kDarken));
+  } else if (is_tablet_mode_) {
+    flags.setColorFilter(SkColorFilter::MakeModeFilter(
+        GetWallpaperDarkenColorForTabletMode(), SkBlendMode::kDarken));
   }
 
   switch (layout) {
diff --git a/ash/wallpaper/wallpaper_view.h b/ash/wallpaper/wallpaper_view.h
index 134ad94..17ee2210 100644
--- a/ash/wallpaper/wallpaper_view.h
+++ b/ash/wallpaper/wallpaper_view.h
@@ -7,6 +7,9 @@
 
 #include <memory>
 
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "ash/wm/tablet_mode/tablet_mode_observer.h"
+#include "base/scoped_observer.h"
 #include "ui/views/context_menu_controller.h"
 #include "ui/views/view.h"
 
@@ -18,7 +21,9 @@
 
 class PreEventDispatchHandler;
 
-class WallpaperView : public views::View, public views::ContextMenuController {
+class WallpaperView : public views::View,
+                      public views::ContextMenuController,
+                      TabletModeObserver {
  public:
   WallpaperView();
   ~WallpaperView() override;
@@ -30,10 +35,20 @@
   void OnPaint(gfx::Canvas* canvas) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
 
+  // Overridden from TabletModeObserver:
+  void OnTabletModeStarted() override;
+  void OnTabletModeEnded() override;
+  void OnTabletControllerDestroyed() override;
+
   // Overridden from views::ContextMenuController:
   void ShowContextMenuForView(views::View* source,
                               const gfx::Point& point,
                               ui::MenuSourceType source_type) override;
+
+  ScopedObserver<TabletModeController, TabletModeObserver>
+      tablet_mode_observer_{this};
+  bool is_tablet_mode_ = false;
+
   std::unique_ptr<PreEventDispatchHandler> pre_dispatch_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(WallpaperView);
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc
index e2a000c..cda09cc 100644
--- a/ash/wm/overview/window_grid.cc
+++ b/ash/wm/overview/window_grid.cc
@@ -33,6 +33,7 @@
 #include "ash/wm/overview/window_selector_delegate.h"
 #include "ash/wm/overview/window_selector_item.h"
 #include "ash/wm/splitview/split_view_drag_indicators.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_window_state.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
@@ -206,7 +207,12 @@
     background_view_ = new views::View();
     background_view_->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
     background_view_->layer()->SetColor(kShieldBaseColor);
-    background_view_->layer()->SetOpacity(kShieldOpacity);
+    background_view_->layer()->SetOpacity(
+        !Shell::Get()
+                ->tablet_mode_controller()
+                ->IsTabletModeWindowManagerEnabled()
+            ? kShieldOpacity
+            : 0.f);
 
     label_ = new views::Label(
         l10n_util::GetStringUTF16(IDS_ASH_OVERVIEW_NO_RECENT_ITEMS),
diff --git a/ash/wm/overview/window_grid.h b/ash/wm/overview/window_grid.h
index 974f6c7..b6d6efa 100644
--- a/ash/wm/overview/window_grid.h
+++ b/ash/wm/overview/window_grid.h
@@ -58,9 +58,9 @@
              const gfx::Rect& bounds_in_screen);
   ~WindowGrid() override;
 
-  // The opacity of the shield widget that is used to darden the background of
+  // The opacity of the shield widget that is used to darken the background of
   // the grid.
-  static constexpr float kShieldOpacity = 0.6f;
+  static constexpr float kShieldOpacity = 0.4f;
 
   // Returns the shield color that is used to darken the background of the grid.
   static SkColor GetShieldColor();
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc
index e52f1ac..5717061 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -166,6 +166,9 @@
   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
       this);
 
+  for (auto& observer : tablet_mode_observers_)
+    observer.OnTabletControllerDestroyed();
+
   TabletMode::SetCallback(TabletMode::TabletModeCallback());
 }
 
diff --git a/ash/wm/tablet_mode/tablet_mode_observer.h b/ash/wm/tablet_mode/tablet_mode_observer.h
index 8420d7e..18575ce 100644
--- a/ash/wm/tablet_mode/tablet_mode_observer.h
+++ b/ash/wm/tablet_mode/tablet_mode_observer.h
@@ -29,8 +29,12 @@
   // connected.
   virtual void OnTabletModeEventsBlockingChanged() {}
 
+  // Called when the tablet mode controller is destroyed, to help manage issues
+  // with observers being destroyed after controllers.
+  virtual void OnTabletControllerDestroyed() {}
+
  protected:
-  virtual ~TabletModeObserver() {}
+  virtual ~TabletModeObserver() = default;
 };
 
 }  // namespace ash
diff --git a/base/BUILD.gn b/base/BUILD.gn
index c361e8c..e86ea57 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -950,8 +950,6 @@
     "trace_event/memory_usage_estimator.h",
     "trace_event/process_memory_dump.cc",
     "trace_event/process_memory_dump.h",
-    "trace_event/trace_arguments.cc",
-    "trace_event/trace_arguments.h",
     "trace_event/trace_buffer.cc",
     "trace_event/trace_buffer.h",
     "trace_event/trace_category.h",
@@ -2531,7 +2529,6 @@
     "trace_event/memory_infra_background_whitelist_unittest.cc",
     "trace_event/memory_usage_estimator_unittest.cc",
     "trace_event/process_memory_dump_unittest.cc",
-    "trace_event/trace_arguments_unittest.cc",
     "trace_event/trace_category_unittest.cc",
     "trace_event/trace_config_unittest.cc",
     "trace_event/trace_event_filter_test_utils.cc",
diff --git a/base/bind_internal.h b/base/bind_internal.h
index aff03a6..d8f574a 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -417,7 +417,7 @@
   }
 };
 
-#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
+#if defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
 
 // For functions.
 template <typename R, typename... Args>
@@ -445,7 +445,7 @@
   }
 };
 
-#endif  // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
+#endif  // defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
 
 #if defined(OS_MACOSX)
 
diff --git a/base/trace_event/blame_context.cc b/base/trace_event/blame_context.cc
index b46412c..0ed9aa7 100644
--- a/base/trace_event/blame_context.cc
+++ b/base/trace_event/blame_context.cc
@@ -33,9 +33,9 @@
 BlameContext::~BlameContext() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(WasInitialized());
-  TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_DELETE_OBJECT,
-                                  category_group_enabled_, type_, scope_, id_,
-                                  nullptr, TRACE_EVENT_FLAG_HAS_ID);
+  TRACE_EVENT_API_ADD_TRACE_EVENT(
+      TRACE_EVENT_PHASE_DELETE_OBJECT, category_group_enabled_, type_, scope_,
+      id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID);
   trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver(this);
 }
 
@@ -43,6 +43,7 @@
   DCHECK(WasInitialized());
   TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_ENTER_CONTEXT,
                                   category_group_enabled_, name_, scope_, id_,
+                                  0 /* num_args */, nullptr, nullptr, nullptr,
                                   nullptr, TRACE_EVENT_FLAG_HAS_ID);
 }
 
@@ -50,6 +51,7 @@
   DCHECK(WasInitialized());
   TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_LEAVE_CONTEXT,
                                   category_group_enabled_, name_, scope_, id_,
+                                  0 /* num_args */, nullptr, nullptr, nullptr,
                                   nullptr, TRACE_EVENT_FLAG_HAS_ID);
 }
 
@@ -61,10 +63,15 @@
   std::unique_ptr<trace_event::TracedValue> snapshot(
       new trace_event::TracedValue);
   AsValueInto(snapshot.get());
-  TraceArguments args("snapshot", std::move(snapshot));
+  static const char* const kArgName = "snapshot";
+  const int kNumArgs = 1;
+  unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE};
+  std::unique_ptr<trace_event::ConvertableToTraceFormat> arg_values[1] = {
+      std::move(snapshot)};
   TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT,
                                   category_group_enabled_, type_, scope_, id_,
-                                  &args, TRACE_EVENT_FLAG_HAS_ID);
+                                  kNumArgs, &kArgName, arg_types, nullptr,
+                                  arg_values, TRACE_EVENT_FLAG_HAS_ID);
 }
 
 void BlameContext::OnTraceLogEnabled() {
@@ -88,9 +95,9 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   category_group_enabled_ =
       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_);
-  TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_CREATE_OBJECT,
-                                  category_group_enabled_, type_, scope_, id_,
-                                  nullptr, TRACE_EVENT_FLAG_HAS_ID);
+  TRACE_EVENT_API_ADD_TRACE_EVENT(
+      TRACE_EVENT_PHASE_CREATE_OBJECT, category_group_enabled_, type_, scope_,
+      id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID);
   trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver(
       weak_factory_.GetWeakPtr());
   TakeSnapshot();
diff --git a/base/trace_event/event_name_filter_unittest.cc b/base/trace_event/event_name_filter_unittest.cc
index d5bd057..134be0d 100644
--- a/base/trace_event/event_name_filter_unittest.cc
+++ b/base/trace_event/event_name_filter_unittest.cc
@@ -12,10 +12,11 @@
 namespace trace_event {
 
 const TraceEvent& MakeTraceEvent(const char* name) {
-  static TraceEvent trace_event;
-  trace_event = TraceEvent(0, TimeTicks(), ThreadTicks(), 'b', nullptr, name,
-                           "", 0, 0, nullptr, 0);
-  return trace_event;
+  static TraceEvent event;
+  event.Reset();
+  event.Initialize(0, TimeTicks(), ThreadTicks(), 'b', nullptr, name, "", 0, 0,
+                   0, nullptr, nullptr, nullptr, nullptr, 0);
+  return event;
 }
 
 TEST(TraceEventNameFilterTest, Whitelist) {
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc
index 5a049cc..8f851f4 100644
--- a/base/trace_event/process_memory_dump.cc
+++ b/base/trace_event/process_memory_dump.cc
@@ -13,7 +13,6 @@
 #include "base/process/process_metrics.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/memory_infra_background_whitelist.h"
-#include "base/trace_event/trace_event_impl.h"
 #include "base/trace_event/traced_value.h"
 #include "base/unguessable_token.h"
 #include "build/build_config.h"
diff --git a/base/trace_event/trace_arguments.cc b/base/trace_event/trace_arguments.cc
deleted file mode 100644
index 002720f..0000000
--- a/base/trace_event/trace_arguments.cc
+++ /dev/null
@@ -1,270 +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 "base/trace_event/trace_arguments.h"
-
-#include <inttypes.h>
-#include <stddef.h>
-#include <string.h>
-
-#include <stdio.h>
-
-#include "base/json/string_escape.h"
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-size_t GetAllocLength(const char* str) {
-  return str ? strlen(str) + 1 : 0;
-}
-
-// Copies |*member| into |*buffer|, sets |*member| to point to this new
-// location, and then advances |*buffer| by the amount written.
-void CopyTraceEventParameter(char** buffer,
-                             const char** member,
-                             const char* end) {
-  if (*member) {
-    size_t written = strlcpy(*buffer, *member, end - *buffer) + 1;
-    DCHECK_LE(static_cast<int>(written), end - *buffer);
-    *member = *buffer;
-    *buffer += written;
-  }
-}
-
-// Append |val| as a JSON output value to |*out|.
-void AppendDoubleAsJSON(double val, std::string* out) {
-  // FIXME: base/json/json_writer.cc is using the same code,
-  //        should be made into a common method.
-  std::string real;
-  if (std::isfinite(val)) {
-    real = NumberToString(val);
-    // Ensure that the number has a .0 if there's no decimal or 'e'.  This
-    // makes sure that when we read the JSON back, it's interpreted as a
-    // real rather than an int.
-    if (real.find('.') == std::string::npos &&
-        real.find('e') == std::string::npos &&
-        real.find('E') == std::string::npos) {
-      real.append(".0");
-    }
-    // The JSON spec requires that non-integer values in the range (-1,1)
-    // have a zero before the decimal point - ".52" is not valid, "0.52" is.
-    if (real[0] == '.') {
-      real.insert(0, "0");
-    } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
-      // "-.1" bad "-0.1" good
-      real.insert(1, "0");
-    }
-  } else if (std::isnan(val)) {
-    // The JSON spec doesn't allow NaN and Infinity (since these are
-    // objects in EcmaScript).  Use strings instead.
-    real = "\"NaN\"";
-  } else if (val < 0) {
-    real = "\"-Infinity\"";
-  } else {
-    real = "\"Infinity\"";
-  }
-  StringAppendF(out, "%s", real.c_str());
-}
-
-const char* TypeToString(char arg_type) {
-  switch (arg_type) {
-    case TRACE_VALUE_TYPE_INT:
-      return "int";
-    case TRACE_VALUE_TYPE_UINT:
-      return "uint";
-    case TRACE_VALUE_TYPE_DOUBLE:
-      return "double";
-    case TRACE_VALUE_TYPE_BOOL:
-      return "bool";
-    case TRACE_VALUE_TYPE_POINTER:
-      return "pointer";
-    case TRACE_VALUE_TYPE_STRING:
-      return "string";
-    case TRACE_VALUE_TYPE_COPY_STRING:
-      return "copy_string";
-    case TRACE_VALUE_TYPE_CONVERTABLE:
-      return "convertable";
-    default:
-      NOTREACHED();
-      return "UNKNOWN_TYPE";
-  }
-}
-
-void AppendValueDebugString(const TraceArguments& args,
-                            size_t idx,
-                            std::string* out) {
-  *out += (args.names()[idx] ? args.names()[idx] : "NULL_NAME");
-  *out += "=";
-  *out += TypeToString(args.types()[idx]);
-  *out += "(";
-  args.values()[idx].AppendAsJSON(args.types()[idx], out);
-  *out += ")";
-}
-
-}  // namespace
-
-void StringStorage::Reset(size_t alloc_size) {
-  if (!alloc_size) {
-    if (data_)
-      ::free(data_);
-    data_ = nullptr;
-  } else if (!data_ || alloc_size != data_->size) {
-    data_ = static_cast<Data*>(::realloc(data_, sizeof(size_t) + alloc_size));
-    data_->size = alloc_size;
-  }
-}
-
-bool StringStorage::Contains(const TraceArguments& args) const {
-  for (size_t n = 0; n < args.size(); ++n) {
-    if (args.types()[n] == TRACE_VALUE_TYPE_COPY_STRING &&
-        !Contains(args.values()[n].as_string)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-static_assert(
-    std::is_pod<TraceValue>::value,
-    "TraceValue must be plain-old-data type for performance reasons!");
-
-void TraceValue::AppendAsJSON(unsigned char type, std::string* out) const {
-  switch (type) {
-    case TRACE_VALUE_TYPE_BOOL:
-      *out += this->as_bool ? "true" : "false";
-      break;
-    case TRACE_VALUE_TYPE_UINT:
-      StringAppendF(out, "%" PRIu64, static_cast<uint64_t>(this->as_uint));
-      break;
-    case TRACE_VALUE_TYPE_INT:
-      StringAppendF(out, "%" PRId64, static_cast<int64_t>(this->as_int));
-      break;
-    case TRACE_VALUE_TYPE_DOUBLE:
-      AppendDoubleAsJSON(this->as_double, out);
-      break;
-    case TRACE_VALUE_TYPE_POINTER:
-      // JSON only supports double and int numbers.
-      // So as not to lose bits from a 64-bit pointer, output as a hex string.
-      StringAppendF(
-          out, "\"0x%" PRIx64 "\"",
-          static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this->as_pointer)));
-      break;
-    case TRACE_VALUE_TYPE_STRING:
-    case TRACE_VALUE_TYPE_COPY_STRING:
-      EscapeJSONString(this->as_string ? this->as_string : "NULL", true, out);
-      break;
-    case TRACE_VALUE_TYPE_CONVERTABLE:
-      this->as_convertable->AppendAsTraceFormat(out);
-      break;
-    default:
-      NOTREACHED() << "Don't know how to print this value";
-      break;
-  }
-}
-
-TraceArguments& TraceArguments::operator=(TraceArguments&& other) noexcept {
-  if (this != &other) {
-    this->~TraceArguments();
-    new (this) TraceArguments(std::move(other));
-  }
-  return *this;
-}
-
-TraceArguments::TraceArguments(int num_args,
-                               const char* const* arg_names,
-                               const unsigned char* arg_types,
-                               const unsigned long long* arg_values) {
-  if (num_args > static_cast<int>(kMaxSize))
-    num_args = static_cast<int>(kMaxSize);
-
-  size_ = static_cast<unsigned char>(num_args);
-  for (size_t n = 0; n < size_; ++n) {
-    types_[n] = arg_types[n];
-    names_[n] = arg_names[n];
-    values_[n].as_uint = arg_values[n];
-  }
-}
-
-void TraceArguments::Reset() {
-  for (size_t n = 0; n < size_; ++n) {
-    if (types_[n] == TRACE_VALUE_TYPE_CONVERTABLE)
-      delete values_[n].as_convertable;
-  }
-  size_ = 0;
-}
-
-void TraceArguments::CopyStringsTo(StringStorage* storage,
-                                   bool copy_all_strings,
-                                   const char** extra_string1,
-                                   const char** extra_string2) {
-  // First, compute total allocation size.
-  size_t alloc_size = 0;
-
-  if (copy_all_strings) {
-    alloc_size +=
-        GetAllocLength(*extra_string1) + GetAllocLength(*extra_string2);
-    for (size_t n = 0; n < size_; ++n)
-      alloc_size += GetAllocLength(names_[n]);
-  }
-  for (size_t n = 0; n < size_; ++n) {
-    if (copy_all_strings && types_[n] == TRACE_VALUE_TYPE_STRING)
-      types_[n] = TRACE_VALUE_TYPE_COPY_STRING;
-    if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING)
-      alloc_size += GetAllocLength(values_[n].as_string);
-  }
-
-  if (alloc_size) {
-    storage->Reset(alloc_size);
-    char* ptr = storage->data();
-    const char* end = ptr + alloc_size;
-    if (copy_all_strings) {
-      CopyTraceEventParameter(&ptr, extra_string1, end);
-      CopyTraceEventParameter(&ptr, extra_string2, end);
-      for (size_t n = 0; n < size_; ++n)
-        CopyTraceEventParameter(&ptr, &names_[n], end);
-    }
-    for (size_t n = 0; n < size_; ++n) {
-      if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING)
-        CopyTraceEventParameter(&ptr, &values_[n].as_string, end);
-    }
-#if DCHECK_IS_ON()
-    DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end;
-    if (copy_all_strings) {
-      if (extra_string1 && *extra_string1)
-        DCHECK(storage->Contains(*extra_string1));
-      if (extra_string2 && *extra_string2)
-        DCHECK(storage->Contains(*extra_string2));
-      for (size_t n = 0; n < size_; ++n)
-        DCHECK(storage->Contains(names_[n]));
-    }
-    for (size_t n = 0; n < size_; ++n) {
-      if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING)
-        DCHECK(storage->Contains(values_[n].as_string));
-    }
-#endif  // DCHECK_IS_ON()
-  } else {
-    storage->Reset();
-  }
-}
-
-void TraceArguments::AppendDebugString(std::string* out) {
-  *out += "TraceArguments(";
-  for (size_t n = 0; n < size_; ++n) {
-    if (n > 0)
-      *out += ", ";
-    AppendValueDebugString(*this, n, out);
-  }
-  *out += ")";
-}
-
-}  // namespace trace_event
-}  // namespace base
diff --git a/base/trace_event/trace_arguments.h b/base/trace_event/trace_arguments.h
deleted file mode 100644
index 31d5bdff..0000000
--- a/base/trace_event/trace_arguments.h
+++ /dev/null
@@ -1,653 +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 BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_
-#define BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_
-
-#include <stdlib.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/trace_event/common/trace_event_common.h"
-
-// Trace macro can have one or two optional arguments, each one of them
-// identified by a name (a C string literal) and a value, which can be an
-// integer, enum, floating point, boolean, string pointer or reference, or
-// std::unique_ptr<ConvertableToTraceFormat> compatible values. Additionally,
-// custom data types need to be supported, like time values or WTF::CString.
-//
-// TraceArguments is a helper class used to store 0 to 2 named arguments
-// corresponding to an individual trace macro call. As efficiently as possible,
-// and with the minimal amount of generated machine code (since this affects
-// any TRACE macro call). Each argument has:
-//
-//  - A name (C string literal, e.g "dumps")
-//  - An 8-bit type value, corresponding to the TRACE_VALUE_TYPE_XXX macros.
-//  - A value, stored in a TraceValue union
-//
-// IMPORTANT: For a TRACE_VALUE_TYPE_CONVERTABLE types, the TraceArguments
-// instance owns the pointed ConvertableToTraceFormat object, i.e. it will
-// delete it automatically on destruction.
-//
-// TraceArguments instances should be built using one of specialized
-// constructors declared below. One cannot modify an instance once it has
-// been built, except for move operations, Reset() and destruction. Examples:
-//
-//    TraceArguments args;    // No arguments.
-//    // args.size() == 0
-//
-//    TraceArguments("foo", 100);
-//    // args.size() == 1
-//    // args.types()[0] == TRACE_VALUE_TYPE_INT
-//    // args.names()[0] == "foo"
-//    // args.values()[0].as_int == 100
-//
-//    TraceArguments("bar", 1ULL);
-//    // args.size() == 1
-//    // args.types()[0] == TRACE_VALUE_TYPE_UINT
-//    // args.names()[0] == "bar"
-//    // args.values()[0].as_uint == 100
-//
-//    TraceArguments("foo", "Hello", "bar", "World");
-//    // args.size() == 2
-//    // args.types()[0] == TRACE_VALUE_TYPE_STRING
-//    // args.types()[1] == TRACE_VALUE_TYPE_STRING
-//    // args.names()[0] == "foo"
-//    // args.names()[1] == "bar"
-//    // args.values()[0].as_string == "Hello"
-//    // args.values()[1].as_string == "World"
-//
-//    std::string some_string = ...;
-//    TraceArguments("str1", some_string);
-//    // args.size() == 1
-//    // args.types()[0] == TRACE_VALUE_TYPE_COPY_STRING
-//    // args.names()[0] == "str1"
-//    // args.values()[0].as_string == some_string.c_str()
-//
-// Note that TRACE_VALUE_TYPE_COPY_STRING corresponds to string pointers
-// that point to temporary values that may disappear soon. The
-// TraceArguments::CopyStringTo() method can be used to copy their content
-// into a StringStorage memory block, and update the |as_string| value pointers
-// to it to avoid keeping any dangling pointers. This is used by TraceEvent
-// to keep copies of such strings in the log after their initialization values
-// have disappeared.
-//
-// The TraceStringWithCopy helper class can be used to initialize a value
-// from a regular string pointer with TRACE_VALUE_TYPE_COPY_STRING too, as in:
-//
-//     const char str[] = "....";
-//     TraceArguments("foo", str, "bar", TraceStringWithCopy(str));
-//     // args.size() == 2
-//     // args.types()[0] == TRACE_VALUE_TYPE_STRING
-//     // args.types()[1] == TRACE_VALUE_TYPE_COPY_STRING
-//     // args.names()[0] == "foo"
-//     // args.names()[1] == "bar"
-//     // args.values()[0].as_string == str
-//     // args.values()[1].as_string == str
-//
-//     StringStorage storage;
-//     args.CopyStringTo(&storage, false, nullptr, nullptr);
-//     // args.size() == 2
-//     // args.types()[0] == TRACE_VALUE_TYPE_STRING
-//     // args.types()[1] == TRACE_VALUE_TYPE_COPY_STRING
-//     // args.names()[0] == "foo"
-//     // args.names()[1] == "bar"
-//     // args.values()[0].as_string == str
-//     // args.values()[1].as_string == Address inside |storage|.
-//
-// Initialization from a std::unique_ptr<ConvertableToTraceFormat>
-// is supported but will move ownership of the pointer objects to the
-// TraceArguments instance:
-//
-//     class MyConvertableType :
-//         public base::trace_event::AsConvertableToTraceFormat {
-//        ...
-//     };
-//
-//     {
-//       TraceArguments args("foo" , std::make_unique<MyConvertableType>(...));
-//       // args.size() == 1
-//       // args.values()[0].as_convertable == address of MyConvertable object.
-//     } // Calls |args| destructor, which will delete the object too.
-//
-// Finally, it is possible to support initialization from custom values by
-// specializing the TraceValue::Helper<> template struct as described below.
-//
-// This is how values of custom types like WTF::CString can be passed directly
-// to trace macros.
-
-namespace base {
-
-class Time;
-class TimeTicks;
-class ThreadTicks;
-
-namespace trace_event {
-
-class TraceEventMemoryOverhead;
-
-// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
-// class must implement this interface. Note that unlike other values,
-// these objects will be owned by the TraceArguments instance that points
-// to them.
-class BASE_EXPORT ConvertableToTraceFormat {
- public:
-  ConvertableToTraceFormat() = default;
-  virtual ~ConvertableToTraceFormat() = default;
-
-  // Append the class info to the provided |out| string. The appended
-  // data must be a valid JSON object. Strings must be properly quoted, and
-  // escaped. There is no processing applied to the content after it is
-  // appended.
-  virtual void AppendAsTraceFormat(std::string* out) const = 0;
-
-  virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
-
-  std::string ToString() const {
-    std::string result;
-    AppendAsTraceFormat(&result);
-    return result;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat);
-};
-
-// A union used to hold the values of individual trace arguments.
-//
-// This is a POD union for performance reason. Initialization from an
-// explicit C++ trace argument should be performed with the Init()
-// templated method described below.
-//
-// Initialization from custom types is possible by implementing a custom
-// TraceValue::Helper<> instantiation as described below.
-//
-// IMPORTANT: Pointer storage inside a TraceUnion follows specific rules:
-//
-//   - |as_pointer| is for raw pointers that should be treated as a simple
-//     address and will never be dereferenced. Associated with the
-//     TRACE_VALUE_TYPE_POINTER type.
-//
-//   - |as_string| is for C-string pointers, associated with both
-//     TRACE_VALUE_TYPE_STRING and TRACE_VALUE_TYPE_COPY_STRING. The former
-//     indicates that the string pointer is persistent (e.g. a C string
-//     literal), while the second indicates that the pointer belongs to a
-//     temporary variable that may disappear soon. The TraceArguments class
-//     provides a CopyStringTo() method to copy these strings into a
-//     StringStorage instance, which is useful if the instance needs to
-//     survive longer than the temporaries.
-//
-//   - |as_convertable| is equivalent to
-//     std::unique_ptr<ConvertableToTraceFormat>, except that it is a pointer
-//     to keep this union POD and avoid un-necessary declarations and potential
-//     code generation. This means that its ownership is passed to the
-//     TraceValue instance when Init(std::unique_ptr<ConvertableToTraceFormat>)
-//     is called, and that it will be deleted by the containing TraceArguments
-//     destructor, or Reset() method.
-//
-union BASE_EXPORT TraceValue {
-  bool as_bool;
-  unsigned long long as_uint;
-  long long as_int;
-  double as_double;
-  const void* as_pointer;
-  const char* as_string;
-  ConvertableToTraceFormat* as_convertable;
-
-  // There is no constructor to keep this structure POD intentionally.
-  // This avoids un-needed initialization when only 0 or 1 arguments are
-  // used to construct a TraceArguments instance. Use Init() instead to
-  // perform explicit initialization from a given C++ value.
-
-  // Initialize TraceValue instance from a C++ trace value.
-  // This relies on the proper specialization of TraceValue::Helper<>
-  // described below. Usage is simply:
-  //
-  //  TraceValue v;
-  //  v.Init(<value>);
-  //
-  // NOTE: For ConvertableToTraceFormat values, see the note above and
-  // the one for TraceValue::Helper for CONVERTABLE_TYPE below.
-  template <typename T>
-  void Init(T&& value) {
-    using ValueType = typename InnerType<T>::type;
-    Helper<ValueType>::SetValue(this, std::forward<T>(value));
-  }
-
-  // Static method to create a new TraceValue instance from a given
-  // initialization value. Note that this deduces the TRACE_VALUE_TYPE_XXX
-  // type but doesn't return it, use ForType<T>::value for this.
-  //
-  // Usage example:
-  //     auto v = TraceValue::Make(100);
-  //     auto v2 = TraceValue::Make("Some text string");
-  //
-  // IMPORTANT: Experience shows that the compiler generates worse code when
-  // using this method rather than calling Init() directly on an existing
-  // TraceValue union :-(
-  //
-  template <typename T>
-  static TraceValue Make(T&& value) {
-    TraceValue ret;
-    ret.Init(std::forward<T>(value));
-    return ret;
-  }
-
-  // Output current value as a JSON string. |type| must be a valid
-  // TRACE_VALUE_TYPE_XXX value.
-  void AppendAsJSON(unsigned char type, std::string* out) const;
-
- private:
-  // InnerType<T>::type removes reference, cv-qualifications and decays
-  // function and arrays into pointers. Only used internally.
-  template <typename T>
-  struct InnerType {
-    using type = typename std::remove_cv<typename std::remove_reference<
-        typename std::decay<T>::type>::type>::type;
-  };
-
- public:
-  // TraceValue::Helper is used to provide information about initialization
-  // value types and an initialization function. It is a struct that should
-  // provide the following for supported initialization value types:
-  //
-  //    - kType: is a static TRACE_VALUE_TYPE_XXX constant.
-  //
-  //    - SetValue(TraceValue*, T): is a static inline method that sets
-  //        TraceValue value from a given T value. Second parameter type
-  //        can also be const T& or T&& to restrict uses.
-  //
-  // IMPORTANT: The type T must be InnerType<Q>, where Q is the real C++
-  // argument type. I.e. you should not have to deal with reference types
-  // in your specialization.
-  //
-  // Specializations are defined for integers, enums, floating point, pointers,
-  // constant C string literals and pointers, std::string, time values below.
-  //
-  // Specializations for custom types are possible provided that there exists
-  // a corresponding Helper specialization, for example:
-  //
-  //    template <>
-  //    struct base::trace_event::TraceValue::Helper<Foo> {
-  //      static constexpr unsigned char kTypes = TRACE_VALUE_TYPE_COPY_STRING;
-  //      static inline void SetValue(TraceValue* v, const Foo& value) {
-  //        v->as_string = value.c_str();
-  //      }
-  //    };
-  //
-  // Will allow code like:
-  //
-  //    Foo foo = ...;
-  //    auto v = TraceValue::Make(foo);
-  //
-  // Or even:
-  //    Foo foo = ...;
-  //    TraceArguments args("foo_arg1", foo);
-  //
-  template <typename T, class = void>
-  struct Helper {};
-
-  // TraceValue::TypeFor<T>::value returns the TRACE_VALUE_TYPE_XXX
-  // corresponding to initialization values of type T.
-  template <typename T>
-  struct TypeFor {
-    using ValueType = typename InnerType<T>::type;
-    static const unsigned char value = Helper<ValueType>::kType;
-  };
-
-  // TraceValue::TypeCheck<T>::value is only defined iff T can be used to
-  // initialize a TraceValue instance. This is useful to restrict template
-  // instantiation to only the appropriate type (see TraceArguments
-  // constructors below).
-  template <typename T,
-            class = decltype(TraceValue::Helper<
-                             typename TraceValue::InnerType<T>::type>::kType)>
-  struct TypeCheck {
-    static const bool value = true;
-  };
-};
-
-// TraceValue::Helper for integers and enums.
-template <typename T>
-struct TraceValue::Helper<
-    T,
-    typename std::enable_if<std::is_integral<T>::value ||
-                            std::is_enum<T>::value>::type> {
-  static constexpr unsigned char kType =
-      std::is_signed<T>::value ? TRACE_VALUE_TYPE_INT : TRACE_VALUE_TYPE_UINT;
-  static inline void SetValue(TraceValue* v, T value) {
-    v->as_uint = static_cast<unsigned long long>(value);
-  }
-};
-
-// TraceValue::Helper for floating-point types
-template <typename T>
-struct TraceValue::
-    Helper<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_DOUBLE;
-  static inline void SetValue(TraceValue* v, T value) { v->as_double = value; }
-};
-
-// TraceValue::Helper for bool.
-template <>
-struct TraceValue::Helper<bool> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_BOOL;
-  static inline void SetValue(TraceValue* v, bool value) { v->as_bool = value; }
-};
-
-//  TraceValue::Helper for generic pointer types.
-template <typename T>
-struct TraceValue::Helper<T*> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_POINTER;
-  static inline void SetValue(TraceValue* v,
-                              const typename std::decay<T>::type* value) {
-    v->as_pointer = value;
-  }
-};
-
-// TraceValue::Helper for raw persistent C strings.
-template <>
-struct TraceValue::Helper<const char*> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_STRING;
-  static inline void SetValue(TraceValue* v, const char* value) {
-    v->as_string = value;
-  }
-};
-
-// TraceValue::Helper for std::string values.
-template <>
-struct TraceValue::Helper<std::string> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING;
-  static inline void SetValue(TraceValue* v, const std::string& value) {
-    v->as_string = value.c_str();
-  }
-};
-
-// Special case for scoped pointers to convertables to trace format.
-// |CONVERTABLE_TYPE| must be a type whose pointers can be converted to a
-// ConvertableToTraceFormat* pointer as well (e.g. a derived class).
-// IMPORTANT: This takes an std::unique_ptr<CONVERTABLE_TYPE> value, and takes
-// ownership of the pointed object!
-template <typename CONVERTABLE_TYPE>
-struct TraceValue::Helper<std::unique_ptr<CONVERTABLE_TYPE>,
-                          typename std::enable_if<std::is_convertible<
-                              CONVERTABLE_TYPE*,
-                              ConvertableToTraceFormat*>::value>::type> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_CONVERTABLE;
-  static inline void SetValue(TraceValue* v,
-                              std::unique_ptr<CONVERTABLE_TYPE> value) {
-    v->as_convertable = value.release();
-  }
-};
-
-// Specialization for time-based values like base::Time, which provide a
-// a ToInternalValue() method.
-template <typename T>
-struct TraceValue::Helper<
-    T,
-    typename std::enable_if<std::is_same<T, base::Time>::value ||
-                            std::is_same<T, base::TimeTicks>::value ||
-                            std::is_same<T, base::ThreadTicks>::value>::type> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_INT;
-  static inline void SetValue(TraceValue* v, const T& value) {
-    v->as_int = value.ToInternalValue();
-  }
-};
-
-// Simple container for const char* that should be copied instead of retained.
-// The goal is to indicate that the C string is copyable, unlike the default
-// Init(const char*) implementation. Usage is:
-//
-//    const char* str = ...;
-//    v.Init(TraceStringWithCopy(str));
-//
-// Which will mark the string as TRACE_VALUE_TYPE_COPY_STRING, instead of
-// TRACE_VALUE_TYPE_STRING.
-//
-class TraceStringWithCopy {
- public:
-  explicit TraceStringWithCopy(const char* str) : str_(str) {}
-  const char* str() const { return str_; }
-
- private:
-  const char* str_;
-};
-
-template <>
-struct TraceValue::Helper<TraceStringWithCopy> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING;
-  static inline void SetValue(TraceValue* v, const TraceStringWithCopy& value) {
-    v->as_string = value.str();
-  }
-};
-
-class TraceArguments;
-
-// A small class used to store a copy of all strings from a given
-// TraceArguments instance (see below). When empty, this should only
-// take the size of a pointer. Otherwise, this will point to a heap
-// allocated block containing a size_t value followed by all characters
-// in the storage area. For most cases, this is more efficient
-// than using a std::unique_ptr<std::string> or an std::vector<char>.
-class BASE_EXPORT StringStorage {
- public:
-  constexpr StringStorage() = default;
-
-  explicit StringStorage(size_t alloc_size) { Reset(alloc_size); }
-
-  ~StringStorage() {
-    if (data_)
-      ::free(data_);
-  }
-
-  StringStorage(StringStorage&& other) : data_(other.data_) {
-    other.data_ = nullptr;
-  }
-
-  StringStorage& operator=(StringStorage&& other) {
-    if (this != &other) {
-      if (data_)
-        ::free(data_);
-      data_ = other.data_;
-      other.data_ = nullptr;
-    }
-    return *this;
-  }
-
-  // Reset storage area to new allocation size. Existing content might not
-  // be preserved. If |alloc_size| is 0, this will free the storage area
-  // as well.
-  void Reset(size_t alloc_size = 0);
-
-  // Accessors.
-  constexpr size_t size() const { return data_ ? data_->size : 0u; }
-  constexpr const char* data() const { return data_ ? data_->chars : nullptr; }
-  constexpr char* data() { return data_ ? data_->chars : nullptr; }
-
-  constexpr const char* begin() const { return data(); }
-  constexpr const char* end() const { return data() + size(); }
-  inline char* begin() { return data(); }
-  inline char* end() { return data() + size(); }
-
-  // True iff storage is empty.
-  constexpr bool empty() const { return size() == 0; }
-
-  // Returns true if |ptr| is inside the storage area, false otherwise.
-  // Used during unit-testing.
-  constexpr bool Contains(const void* ptr) const {
-    const char* char_ptr = static_cast<const char*>(ptr);
-    return (char_ptr >= begin() && char_ptr < end());
-  }
-
-  // Returns true if all string pointers in |args| are contained in this
-  // storage area.
-  bool Contains(const TraceArguments& args) const;
-
-  // Return an estimate of the memory overhead of this instance. This doesn't
-  // count the size of |data_| itself.
-  constexpr size_t EstimateTraceMemoryOverhead() const {
-    return data_ ? 0 : sizeof(size_t) + data_->size;
-  }
-
- private:
-  // Heap allocated data block (variable size), made of:
-  //
-  //   - size: a size_t field, giving the size of the following |chars| array.
-  //   - chars: an array of |size| characters, holding all zero-terminated
-  //     strings referenced from a TraceArguments instance.
-  struct Data {
-    size_t size = 0;
-    char chars[1];  // really |size| character items in storage.
-  };
-
-  // This is an owning pointer. Normally, using a std::unique_ptr<> would be
-  // enough, but the compiler will then complaing about inlined constructors
-  // and destructors being too complex (!), resulting in larger code for no
-  // good reason.
-  Data* data_ = nullptr;
-};
-
-// TraceArguments models an array of kMaxSize trace-related items,
-// each one of them having:
-//   - a name, which is a constant char array literal.
-//   - a type, as described by TRACE_VALUE_TYPE_XXX macros.
-//   - a value, stored in a TraceValue union.
-//
-// IMPORTANT: For TRACE_VALUE_TYPE_CONVERTABLE, the value holds an owning
-//            pointer to an AsConvertableToTraceFormat instance, which will
-//            be destroyed with the array (or moved out of it when passed
-//            to a TraceEvent instance).
-//
-// For TRACE_VALUE_TYPE_COPY_STRING, the value holds a const char* pointer
-// whose content will be copied when creating a TraceEvent instance.
-//
-// IMPORTANT: The constructor, destructor and SetArgument() methods are all
-// inlined intentionally, in order to let the compiler remove un-necessary
-// operations and reduce machine code.
-//
-class BASE_EXPORT TraceArguments {
- public:
-  // Maximum number of arguments held by this structure.
-  static constexpr size_t kMaxSize = 2;
-
-  // Default constructor, no arguments.
-  TraceArguments() : size_(0) {}
-
-  // Constructor for a single argument.
-  template <typename T, class = decltype(TraceValue::TypeCheck<T>::value)>
-  TraceArguments(const char* arg1_name, T&& arg1_value) : size_(1) {
-    types_[0] = TraceValue::TypeFor<T>::value;
-    names_[0] = arg1_name;
-    values_[0].Init(std::forward<T>(arg1_value));
-  }
-
-  // Constructor for two arguments.
-  template <typename T1,
-            typename T2,
-            class = decltype(TraceValue::TypeCheck<T1>::value &&
-                             TraceValue::TypeCheck<T2>::value)>
-  TraceArguments(const char* arg1_name,
-                 T1&& arg1_value,
-                 const char* arg2_name,
-                 T2&& arg2_value)
-      : size_(2) {
-    types_[0] = TraceValue::TypeFor<T1>::value;
-    types_[1] = TraceValue::TypeFor<T2>::value;
-    names_[0] = arg1_name;
-    names_[1] = arg2_name;
-    values_[0].Init(std::forward<T1>(arg1_value));
-    values_[1].Init(std::forward<T2>(arg2_value));
-  }
-
-  // Constructor used to convert a legacy set of arguments when there
-  // are no convertable values at all.
-  TraceArguments(int num_args,
-                 const char* const* arg_names,
-                 const unsigned char* arg_types,
-                 const unsigned long long* arg_values);
-
-  // Constructor used to convert legacy set of arguments, where the
-  // convertable values are also provided by an array of CONVERTABLE_TYPE.
-  template <typename CONVERTABLE_TYPE>
-  TraceArguments(int num_args,
-                 const char* const* arg_names,
-                 const unsigned char* arg_types,
-                 const unsigned long long* arg_values,
-                 CONVERTABLE_TYPE* arg_convertables) {
-    static int max_args = static_cast<int>(kMaxSize);
-    if (num_args > max_args)
-      num_args = max_args;
-    size_ = static_cast<unsigned char>(num_args);
-    for (size_t n = 0; n < size_; ++n) {
-      types_[n] = arg_types[n];
-      names_[n] = arg_names[n];
-      if (arg_types[n] == TRACE_VALUE_TYPE_CONVERTABLE) {
-        values_[n].Init(
-            std::forward<CONVERTABLE_TYPE>(std::move(arg_convertables[n])));
-      } else {
-        values_[n].as_uint = arg_values[n];
-      }
-    }
-  }
-
-  // Destructor. NOTE: Intentionally inlined (see note above).
-  ~TraceArguments() {
-    for (size_t n = 0; n < size_; ++n) {
-      if (types_[n] == TRACE_VALUE_TYPE_CONVERTABLE)
-        delete values_[n].as_convertable;
-    }
-  }
-
-  // Disallow copy operations.
-  TraceArguments(const TraceArguments&) = delete;
-  TraceArguments& operator=(const TraceArguments&) = delete;
-
-  // Allow move operations.
-  TraceArguments(TraceArguments&& other) noexcept {
-    ::memcpy(this, &other, sizeof(*this));
-    // All owning pointers were copied to |this|. Setting |other.size_| will
-    // mask the pointer values still in |other|.
-    other.size_ = 0;
-  }
-
-  TraceArguments& operator=(TraceArguments&&) noexcept;
-
-  // Accessors
-  size_t size() const { return size_; }
-  const unsigned char* types() const { return types_; }
-  const char* const* names() const { return names_; }
-  const TraceValue* values() const { return values_; }
-
-  // Reset to empty arguments list.
-  void Reset();
-
-  // Use |storage| to copy all copyable strings.
-  // If |copy_all_strings| is false, then only the TRACE_VALUE_TYPE_COPY_STRING
-  // values will be copied into storage. If it is true, then argument names are
-  // also copied to storage, as well as the strings pointed to by
-  // |*extra_string1| and |*extra_string2|.
-  // NOTE: If there are no strings to copy, |*storage| is left untouched.
-  void CopyStringsTo(StringStorage* storage,
-                     bool copy_all_strings,
-                     const char** extra_string1,
-                     const char** extra_string2);
-
-  // Append debug string representation to |*out|.
-  void AppendDebugString(std::string* out);
-
- private:
-  unsigned char size_;
-  unsigned char types_[kMaxSize];
-  const char* names_[kMaxSize];
-  TraceValue values_[kMaxSize];
-};
-
-}  // namespace trace_event
-}  // namespace base
-
-#endif  // BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_
diff --git a/base/trace_event/trace_arguments_unittest.cc b/base/trace_event/trace_arguments_unittest.cc
deleted file mode 100644
index f7be83e0f..0000000
--- a/base/trace_event/trace_arguments_unittest.cc
+++ /dev/null
@@ -1,459 +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 "base/trace_event/trace_arguments.h"
-
-#include <gtest/gtest.h>
-#include <string>
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-// Simple convertable that holds a string to append to the trace,
-// and can also write to a boolean flag on destruction.
-class MyConvertable : public ConvertableToTraceFormat {
- public:
-  MyConvertable(const char* text, bool* destroy_flag = nullptr)
-      : text_(text), destroy_flag_(destroy_flag) {}
-  ~MyConvertable() override {
-    if (destroy_flag_)
-      *destroy_flag_ = true;
-  }
-  void AppendAsTraceFormat(std::string* out) const override { *out += text_; }
-  const char* text() const { return text_; }
-
- private:
-  const char* text_;
-  bool* destroy_flag_;
-};
-
-}  // namespace
-
-TEST(TraceArguments, StringStorageDefaultConstruction) {
-  StringStorage storage;
-  EXPECT_TRUE(storage.empty());
-  EXPECT_FALSE(storage.data());
-  EXPECT_EQ(0U, storage.size());
-}
-
-TEST(TraceArguments, StringStorageConstructionWithSize) {
-  const size_t kSize = 128;
-  StringStorage storage(kSize);
-  EXPECT_FALSE(storage.empty());
-  EXPECT_TRUE(storage.data());
-  EXPECT_EQ(kSize, storage.size());
-  EXPECT_EQ(storage.data(), storage.begin());
-  EXPECT_EQ(storage.data() + kSize, storage.end());
-}
-
-TEST(TraceArguments, StringStorageReset) {
-  StringStorage storage(128);
-  EXPECT_FALSE(storage.empty());
-
-  storage.Reset();
-  EXPECT_TRUE(storage.empty());
-  EXPECT_FALSE(storage.data());
-  EXPECT_EQ(0u, storage.size());
-}
-
-TEST(TraceArguments, StringStorageResetWithSize) {
-  StringStorage storage;
-  EXPECT_TRUE(storage.empty());
-
-  const size_t kSize = 128;
-  storage.Reset(kSize);
-  EXPECT_FALSE(storage.empty());
-  EXPECT_TRUE(storage.data());
-  EXPECT_EQ(kSize, storage.size());
-  EXPECT_EQ(storage.data(), storage.begin());
-  EXPECT_EQ(storage.data() + kSize, storage.end());
-}
-
-static void CheckJSONFor(TraceValue v, char type, const char* expected) {
-  std::string out;
-  v.AppendAsJSON(type, &out);
-  EXPECT_STREQ(expected, out.c_str());
-}
-
-TEST(TraceArguments, TraceValueAppendAsJSON) {
-  TraceValue v;
-
-  v.Init(-1024);
-  CheckJSONFor(v, TRACE_VALUE_TYPE_INT, "-1024");
-  v.Init(1024ULL);
-  CheckJSONFor(v, TRACE_VALUE_TYPE_UINT, "1024");
-  v.Init(3.1415926535);
-  CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "3.1415926535");
-  v.Init(true);
-  CheckJSONFor(v, TRACE_VALUE_TYPE_BOOL, "true");
-  v.Init(false);
-  CheckJSONFor(v, TRACE_VALUE_TYPE_BOOL, "false");
-  v.Init("Some \"nice\" String");
-  CheckJSONFor(v, TRACE_VALUE_TYPE_STRING, "\"Some \\\"nice\\\" String\"");
-  CheckJSONFor(v, TRACE_VALUE_TYPE_COPY_STRING, "\"Some \\\"nice\\\" String\"");
-}
-
-TEST(TraceArguments, DefaultConstruction) {
-  TraceArguments args;
-  EXPECT_EQ(0U, args.size());
-}
-
-TEST(TraceArguments, ConstructorSingleInteger) {
-  TraceArguments args("foo_int", int(10));
-  EXPECT_EQ(1U, args.size());
-  EXPECT_EQ(TRACE_VALUE_TYPE_INT, args.types()[0]);
-  EXPECT_STREQ("foo_int", args.names()[0]);
-  EXPECT_EQ(10, args.values()[0].as_int);
-}
-
-TEST(TraceArguments, ConstructorSingleFloat) {
-  TraceArguments args("foo_pi", float(3.1415));
-  double expected = float(3.1415);
-  EXPECT_EQ(1U, args.size());
-  EXPECT_EQ(TRACE_VALUE_TYPE_DOUBLE, args.types()[0]);
-  EXPECT_STREQ("foo_pi", args.names()[0]);
-  EXPECT_EQ(expected, args.values()[0].as_double);
-}
-
-TEST(TraceArguments, ConstructorSingleNoCopyString) {
-  const char kText[] = "Persistent string";
-  TraceArguments args("foo_cstring", kText);
-  EXPECT_EQ(1U, args.size());
-  EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[0]);
-  EXPECT_STREQ("foo_cstring", args.names()[0]);
-  EXPECT_EQ(kText, args.values()[0].as_string);
-}
-
-TEST(TraceArguments, ConstructorSingleStdString) {
-  std::string text = "Non-persistent string";
-  TraceArguments args("foo_stdstring", text);
-  EXPECT_EQ(1U, args.size());
-  EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
-  EXPECT_STREQ("foo_stdstring", args.names()[0]);
-  EXPECT_EQ(text.c_str(), args.values()[0].as_string);
-}
-
-TEST(TraceArguments, ConstructorSingleTraceStringWithCopy) {
-  const char kText[] = "Persistent string #2";
-  TraceArguments args("foo_tracestring", TraceStringWithCopy(kText));
-  EXPECT_EQ(1U, args.size());
-  EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
-  EXPECT_STREQ("foo_tracestring", args.names()[0]);
-  EXPECT_EQ(kText, args.values()[0].as_string);
-}
-
-TEST(TraceArguments, ConstructorSinglePointer) {
-  bool destroy_flag = false;
-  {
-    // Simple class that can set a boolean flag on destruction.
-    class Foo {
-     public:
-      Foo(bool* destroy_flag) : destroy_flag_(destroy_flag) {}
-      ~Foo() {
-        if (destroy_flag_)
-          *destroy_flag_ = true;
-      }
-
-     private:
-      bool* destroy_flag_;
-    };
-    auto foo = std::make_unique<Foo>(&destroy_flag);
-    EXPECT_FALSE(destroy_flag);
-    // This test also verifies that the object is not destroyed by the
-    // TraceArguments destructor. This should only be possible for
-    // TRACE_VALUE_TYPE_CONVERTABLE instances.
-    {
-      TraceArguments args("foo_pointer", foo.get());
-      EXPECT_EQ(1U, args.size());
-      EXPECT_EQ(TRACE_VALUE_TYPE_POINTER, args.types()[0]);
-      EXPECT_STREQ("foo_pointer", args.names()[0]);
-      EXPECT_EQ(foo.get(), args.values()[0].as_pointer);
-      EXPECT_FALSE(destroy_flag);
-    }  // Calls TraceArguments destructor.
-    EXPECT_FALSE(destroy_flag);
-  }  // Calls Foo destructor.
-  EXPECT_TRUE(destroy_flag);
-}
-
-TEST(TraceArguments, ConstructorSingleConvertable) {
-  bool destroy_flag = false;
-  const char kText[] = "Text for MyConvertable instance";
-  MyConvertable* ptr = new MyConvertable(kText, &destroy_flag);
-
-  // This test also verifies that the MyConvertable instance is properly
-  // destroyed when the TraceArguments destructor is called.
-  EXPECT_FALSE(destroy_flag);
-  {
-    TraceArguments args("foo_convertable", std::unique_ptr<MyConvertable>(ptr));
-    EXPECT_EQ(1U, args.size());
-    EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[0]);
-    EXPECT_STREQ("foo_convertable", args.names()[0]);
-    EXPECT_EQ(ptr, args.values()[0].as_convertable);
-    EXPECT_FALSE(destroy_flag);
-  }  // Calls TraceArguments destructor.
-  EXPECT_TRUE(destroy_flag);
-}
-
-TEST(TraceArguments, ConstructorWithTwoArguments) {
-  const char kText1[] = "First argument";
-  const char kText2[] = "Second argument";
-  bool destroy_flag = false;
-
-  {
-    MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag);
-    TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable",
-                         std::unique_ptr<MyConvertable>(ptr));
-    EXPECT_EQ(2U, args1.size());
-    EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]);
-    EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]);
-    EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]);
-    EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]);
-    EXPECT_EQ(kText1, args1.values()[0].as_string);
-    EXPECT_EQ(ptr, args1.values()[1].as_convertable);
-    EXPECT_FALSE(destroy_flag);
-  }  // calls |args1| destructor. Should delete |ptr|.
-  EXPECT_TRUE(destroy_flag);
-}
-
-TEST(TraceArguments, ConstructorLegacyNoConvertables) {
-  const char* const kNames[3] = {"legacy_arg1", "legacy_arg2", "legacy_arg3"};
-  const unsigned char kTypes[3] = {
-      TRACE_VALUE_TYPE_INT, TRACE_VALUE_TYPE_STRING, TRACE_VALUE_TYPE_POINTER,
-  };
-  static const char kText[] = "Some text";
-  const unsigned long long kValues[3] = {
-      1000042ULL, reinterpret_cast<unsigned long long>(kText),
-      reinterpret_cast<unsigned long long>(kText + 2),
-  };
-  TraceArguments args(3, kNames, kTypes, kValues);
-  // Check that only the first kMaxSize arguments are taken!
-  EXPECT_EQ(2U, args.size());
-  EXPECT_STREQ(kNames[0], args.names()[0]);
-  EXPECT_STREQ(kNames[1], args.names()[1]);
-  EXPECT_EQ(TRACE_VALUE_TYPE_INT, args.types()[0]);
-  EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[1]);
-  EXPECT_EQ(kValues[0], args.values()[0].as_uint);
-  EXPECT_EQ(kText, args.values()[1].as_string);
-};
-
-TEST(TraceArguments, ConstructorLegacyWithConvertables) {
-  const char* const kNames[3] = {"legacy_arg1", "legacy_arg2", "legacy_arg3"};
-  const unsigned char kTypes[3] = {
-      TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE,
-      TRACE_VALUE_TYPE_CONVERTABLE,
-  };
-  std::unique_ptr<MyConvertable> convertables[3] = {
-      std::make_unique<MyConvertable>("First one"),
-      std::make_unique<MyConvertable>("Second one"),
-      std::make_unique<MyConvertable>("Third one"),
-  };
-  TraceArguments args(3, kNames, kTypes, nullptr, convertables);
-  // Check that only the first kMaxSize arguments are taken!
-  EXPECT_EQ(2U, args.size());
-  EXPECT_STREQ(kNames[0], args.names()[0]);
-  EXPECT_STREQ(kNames[1], args.names()[1]);
-  EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[0]);
-  EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[1]);
-  // Check that only the first two items were moved to |args|.
-  EXPECT_FALSE(convertables[0].get());
-  EXPECT_FALSE(convertables[1].get());
-  EXPECT_TRUE(convertables[2].get());
-}
-
-TEST(TraceArguments, MoveConstruction) {
-  const char kText1[] = "First argument";
-  const char kText2[] = "Second argument";
-  bool destroy_flag = false;
-
-  {
-    MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag);
-    TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable",
-                         std::unique_ptr<MyConvertable>(ptr));
-    EXPECT_EQ(2U, args1.size());
-    EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]);
-    EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]);
-    EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]);
-    EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]);
-    EXPECT_EQ(kText1, args1.values()[0].as_string);
-    EXPECT_EQ(ptr, args1.values()[1].as_convertable);
-
-    {
-      TraceArguments args2(std::move(args1));
-      EXPECT_FALSE(destroy_flag);
-
-      // |args1| is now empty.
-      EXPECT_EQ(0U, args1.size());
-
-      // Check that everything was transferred to |args2|.
-      EXPECT_EQ(2U, args2.size());
-      EXPECT_STREQ("foo_arg1_cstring", args2.names()[0]);
-      EXPECT_STREQ("foo_arg2_convertable", args2.names()[1]);
-      EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args2.types()[0]);
-      EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args2.types()[1]);
-      EXPECT_EQ(kText1, args2.values()[0].as_string);
-      EXPECT_EQ(ptr, args2.values()[1].as_convertable);
-    }  // Calls |args2| destructor. Should delete |ptr|.
-    EXPECT_TRUE(destroy_flag);
-    destroy_flag = false;
-  }  // Calls |args1| destructor. Should not delete |ptr|.
-  EXPECT_FALSE(destroy_flag);
-}
-
-TEST(TraceArguments, MoveAssignment) {
-  const char kText1[] = "First argument";
-  const char kText2[] = "Second argument";
-  bool destroy_flag = false;
-
-  {
-    MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag);
-    TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable",
-                         std::unique_ptr<MyConvertable>(ptr));
-    EXPECT_EQ(2U, args1.size());
-    EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]);
-    EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]);
-    EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]);
-    EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]);
-    EXPECT_EQ(kText1, args1.values()[0].as_string);
-    EXPECT_EQ(ptr, args1.values()[1].as_convertable);
-
-    {
-      TraceArguments args2;
-
-      args2 = std::move(args1);
-      EXPECT_FALSE(destroy_flag);
-
-      // |args1| is now empty.
-      EXPECT_EQ(0U, args1.size());
-
-      // Check that everything was transferred to |args2|.
-      EXPECT_EQ(2U, args2.size());
-      EXPECT_STREQ("foo_arg1_cstring", args2.names()[0]);
-      EXPECT_STREQ("foo_arg2_convertable", args2.names()[1]);
-      EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args2.types()[0]);
-      EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args2.types()[1]);
-      EXPECT_EQ(kText1, args2.values()[0].as_string);
-      EXPECT_EQ(ptr, args2.values()[1].as_convertable);
-    }  // Calls |args2| destructor. Should delete |ptr|.
-    EXPECT_TRUE(destroy_flag);
-    destroy_flag = false;
-  }  // Calls |args1| destructor. Should not delete |ptr|.
-  EXPECT_FALSE(destroy_flag);
-}
-
-TEST(TraceArguments, Reset) {
-  bool destroy_flag = false;
-  {
-    TraceArguments args(
-        "foo_arg1", "Hello", "foo_arg2",
-        std::make_unique<MyConvertable>("World", &destroy_flag));
-
-    EXPECT_EQ(2U, args.size());
-    EXPECT_FALSE(destroy_flag);
-    args.Reset();
-    EXPECT_EQ(0U, args.size());
-    EXPECT_TRUE(destroy_flag);
-    destroy_flag = false;
-  }  // Calls |args| destructor. Should not delete twice.
-  EXPECT_FALSE(destroy_flag);
-}
-
-TEST(TraceArguments, CopyStringsTo_NoStrings) {
-  StringStorage storage;
-
-  TraceArguments args("arg1", 10, "arg2", 42);
-  args.CopyStringsTo(&storage, false, nullptr, nullptr);
-  EXPECT_TRUE(storage.empty());
-  EXPECT_EQ(0U, storage.size());
-}
-
-TEST(TraceArguments, CopyStringsTo_OnlyArgs) {
-  StringStorage storage;
-
-  TraceArguments args("arg1", TraceStringWithCopy("Hello"), "arg2",
-                      TraceStringWithCopy("World"));
-
-  const char kExtra1[] = "extra1";
-  const char kExtra2[] = "extra2";
-  const char* extra1 = kExtra1;
-  const char* extra2 = kExtra2;
-
-  // Types should be copyable strings.
-  EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
-  EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]);
-
-  args.CopyStringsTo(&storage, false, &extra1, &extra2);
-
-  // Storage should be allocated.
-  EXPECT_TRUE(storage.data());
-  EXPECT_NE(0U, storage.size());
-
-  // Types should not be changed.
-  EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
-  EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]);
-
-  // names should not be copied.
-  EXPECT_FALSE(storage.Contains(args.names()[0]));
-  EXPECT_FALSE(storage.Contains(args.names()[1]));
-  EXPECT_STREQ("arg1", args.names()[0]);
-  EXPECT_STREQ("arg2", args.names()[1]);
-
-  // strings should be copied.
-  EXPECT_TRUE(storage.Contains(args.values()[0].as_string));
-  EXPECT_TRUE(storage.Contains(args.values()[1].as_string));
-  EXPECT_STREQ("Hello", args.values()[0].as_string);
-  EXPECT_STREQ("World", args.values()[1].as_string);
-
-  // |extra1| and |extra2| should not be copied.
-  EXPECT_EQ(kExtra1, extra1);
-  EXPECT_EQ(kExtra2, extra2);
-}
-
-TEST(TraceArguments, CopyStringsTo_Everything) {
-  StringStorage storage;
-
-  TraceArguments args("arg1", "Hello", "arg2", "World");
-  const char kExtra1[] = "extra1";
-  const char kExtra2[] = "extra2";
-  const char* extra1 = kExtra1;
-  const char* extra2 = kExtra2;
-
-  // Types should be normal strings.
-  EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[0]);
-  EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[1]);
-
-  args.CopyStringsTo(&storage, true, &extra1, &extra2);
-
-  // Storage should be allocated.
-  EXPECT_TRUE(storage.data());
-  EXPECT_NE(0U, storage.size());
-
-  // Types should be changed to copyable strings.
-  EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
-  EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]);
-
-  // names should be copied.
-  EXPECT_TRUE(storage.Contains(args.names()[0]));
-  EXPECT_TRUE(storage.Contains(args.names()[1]));
-  EXPECT_STREQ("arg1", args.names()[0]);
-  EXPECT_STREQ("arg2", args.names()[1]);
-
-  // strings should be copied.
-  EXPECT_TRUE(storage.Contains(args.values()[0].as_string));
-  EXPECT_TRUE(storage.Contains(args.values()[1].as_string));
-  EXPECT_STREQ("Hello", args.values()[0].as_string);
-  EXPECT_STREQ("World", args.values()[1].as_string);
-
-  // |extra1| and |extra2| should be copied.
-  EXPECT_NE(kExtra1, extra1);
-  EXPECT_NE(kExtra2, extra2);
-  EXPECT_TRUE(storage.Contains(extra1));
-  EXPECT_TRUE(storage.Contains(extra2));
-  EXPECT_STREQ(kExtra1, extra1);
-  EXPECT_STREQ(kExtra2, extra2);
-}
-
-}  // namespace trace_event
-}  // namespace base
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index b6b71d7..271022e 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -21,7 +21,6 @@
 #include "base/time/time_override.h"
 #include "base/trace_event/common/trace_event_common.h"
 #include "base/trace_event/heap_profiler.h"
-#include "base/trace_event/trace_arguments.h"
 #include "base/trace_event/trace_category.h"
 #include "base/trace_event/trace_event_system_stats_monitor.h"
 #include "base/trace_event/trace_log.h"
@@ -29,7 +28,8 @@
 
 // By default, const char* argument values are assumed to have long-lived scope
 // and will not be copied. Use this macro to force a const char* to be copied.
-#define TRACE_STR_COPY(str) ::base::trace_event::TraceStringWithCopy(str)
+#define TRACE_STR_COPY(str) \
+    trace_event_internal::TraceStringWithCopy(str)
 
 // DEPRECATED: do not use: Consider using TRACE_ID_{GLOBAL, LOCAL} macros,
 // instead. By default, uint64_t ID argument values are not mangled with the
@@ -642,13 +642,115 @@
   unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID;
 };
 
+// Simple union to store various types as unsigned long long.
+union TraceValueUnion {
+  bool as_bool;
+  unsigned long long as_uint;
+  long long as_int;
+  double as_double;
+  const void* as_pointer;
+  const char* as_string;
+};
+
+// Simple container for const char* that should be copied instead of retained.
+class TraceStringWithCopy {
+ public:
+  explicit TraceStringWithCopy(const char* str) : str_(str) {}
+  const char* str() const { return str_; }
+ private:
+  const char* str_;
+};
+
+// Define SetTraceValue for each allowed type. It stores the type and
+// value in the return arguments. This allows this API to avoid declaring any
+// structures so that it is portable to third_party libraries.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
+                                         arg_expression, \
+                                         union_member, \
+                                         value_type_id) \
+    static inline void SetTraceValue( \
+        actual_type arg, \
+        unsigned char* type, \
+        unsigned long long* value) { \
+      TraceValueUnion type_value; \
+      type_value.union_member = arg_expression; \
+      *type = value_type_id; \
+      *value = type_value.as_uint; \
+    }
+// Simpler form for int types that can be safely casted.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
+                                             value_type_id) \
+    static inline void SetTraceValue( \
+        actual_type arg, \
+        unsigned char* type, \
+        unsigned long long* value) { \
+      *type = value_type_id; \
+      *value = static_cast<unsigned long long>(arg); \
+    }
+
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, as_bool, TRACE_VALUE_TYPE_BOOL)
+INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, as_double,
+                                 TRACE_VALUE_TYPE_DOUBLE)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, as_pointer,
+                                 TRACE_VALUE_TYPE_POINTER)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, as_string,
+                                 TRACE_VALUE_TYPE_STRING)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(),
+                                 as_string, TRACE_VALUE_TYPE_COPY_STRING)
+
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
+
+// std::string version of SetTraceValue so that trace arguments can be strings.
+static inline void SetTraceValue(const std::string& arg,
+                                 unsigned char* type,
+                                 unsigned long long* value) {
+  TraceValueUnion type_value;
+  type_value.as_string = arg.c_str();
+  *type = TRACE_VALUE_TYPE_COPY_STRING;
+  *value = type_value.as_uint;
+}
+
+// base::Time, base::TimeTicks, etc. versions of SetTraceValue to make it easier
+// to trace these types.
+static inline void SetTraceValue(const base::Time arg,
+                                 unsigned char* type,
+                                 unsigned long long* value) {
+  *type = TRACE_VALUE_TYPE_INT;
+  *value = arg.ToInternalValue();
+}
+
+static inline void SetTraceValue(const base::TimeTicks arg,
+                                 unsigned char* type,
+                                 unsigned long long* value) {
+  *type = TRACE_VALUE_TYPE_INT;
+  *value = arg.ToInternalValue();
+}
+
+static inline void SetTraceValue(const base::ThreadTicks arg,
+                                 unsigned char* type,
+                                 unsigned long long* value) {
+  *type = TRACE_VALUE_TYPE_INT;
+  *value = arg.ToInternalValue();
+}
+
 // These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template
 // functions are defined here instead of in the macro, because the arg_values
 // could be temporary objects, such as std::string. In order to store
 // pointers to the internal c_str and pass through to the tracing API,
 // the arg_values must live throughout these procedures.
 
-template <class ARG1_TYPE>
+template <class ARG1_CONVERTABLE_TYPE>
 static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
@@ -661,15 +763,18 @@
     unsigned int flags,
     unsigned long long bind_id,
     const char* arg1_name,
-    ARG1_TYPE&& arg1_val) {
-  base::trace_event::TraceArguments args(arg1_name,
-                                         std::forward<ARG1_TYPE>(arg1_val));
+    std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) {
+  const int num_args = 1;
+  unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE };
+  std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
+      convertable_values[1] = {std::move(arg1_val)};
   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
-      timestamp, &args, flags);
+      timestamp, num_args, &arg1_name, arg_types, NULL, convertable_values,
+      flags);
 }
 
-template <class ARG1_TYPE, class ARG2_TYPE>
+template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE>
 static inline base::trace_event::TraceEventHandle
 AddTraceEventWithThreadIdAndTimestamp(
     char phase,
@@ -682,15 +787,82 @@
     unsigned int flags,
     unsigned long long bind_id,
     const char* arg1_name,
-    ARG1_TYPE&& arg1_val,
+    const ARG1_TYPE& arg1_val,
     const char* arg2_name,
-    ARG2_TYPE&& arg2_val) {
-  base::trace_event::TraceArguments args(
-      arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name,
-      std::forward<ARG2_TYPE>(arg2_val));
+    std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) {
+  const int num_args = 2;
+  const char* arg_names[2] = { arg1_name, arg2_name };
+
+  unsigned char arg_types[2];
+  unsigned long long arg_values[2];
+  SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
+  arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE;
+  std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
+      convertable_values[2] = {nullptr, std::move(arg2_val)};
   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
-      timestamp, &args, flags);
+      timestamp, num_args, arg_names, arg_types, arg_values, convertable_values,
+      flags);
+}
+
+template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE>
+static inline base::trace_event::TraceEventHandle
+AddTraceEventWithThreadIdAndTimestamp(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    int thread_id,
+    const base::TimeTicks& timestamp,
+    unsigned int flags,
+    unsigned long long bind_id,
+    const char* arg1_name,
+    std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val,
+    const char* arg2_name,
+    const ARG2_TYPE& arg2_val) {
+  const int num_args = 2;
+  const char* arg_names[2] = { arg1_name, arg2_name };
+
+  unsigned char arg_types[2];
+  unsigned long long arg_values[2];
+  arg_types[0] = TRACE_VALUE_TYPE_CONVERTABLE;
+  arg_values[0] = 0;
+  SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
+  std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
+      convertable_values[2] = {std::move(arg1_val), nullptr};
+  return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
+      phase, category_group_enabled, name, scope, id, bind_id, thread_id,
+      timestamp, num_args, arg_names, arg_types, arg_values, convertable_values,
+      flags);
+}
+
+template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE>
+static inline base::trace_event::TraceEventHandle
+AddTraceEventWithThreadIdAndTimestamp(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    int thread_id,
+    const base::TimeTicks& timestamp,
+    unsigned int flags,
+    unsigned long long bind_id,
+    const char* arg1_name,
+    std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val,
+    const char* arg2_name,
+    std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) {
+  const int num_args = 2;
+  const char* arg_names[2] = { arg1_name, arg2_name };
+  unsigned char arg_types[2] =
+      { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE };
+  std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
+      convertable_values[2] = {std::move(arg1_val), std::move(arg2_val)};
+  return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
+      phase, category_group_enabled, name, scope, id, bind_id, thread_id,
+      timestamp, num_args, arg_names, arg_types, NULL, convertable_values,
+      flags);
 }
 
 static inline base::trace_event::TraceEventHandle
@@ -706,7 +878,7 @@
     unsigned long long bind_id) {
   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
-      timestamp, nullptr, flags);
+      timestamp, kZeroNumArgs, NULL, NULL, NULL, NULL, flags);
 }
 
 static inline base::trace_event::TraceEventHandle AddTraceEvent(
@@ -724,25 +896,30 @@
       bind_id);
 }
 
-template <class ARG1_TYPE>
-static inline base::trace_event::TraceEventHandle AddTraceEvent(
+template<class ARG1_TYPE>
+static inline base::trace_event::TraceEventHandle
+AddTraceEventWithThreadIdAndTimestamp(
     char phase,
     const unsigned char* category_group_enabled,
     const char* name,
     const char* scope,
     unsigned long long id,
+    int thread_id,
+    const base::TimeTicks& timestamp,
     unsigned int flags,
     unsigned long long bind_id,
     const char* arg1_name,
-    ARG1_TYPE&& arg1_val) {
-  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
-  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
-  return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id, thread_id, now, flags,
-      bind_id, arg1_name, std::forward<ARG1_TYPE>(arg1_val));
+    const ARG1_TYPE& arg1_val) {
+  const int num_args = 1;
+  unsigned char arg_types[1];
+  unsigned long long arg_values[1];
+  SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
+  return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
+      phase, category_group_enabled, name, scope, id, bind_id, thread_id,
+      timestamp, num_args, &arg1_name, arg_types, arg_values, NULL, flags);
 }
 
-template <class ARG1_TYPE, class ARG2_TYPE>
+template<class ARG1_TYPE>
 static inline base::trace_event::TraceEventHandle AddTraceEvent(
     char phase,
     const unsigned char* category_group_enabled,
@@ -752,26 +929,171 @@
     unsigned int flags,
     unsigned long long bind_id,
     const char* arg1_name,
-    ARG1_TYPE&& arg1_val,
-    const char* arg2_name,
-    ARG2_TYPE&& arg2_val) {
+    const ARG1_TYPE& arg1_val) {
   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
   base::TimeTicks now = TRACE_TIME_TICKS_NOW();
   return AddTraceEventWithThreadIdAndTimestamp(
       phase, category_group_enabled, name, scope, id, thread_id, now, flags,
-      bind_id, arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name,
-      std::forward<ARG2_TYPE>(arg2_val));
+      bind_id, arg1_name, arg1_val);
+}
+
+template <class ARG1_CONVERTABLE_TYPE>
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    unsigned int flags,
+    unsigned long long bind_id,
+    const char* arg1_name,
+    std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) {
+  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
+  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
+  return AddTraceEventWithThreadIdAndTimestamp(
+      phase, category_group_enabled, name, scope, id, thread_id, now, flags,
+      bind_id, arg1_name, std::move(arg1_val));
+}
+
+template<class ARG1_TYPE, class ARG2_TYPE>
+static inline base::trace_event::TraceEventHandle
+AddTraceEventWithThreadIdAndTimestamp(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    int thread_id,
+    const base::TimeTicks& timestamp,
+    unsigned int flags,
+    unsigned long long bind_id,
+    const char* arg1_name,
+    const ARG1_TYPE& arg1_val,
+    const char* arg2_name,
+    const ARG2_TYPE& arg2_val) {
+  const int num_args = 2;
+  const char* arg_names[2] = { arg1_name, arg2_name };
+  unsigned char arg_types[2];
+  unsigned long long arg_values[2];
+  SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
+  SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
+  return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
+      phase, category_group_enabled, name, scope, id, bind_id, thread_id,
+      timestamp, num_args, arg_names, arg_types, arg_values, NULL, flags);
+}
+
+template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE>
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    unsigned int flags,
+    unsigned long long bind_id,
+    const char* arg1_name,
+    std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val,
+    const char* arg2_name,
+    const ARG2_TYPE& arg2_val) {
+  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
+  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
+  return AddTraceEventWithThreadIdAndTimestamp(
+      phase, category_group_enabled, name, scope, id, thread_id, now, flags,
+      bind_id, arg1_name, std::move(arg1_val), arg2_name, arg2_val);
+}
+
+template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE>
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    unsigned int flags,
+    unsigned long long bind_id,
+    const char* arg1_name,
+    const ARG1_TYPE& arg1_val,
+    const char* arg2_name,
+    std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) {
+  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
+  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
+  return AddTraceEventWithThreadIdAndTimestamp(
+      phase, category_group_enabled, name, scope, id, thread_id, now, flags,
+      bind_id, arg1_name, arg1_val, arg2_name, std::move(arg2_val));
+}
+
+template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE>
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    unsigned int flags,
+    unsigned long long bind_id,
+    const char* arg1_name,
+    std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val,
+    const char* arg2_name,
+    std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) {
+  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
+  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
+  return AddTraceEventWithThreadIdAndTimestamp(
+      phase, category_group_enabled, name, scope, id, thread_id, now, flags,
+      bind_id, arg1_name, std::move(arg1_val), arg2_name, std::move(arg2_val));
+}
+
+template<class ARG1_TYPE, class ARG2_TYPE>
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    unsigned int flags,
+    unsigned long long bind_id,
+    const char* arg1_name,
+    const ARG1_TYPE& arg1_val,
+    const char* arg2_name,
+    const ARG2_TYPE& arg2_val) {
+  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
+  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
+  return AddTraceEventWithThreadIdAndTimestamp(
+      phase, category_group_enabled, name, scope, id, thread_id, now, flags,
+      bind_id, arg1_name, arg1_val, arg2_name, arg2_val);
+}
+
+template <class ARG1_CONVERTABLE_TYPE>
+static inline void AddMetadataEvent(
+    const unsigned char* category_group_enabled,
+    const char* event_name,
+    const char* arg_name,
+    std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg_value) {
+  const char* arg_names[1] = {arg_name};
+  unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE};
+  std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
+      convertable_values[1] = {std::move(arg_value)};
+  base::trace_event::TraceLog::GetInstance()->AddMetadataEvent(
+      category_group_enabled, event_name,
+      1,  // num_args
+      arg_names, arg_types,
+      nullptr,  // arg_values
+      convertable_values, TRACE_EVENT_FLAG_NONE);
 }
 
 template <class ARG1_TYPE>
 static void AddMetadataEvent(const unsigned char* category_group_enabled,
                              const char* event_name,
                              const char* arg_name,
-                             ARG1_TYPE&& arg_val) {
-  base::trace_event::TraceArguments args(arg_name,
-                                         std::forward<ARG1_TYPE>(arg_val));
+                             const ARG1_TYPE& arg_val) {
+  const int num_args = 1;
+  const char* arg_names[1] = {arg_name};
+  unsigned char arg_types[1];
+  unsigned long long arg_values[1];
+  SetTraceValue(arg_val, &arg_types[0], &arg_values[0]);
+
   base::trace_event::TraceLog::GetInstance()->AddMetadataEvent(
-      category_group_enabled, event_name, &args, TRACE_EVENT_FLAG_NONE);
+      category_group_enabled, event_name, num_args, arg_names, arg_types,
+      arg_values, nullptr, TRACE_EVENT_FLAG_NONE);
 }
 
 // Used by TRACE_EVENTx macros. Do not use directly.
diff --git a/base/trace_event/trace_event_android.cc b/base/trace_event/trace_event_android.cc
index a1e51e8..30d9c74 100644
--- a/base/trace_event/trace_event_android.cc
+++ b/base/trace_event/trace_event_android.cc
@@ -39,25 +39,32 @@
   }
 }
 
-void WriteEvent(char phase,
-                const char* category_group,
-                const char* name,
-                unsigned long long id,
-                const TraceArguments& args,
-                unsigned int flags) {
+void WriteEvent(
+    char phase,
+    const char* category_group,
+    const char* name,
+    unsigned long long id,
+    const char** arg_names,
+    const unsigned char* arg_types,
+    const TraceEvent::TraceValue* arg_values,
+    const std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
+    unsigned int flags) {
   std::string out = StringPrintf("%c|%d|%s", phase, getpid(), name);
   if (flags & TRACE_EVENT_FLAG_HAS_ID)
     StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id));
   out += '|';
 
-  const char* const* arg_names = args.names();
-  for (size_t i = 0; i < args.size() && arg_names[i]; ++i) {
+  for (int i = 0; i < kTraceMaxNumArgs && arg_names[i];
+       ++i) {
     if (i)
       out += ';';
     out += arg_names[i];
     out += '=';
     std::string::size_type value_start = out.length();
-    args.values()[i].AppendAsJSON(args.types()[i], &out);
+    if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE)
+      convertable_values[i]->AppendAsTraceFormat(&out);
+    else
+      TraceEvent::AppendValueAsJSON(arg_types[i], arg_values[i], &out);
 
     // Remove the quotes which may confuse the atrace script.
     ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'");
@@ -140,35 +147,43 @@
 
   switch (phase_) {
     case TRACE_EVENT_PHASE_BEGIN:
-      WriteEvent('B', category_group, name_, id_, args_, flags_);
+      WriteEvent('B', category_group, name_, id_,
+                 arg_names_, arg_types_, arg_values_, convertable_values_,
+                 flags_);
       break;
 
     case TRACE_EVENT_PHASE_COMPLETE:
-      WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E', category_group,
-                 name_, id_, args_, flags_);
+      WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E',
+                 category_group, name_, id_,
+                 arg_names_, arg_types_, arg_values_, convertable_values_,
+                 flags_);
       break;
 
     case TRACE_EVENT_PHASE_END:
       // Though a single 'E' is enough, here append pid, name and
       // category_group etc. So that unpaired events can be found easily.
-      WriteEvent('E', category_group, name_, id_, args_, flags_);
+      WriteEvent('E', category_group, name_, id_,
+                 arg_names_, arg_types_, arg_values_, convertable_values_,
+                 flags_);
       break;
 
     case TRACE_EVENT_PHASE_INSTANT:
       // Simulate an instance event with a pair of begin/end events.
-      WriteEvent('B', category_group, name_, id_, args_, flags_);
+      WriteEvent('B', category_group, name_, id_,
+                 arg_names_, arg_types_, arg_values_, convertable_values_,
+                 flags_);
       WriteToATrace(g_atrace_fd, "E", 1);
       break;
 
     case TRACE_EVENT_PHASE_COUNTER:
-      for (size_t i = 0; i < arg_size() && arg_name(i); ++i) {
-        DCHECK(arg_type(i) == TRACE_VALUE_TYPE_INT);
-        std::string out =
-            base::StringPrintf("C|%d|%s-%s", getpid(), name_, arg_name(i));
+      for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
+        DCHECK(arg_types_[i] == TRACE_VALUE_TYPE_INT);
+        std::string out = base::StringPrintf(
+            "C|%d|%s-%s", getpid(), name_, arg_names_[i]);
         if (flags_ & TRACE_EVENT_FLAG_HAS_ID)
           StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id_));
-        StringAppendF(&out, "|%d|%s", static_cast<int>(arg_value(i).as_int),
-                      category_group);
+        StringAppendF(&out, "|%d|%s",
+                      static_cast<int>(arg_values_[i].as_int), category_group);
         WriteToATrace(g_atrace_fd, out.c_str(), out.size());
       }
       break;
diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h
index 7860abf5..2d2eb54 100644
--- a/base/trace_event/trace_event_argument.h
+++ b/base/trace_event/trace_event_argument.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// 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.
 
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc
index 65ce7d7e..e6d8107 100644
--- a/base/trace_event/trace_event_etw_export_win.cc
+++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -172,11 +172,16 @@
 }
 
 // static
-void TraceEventETWExport::AddEvent(char phase,
-                                   const unsigned char* category_group_enabled,
-                                   const char* name,
-                                   unsigned long long id,
-                                   const TraceArguments* args) {
+void TraceEventETWExport::AddEvent(
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    unsigned long long id,
+    int num_args,
+    const char* const* arg_names,
+    const unsigned char* arg_types,
+    const unsigned long long* arg_values,
+    const std::unique_ptr<ConvertableToTraceFormat>* convertable_values) {
   // We bail early in case exporting is disabled or no consumer is listening.
   auto* instance = GetInstance();
   if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent())
@@ -254,22 +259,26 @@
   }
 
   std::string arg_values_string[3];
-  size_t num_args = args ? args->size() : 0;
-  for (size_t i = 0; i < num_args; i++) {
-    if (args->types()[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
+  for (int i = 0; i < num_args; i++) {
+    if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
       // Temporarily do nothing here. This function consumes 1/3 to 1/2 of
       // *total* process CPU time when ETW tracing, and many of the strings
       // created exceed WPA's 4094 byte limit and are shown as:
       // "Unable to parse data". See crbug.com/488257
+      // convertable_values[i]->AppendAsTraceFormat(arg_values_string + i);
     } else {
-      args->values()[i].AppendAsJSON(args->types()[i], arg_values_string + i);
+      TraceEvent::TraceValue trace_event;
+      trace_event.as_uint = arg_values[i];
+      TraceEvent::AppendValueAsJSON(arg_types[i], trace_event,
+                                    arg_values_string + i);
     }
   }
 
   EventWriteChromeEvent(
-      name, phase_string, num_args > 0 ? args->names()[0] : "",
-      arg_values_string[0].c_str(), num_args > 1 ? args->names()[1] : "",
-      arg_values_string[1].c_str(), "", "");
+      name, phase_string, num_args > 0 ? arg_names[0] : "",
+      arg_values_string[0].c_str(), num_args > 1 ? arg_names[1] : "",
+      arg_values_string[1].c_str(), num_args > 2 ? arg_names[2] : "",
+      arg_values_string[2].c_str());
 }
 
 // static
diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h
index edcaef9a..8a85b221 100644
--- a/base/trace_event/trace_event_etw_export_win.h
+++ b/base/trace_event/trace_event_etw_export_win.h
@@ -41,11 +41,16 @@
 
   // Exports an event to ETW. This is mainly used in
   // TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events.
-  static void AddEvent(char phase,
-                       const unsigned char* category_group_enabled,
-                       const char* name,
-                       unsigned long long id,
-                       const TraceArguments* args);
+  static void AddEvent(
+      char phase,
+      const unsigned char* category_group_enabled,
+      const char* name,
+      unsigned long long id,
+      int num_args,
+      const char* const* arg_names,
+      const unsigned char* arg_types,
+      const unsigned long long* arg_values,
+      const std::unique_ptr<ConvertableToTraceFormat>* convertable_values);
 
   // Exports an ETW event that marks the end of a complete event.
   static void AddCompleteEndEvent(const char* name);
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index cc423006..3458115 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -19,61 +19,169 @@
 #include "base/trace_event/trace_log.h"
 #include "base/trace_event/traced_value.h"
 
-#include <algorithm>
-
 namespace base {
 namespace trace_event {
 
+namespace {
+
+size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; }
+
+// Copies |*member| into |*buffer|, sets |*member| to point to this new
+// location, and then advances |*buffer| by the amount written.
+void CopyTraceEventParameter(char** buffer,
+                             const char** member,
+                             const char* end) {
+  if (*member) {
+    size_t written = strlcpy(*buffer, *member, end - *buffer) + 1;
+    DCHECK_LE(static_cast<int>(written), end - *buffer);
+    *member = *buffer;
+    *buffer += written;
+  }
+}
+
+}  // namespace
+
 TraceEvent::TraceEvent()
     : duration_(TimeDelta::FromInternalValue(-1)),
       scope_(trace_event_internal::kGlobalScope),
-      id_(0),
+      id_(0u),
       category_group_enabled_(nullptr),
       name_(nullptr),
-      thread_id_(-1),
+      thread_id_(0),
       flags_(0),
-      phase_(TRACE_EVENT_PHASE_BEGIN) {}
-
-TraceEvent::TraceEvent(int thread_id,
-                       TimeTicks timestamp,
-                       ThreadTicks thread_timestamp,
-                       char phase,
-                       const unsigned char* category_group_enabled,
-                       const char* name,
-                       const char* scope,
-                       unsigned long long id,
-                       unsigned long long bind_id,
-                       TraceArguments* args,
-                       unsigned int flags)
-    : timestamp_(timestamp),
-      thread_timestamp_(thread_timestamp),
-      duration_(TimeDelta::FromInternalValue(-1)),
-      thread_duration_(TimeDelta::FromInternalValue(-1)),
-      scope_(scope),
-      id_(id),
-      category_group_enabled_(category_group_enabled),
-      name_(name),
-      thread_id_(thread_id),
-      flags_(flags),
-      bind_id_(bind_id),
-      phase_(phase) {
-  if (args)
-    args_ = std::move(*args);
-  args_.CopyStringsTo(&parameter_copy_storage_,
-                      !!(flags_ & TRACE_EVENT_FLAG_COPY), &name_, &scope_);
+      phase_(TRACE_EVENT_PHASE_BEGIN) {
+  for (int i = 0; i < kTraceMaxNumArgs; ++i)
+    arg_names_[i] = nullptr;
+  memset(arg_values_, 0, sizeof(arg_values_));
 }
 
 TraceEvent::~TraceEvent() = default;
 
-TraceEvent::TraceEvent(TraceEvent&& other) noexcept = default;
-TraceEvent& TraceEvent::operator=(TraceEvent&& other) noexcept = default;
+void TraceEvent::MoveFrom(std::unique_ptr<TraceEvent> other) {
+  timestamp_ = other->timestamp_;
+  thread_timestamp_ = other->thread_timestamp_;
+  duration_ = other->duration_;
+  scope_ = other->scope_;
+  id_ = other->id_;
+  category_group_enabled_ = other->category_group_enabled_;
+  name_ = other->name_;
+  if (other->flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID)
+    process_id_ = other->process_id_;
+  else
+    thread_id_ = other->thread_id_;
+  phase_ = other->phase_;
+  flags_ = other->flags_;
+  parameter_copy_storage_ = std::move(other->parameter_copy_storage_);
+
+  for (int i = 0; i < kTraceMaxNumArgs; ++i) {
+    arg_names_[i] = other->arg_names_[i];
+    arg_types_[i] = other->arg_types_[i];
+    arg_values_[i] = other->arg_values_[i];
+    convertable_values_[i] = std::move(other->convertable_values_[i]);
+  }
+}
+
+void TraceEvent::Initialize(
+    int thread_id,
+    TimeTicks timestamp,
+    ThreadTicks thread_timestamp,
+    char phase,
+    const unsigned char* category_group_enabled,
+    const char* name,
+    const char* scope,
+    unsigned long long id,
+    unsigned long long bind_id,
+    int num_args,
+    const char* const* arg_names,
+    const unsigned char* arg_types,
+    const unsigned long long* arg_values,
+    std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
+    unsigned int flags) {
+  timestamp_ = timestamp;
+  thread_timestamp_ = thread_timestamp;
+  duration_ = TimeDelta::FromInternalValue(-1);
+  scope_ = scope;
+  id_ = id;
+  category_group_enabled_ = category_group_enabled;
+  name_ = name;
+  thread_id_ = thread_id;
+  phase_ = phase;
+  flags_ = flags;
+  bind_id_ = bind_id;
+
+  // Clamp num_args since it may have been set by a third_party library.
+  num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
+  int i = 0;
+  for (; i < num_args; ++i) {
+    arg_names_[i] = arg_names[i];
+    arg_types_[i] = arg_types[i];
+
+    if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
+      convertable_values_[i] = std::move(convertable_values[i]);
+    } else {
+      arg_values_[i].as_uint = arg_values[i];
+      convertable_values_[i].reset();
+    }
+  }
+  for (; i < kTraceMaxNumArgs; ++i) {
+    arg_names_[i] = nullptr;
+    arg_values_[i].as_uint = 0u;
+    convertable_values_[i].reset();
+    arg_types_[i] = TRACE_VALUE_TYPE_UINT;
+  }
+
+  bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
+  size_t alloc_size = 0;
+  if (copy) {
+    alloc_size += GetAllocLength(name) + GetAllocLength(scope);
+    for (i = 0; i < num_args; ++i) {
+      alloc_size += GetAllocLength(arg_names_[i]);
+      if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
+        arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
+    }
+  }
+
+  bool arg_is_copy[kTraceMaxNumArgs];
+  for (i = 0; i < num_args; ++i) {
+    // No copying of convertable types, we retain ownership.
+    if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
+      continue;
+
+    // We only take a copy of arg_vals if they are of type COPY_STRING.
+    arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
+    if (arg_is_copy[i])
+      alloc_size += GetAllocLength(arg_values_[i].as_string);
+  }
+
+  if (alloc_size) {
+    parameter_copy_storage_.reset(new std::string);
+    parameter_copy_storage_->resize(alloc_size);
+    char* ptr = base::data(*parameter_copy_storage_);
+    const char* end = ptr + alloc_size;
+    if (copy) {
+      CopyTraceEventParameter(&ptr, &name_, end);
+      CopyTraceEventParameter(&ptr, &scope_, end);
+      for (i = 0; i < num_args; ++i) {
+        CopyTraceEventParameter(&ptr, &arg_names_[i], end);
+      }
+    }
+    for (i = 0; i < num_args; ++i) {
+      if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
+        continue;
+      if (arg_is_copy[i])
+        CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end);
+    }
+    DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end;
+  }
+}
 
 void TraceEvent::Reset() {
-  // Only reset fields that won't be initialized in constructor, or that may
+  // Only reset fields that won't be initialized in Initialize(), or that may
   // hold references to other objects.
   duration_ = TimeDelta::FromInternalValue(-1);
-  args_.Reset();
-  parameter_copy_storage_.Reset();
+  parameter_copy_storage_.reset();
+  for (int i = 0; i < kTraceMaxNumArgs; ++i)
+    convertable_values_[i].reset();
 }
 
 void TraceEvent::UpdateDuration(const TimeTicks& now,
@@ -89,12 +197,80 @@
 
 void TraceEvent::EstimateTraceMemoryOverhead(
     TraceEventMemoryOverhead* overhead) {
-  overhead->Add(TraceEventMemoryOverhead::kTraceEvent,
-                parameter_copy_storage_.EstimateTraceMemoryOverhead());
+  overhead->Add(TraceEventMemoryOverhead::kTraceEvent, sizeof(*this));
 
-  for (size_t i = 0; i < arg_size(); ++i) {
-    if (arg_type(i) == TRACE_VALUE_TYPE_CONVERTABLE)
-      arg_value(i).as_convertable->EstimateTraceMemoryOverhead(overhead);
+  if (parameter_copy_storage_)
+    overhead->AddString(*parameter_copy_storage_);
+
+  for (size_t i = 0; i < kTraceMaxNumArgs; ++i) {
+    if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
+      convertable_values_[i]->EstimateTraceMemoryOverhead(overhead);
+  }
+}
+
+// static
+void TraceEvent::AppendValueAsJSON(unsigned char type,
+                                   TraceEvent::TraceValue value,
+                                   std::string* out) {
+  switch (type) {
+    case TRACE_VALUE_TYPE_BOOL:
+      *out += value.as_bool ? "true" : "false";
+      break;
+    case TRACE_VALUE_TYPE_UINT:
+      StringAppendF(out, "%" PRIu64, static_cast<uint64_t>(value.as_uint));
+      break;
+    case TRACE_VALUE_TYPE_INT:
+      StringAppendF(out, "%" PRId64, static_cast<int64_t>(value.as_int));
+      break;
+    case TRACE_VALUE_TYPE_DOUBLE: {
+      // FIXME: base/json/json_writer.cc is using the same code,
+      //        should be made into a common method.
+      std::string real;
+      double val = value.as_double;
+      if (std::isfinite(val)) {
+        real = NumberToString(val);
+        // Ensure that the number has a .0 if there's no decimal or 'e'.  This
+        // makes sure that when we read the JSON back, it's interpreted as a
+        // real rather than an int.
+        if (real.find('.') == std::string::npos &&
+            real.find('e') == std::string::npos &&
+            real.find('E') == std::string::npos) {
+          real.append(".0");
+        }
+        // The JSON spec requires that non-integer values in the range (-1,1)
+        // have a zero before the decimal point - ".52" is not valid, "0.52" is.
+        if (real[0] == '.') {
+          real.insert(0, "0");
+        } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
+          // "-.1" bad "-0.1" good
+          real.insert(1, "0");
+        }
+      } else if (std::isnan(val)){
+        // The JSON spec doesn't allow NaN and Infinity (since these are
+        // objects in EcmaScript).  Use strings instead.
+        real = "\"NaN\"";
+      } else if (val < 0) {
+        real = "\"-Infinity\"";
+      } else {
+        real = "\"Infinity\"";
+      }
+      StringAppendF(out, "%s", real.c_str());
+      break;
+    }
+    case TRACE_VALUE_TYPE_POINTER:
+      // JSON only supports double and int numbers.
+      // So as not to lose bits from a 64-bit pointer, output as a hex string.
+      StringAppendF(
+          out, "\"0x%" PRIx64 "\"",
+          static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value.as_pointer)));
+      break;
+    case TRACE_VALUE_TYPE_STRING:
+    case TRACE_VALUE_TYPE_COPY_STRING:
+      EscapeJSONString(value.as_string ? value.as_string : "NULL", true, out);
+      break;
+    default:
+      NOTREACHED() << "Don't know how to print this value";
+      break;
   }
 }
 
@@ -129,7 +305,7 @@
   // approach
   ArgumentNameFilterPredicate argument_name_filter_predicate;
   bool strip_args =
-      arg_size() > 0 && arg_name(0) && !argument_filter_predicate.is_null() &&
+      arg_names_[0] && !argument_filter_predicate.is_null() &&
       !argument_filter_predicate.Run(category_group_name, name_,
                                      &argument_name_filter_predicate);
 
@@ -138,16 +314,19 @@
   } else {
     *out += "{";
 
-    for (size_t i = 0; i < arg_size() && arg_name(i); ++i) {
+    for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
       if (i > 0)
         *out += ",";
       *out += "\"";
-      *out += arg_name(i);
+      *out += arg_names_[i];
       *out += "\":";
 
       if (argument_name_filter_predicate.is_null() ||
-          argument_name_filter_predicate.Run(arg_name(i))) {
-        arg_value(i).AppendAsJSON(arg_type(i), out);
+          argument_name_filter_predicate.Run(arg_names_[i])) {
+        if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
+          convertable_values_[i]->AppendAsTraceFormat(out);
+        else
+          AppendValueAsJSON(arg_types_[i], arg_values_[i], out);
       } else {
         *out += "\"__stripped__\"";
       }
@@ -248,14 +427,19 @@
   *out << name_ << "[";
   *out << TraceLog::GetCategoryGroupName(category_group_enabled_);
   *out << "]";
-  if (arg_size() > 0 && arg_name(0)) {
+  if (arg_names_[0]) {
     *out << ", {";
-    for (size_t i = 0; i < arg_size() && arg_name(i); ++i) {
+    for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
       if (i > 0)
         *out << ", ";
-      *out << arg_name(i) << ":";
+      *out << arg_names_[i] << ":";
       std::string value_as_text;
-      arg_value(i).AppendAsJSON(arg_type(i), &value_as_text);
+
+      if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
+        convertable_values_[i]->AppendAsTraceFormat(&value_as_text);
+      else
+        AppendValueAsJSON(arg_types_[i], arg_values_[i], &value_as_text);
+
       *out << value_as_text;
     }
     *out << "}";
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index 9c88afe..4b4b88f5 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -23,8 +23,6 @@
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_local.h"
-#include "base/trace_event/common/trace_event_common.h"
-#include "base/trace_event/trace_arguments.h"
 #include "base/trace_event/trace_event_memory_overhead.h"
 #include "build/build_config.h"
 
@@ -38,6 +36,33 @@
                             ArgumentNameFilterPredicate*)>
     ArgumentFilterPredicate;
 
+// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
+// class must implement this interface.
+class BASE_EXPORT ConvertableToTraceFormat {
+ public:
+  ConvertableToTraceFormat() = default;
+  virtual ~ConvertableToTraceFormat() = default;
+
+  // Append the class info to the provided |out| string. The appended
+  // data must be a valid JSON object. Strings must be properly quoted, and
+  // escaped. There is no processing applied to the content after it is
+  // appended.
+  virtual void AppendAsTraceFormat(std::string* out) const = 0;
+
+  virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
+
+  std::string ToString() const {
+    std::string result;
+    AppendAsTraceFormat(&result);
+    return result;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat);
+};
+
+const int kTraceMaxNumArgs = 2;
+
 struct TraceEventHandle {
   uint32_t chunk_seq;
   // These numbers of bits must be kept consistent with
@@ -49,27 +74,35 @@
 
 class BASE_EXPORT TraceEvent {
  public:
-  // TODO(898794): Remove once all users have been updated.
-  using TraceValue = base::trace_event::TraceValue;
+  union TraceValue {
+    bool as_bool;
+    unsigned long long as_uint;
+    long long as_int;
+    double as_double;
+    const void* as_pointer;
+    const char* as_string;
+  };
 
   TraceEvent();
   ~TraceEvent();
 
-  // Allow move operations.
-  TraceEvent(TraceEvent&&) noexcept;
-  TraceEvent& operator=(TraceEvent&&) noexcept;
+  void MoveFrom(std::unique_ptr<TraceEvent> other);
 
-  TraceEvent(int thread_id,
-             TimeTicks timestamp,
-             ThreadTicks thread_timestamp,
-             char phase,
-             const unsigned char* category_group_enabled,
-             const char* name,
-             const char* scope,
-             unsigned long long id,
-             unsigned long long bind_id,
-             TraceArguments* args,
-             unsigned int flags);
+  void Initialize(int thread_id,
+                  TimeTicks timestamp,
+                  ThreadTicks thread_timestamp,
+                  char phase,
+                  const unsigned char* category_group_enabled,
+                  const char* name,
+                  const char* scope,
+                  unsigned long long id,
+                  unsigned long long bind_id,
+                  int num_args,
+                  const char* const* arg_names,
+                  const unsigned char* arg_types,
+                  const unsigned long long* arg_values,
+                  std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
+                  unsigned int flags);
 
   void Reset();
 
@@ -83,12 +116,9 @@
       const ArgumentFilterPredicate& argument_filter_predicate) const;
   void AppendPrettyPrinted(std::ostringstream* out) const;
 
-  // TODO(898794): Remove once caller has been updated.
   static void AppendValueAsJSON(unsigned char type,
                                 TraceValue value,
-                                std::string* out) {
-    value.AppendAsJSON(type, out);
-  }
+                                std::string* out);
 
   TimeTicks timestamp() const { return timestamp_; }
   ThreadTicks thread_timestamp() const { return thread_timestamp_; }
@@ -102,8 +132,8 @@
   unsigned long long bind_id() const { return bind_id_; }
   // Exposed for unittesting:
 
-  const StringStorage& parameter_copy_storage() const {
-    return parameter_copy_storage_;
+  const std::string* parameter_copy_storage() const {
+    return parameter_copy_storage_.get();
   }
 
   const unsigned char* category_group_enabled() const {
@@ -112,17 +142,12 @@
 
   const char* name() const { return name_; }
 
-  size_t arg_size() const { return args_.size(); }
-  unsigned char arg_type(size_t index) const { return args_.types()[index]; }
-  const char* arg_name(size_t index) const { return args_.names()[index]; }
-  const TraceValue& arg_value(size_t index) const {
-    return args_.values()[index];
-  }
+  unsigned char arg_type(size_t index) const { return arg_types_[index]; }
+  const char* arg_name(size_t index) const { return arg_names_[index]; }
+  const TraceValue& arg_value(size_t index) const { return arg_values_[index]; }
 
   const ConvertableToTraceFormat* arg_convertible_value(size_t index) const {
-    return (arg_type(index) == TRACE_VALUE_TYPE_CONVERTABLE)
-               ? arg_value(index).as_convertable
-               : nullptr;
+    return convertable_values_[index].get();
   }
 
 #if defined(OS_ANDROID)
@@ -138,10 +163,13 @@
   // scope_ and id_ can be used to store phase-specific data.
   const char* scope_;
   unsigned long long id_;
+  TraceValue arg_values_[kTraceMaxNumArgs];
+  const char* arg_names_[kTraceMaxNumArgs];
+  std::unique_ptr<ConvertableToTraceFormat>
+      convertable_values_[kTraceMaxNumArgs];
   const unsigned char* category_group_enabled_;
   const char* name_;
-  StringStorage parameter_copy_storage_;
-  TraceArguments args_;
+  std::unique_ptr<std::string> parameter_copy_storage_;
   // Depending on TRACE_EVENT_FLAG_HAS_PROCESS_ID the event will have either:
   //  tid: thread_id_, pid: current_process_id (default case).
   //  tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID).
@@ -151,6 +179,7 @@
   };
   unsigned int flags_;
   unsigned long long bind_id_;
+  unsigned char arg_types_[kTraceMaxNumArgs];
   char phase_;
 
   DISALLOW_COPY_AND_ASSIGN(TraceEvent);
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc
index c5928ec..4f51f97 100644
--- a/base/trace_event/trace_event_unittest.cc
+++ b/base/trace_event/trace_event_unittest.cc
@@ -1697,10 +1697,10 @@
     ASSERT_TRUE(event2);
     EXPECT_STREQ("name1", event1->name());
     EXPECT_STREQ("name2", event2->name());
-    EXPECT_FALSE(event1->parameter_copy_storage().empty());
-    EXPECT_FALSE(event2->parameter_copy_storage().empty());
-    EXPECT_GT(event1->parameter_copy_storage().size(), 0u);
-    EXPECT_GT(event2->parameter_copy_storage().size(), 0u);
+    EXPECT_TRUE(event1->parameter_copy_storage() != nullptr);
+    EXPECT_TRUE(event2->parameter_copy_storage() != nullptr);
+    EXPECT_GT(event1->parameter_copy_storage()->size(), 0u);
+    EXPECT_GT(event2->parameter_copy_storage()->size(), 0u);
     EndTraceAndFlush();
   }
 
@@ -1730,8 +1730,8 @@
     ASSERT_TRUE(event2);
     EXPECT_STREQ("name1", event1->name());
     EXPECT_STREQ("name2", event2->name());
-    EXPECT_TRUE(event1->parameter_copy_storage().empty());
-    EXPECT_TRUE(event2->parameter_copy_storage().empty());
+    EXPECT_TRUE(event1->parameter_copy_storage() == nullptr);
+    EXPECT_TRUE(event2->parameter_copy_storage() == nullptr);
     EndTraceAndFlush();
   }
 }
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index 1f539f9..82474dd7 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -109,14 +109,26 @@
   if (!trace_event)
     return;
 
-  TraceArguments args(arg_name, value);
-  *trace_event = TraceEvent(
-      thread_id, TimeTicks(), ThreadTicks(), TRACE_EVENT_PHASE_METADATA,
-      CategoryRegistry::kCategoryMetadata->state_ptr(), metadata_name,
+  int num_args = 1;
+  unsigned char arg_type;
+  unsigned long long arg_value;
+  ::trace_event_internal::SetTraceValue(value, &arg_type, &arg_value);
+  trace_event->Initialize(
+      thread_id,
+      TimeTicks(),
+      ThreadTicks(),
+      TRACE_EVENT_PHASE_METADATA,
+      CategoryRegistry::kCategoryMetadata->state_ptr(),
+      metadata_name,
       trace_event_internal::kGlobalScope,  // scope
-      trace_event_internal::kNoId,         // id
-      trace_event_internal::kNoId,         // bind_id
-      &args, TRACE_EVENT_FLAG_NONE);
+      trace_event_internal::kNoId,  // id
+      trace_event_internal::kNoId,  // bind_id
+      num_args,
+      &arg_name,
+      &arg_type,
+      &arg_value,
+      nullptr,
+      TRACE_EVENT_FLAG_NONE);
 }
 
 class AutoThreadLocalBoolean {
@@ -1069,12 +1081,21 @@
     unsigned int flags) {
   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
   base::TimeTicks now = TRACE_TIME_TICKS_NOW();
-  TraceArguments args(num_args, arg_names, arg_types, arg_values,
-                      convertable_values);
   return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id,
+      phase,
+      category_group_enabled,
+      name,
+      scope,
+      id,
       trace_event_internal::kNoId,  // bind_id
-      thread_id, now, &args, flags);
+      thread_id,
+      now,
+      num_args,
+      arg_names,
+      arg_types,
+      arg_values,
+      convertable_values,
+      flags);
 }
 
 TraceEventHandle TraceLog::AddTraceEventWithBindId(
@@ -1092,11 +1113,21 @@
     unsigned int flags) {
   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
   base::TimeTicks now = TRACE_TIME_TICKS_NOW();
-  TraceArguments args(num_args, arg_names, arg_types, arg_values,
-                      convertable_values);
   return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id, bind_id, thread_id, now,
-      &args, flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID);
+      phase,
+      category_group_enabled,
+      name,
+      scope,
+      id,
+      bind_id,
+      thread_id,
+      now,
+      num_args,
+      arg_names,
+      arg_types,
+      arg_values,
+      convertable_values,
+      flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID);
 }
 
 TraceEventHandle TraceLog::AddTraceEventWithProcessId(
@@ -1113,12 +1144,21 @@
     std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
     unsigned int flags) {
   base::TimeTicks now = TRACE_TIME_TICKS_NOW();
-  TraceArguments args(num_args, arg_names, arg_types, arg_values,
-                      convertable_values);
   return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id,
+      phase,
+      category_group_enabled,
+      name,
+      scope,
+      id,
       trace_event_internal::kNoId,  // bind_id
-      process_id, now, &args, flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
+      process_id,
+      now,
+      num_args,
+      arg_names,
+      arg_types,
+      arg_values,
+      convertable_values,
+      flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
 }
 
 // Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp
@@ -1137,78 +1177,21 @@
     const unsigned long long* arg_values,
     std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
     unsigned int flags) {
-  TraceArguments args(num_args, arg_names, arg_types, arg_values,
-                      convertable_values);
   return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id,
+      phase,
+      category_group_enabled,
+      name,
+      scope,
+      id,
       trace_event_internal::kNoId,  // bind_id
-      thread_id, timestamp, &args, flags);
-}
-
-TraceEventHandle TraceLog::AddTraceEvent(
-    char phase,
-    const unsigned char* category_group_enabled,
-    const char* name,
-    const char* scope,
-    unsigned long long id,
-    TraceArguments* args,
-    unsigned int flags) {
-  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
-  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
-  return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id,
-      trace_event_internal::kNoId,  // bind_id
-      thread_id, now, args, flags);
-}
-
-TraceEventHandle TraceLog::AddTraceEventWithBindId(
-    char phase,
-    const unsigned char* category_group_enabled,
-    const char* name,
-    const char* scope,
-    unsigned long long id,
-    unsigned long long bind_id,
-    TraceArguments* args,
-    unsigned int flags) {
-  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
-  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
-  return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id, bind_id, thread_id, now,
-      args, flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID);
-}
-
-TraceEventHandle TraceLog::AddTraceEventWithProcessId(
-    char phase,
-    const unsigned char* category_group_enabled,
-    const char* name,
-    const char* scope,
-    unsigned long long id,
-    int process_id,
-    TraceArguments* args,
-    unsigned int flags) {
-  base::TimeTicks now = TRACE_TIME_TICKS_NOW();
-  return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id,
-      trace_event_internal::kNoId,  // bind_id
-      process_id, now, args, flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
-}
-
-// Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp
-// with kNoId as bind_id
-TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
-    char phase,
-    const unsigned char* category_group_enabled,
-    const char* name,
-    const char* scope,
-    unsigned long long id,
-    int thread_id,
-    const TimeTicks& timestamp,
-    TraceArguments* args,
-    unsigned int flags) {
-  return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id,
-      trace_event_internal::kNoId,  // bind_id
-      thread_id, timestamp, args, flags);
+      thread_id,
+      timestamp,
+      num_args,
+      arg_names,
+      arg_types,
+      arg_values,
+      convertable_values,
+      flags);
 }
 
 TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
@@ -1226,24 +1209,6 @@
     const unsigned long long* arg_values,
     std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
     unsigned int flags) {
-  TraceArguments args(num_args, arg_names, arg_types, arg_values,
-                      convertable_values);
-  return AddTraceEventWithThreadIdAndTimestamp(
-      phase, category_group_enabled, name, scope, id, bind_id, thread_id,
-      timestamp, &args, flags);
-}
-
-TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
-    char phase,
-    const unsigned char* category_group_enabled,
-    const char* name,
-    const char* scope,
-    unsigned long long id,
-    unsigned long long bind_id,
-    int thread_id,
-    const TimeTicks& timestamp,
-    TraceArguments* args,
-    unsigned int flags) {
   TraceEventHandle handle = {0, 0, 0};
   if (!*category_group_enabled)
     return handle;
@@ -1316,13 +1281,15 @@
   // acquiring the lock, which is not needed for ETW as it's already threadsafe.
   if (*category_group_enabled & TraceCategory::ENABLED_FOR_ETW_EXPORT)
     TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id,
-                                  args);
+                                  num_args, arg_names, arg_types, arg_values,
+                                  convertable_values);
 #endif  // OS_WIN
 
   AddTraceEventOverrideCallback trace_event_override =
       reinterpret_cast<AddTraceEventOverrideCallback>(
           subtle::NoBarrier_Load(&trace_event_override_));
   if (trace_event_override) {
+    TraceEvent new_trace_event;
     // If we have an override in place for events, rather than sending
     // them to the tracelog, we don't have a way of going back and updating
     // the duration of _COMPLETE events. Instead, we emit separate _BEGIN
@@ -1330,9 +1297,10 @@
     if (phase == TRACE_EVENT_PHASE_COMPLETE)
       phase = TRACE_EVENT_PHASE_BEGIN;
 
-    TraceEvent new_trace_event(thread_id, offset_event_timestamp, thread_now,
+    new_trace_event.Initialize(thread_id, offset_event_timestamp, thread_now,
                                phase, category_group_enabled, name, scope, id,
-                               bind_id, args, flags);
+                               bind_id, num_args, arg_names, arg_types,
+                               arg_values, convertable_values, flags);
 
     trace_event_override(new_trace_event);
     return handle;
@@ -1342,9 +1310,11 @@
   std::unique_ptr<TraceEvent> filtered_trace_event;
   bool disabled_by_filters = false;
   if (*category_group_enabled & TraceCategory::ENABLED_FOR_FILTERING) {
-    auto new_trace_event = std::make_unique<TraceEvent>(
-        thread_id, offset_event_timestamp, thread_now, phase,
-        category_group_enabled, name, scope, id, bind_id, args, flags);
+    std::unique_ptr<TraceEvent> new_trace_event(new TraceEvent);
+    new_trace_event->Initialize(thread_id, offset_event_timestamp, thread_now,
+                                phase, category_group_enabled, name, scope, id,
+                                bind_id, num_args, arg_names, arg_types,
+                                arg_values, convertable_values, flags);
 
     disabled_by_filters = true;
     ForEachCategoryFilter(
@@ -1373,11 +1343,12 @@
 
     if (trace_event) {
       if (filtered_trace_event) {
-        *trace_event = std::move(*filtered_trace_event);
+        trace_event->MoveFrom(std::move(filtered_trace_event));
       } else {
-        *trace_event = TraceEvent(thread_id, offset_event_timestamp, thread_now,
-                                  phase, category_group_enabled, name, scope,
-                                  id, bind_id, args, flags);
+        trace_event->Initialize(thread_id, offset_event_timestamp, thread_now,
+                                phase, category_group_enabled, name, scope, id,
+                                bind_id, num_args, arg_names, arg_types,
+                                arg_values, convertable_values, flags);
       }
 
 #if defined(OS_ANDROID)
@@ -1407,27 +1378,19 @@
     const unsigned long long* arg_values,
     std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
     unsigned int flags) {
-  TraceArguments args(num_args, arg_names, arg_types, arg_values,
-                      convertable_values);
-  return AddMetadataEvent(category_group_enabled, name, &args, flags);
-}
-
-void TraceLog::AddMetadataEvent(const unsigned char* category_group_enabled,
-                                const char* name,
-                                TraceArguments* args,
-                                unsigned int flags) {
   HEAP_PROFILER_SCOPED_IGNORE;
+  std::unique_ptr<TraceEvent> trace_event(new TraceEvent);
   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
   ThreadTicks thread_now = ThreadNow();
   TimeTicks now = OffsetNow();
   AutoLock lock(lock_);
-  auto trace_event = std::make_unique<TraceEvent>(
+  trace_event->Initialize(
       thread_id, now, thread_now, TRACE_EVENT_PHASE_METADATA,
       category_group_enabled, name,
       trace_event_internal::kGlobalScope,  // scope
       trace_event_internal::kNoId,         // id
       trace_event_internal::kNoId,         // bind_id
-      args, flags);
+      num_args, arg_names, arg_types, arg_values, convertable_values, flags);
   metadata_events_.push_back(std::move(trace_event));
 }
 
@@ -1537,13 +1500,14 @@
     // we don't have way of updating the prior event so we'll emit a
     // separate _END event instead.
     if (trace_event_override) {
-      TraceEvent new_trace_event(
+      TraceEvent new_trace_event;
+      new_trace_event.Initialize(
           static_cast<int>(base::PlatformThread::CurrentId()), now, thread_now,
           TRACE_EVENT_PHASE_END, category_group_enabled, name,
           trace_event_internal::kGlobalScope,
           trace_event_internal::kNoId /* id */,
-          trace_event_internal::kNoId /* bind_id */, nullptr,
-          TRACE_EVENT_FLAG_NONE);
+          trace_event_internal::kNoId /* bind_id */, 0, nullptr, nullptr,
+          nullptr, nullptr, TRACE_EVENT_FLAG_NONE);
       trace_event_override(new_trace_event);
 
 #if defined(OS_ANDROID)
@@ -1620,7 +1584,7 @@
     while (!metadata_events_.empty()) {
       TraceEvent* event =
           AddEventToThreadSharedChunkWhileLocked(nullptr, false);
-      *event = std::move(*metadata_events_.back());
+      event->MoveFrom(std::move(metadata_events_.back()));
       metadata_events_.pop_back();
     }
   }
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h
index 89b423b..e1d233a 100644
--- a/base/trace_event/trace_log.h
+++ b/base/trace_event/trace_log.h
@@ -203,58 +203,6 @@
   // Called by TRACE_EVENT* macros, don't call this directly.
   // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied
   // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above.
-  TraceEventHandle AddTraceEvent(char phase,
-                                 const unsigned char* category_group_enabled,
-                                 const char* name,
-                                 const char* scope,
-                                 unsigned long long id,
-                                 TraceArguments* args,
-                                 unsigned int flags);
-  TraceEventHandle AddTraceEventWithBindId(
-      char phase,
-      const unsigned char* category_group_enabled,
-      const char* name,
-      const char* scope,
-      unsigned long long id,
-      unsigned long long bind_id,
-      TraceArguments* args,
-      unsigned int flags);
-  TraceEventHandle AddTraceEventWithProcessId(
-      char phase,
-      const unsigned char* category_group_enabled,
-      const char* name,
-      const char* scope,
-      unsigned long long id,
-      int process_id,
-      TraceArguments* args,
-      unsigned int flags);
-  TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
-      char phase,
-      const unsigned char* category_group_enabled,
-      const char* name,
-      const char* scope,
-      unsigned long long id,
-      int thread_id,
-      const TimeTicks& timestamp,
-      TraceArguments* args,
-      unsigned int flags);
-  TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
-      char phase,
-      const unsigned char* category_group_enabled,
-      const char* name,
-      const char* scope,
-      unsigned long long id,
-      unsigned long long bind_id,
-      int thread_id,
-      const TimeTicks& timestamp,
-      TraceArguments* args,
-      unsigned int flags);
-
-  // Adds a metadata event that will be written when the trace log is flushed.
-  void AddMetadataEvent(const unsigned char* category_group_enabled,
-                        const char* name,
-                        TraceArguments* args,
-                        unsigned int flags);
   TraceEventHandle AddTraceEvent(
       char phase,
       const unsigned char* category_group_enabled,
@@ -267,8 +215,6 @@
       const unsigned long long* arg_values,
       std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
       unsigned int flags);
-
-  // TODO(898794): Remove methods below when all callers have been updated.
   TraceEventHandle AddTraceEventWithBindId(
       char phase,
       const unsigned char* category_group_enabled,
diff --git a/base/trace_event/traced_value.cc b/base/trace_event/traced_value.cc
index a159928..3f4c743 100644
--- a/base/trace_event/traced_value.cc
+++ b/base/trace_event/traced_value.cc
@@ -521,10 +521,10 @@
       }
 
       case kTypeBool: {
-        TraceValue json_value;
+        TraceEvent::TraceValue json_value;
         CHECK(it.ReadBool(&json_value.as_bool));
         maybe_append_key_name(state_stack[current_state_index], &it, out);
-        json_value.AppendAsJSON(TRACE_VALUE_TYPE_BOOL, out);
+        TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, json_value, out);
         break;
       }
 
@@ -532,17 +532,17 @@
         int value;
         CHECK(it.ReadInt(&value));
         maybe_append_key_name(state_stack[current_state_index], &it, out);
-        TraceValue json_value;
+        TraceEvent::TraceValue json_value;
         json_value.as_int = value;
-        json_value.AppendAsJSON(TRACE_VALUE_TYPE_INT, out);
+        TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, json_value, out);
         break;
       }
 
       case kTypeDouble: {
-        TraceValue json_value;
+        TraceEvent::TraceValue json_value;
         CHECK(it.ReadDouble(&json_value.as_double));
         maybe_append_key_name(state_stack[current_state_index], &it, out);
-        json_value.AppendAsJSON(TRACE_VALUE_TYPE_DOUBLE, out);
+        TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, json_value, out);
         break;
       }
 
@@ -550,9 +550,9 @@
         std::string value;
         CHECK(it.ReadString(&value));
         maybe_append_key_name(state_stack[current_state_index], &it, out);
-        TraceValue json_value;
+        TraceEvent::TraceValue json_value;
         json_value.as_string = value.c_str();
-        json_value.AppendAsJSON(TRACE_VALUE_TYPE_STRING, out);
+        TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, json_value, out);
         break;
       }
 
diff --git a/build/android/pylib/base/base_test_result.py b/build/android/pylib/base/base_test_result.py
index a553532..bb25a74 100644
--- a/build/android/pylib/base/base_test_result.py
+++ b/build/android/pylib/base/base_test_result.py
@@ -10,13 +10,13 @@
 class ResultType(object):
   """Class enumerating test types."""
   # The test passed.
-  PASS = 'PASS'
+  PASS = 'SUCCESS'
 
   # The test was intentionally skipped.
-  SKIP = 'SKIP'
+  SKIP = 'SKIPPED'
 
   # The test failed.
-  FAIL = 'FAIL'
+  FAIL = 'FAILURE'
 
   # The test caused the containing process to crash.
   CRASH = 'CRASH'
diff --git a/build/android/pylib/base/test_run.py b/build/android/pylib/base/test_run.py
index 59e595d..3a712c21 100644
--- a/build/android/pylib/base/test_run.py
+++ b/build/android/pylib/base/test_run.py
@@ -24,11 +24,12 @@
   def SetUp(self):
     raise NotImplementedError
 
-  def RunTests(self):
-    """Runs Tests and returns test results.
+  def RunTests(self, results):
+    """Runs Tests and populates |results|.
 
-    Returns:
-      Should return list of |base_test_result.TestRunResults| objects.
+    Args:
+      results: An array that should be populated with
+               |base_test_result.TestRunResults| objects.
     """
     raise NotImplementedError
 
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py
index 8053814..9559b43 100644
--- a/build/android/pylib/local/device/local_device_environment.py
+++ b/build/android/pylib/local/device/local_device_environment.py
@@ -133,7 +133,7 @@
       device_arg = self._device_serials
 
     self._devices = device_utils.DeviceUtils.HealthyDevices(
-        self._blacklist, retries=4,
+        self._blacklist, retries=5,
         enable_device_files_cache=self._enable_device_cache,
         default_retries=self._max_tries - 1, device_arg=device_arg)
 
diff --git a/build/android/pylib/local/device/local_device_gtest_run.py b/build/android/pylib/local/device/local_device_gtest_run.py
index 4734883..f29d672 100644
--- a/build/android/pylib/local/device/local_device_gtest_run.py
+++ b/build/android/pylib/local/device/local_device_gtest_run.py
@@ -317,7 +317,11 @@
             for h, d in host_device_tuples]
         dev.PushChangedFiles(
             host_device_tuples_substituted,
-            delete_device_stale=True)
+            delete_device_stale=True,
+            # Some gtest suites, e.g. unit_tests, have data dependencies that
+            # can take longer than the default timeout to push. See
+            # crbug.com/791632 for context.
+            timeout=600)
         if not host_device_tuples:
           dev.RemovePath(device_root, force=True, recursive=True, rename=True)
           dev.RunShellCommand(['mkdir', '-p', device_root], check_return=True)
diff --git a/build/android/pylib/local/device/local_device_perf_test_run.py b/build/android/pylib/local/device/local_device_perf_test_run.py
index 656f233..bc82840 100644
--- a/build/android/pylib/local/device/local_device_perf_test_run.py
+++ b/build/android/pylib/local/device/local_device_perf_test_run.py
@@ -412,7 +412,7 @@
     return sorted(devices)
 
   #override
-  def RunTests(self):
+  def RunTests(self, results):
     def run_no_devices_tests():
       if not self._no_device_tests:
         return []
@@ -451,7 +451,12 @@
     host_test_results, device_test_results = reraiser_thread.RunAsync(
         [run_no_devices_tests, run_devices_tests])
 
-    return host_test_results + device_test_results
+    # Ideally, results would be populated as early as possible, so that in the
+    # event of an exception or timeout, the caller will still have partially
+    # populated results. This looks like it can be done prior to dispatching
+    # tests, but will hold off on making this change unless it looks like it
+    # might provide utility.
+    results.extend(host_test_results + device_test_results)
 
   # override
   def TestPackage(self):
@@ -480,12 +485,16 @@
     pass
 
   # override
-  def RunTests(self):
+  def RunTests(self, results):
     result_type = self._test_instance.OutputJsonList()
     result = base_test_result.TestRunResults()
     result.AddResult(
         base_test_result.BaseTestResult('OutputJsonList', result_type))
-    return [result]
+
+    # Ideally, results would be populated as early as possible, so that in the
+    # event of an exception or timeout, the caller will still have partially
+    # populated results.
+    results.append(result)
 
   # override
   def _CreateShards(self, _tests):
@@ -502,12 +511,16 @@
     pass
 
   # override
-  def RunTests(self):
+  def RunTests(self, results):
     result_type = self._test_instance.PrintTestOutput()
     result = base_test_result.TestRunResults()
     result.AddResult(
         base_test_result.BaseTestResult('PrintStep', result_type))
-    return [result]
+
+    # Ideally, results would be populated as early as possible, so that in the
+    # event of an exception or timeout, the caller will still have partially
+    # populated results.
+    results.append(result)
 
   # override
   def _CreateShards(self, _tests):
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py
index 00d715b..d76e363e 100644
--- a/build/android/pylib/local/device/local_device_test_run.py
+++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -54,7 +54,7 @@
     self._tools = {}
 
   #override
-  def RunTests(self):
+  def RunTests(self, results):
     tests = self._GetTests()
 
     exit_now = threading.Event()
@@ -115,7 +115,6 @@
     try:
       with signal_handler.SignalHandler(signal.SIGTERM, stop_tests):
         tries = 0
-        results = []
         while tries < self._env.max_tries and tests:
           logging.info('STARTING TRY #%d/%d', tries + 1, self._env.max_tries)
           if tries > 0 and self._env.recover_devices:
@@ -144,6 +143,11 @@
                   t, base_test_result.ResultType.NOTRUN)
               for t in test_names if not t.endswith('*'))
 
+          # As soon as we know the names of the tests, we populate |results|.
+          # The tests in try_results will have their results updated by
+          # try_results.AddResult() as they are run.
+          results.append(try_results)
+
           try:
             if self._ShouldShard():
               tc = test_collection.TestCollection(self._CreateShards(tests))
@@ -160,8 +164,6 @@
                       base_test_result.ResultType.TIMEOUT,
                       log=_SIGTERM_TEST_LOG))
             raise
-          finally:
-            results.append(try_results)
 
           tries += 1
           tests = self._GetTestsToRetry(tests, try_results)
@@ -174,8 +176,6 @@
     except TestsTerminated:
       pass
 
-    return results
-
   def _GetTestsToRetry(self, tests, try_results):
 
     def is_failure_result(test_result):
diff --git a/build/android/pylib/local/machine/local_machine_junit_test_run.py b/build/android/pylib/local/machine/local_machine_junit_test_run.py
index 147104b1..b8ce0ec 100644
--- a/build/android/pylib/local/machine/local_machine_junit_test_run.py
+++ b/build/android/pylib/local/machine/local_machine_junit_test_run.py
@@ -29,7 +29,7 @@
     pass
 
   #override
-  def RunTests(self):
+  def RunTests(self, results):
     with tempfile_ext.NamedTemporaryDirectory() as temp_dir:
       json_file_path = os.path.join(temp_dir, 'results.json')
 
@@ -119,8 +119,7 @@
 
       test_run_results = base_test_result.TestRunResults()
       test_run_results.AddResults(results_list)
-
-      return [test_run_results]
+      results.append(test_run_results)
 
   #override
   def TearDown(self):
diff --git a/build/android/pylib/results/json_results.py b/build/android/pylib/results/json_results.py
index c3bfa4c0..6a10ba4 100644
--- a/build/android/pylib/results/json_results.py
+++ b/build/android/pylib/results/json_results.py
@@ -72,20 +72,6 @@
   #   ],
   # }
 
-  def status_as_string(s):
-    if s == base_test_result.ResultType.PASS:
-      return 'SUCCESS'
-    elif s == base_test_result.ResultType.SKIP:
-      return 'SKIPPED'
-    elif s == base_test_result.ResultType.FAIL:
-      return 'FAILURE'
-    elif s == base_test_result.ResultType.CRASH:
-      return 'CRASH'
-    elif s == base_test_result.ResultType.TIMEOUT:
-      return 'TIMEOUT'
-    elif s == base_test_result.ResultType.UNKNOWN:
-      return 'UNKNOWN'
-
   all_tests = set()
   per_iteration_data = []
   test_run_links = {}
@@ -103,7 +89,7 @@
 
     for r in results_iterable:
       result_dict = {
-          'status': status_as_string(r.GetType()),
+          'status': r.GetType(),
           'elapsed_time_ms': r.GetDuration(),
           'output_snippet': unicode(r.GetLog(), errors='replace'),
           'losless_snippet': True,
@@ -152,18 +138,9 @@
   """
 
   def string_as_status(s):
-    if s == 'SUCCESS':
-      return base_test_result.ResultType.PASS
-    elif s == 'SKIPPED':
-      return base_test_result.ResultType.SKIP
-    elif s == 'FAILURE':
-      return base_test_result.ResultType.FAIL
-    elif s == 'CRASH':
-      return base_test_result.ResultType.CRASH
-    elif s == 'TIMEOUT':
-      return base_test_result.ResultType.TIMEOUT
-    else:
-      return base_test_result.ResultType.UNKNOWN
+    if s in base_test_result.ResultType.GetTypes():
+      return s
+    return base_test_result.ResultType.UNKNOWN
 
   results_list = []
   testsuite_runs = json_results['per_iteration_data']
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 4f84153..d4bbcec 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -844,12 +844,18 @@
           lambda: collections.defaultdict(int))
       iteration_count = 0
       for _ in repetitions:
-        raw_results = test_run.RunTests()
-        if not raw_results:
-          continue
-
+        # raw_results will be populated with base_test_result.TestRunResults by
+        # test_run.RunTests(). It is immediately added to all_raw_results so
+        # that in the event of an exception, all_raw_results will already have
+        # the up-to-date results and those can be written to disk.
+        raw_results = []
         all_raw_results.append(raw_results)
 
+        test_run.RunTests(raw_results)
+        if not raw_results:
+          all_raw_results.pop()
+          continue
+
         iteration_results = base_test_result.TestRunResults()
         for r in reversed(raw_results):
           iteration_results.AddTestRunResults(r)
diff --git a/build/config/android/BUILD.gn b/build/config/android/BUILD.gn
index 5ebde213..f21001c6 100644
--- a/build/config/android/BUILD.gn
+++ b/build/config/android/BUILD.gn
@@ -203,6 +203,12 @@
   ldflags = [ "-Wl,--pack-dyn-relocs=android" ]
 }
 
+# Pack relocations with Android-specific relocations and RELR relocations that
+# are only supported by the crazy linker and Android P+.
+config("lld_pack_relocations_with_relr") {
+  ldflags = [ "-Wl,--pack-dyn-relocs=android+relr,--use-android-relr-tags" ]
+}
+
 # Used for instrumented build to generate the orderfile.
 config("default_orderfile_instrumentation") {
   if (use_order_profiling) {
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index 5fcda742..722468c 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -198,7 +198,7 @@
     }
 
     tool("rc") {
-      command = "$python_path $tool_wrapper_path rc-wrapper $env rc.exe {{defines}} {{include_dirs}} /fo{{output}} {{source}}"
+      command = "$python_path $tool_wrapper_path rc-wrapper $env rc.exe /nologo {{defines}} {{include_dirs}} /fo{{output}} {{source}}"
       depsformat = "msvc"
       outputs = [
         "$object_subdir/{{source_name_part}}.res",
@@ -208,12 +208,12 @@
 
     tool("asm") {
       if (toolchain_args.current_cpu == "x64") {
-        ml = "ml64.exe"
+        ml = "ml64.exe /nologo"
       } else if (toolchain_args.current_cpu == "arm64") {
         prefix = rebase_path("$clang_base_path/bin", root_build_dir)
         ml = "${goma_prefix}${prefix}/${clang_cl} --target=arm64-windows"
       } else {
-        ml = "ml.exe"
+        ml = "ml.exe /nologo"
       }
       command = "$python_path $tool_wrapper_path asm-wrapper $env $ml {{defines}} {{include_dirs}} {{asmflags}} "
       if (toolchain_args.current_cpu == "arm64") {
diff --git a/build/toolchain/win/rc/rc.py b/build/toolchain/win/rc/rc.py
index 73da888..2338762 100755
--- a/build/toolchain/win/rc/rc.py
+++ b/build/toolchain/win/rc/rc.py
@@ -11,6 +11,7 @@
 -I<dir>        Add include path.
 -D<sym>        Define a macro for the preprocessor.
 /fo<out>       Set path of output .res file.
+/nologo        Ignored (rc.py doesn't print a logo by default).
 /showIncludes  Print referenced header and resource files."""
 
 from __future__ import print_function
@@ -51,6 +52,8 @@
               file=sys.stderr)
         sys.exit(1)
       output = flag[3:]
+    elif flag == '/nologo':
+      pass
     elif flag == '/showIncludes':
       show_includes = True
     elif (flag.startswith('-') or
diff --git a/build/toolchain/win/tool_wrapper.py b/build/toolchain/win/tool_wrapper.py
index 6479440..6f01ebf40 100644
--- a/build/toolchain/win/tool_wrapper.py
+++ b/build/toolchain/win/tool_wrapper.py
@@ -169,20 +169,15 @@
     """Filter logo banner from invocations of asm.exe."""
     env = self._GetEnv(arch)
     if sys.platform == 'win32':
-        # Windows ARM64 uses clang-cl as assembler which has '/' as path
-        # separator, convert it to '\\' when running on Windows.
-        args = list(args) # *args is a tuple by default, which is read-only
-        args[0] = args[0].replace('/', '\\')
+      # Windows ARM64 uses clang-cl as assembler which has '/' as path
+      # separator, convert it to '\\' when running on Windows.
+      args = list(args) # *args is a tuple by default, which is read-only
+      args[0] = args[0].replace('/', '\\')
     popen = subprocess.Popen(args, shell=True, env=env,
                              stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     out, _ = popen.communicate()
     for line in out.splitlines():
-      # Split to avoid triggering license checks:
-      if (not line.startswith('Copy' + 'right (C' +
-                              ') Microsoft Corporation') and
-          not line.startswith('Microsoft (R) Macro Assembler') and
-          not line.startswith(' Assembling: ') and
-          line):
+      if not line.startswith(' Assembling: '):
         print line
     return popen.returncode
 
@@ -220,18 +215,7 @@
 
     # 2. Run Microsoft rc.exe.
     if sys.platform == 'win32' and rc_exe_exit_code == 0:
-      popen = subprocess.Popen(args, shell=True, env=env,
-                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-      out, _ = popen.communicate()
-      # Filter logo banner from invocations of rc.exe. Older versions of RC
-      # don't support the /nologo flag.
-      for line in out.splitlines():
-        if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler')
-            and not line.startswith('Copy' + 'right (C' +
-                                ') Microsoft Corporation')
-            and line):
-          print line
-      rc_exe_exit_code = popen.returncode
+      rc_exe_exit_code = subprocess.call(args, shell=True, env=env)
       # Assert Microsoft rc.exe and rc.py produced identical .res files.
       if rc_exe_exit_code == 0:
         import filecmp
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 3315d437..d2dbd42 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -508,7 +508,7 @@
     inputs_.mask_layer->RemoveFromParent();
     DCHECK(!inputs_.mask_layer->parent());
     inputs_.mask_layer->SetParent(this);
-    if (inputs_.filters.IsEmpty() && inputs_.background_filters.IsEmpty() &&
+    if (inputs_.filters.IsEmpty() && inputs_.backdrop_filters.IsEmpty() &&
         (!layer_tree_host_ ||
          layer_tree_host_->GetSettings().enable_mask_tiling)) {
       inputs_.mask_layer->SetLayerMaskType(
@@ -536,11 +536,11 @@
   SetNeedsCommit();
 }
 
-void Layer::SetBackgroundFilters(const FilterOperations& filters) {
+void Layer::SetBackdropFilters(const FilterOperations& filters) {
   DCHECK(IsPropertyChangeAllowed());
-  if (inputs_.background_filters == filters)
+  if (inputs_.backdrop_filters == filters)
     return;
-  inputs_.background_filters = filters;
+  inputs_.backdrop_filters = filters;
 
   // We will not set the mask type to MULTI_TEXTURE_MASK if the mask layer's
   // filters are removed, because we do not want to reraster if the filters are
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 6522e552..8a4094ca 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -278,9 +278,9 @@
   // Set or get the list of filters that should be applied to the content this
   // layer and its subtree will be drawn into. The effect is clipped to only
   // apply directly behind this layer and its subtree.
-  void SetBackgroundFilters(const FilterOperations& filters);
-  const FilterOperations& background_filters() const {
-    return inputs_.background_filters;
+  void SetBackdropFilters(const FilterOperations& filters);
+  const FilterOperations& backdrop_filters() const {
+    return inputs_.backdrop_filters;
   }
 
   // Set or get an optimization hint that the contents of this layer are fully
@@ -895,7 +895,7 @@
     SkColor background_color;
 
     FilterOperations filters;
-    FilterOperations background_filters;
+    FilterOperations backdrop_filters;
     gfx::PointF filters_origin;
 
     gfx::ScrollOffset scroll_offset;
diff --git a/cc/layers/layer_impl_test_properties.h b/cc/layers/layer_impl_test_properties.h
index 0171895c..31cebf4 100644
--- a/cc/layers/layer_impl_test_properties.h
+++ b/cc/layers/layer_impl_test_properties.h
@@ -47,7 +47,7 @@
   int sorting_context_id;
   float opacity;
   FilterOperations filters;
-  FilterOperations background_filters;
+  FilterOperations backdrop_filters;
   gfx::PointF filters_origin;
   SkBlendMode blend_mode;
   LayerPositionConstraint position_constraint;
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 1b4dc11..1f207f8 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -397,7 +397,7 @@
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(
-      root->SetBackgroundFilters(arbitrary_filters));
+      root->SetBackdropFilters(arbitrary_filters));
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
       root->PushPropertiesTo(root_impl.get());
       child->PushPropertiesTo(child_impl.get());
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 9a49483..4e90999 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -149,8 +149,8 @@
   return surface_scale;
 }
 
-const FilterOperations& RenderSurfaceImpl::BackgroundFilters() const {
-  return OwningEffectNode()->background_filters;
+const FilterOperations& RenderSurfaceImpl::BackdropFilters() const {
+  return OwningEffectNode()->backdrop_filters;
 }
 
 bool RenderSurfaceImpl::TrilinearFiltering() const {
@@ -374,7 +374,7 @@
   pass->SetNew(id(), content_rect(), damage_rect,
                draw_properties_.screen_space_transform);
   pass->filters = Filters();
-  pass->background_filters = BackgroundFilters();
+  pass->backdrop_filters = BackdropFilters();
   pass->generate_mipmap = TrilinearFiltering();
   pass->cache_render_pass = ShouldCacheRenderSurface();
   pass->has_damage_from_contributing_content =
diff --git a/cc/layers/render_surface_impl.h b/cc/layers/render_surface_impl.h
index 8e7c1430..6e648a4 100644
--- a/cc/layers/render_surface_impl.h
+++ b/cc/layers/render_surface_impl.h
@@ -149,7 +149,7 @@
   bool HasMaskingContributingSurface() const;
 
   const FilterOperations& Filters() const;
-  const FilterOperations& BackgroundFilters() const;
+  const FilterOperations& BackdropFilters() const;
   gfx::PointF FiltersOrigin() const;
   gfx::Transform SurfaceScale() const;
 
diff --git a/cc/paint/paint_image_generator.h b/cc/paint/paint_image_generator.h
index 95189c7..d0ce1c7 100644
--- a/cc/paint/paint_image_generator.h
+++ b/cc/paint/paint_image_generator.h
@@ -14,7 +14,8 @@
 #include "third_party/skia/include/core/SkData.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
 #include "third_party/skia/include/core/SkSize.h"
-#include "third_party/skia/include/core/SkYUVSizeInfo.h"
+#include "third_party/skia/include/core/SkYUVAIndex.h"
+#include "third_party/skia/include/core/SkYUVASizeInfo.h"
 
 namespace cc {
 
@@ -44,21 +45,25 @@
 
   // Returns true if the generator supports YUV decoding, providing the output
   // information in |info| and |color_space|.
-  virtual bool QueryYUV8(SkYUVSizeInfo* info,
-                         SkYUVColorSpace* color_space) const = 0;
+  virtual bool QueryYUVA8(SkYUVASizeInfo* info,
+                          SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+                          SkYUVColorSpace* color_space) const = 0;
 
   // Decodes to YUV into the provided |planes| for each of the Y, U, and V
   // planes, and returns true on success. The method should only be used if
-  // QueryYUV8 returns true.
-  // |info| needs to exactly match the values returned by the query, except the
-  // WidthBytes may be larger than the recommendation (but not smaller).
+  // QueryYUVA8 returns true.
+  // |info| and |indices| need to exactly match the values returned by the
+  // query, except the info.fWidthBytes may be larger than the recommendation
+  // (but not smaller).
   //
   // TODO(khushalsagar): |lazy_pixel_ref| is only present for
   // DecodingImageGenerator tracing needs. Remove it.
-  virtual bool GetYUV8Planes(const SkYUVSizeInfo& info,
-                             void* planes[3],
-                             size_t frame_index,
-                             uint32_t lazy_pixel_ref) = 0;
+  virtual bool GetYUVA8Planes(
+      const SkYUVASizeInfo& info,
+      const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+      void* planes[3],
+      size_t frame_index,
+      uint32_t lazy_pixel_ref) = 0;
 
   // Returns the smallest size that is at least as big as the requested size,
   // such that we can decode to exactly that scale.
diff --git a/cc/paint/skia_paint_image_generator.cc b/cc/paint/skia_paint_image_generator.cc
index fc42d24..3eb864f 100644
--- a/cc/paint/skia_paint_image_generator.cc
+++ b/cc/paint/skia_paint_image_generator.cc
@@ -31,15 +31,19 @@
       info, pixels, row_bytes, frame_index_, client_id_, uniqueID());
 }
 
-bool SkiaPaintImageGenerator::onQueryYUV8(SkYUVSizeInfo* size_info,
-                                          SkYUVColorSpace* color_space) const {
-  return paint_image_generator_->QueryYUV8(size_info, color_space);
+bool SkiaPaintImageGenerator::onQueryYUVA8(
+    SkYUVASizeInfo* size_info,
+    SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+    SkYUVColorSpace* color_space) const {
+  return paint_image_generator_->QueryYUVA8(size_info, indices, color_space);
 }
 
-bool SkiaPaintImageGenerator::onGetYUV8Planes(const SkYUVSizeInfo& size_info,
-                                              void* planes[3]) {
-  return paint_image_generator_->GetYUV8Planes(size_info, planes, frame_index_,
-                                               uniqueID());
+bool SkiaPaintImageGenerator::onGetYUVA8Planes(
+    const SkYUVASizeInfo& size_info,
+    const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+    void* planes[4]) {
+  return paint_image_generator_->GetYUVA8Planes(size_info, indices, planes,
+                                                frame_index_, uniqueID());
 }
 
 }  // namespace cc
diff --git a/cc/paint/skia_paint_image_generator.h b/cc/paint/skia_paint_image_generator.h
index c93e03b..55068c2 100644
--- a/cc/paint/skia_paint_image_generator.h
+++ b/cc/paint/skia_paint_image_generator.h
@@ -25,10 +25,12 @@
                    void* pixels,
                    size_t row_bytes,
                    const Options& options) override;
-  bool onQueryYUV8(SkYUVSizeInfo* size_info,
-                   SkYUVColorSpace* color_space) const override;
-  bool onGetYUV8Planes(const SkYUVSizeInfo& size_info,
-                       void* planes[3]) override;
+  bool onQueryYUVA8(SkYUVASizeInfo* size_info,
+                    SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+                    SkYUVColorSpace* color_space) const override;
+  bool onGetYUVA8Planes(const SkYUVASizeInfo& size_info,
+                        const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+                        void* planes[3]) override;
 
  private:
   sk_sp<PaintImageGenerator> paint_image_generator_;
diff --git a/cc/test/fake_paint_image_generator.cc b/cc/test/fake_paint_image_generator.cc
index 0c03f4f..d2a35ae8 100644
--- a/cc/test/fake_paint_image_generator.cc
+++ b/cc/test/fake_paint_image_generator.cc
@@ -42,15 +42,17 @@
   return true;
 }
 
-bool FakePaintImageGenerator::QueryYUV8(SkYUVSizeInfo* info,
-                                        SkYUVColorSpace* color_space) const {
+bool FakePaintImageGenerator::QueryYUVA8(SkYUVASizeInfo* info,
+                                         SkYUVAIndex indices[],
+                                         SkYUVColorSpace* color_space) const {
   return false;
 }
 
-bool FakePaintImageGenerator::GetYUV8Planes(const SkYUVSizeInfo& info,
-                                            void* planes[3],
-                                            size_t frame_index,
-                                            uint32_t lazy_pixel_ref) {
+bool FakePaintImageGenerator::GetYUVA8Planes(const SkYUVASizeInfo& info,
+                                             const SkYUVAIndex indices[],
+                                             void* planes[4],
+                                             size_t frame_index,
+                                             uint32_t lazy_pixel_ref) {
   NOTREACHED();
   return false;
 }
diff --git a/cc/test/fake_paint_image_generator.h b/cc/test/fake_paint_image_generator.h
index 0881fe13..45f66fdb 100644
--- a/cc/test/fake_paint_image_generator.h
+++ b/cc/test/fake_paint_image_generator.h
@@ -26,12 +26,14 @@
                  size_t frame_index,
                  PaintImage::GeneratorClientId client_id,
                  uint32_t lazy_pixel_ref) override;
-  bool QueryYUV8(SkYUVSizeInfo* info,
-                 SkYUVColorSpace* color_space) const override;
-  bool GetYUV8Planes(const SkYUVSizeInfo& info,
-                     void* planes[3],
-                     size_t frame_index,
-                     uint32_t lazy_pixel_ref) override;
+  bool QueryYUVA8(SkYUVASizeInfo* info,
+                  SkYUVAIndex indices[],
+                  SkYUVColorSpace* color_space) const override;
+  bool GetYUVA8Planes(const SkYUVASizeInfo& info,
+                      const SkYUVAIndex indices[],
+                      void* planes[4],
+                      size_t frame_index,
+                      uint32_t lazy_pixel_ref) override;
   SkISize GetSupportedDecodeSize(const SkISize& requested_size) const override;
 
   const base::flat_map<size_t, int>& frames_decoded() const {
diff --git a/cc/trees/damage_tracker.cc b/cc/trees/damage_tracker.cc
index 925069e0..dded361 100644
--- a/cc/trees/damage_tracker.cc
+++ b/cc/trees/damage_tracker.cc
@@ -64,7 +64,7 @@
   //
   // - This algorithm requires that descendant surfaces compute their damage
   //   before ancestor surfaces. Further, since contributing surfaces with
-  //   background filters can expand the damage caused by contributors
+  //   backdrop filters can expand the damage caused by contributors
   //   underneath them (that is, before them in draw order), the exact damage
   //   caused by these contributors must be computed before computing the damage
   //   caused by the contributing surface. This is implemented by visiting
@@ -338,11 +338,11 @@
   if (!is_valid_rect || damage_rect.IsEmpty())
     return;
 
-  // Compute the pixels in the background of the surface that could be affected
+  // Compute the pixels in the backdrop of the surface that could be affected
   // by the damage in the content below.
   gfx::Rect expanded_damage_rect = filters.MapRect(damage_rect, SkMatrix::I());
 
-  // Restrict it to the rectangle in which the background filter is shown.
+  // Restrict it to the rectangle in which the backdrop filter is shown.
   expanded_damage_rect.Intersect(pre_filter_rect);
 
   damage_for_this_update_.Union(expanded_damage_rect);
@@ -452,17 +452,16 @@
     }
   }
 
-  // If the layer has a background filter, this may cause pixels in our surface
+  // If the layer has a backdrop filter, this may cause pixels in our surface
   // to be expanded, so we will need to expand any damage at or below this
   // layer. We expand the damage from this layer too, as we need to readback
   // those pixels from the surface with only the contents of layers below this
   // one in them. This means we need to redraw any pixels in the surface being
   // used for the blur in this layer this frame.
-  const FilterOperations& background_filters =
-      render_surface->BackgroundFilters();
-  if (background_filters.HasFilterThatMovesPixels()) {
+  const FilterOperations& backdrop_filters = render_surface->BackdropFilters();
+  if (backdrop_filters.HasFilterThatMovesPixels()) {
     ExpandDamageInsideRectWithFilters(surface_rect_in_target_space,
-                                      background_filters);
+                                      backdrop_filters);
   }
 
   // True if any changes from contributing render surface.
diff --git a/cc/trees/damage_tracker_unittest.cc b/cc/trees/damage_tracker_unittest.cc
index d4c7558..03d1e9716 100644
--- a/cc/trees/damage_tracker_unittest.cc
+++ b/cc/trees/damage_tracker_unittest.cc
@@ -924,7 +924,7 @@
   EXPECT_EQ(expected_child_damage_rect, child_damage_rect);
 }
 
-TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) {
+TEST_F(DamageTrackerTest, VerifyDamageForBackdropBlurredChild) {
   LayerImpl* root = CreateAndSetUpTestTreeWithTwoSurfaces();
   LayerImpl* child1 = root->test_properties()->children[0];
   LayerImpl* child2 = root->test_properties()->children[1];
@@ -937,13 +937,13 @@
 
   // Setting the filter will damage the whole surface.
   ClearDamageForAllSurfaces(root);
-  child1->test_properties()->background_filters = filters;
+  child1->test_properties()->backdrop_filters = filters;
   child1->NoteLayerPropertyChanged();
   root->layer_tree_impl()->property_trees()->needs_rebuild = true;
   EmulateDrawingOneFrame(root);
 
   // CASE 1: Setting the update rect should cause the corresponding damage to
-  //         the surface, blurred based on the size of the child's background
+  //         the surface, blurred based on the size of the child's backdrop
   //         blur filter. Note that child1's render surface has a size of
   //         206x208 due to contributions from grand_child1 and grand_child2.
   ClearDamageForAllSurfaces(root);
@@ -964,7 +964,7 @@
   EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
 
   // CASE 2: Setting the update rect should cause the corresponding damage to
-  //         the surface, blurred based on the size of the child's background
+  //         the surface, blurred based on the size of the child's backdrop
   //         blur filter. Since the damage extends to the right/bottom outside
   //         of the blurred layer, only the left/top should end up expanded.
   ClearDamageForAllSurfaces(root);
@@ -1053,7 +1053,7 @@
 
   // CASE 7: No changes, so should not damage the surface.
   ClearDamageForAllSurfaces(root);
-  // We want to make sure that the background filter doesn't cause empty damage
+  // We want to make sure that the backdrop filter doesn't cause empty damage
   // to get expanded. We position child1 so that an expansion of the empty rect
   // would have non-empty intersection with child1 in its target space (root
   // space).
@@ -1791,7 +1791,7 @@
   FilterOperations filters;
   filters.Append(FilterOperation::CreateBlurFilter(5.f));
   root->SetDrawsContent(true);
-  root->test_properties()->background_filters = filters;
+  root->test_properties()->backdrop_filters = filters;
 
   // Really far left.
   child1->SetPosition(gfx::PointF(std::numeric_limits<int>::min() + 100, 0));
@@ -1917,7 +1917,7 @@
   FilterOperations filters;
   filters.Append(FilterOperation::CreateBlurFilter(5.f));
   child1->SetDrawsContent(true);
-  child1->test_properties()->background_filters = filters;
+  child1->test_properties()->backdrop_filters = filters;
 
   // Really far left.
   grandchild1->SetPosition(
diff --git a/cc/trees/effect_node.cc b/cc/trees/effect_node.cc
index 7809564b..b9480610 100644
--- a/cc/trees/effect_node.cc
+++ b/cc/trees/effect_node.cc
@@ -48,7 +48,7 @@
          cache_render_surface == other.cache_render_surface &&
          has_copy_request == other.has_copy_request &&
          filters == other.filters &&
-         background_filters == other.background_filters &&
+         backdrop_filters == other.backdrop_filters &&
          filters_origin == other.filters_origin &&
          blend_mode == other.blend_mode &&
          surface_contents_scale == other.surface_contents_scale &&
diff --git a/cc/trees/effect_node.h b/cc/trees/effect_node.h
index 3609ad6..61fb30a 100644
--- a/cc/trees/effect_node.h
+++ b/cc/trees/effect_node.h
@@ -39,7 +39,7 @@
   float screen_space_opacity;
 
   FilterOperations filters;
-  FilterOperations background_filters;
+  FilterOperations backdrop_filters;
   gfx::PointF filters_origin;
 
   SkBlendMode blend_mode;
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index 57bed051..17a7846 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -1409,7 +1409,7 @@
 }
 
 TEST_F(LayerTreeHostCommonTest,
-       RenderSurfaceListForTransparentChildWithBackgroundFilter) {
+       RenderSurfaceListForTransparentChildWithBackdropFilter) {
   LayerImpl* root = root_layer_for_testing();
   LayerImpl* render_surface1 = AddChild<LayerImpl>(root);
   LayerImpl* child = AddChild<LayerImpl>(render_surface1);
@@ -1421,7 +1421,7 @@
   render_surface1->SetDrawsContent(true);
   FilterOperations filters;
   filters.Append(FilterOperation::CreateBlurFilter(1.5f));
-  render_surface1->test_properties()->background_filters = filters;
+  render_surface1->test_properties()->backdrop_filters = filters;
   child->SetBounds(gfx::Size(10, 10));
   child->SetDrawsContent(true);
   root->layer_tree_impl()->SetElementIdsForTesting();
@@ -1434,7 +1434,7 @@
     LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
     EXPECT_EQ(2U, render_surface_list.size());
   }
-  // The layer is fully transparent, but has a background filter, so it
+  // The layer is fully transparent, but has a backdrop filter, so it
   // shouldn't be skipped and should be drawn.
   ASSERT_TRUE(GetRenderSurface(root));
   EXPECT_EQ(1, GetRenderSurface(root)->num_contributors());
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index c346e58a..3a6ca78f 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1437,7 +1437,7 @@
     }
 
     if (pass->quad_list.empty() && pass->copy_requests.empty() &&
-        pass->filters.IsEmpty() && pass->background_filters.IsEmpty()) {
+        pass->filters.IsEmpty() && pass->backdrop_filters.IsEmpty()) {
       // Remove the pass and decrement |i| to counter the for loop's increment,
       // so we don't skip the next pass in the loop.
       frame->render_passes.erase(frame->render_passes.begin() + i);
diff --git a/cc/trees/layer_tree_host_pixeltest_blending.cc b/cc/trees/layer_tree_host_pixeltest_blending.cc
index 93dee1a..3949979 100644
--- a/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -294,7 +294,7 @@
   RunPixelResourceTest(background, expected);
 }
 
-TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithBackgroundFilter) {
+TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithBackdropFilter) {
   const int kRootWidth = 2;
   const int kRootHeight = 2;
   InitializeFromTestCase(resource_type());
@@ -302,7 +302,7 @@
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(kRootWidth, kRootHeight), kCSSOrange);
 
-  // Orange child layers have a background filter set and they will blend with
+  // Orange child layers have a backdrop filter set and they will blend with
   // the green background
   gfx::Rect child_rect(0, 0, kRootWidth, kRootHeight);
   scoped_refptr<SolidColorLayer> green_lane =
@@ -310,7 +310,7 @@
   background->AddChild(green_lane);
   FilterOperations filters;
   filters.Append(FilterOperation::CreateGrayscaleFilter(.75));
-  green_lane->SetBackgroundFilters(filters);
+  green_lane->SetBackdropFilters(filters);
   green_lane->SetBlendMode(current_blend_mode());
 
   SkBitmap expected;
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc
index 378d433..67e3b25 100644
--- a/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -19,11 +19,11 @@
 
 class LayerTreeHostFiltersPixelTest : public LayerTreePixelTest {};
 
-TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlur) {
+TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlur) {
   scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
       gfx::Rect(200, 200), SK_ColorWHITE);
 
-  // The green box is entirely behind a layer with background blur, so it
+  // The green box is entirely behind a layer with backdrop blur, so it
   // should appear blurred on its edges.
   scoped_refptr<SolidColorLayer> green = CreateSolidColorLayer(
       gfx::Rect(50, 50, 100, 100), kCSSGreen);
@@ -35,7 +35,7 @@
   FilterOperations filters;
   filters.Append(FilterOperation::CreateBlurFilter(
       2.f, SkBlurImageFilter::kClamp_TileMode));
-  blur->SetBackgroundFilters(filters);
+  blur->SetBackdropFilters(filters);
 
 #if defined(OS_WIN) || defined(ARCH_CPU_ARM64)
   // Windows and ARM64 have 436 pixels off by 1: crbug.com/259915
@@ -53,17 +53,16 @@
       small_error_allowed));
 #endif
 
-  RunPixelTest(PIXEL_TEST_GL,
-               background,
-               base::FilePath(FILE_PATH_LITERAL("background_filter_blur.png")));
+  RunPixelTest(PIXEL_TEST_GL, background,
+               base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur.png")));
 }
 
-TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOutsets) {
+TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOutsets) {
   scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
       gfx::Rect(200, 200), SK_ColorWHITE);
 
-  // The green border is outside the layer with background blur, but the
-  // background blur should use pixels from outside its layer borders, up to the
+  // The green border is outside the layer with backdrop blur, but the
+  // backdrop blur should use pixels from outside its layer borders, up to the
   // radius of the blur effect. So the border should be blurred underneath the
   // top layer causing the green to bleed under the transparent layer, but not
   // in the 1px region between the transparent layer and the green border.
@@ -77,7 +76,7 @@
   FilterOperations filters;
   filters.Append(FilterOperation::CreateBlurFilter(
       5.f, SkBlurImageFilter::kClamp_TileMode));
-  blur->SetBackgroundFilters(filters);
+  blur->SetBackdropFilters(filters);
 
 #if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64)
 #if defined(OS_WIN) || defined(ARCH_CPU_ARM64)
@@ -101,12 +100,11 @@
 #endif
 
   RunPixelTest(
-      PIXEL_TEST_GL,
-      background,
-      base::FilePath(FILE_PATH_LITERAL("background_filter_blur_outsets.png")));
+      PIXEL_TEST_GL, background,
+      base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_outsets.png")));
 }
 
-TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) {
+TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOffAxis) {
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorTRANSPARENT);
 
@@ -144,7 +142,7 @@
   FilterOperations filters;
   filters.Append(FilterOperation::CreateBlurFilter(
       2.f, SkBlurImageFilter::kClamp_TileMode));
-  blur->SetBackgroundFilters(filters);
+  blur->SetBackdropFilters(filters);
 
 #if defined(OS_WIN) || defined(ARCH_CPU_ARM64)
 #if defined(OS_WIN)
@@ -168,9 +166,8 @@
 #endif
 
   RunPixelTest(
-      PIXEL_TEST_GL,
-      background,
-      base::FilePath(FILE_PATH_LITERAL("background_filter_blur_off_axis.png")));
+      PIXEL_TEST_GL, background,
+      base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_off_axis.png")));
 }
 
 class LayerTreeHostFiltersScaledPixelTest
@@ -384,7 +381,7 @@
   RunPixelTestType(PIXEL_TEST_SOFTWARE);
 }
 
-class ImageScaledBackgroundFilter : public LayerTreeHostFiltersPixelTest {
+class ImageScaledBackdropFilter : public LayerTreeHostFiltersPixelTest {
  protected:
   void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) {
     scoped_refptr<SolidColorLayer> background =
@@ -422,7 +419,7 @@
 
     FilterOperations filters;
     filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f));
-    filter->SetBackgroundFilters(filters);
+    filter->SetBackdropFilters(filters);
 
 #if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64)
 #if defined(OS_WIN)
@@ -451,19 +448,19 @@
   }
 };
 
-TEST_F(ImageScaledBackgroundFilter, ImageFilterScaled_GL) {
+TEST_F(ImageScaledBackdropFilter, ImageFilterScaled_GL) {
   RunPixelTestType(PIXEL_TEST_GL,
                    base::FilePath(FILE_PATH_LITERAL(
-                       "background_filter_on_scaled_layer_gl.png")));
+                       "backdrop_filter_on_scaled_layer_gl.png")));
 }
 
-TEST_F(ImageScaledBackgroundFilter, ImageFilterScaled_Software) {
+TEST_F(ImageScaledBackdropFilter, ImageFilterScaled_Software) {
   RunPixelTestType(PIXEL_TEST_SOFTWARE,
                    base::FilePath(FILE_PATH_LITERAL(
-                       "background_filter_on_scaled_layer_sw.png")));
+                       "backdrop_filter_on_scaled_layer_sw.png")));
 }
 
-class ImageBackgroundFilter : public LayerTreeHostFiltersPixelTest {
+class ImageBackdropFilter : public LayerTreeHostFiltersPixelTest {
  protected:
   void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) {
     // Add a white background with a rotated red rect in the center.
@@ -499,7 +496,7 @@
     FilterOperations filters;
     filters.Append(FilterOperation::CreateBlurFilter(
         5.0f, SkBlurImageFilter::kClamp_TileMode));
-    filter->SetBackgroundFilters(filters);
+    filter->SetBackdropFilters(filters);
 
     // Allow some fuzziness so that this doesn't fail when Skia makes minor
     // changes to blur or rectangle rendering.
@@ -518,16 +515,16 @@
   }
 };
 
-TEST_F(ImageBackgroundFilter, BackgroundFilterRotated_GL) {
+TEST_F(ImageBackdropFilter, BackdropFilterRotated_GL) {
   RunPixelTestType(
       PIXEL_TEST_GL,
-      base::FilePath(FILE_PATH_LITERAL("background_filter_rotated_gl.png")));
+      base::FilePath(FILE_PATH_LITERAL("backdrop_filter_rotated_gl.png")));
 }
 
-TEST_F(ImageBackgroundFilter, BackgroundFilterRotated_Software) {
+TEST_F(ImageBackdropFilter, BackdropFilterRotated_Software) {
   RunPixelTestType(
       PIXEL_TEST_SOFTWARE,
-      base::FilePath(FILE_PATH_LITERAL("background_filter_rotated_sw.png")));
+      base::FilePath(FILE_PATH_LITERAL("backdrop_filter_rotated_sw.png")));
 }
 
 class ImageScaledRenderSurface : public LayerTreeHostFiltersPixelTest {
@@ -615,7 +612,7 @@
     FilterOperations border_filters;
     border_filters.Append(
         FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */));
-    border_edge_zoom->SetBackgroundFilters(border_filters);
+    border_edge_zoom->SetBackdropFilters(border_filters);
     root->AddChild(border_edge_zoom);
 
     // Test a zoom that extends past the edge of the screen.
@@ -624,7 +621,7 @@
     FilterOperations top_filters;
     top_filters.Append(
         FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */));
-    top_edge_zoom->SetBackgroundFilters(top_filters);
+    top_edge_zoom->SetBackdropFilters(top_filters);
     root->AddChild(top_edge_zoom);
 
     // Test a zoom that is fully within the screen.
@@ -633,7 +630,7 @@
     FilterOperations mid_filters;
     mid_filters.Append(
         FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */));
-    contained_zoom->SetBackgroundFilters(mid_filters);
+    contained_zoom->SetBackdropFilters(mid_filters);
     root->AddChild(contained_zoom);
 
 #if defined(OS_WIN)
@@ -1056,7 +1053,7 @@
       base::FilePath(FILE_PATH_LITERAL("filter_with_giant_crop_rect.png")));
 }
 
-class BackgroundFilterWithDeviceScaleFactorTest
+class BackdropFilterWithDeviceScaleFactorTest
     : public LayerTreeHostFiltersPixelTest {
  protected:
   void RunPixelTestType(float device_scale_factor,
@@ -1076,7 +1073,7 @@
     FilterOperations filters;
     filters.Append(FilterOperation::CreateReferenceFilter(
         sk_make_sp<OffsetPaintFilter>(0, 80, nullptr)));
-    filtered->SetBackgroundFilters(filters);
+    filtered->SetBackdropFilters(filters);
     root->AddChild(filtered);
 
     // This should appear as a grid of 4 100x100 squares which are:
@@ -1102,28 +1099,28 @@
   float device_scale_factor_ = 1;
 };
 
-TEST_F(BackgroundFilterWithDeviceScaleFactorTest, StandardDpi_GL) {
+TEST_F(BackdropFilterWithDeviceScaleFactorTest, StandardDpi_GL) {
   RunPixelTestType(
       1.f, PIXEL_TEST_GL,
-      base::FilePath(FILE_PATH_LITERAL("offset_background_filter_1x.png")));
+      base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_1x.png")));
 }
 
-TEST_F(BackgroundFilterWithDeviceScaleFactorTest, StandardDpi_Software) {
+TEST_F(BackdropFilterWithDeviceScaleFactorTest, StandardDpi_Software) {
   RunPixelTestType(
       1.f, PIXEL_TEST_SOFTWARE,
-      base::FilePath(FILE_PATH_LITERAL("offset_background_filter_1x.png")));
+      base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_1x.png")));
 }
 
-TEST_F(BackgroundFilterWithDeviceScaleFactorTest, HiDpi_GL) {
+TEST_F(BackdropFilterWithDeviceScaleFactorTest, HiDpi_GL) {
   RunPixelTestType(
       2.f, PIXEL_TEST_GL,
-      base::FilePath(FILE_PATH_LITERAL("offset_background_filter_2x.png")));
+      base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_2x.png")));
 }
 
-TEST_F(BackgroundFilterWithDeviceScaleFactorTest, HiDpi_Software) {
+TEST_F(BackdropFilterWithDeviceScaleFactorTest, HiDpi_Software) {
   RunPixelTestType(
       2.f, PIXEL_TEST_SOFTWARE,
-      base::FilePath(FILE_PATH_LITERAL("offset_background_filter_2x.png")));
+      base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_2x.png")));
 }
 
 }  // namespace
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 6732d5e2..4639cb3c 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -267,19 +267,19 @@
   gfx::Size bounds_;
 };
 
-using LayerTreeHostMasksForBackgroundFiltersPixelTest =
+using LayerTreeHostMasksForBackdropFiltersPixelTest =
     ParameterizedPixelResourceTest;
 
 INSTANTIATE_TEST_CASE_P(
     PixelResourceTest,
-    LayerTreeHostMasksForBackgroundFiltersPixelTest,
+    LayerTreeHostMasksForBackdropFiltersPixelTest,
     ::testing::Combine(
         ::testing::Values(SOFTWARE, GPU, ONE_COPY, ZERO_COPY),
         ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK,
                           Layer::LayerMaskType::MULTI_TEXTURE_MASK)));
 
-TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
-       MaskOfLayerWithBackgroundFilter) {
+TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest,
+       MaskOfLayerWithBackdropFilter) {
   scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
       gfx::Rect(100, 100), SK_ColorWHITE);
 
@@ -296,7 +296,7 @@
 
   FilterOperations filters;
   filters.Append(FilterOperation::CreateGrayscaleFilter(1.0));
-  blur->SetBackgroundFilters(filters);
+  blur->SetBackdropFilters(filters);
 
   gfx::Size mask_bounds(100, 100);
   CircleContentLayerClient mask_client(mask_bounds);
@@ -322,14 +322,12 @@
 
   base::FilePath image_name =
       (test_case_ == GPU)
-          ? base::FilePath(
-                FILE_PATH_LITERAL("mask_of_background_filter_gpu.png"))
-          : base::FilePath(FILE_PATH_LITERAL("mask_of_background_filter.png"));
+          ? base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter_gpu.png"))
+          : base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter.png"));
   RunPixelResourceTest(background, image_name);
 }
 
-TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
-       MaskOfLayerWithBlend) {
+TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest, MaskOfLayerWithBlend) {
   scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
       gfx::Rect(128, 128), SK_ColorWHITE);
 
@@ -733,8 +731,8 @@
   RunPixelResourceTest(root, image_name);
 }
 
-TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
-       MaskOfLayerWithBackgroundFilterAndBlend) {
+TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest,
+       MaskOfLayerWithBackdropFilterAndBlend) {
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(128, 128), SK_ColorWHITE);
 
@@ -757,7 +755,7 @@
 
   FilterOperations filters;
   filters.Append(FilterOperation::CreateGrayscaleFilter(1.0));
-  picture_horizontal->SetBackgroundFilters(filters);
+  picture_horizontal->SetBackdropFilters(filters);
 
   background->AddChild(picture_vertical);
   background->AddChild(picture_horizontal);
@@ -783,7 +781,7 @@
 
   RunPixelResourceTest(background,
                        base::FilePath(FILE_PATH_LITERAL(
-                           "mask_of_background_filter_and_blend.png")));
+                           "mask_of_backdrop_filter_and_blend.png")));
 }
 
 }  // namespace
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc
index 906eab9..3c73e1d 100644
--- a/cc/trees/occlusion_tracker.cc
+++ b/cc/trees/occlusion_tracker.cc
@@ -224,8 +224,8 @@
     return;
 
   gfx::Rect affected_area_in_target =
-      contributing_surface->BackgroundFilters().MapRectReverse(target_rect,
-                                                               SkMatrix::I());
+      contributing_surface->BackdropFilters().MapRectReverse(target_rect,
+                                                             SkMatrix::I());
   // Unite target_rect because we only care about positive outsets.
   affected_area_in_target.Union(target_rect);
 
@@ -288,7 +288,7 @@
           old_surface->draw_transform());
 
   gfx::Rect unoccluded_surface_rect;
-  if (old_surface->BackgroundFilters().HasFilterThatMovesPixels()) {
+  if (old_surface->BackdropFilters().HasFilterThatMovesPixels()) {
     Occlusion surface_occlusion = GetCurrentOcclusionForContributingSurface(
         old_surface->draw_transform());
     unoccluded_surface_rect =
@@ -320,7 +320,7 @@
     }
   }
 
-  if (!old_surface->BackgroundFilters().HasFilterThatMovesPixels())
+  if (!old_surface->BackdropFilters().HasFilterThatMovesPixels())
     return;
 
   ReduceOcclusionBelowSurface(old_surface, unoccluded_surface_rect,
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc
index 8893f46d..0ba135b2 100644
--- a/cc/trees/occlusion_tracker_unittest.cc
+++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -1255,10 +1255,10 @@
 
 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfSurface);
 
-class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
+class OcclusionTrackerTestDontOccludePixelsNeededForBackdropFilter
     : public OcclusionTrackerTest {
  protected:
-  explicit OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter(
+  explicit OcclusionTrackerTestDontOccludePixelsNeededForBackdropFilter(
       bool opaque_layers)
       : OcclusionTrackerTest(opaque_layers) {}
   void RunMyTest() override {
@@ -1282,13 +1282,13 @@
       // Make a 50x50 filtered surface that is adjacent to occluding layers
       // which are above it in the z-order in various configurations. The
       // surface is scaled to test that the pixel moving is done in the target
-      // space, where the background filter is applied.
+      // space, where the backdrop filter is applied.
       TestContentLayerImpl* parent = this->CreateRoot(
           this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
       LayerImpl* filtered_surface = this->CreateDrawingLayer(
           parent, scale_by_half, gfx::PointF(50.f, 50.f), gfx::Size(100, 100),
           false);
-      filtered_surface->test_properties()->background_filters = filters;
+      filtered_surface->test_properties()->backdrop_filters = filters;
       gfx::Rect occlusion_rect;
       switch (i) {
         case LEFT:
@@ -1333,7 +1333,7 @@
       EXPECT_EQ(occlusion_inside_surface.ToString(),
                 occlusion.occlusion_from_outside_target().ToString());
 
-      // The surface has a background blur, so it needs pixels that are
+      // The surface has a backdrop blur, so it needs pixels that are
       // currently considered occluded in order to be drawn. The pixels it
       // needs should be removed from the occluded area, so that they are drawn
       // when we get to the parent.
@@ -1367,12 +1367,12 @@
 };
 
 ALL_OCCLUSIONTRACKER_TEST(
-    OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter);
+    OcclusionTrackerTestDontOccludePixelsNeededForBackdropFilter);
 
-class OcclusionTrackerTestPixelsNeededForDropShadowBackgroundFilter
+class OcclusionTrackerTestPixelsNeededForDropShadowBackdropFilter
     : public OcclusionTrackerTest {
  protected:
-  explicit OcclusionTrackerTestPixelsNeededForDropShadowBackgroundFilter(
+  explicit OcclusionTrackerTestPixelsNeededForDropShadowBackdropFilter(
       bool opaque_layers)
       : OcclusionTrackerTest(opaque_layers) {}
   void RunMyTest() override {
@@ -1397,13 +1397,13 @@
       // Make a 50x50 filtered surface that is adjacent to occluding layers
       // which are above it in the z-order in various configurations. The
       // surface is scaled to test that the pixel moving is done in the target
-      // space, where the background filter is applied.
+      // space, where the backdrop filter is applied.
       TestContentLayerImpl* parent = this->CreateRoot(
           this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
       LayerImpl* filtered_surface = this->CreateDrawingLayer(
           parent, scale_by_half, gfx::PointF(50.f, 50.f), gfx::Size(100, 100),
           false);
-      filtered_surface->test_properties()->background_filters = filters;
+      filtered_surface->test_properties()->backdrop_filters = filters;
       gfx::Rect occlusion_rect;
       switch (i) {
         case LEFT:
@@ -1448,7 +1448,7 @@
       EXPECT_EQ(occlusion_inside_surface.ToString(),
                 occlusion.occlusion_from_outside_target().ToString());
 
-      // The surface has a background filter, so it needs pixels that are
+      // The surface has a backdrop filter, so it needs pixels that are
       // currently considered occluded in order to be drawn. The pixels it
       // needs should be removed from the occluded area, so that they are drawn
       // when we get to the parent.
@@ -1459,7 +1459,7 @@
       switch (i) {
         case LEFT:
           // The right half of the occlusion is close enough to cast a shadow
-          // that would be visible in the background filter. The shadow reaches
+          // that would be visible in the backdrop filter. The shadow reaches
           // 3*5 + 10 = 25 pixels to the right.
           expected_occlusion = gfx::Rect(0, 0, 25, 200);
           break;
@@ -1488,12 +1488,12 @@
 };
 
 ALL_OCCLUSIONTRACKER_TEST(
-    OcclusionTrackerTestPixelsNeededForDropShadowBackgroundFilter);
+    OcclusionTrackerTestPixelsNeededForDropShadowBackdropFilter);
 
-class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice
+class OcclusionTrackerTestTwoBackdropFiltersReduceOcclusionTwice
     : public OcclusionTrackerTest {
  protected:
-  explicit OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice(
+  explicit OcclusionTrackerTestTwoBackdropFiltersReduceOcclusionTwice(
       bool opaque_layers)
       : OcclusionTrackerTest(opaque_layers) {}
   void RunMyTest() override {
@@ -1520,8 +1520,8 @@
     filtered_surface2->test_properties()->force_render_surface = true;
     FilterOperations filters;
     filters.Append(FilterOperation::CreateBlurFilter(1.f));
-    filtered_surface1->test_properties()->background_filters = filters;
-    filtered_surface2->test_properties()->background_filters = filters;
+    filtered_surface1->test_properties()->backdrop_filters = filters;
+    filtered_surface2->test_properties()->backdrop_filters = filters;
 
     this->CalcDrawEtc(root);
 
@@ -1554,12 +1554,12 @@
 };
 
 ALL_OCCLUSIONTRACKER_TEST(
-    OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice);
+    OcclusionTrackerTestTwoBackdropFiltersReduceOcclusionTwice);
 
-class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter
+class OcclusionTrackerTestDontReduceOcclusionBelowBackdropFilter
     : public OcclusionTrackerTest {
  protected:
-  explicit OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter(
+  explicit OcclusionTrackerTestDontReduceOcclusionBelowBackdropFilter(
       bool opaque_layers)
       : OcclusionTrackerTest(opaque_layers) {}
   void RunMyTest() override {
@@ -1568,7 +1568,7 @@
 
     // Make a 50x50 surface, with a smaller 30x30 layer centered below it.
     // The surface is scaled to test that the pixel moving is done in the target
-    // space, where the background filter is applied, and the surface appears at
+    // space, where the backdrop filter is applied, and the surface appears at
     // 50, 50.
     TestContentLayerImpl* parent = this->CreateRoot(
         this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
@@ -1583,13 +1583,13 @@
     filtered_surface->test_properties()->force_render_surface = true;
     FilterOperations filters;
     filters.Append(FilterOperation::CreateBlurFilter(3.f));
-    filtered_surface->test_properties()->background_filters = filters;
+    filtered_surface->test_properties()->backdrop_filters = filters;
 
     this->CalcDrawEtc(parent);
 
     TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000));
 
-    // The surface has a background blur, so it blurs non-opaque pixels below
+    // The surface has a backdrop blur, so it blurs non-opaque pixels below
     // it.
     this->VisitLayer(filtered_surface, &occlusion);
     this->VisitContributingSurface(filtered_surface, &occlusion);
@@ -1616,12 +1616,12 @@
 };
 
 ALL_OCCLUSIONTRACKER_TEST(
-    OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter);
+    OcclusionTrackerTestDontReduceOcclusionBelowBackdropFilter);
 
-class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded
+class OcclusionTrackerTestDontReduceOcclusionIfBackdropFilterIsOccluded
     : public OcclusionTrackerTest {
  protected:
-  explicit OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded(
+  explicit OcclusionTrackerTestDontReduceOcclusionIfBackdropFilterIsOccluded(
       bool opaque_layers)
       : OcclusionTrackerTest(opaque_layers) {}
   void RunMyTest() override {
@@ -1631,7 +1631,7 @@
     // Make a 50x50 filtered surface that is completely occluded by an opaque
     // layer which is above it in the z-order.  The surface is
     // scaled to test that the pixel moving is done in the target space, where
-    // the background filter is applied, and the surface appears at 50, 50.
+    // the backdrop filter is applied, and the surface appears at 50, 50.
     TestContentLayerImpl* parent = this->CreateRoot(
         this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
     LayerImpl* filtered_surface =
@@ -1645,7 +1645,7 @@
     filtered_surface->test_properties()->force_render_surface = true;
     FilterOperations filters;
     filters.Append(FilterOperation::CreateBlurFilter(3.f));
-    filtered_surface->test_properties()->background_filters = filters;
+    filtered_surface->test_properties()->backdrop_filters = filters;
 
     this->CalcDrawEtc(parent);
 
@@ -1664,7 +1664,7 @@
                 occlusion.occlusion_from_outside_target().ToString());
     }
 
-    // The surface has a background blur, so it blurs non-opaque pixels below
+    // The surface has a backdrop blur, so it blurs non-opaque pixels below
     // it.
     this->VisitContributingSurface(filtered_surface, &occlusion);
     {
@@ -1681,7 +1681,7 @@
 };
 
 ALL_OCCLUSIONTRACKER_TEST(
-    OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded);
+    OcclusionTrackerTestDontReduceOcclusionIfBackdropFilterIsOccluded);
 
 class OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded
     : public OcclusionTrackerTest {
@@ -1695,7 +1695,7 @@
 
     // Make a 50x50 surface which is partially occluded by opaque layers which
     // are above it in the z-order.  The surface is scaled to test that the
-    // pixel moving is done in the target space, where the background filter is
+    // pixel moving is done in the target space, where the backdrop filter is
     // applied, but the surface appears at 50, 50.
     TestContentLayerImpl* parent = this->CreateRoot(
         this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
@@ -1713,7 +1713,7 @@
     filtered_surface->test_properties()->force_render_surface = true;
     FilterOperations filters;
     filters.Append(FilterOperation::CreateBlurFilter(3.f));
-    filtered_surface->test_properties()->background_filters = filters;
+    filtered_surface->test_properties()->backdrop_filters = filters;
 
     this->CalcDrawEtc(parent);
 
@@ -1722,7 +1722,7 @@
     this->VisitLayer(beside_surface_layer, &occlusion);
     this->VisitLayer(above_surface_layer, &occlusion);
 
-    // The surface has a background blur, so it blurs non-opaque pixels below
+    // The surface has a backdrop blur, so it blurs non-opaque pixels below
     // it.
     this->VisitLayer(filtered_surface, &occlusion);
     this->VisitContributingSurface(filtered_surface, &occlusion);
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 00fbcb7..557bc63 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -784,7 +784,7 @@
   // Exceptions:
   // 1) Nodes that contribute to copy requests, whether hidden or not, must be
   //    drawn.
-  // 2) Nodes that have a background filter.
+  // 2) Nodes that have a backdrop filter.
   // 3) Nodes with animating screen space opacity on main thread or pending tree
   //    are drawn if their parent is drawn irrespective of their opacity.
   if (node->has_copy_request || node->cache_render_surface)
@@ -792,7 +792,7 @@
   else if (EffectiveOpacity(node) == 0.f &&
            (!node->has_potential_opacity_animation ||
             property_trees()->is_active) &&
-           node->background_filters.IsEmpty())
+           node->backdrop_filters.IsEmpty())
     node->is_drawn = false;
   else if (parent_node)
     node->is_drawn = parent_node->is_drawn;
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index b55d165..cf98d8e8 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -740,12 +740,12 @@
   return layer->test_properties()->filters_origin;
 }
 
-static inline const FilterOperations& BackgroundFilters(Layer* layer) {
-  return layer->background_filters();
+static inline const FilterOperations& BackdropFilters(Layer* layer) {
+  return layer->backdrop_filters();
 }
 
-static inline const FilterOperations& BackgroundFilters(LayerImpl* layer) {
-  return layer->test_properties()->background_filters;
+static inline const FilterOperations& BackdropFilters(LayerImpl* layer) {
+  return layer->test_properties()->backdrop_filters;
 }
 
 static inline bool HideLayerAndSubtree(Layer* layer) {
@@ -794,7 +794,7 @@
   }
 
   // If the layer uses a CSS filter.
-  if (!Filters(layer).IsEmpty() || !BackgroundFilters(layer).IsEmpty()) {
+  if (!Filters(layer).IsEmpty() || !BackdropFilters(layer).IsEmpty()) {
     return true;
   }
 
@@ -983,7 +983,7 @@
   node->cache_render_surface = CacheRenderSurface(layer);
   node->has_copy_request = HasCopyRequest(layer);
   node->filters = Filters(layer);
-  node->background_filters = BackgroundFilters(layer);
+  node->backdrop_filters = BackdropFilters(layer);
   node->filters_origin = FiltersOrigin(layer);
   node->trilinear_filtering = TrilinearFiltering(layer);
   node->has_potential_opacity_animation = has_potential_opacity_animation;
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 0b561c8..21d5115 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1010,7 +1010,7 @@
     }
 
     if (chromium_linker_supported && use_lld) {
-      configs += [ "//build/config/android:lld_pack_relocations" ]
+      configs += [ "//build/config/android:lld_pack_relocations_with_relr" ]
     }
     if (chromium_linker_supported && target_cpu != "mipsel" &&
         target_cpu != "mipsel64") {
@@ -1273,7 +1273,7 @@
     "//components/sync:test_support_fake_server_android",
   ]
   if (chromium_linker_supported && use_lld) {
-    configs += [ "//build/config/android:lld_pack_relocations" ]
+    configs += [ "//build/config/android:lld_pack_relocations_with_relr" ]
   }
   if (enable_vr) {
     sources += [ "../browser/android/vr/register_jni.cc" ]
diff --git a/chrome/android/java/res/values/values.xml b/chrome/android/java/res/values/values.xml
index 9cda9a8..e695da1 100644
--- a/chrome/android/java/res/values/values.xml
+++ b/chrome/android/java/res/values/values.xml
@@ -57,7 +57,7 @@
     <string name="help_context_sad_tab">mobile_awsnap</string>
     <string name="help_context_clear_browsing_data">clear_browsing_data</string>
     <string name="help_context_change_sync_passphrase">change_sync_passphrase</string>
-    <string name="help_context_sync_and_services">sync_and_services</string>
+    <string name="help_context_sync_and_services">syncgoogleservices</string>
     <!-- TODO(peconn): Add help section. -->
     <!-- <string name="help_context_suggestions">mobile_content_suggestions</string> -->
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index 01ac935..924ade8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1424,7 +1424,6 @@
         maybeRemoveWindowBackground();
         DownloadManagerService.getDownloadManagerService().onActivityLaunched();
 
-        VrModuleProvider.init();
         VrModuleProvider.getDelegate().onNativeLibraryAvailable();
         if (getSavedInstanceState() == null && getIntent() != null) {
             VrModuleProvider.getDelegate().onNewIntentWithNative(this, getIntent());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
index 291d134..5ae8239e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
@@ -4,12 +4,10 @@
 
 package org.chromium.chrome.browser.browserservices;
 
-import android.content.Context;
 import android.net.Uri;
-import android.support.annotation.NonNull;
 import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.PostMessageServiceConnection;
+import android.support.customtabs.PostMessageBackend;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
@@ -24,43 +22,32 @@
 /**
  * A class that handles postMessage communications with a designated {@link CustomTabsSessionToken}.
  */
-public class PostMessageHandler
-        extends PostMessageServiceConnection implements OriginVerificationListener {
+public class PostMessageHandler implements OriginVerificationListener {
     private final MessageCallback mMessageCallback;
+    private final PostMessageBackend mPostMessageBackend;
     private WebContents mWebContents;
-    private boolean mMessageChannelCreated;
-    private boolean mBoundToService;
     private MessagePort[] mChannel;
     private Uri mPostMessageUri;
-    private String mPackageName;
 
     /**
      * Basic constructor. Everytime the given {@link CustomTabsSessionToken} is associated with a
      * new {@link WebContents},
      * {@link PostMessageHandler#reset(WebContents)} should be called to
      * reset all internal state.
-     * @param session The {@link CustomTabsSessionToken} to establish the postMessage communication
-     *                with.
+     * @param postMessageBackend The {@link PostMessageBackend} to which updates about the channel
+     *                           and posted messages will be sent.
      */
-    public PostMessageHandler(CustomTabsSessionToken session) {
-        super(session);
+    public PostMessageHandler(PostMessageBackend postMessageBackend) {
+        mPostMessageBackend = postMessageBackend;
         mMessageCallback = new MessageCallback() {
             @Override
             public void onMessage(String message, MessagePort[] sentPorts) {
-                if (mBoundToService) postMessage(message, null);
+                mPostMessageBackend.onPostMessage(message, null);
             }
         };
     }
 
     /**
-     * Sets the package name unique to the session.
-     * @param packageName The package name for the client app for the owning session.
-     */
-    public void setPackageName(@NonNull String packageName) {
-        mPackageName = packageName;
-    }
-
-    /**
      * Resets the internal state of the handler, linking the associated
      * {@link CustomTabsSessionToken} with a new {@link WebContents} and the {@link Tab} that
      * contains it.
@@ -70,7 +57,6 @@
     public void reset(final WebContents webContents) {
         if (webContents == null || webContents.isDestroyed()) {
             disconnectChannel();
-            unbindFromContext(ContextUtils.getApplicationContext());
             return;
         }
         // Can't reset with the same web contents twice.
@@ -89,7 +75,6 @@
                         && mChannel != null) {
                     webContents.removeObserver(this);
                     disconnectChannel();
-                    unbindFromContext(ContextUtils.getApplicationContext());
                     return;
                 }
                 mNavigatedOnce = true;
@@ -98,7 +83,6 @@
             @Override
             public void renderProcessGone(boolean wasOomProtected) {
                 disconnectChannel();
-                unbindFromContext(ContextUtils.getApplicationContext());
             }
 
             @Override
@@ -109,16 +93,6 @@
         };
     }
 
-    /**
-     * See
-     * {@link PostMessageServiceConnection#bindSessionToPostMessageService(Context, String)}.
-     * Attempts to bind with the package name set during initialization.
-     */
-    public boolean bindSessionToPostMessageService() {
-        return super.bindSessionToPostMessageService(
-                ContextUtils.getApplicationContext(), mPackageName);
-    }
-
     private void initializeWithWebContents(final WebContents webContents) {
         mChannel = webContents.createMessageChannel();
         mChannel[0].setMessageCallback(mMessageCallback, null);
@@ -126,8 +100,7 @@
         webContents.postMessageToFrame(
                 null, "", mPostMessageUri.toString(), "", new MessagePort[] {mChannel[1]});
 
-        mMessageChannelCreated = true;
-        if (mBoundToService) notifyMessageChannelReady(null);
+        mPostMessageBackend.onNotifyMessageChannelReady(null);
     }
 
     private void disconnectChannel() {
@@ -135,6 +108,7 @@
         mChannel[0].close();
         mChannel = null;
         mWebContents = null;
+        mPostMessageBackend.onDisconnectChannel(ContextUtils.getApplicationContext());
     }
 
     /**
@@ -174,22 +148,6 @@
     }
 
     @Override
-    public void unbindFromContext(Context context) {
-        if (mBoundToService) super.unbindFromContext(context);
-    }
-
-    @Override
-    public void onPostMessageServiceConnected() {
-        mBoundToService = true;
-        if (mMessageChannelCreated) notifyMessageChannelReady(null);
-    }
-
-    @Override
-    public void onPostMessageServiceDisconnected() {
-        mBoundToService = false;
-    }
-
-    @Override
     public void onOriginVerified(String packageName, Origin origin, boolean result,
             Boolean online) {
         if (!result) return;
@@ -204,12 +162,4 @@
     public Uri getPostMessageUriForTesting() {
         return mPostMessageUri;
     }
-
-    /**
-     * Cleans up any dependencies that this handler might have.
-     * @param context Context to use for unbinding if necessary.
-     */
-    public void cleanup(Context context) {
-        if (mBoundToService) super.unbindFromContext(context);
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
index 4ba608ed..2cf6b9c2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
@@ -20,6 +20,7 @@
 import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsService.Relation;
 import android.support.customtabs.CustomTabsSessionToken;
+import android.support.customtabs.PostMessageServiceConnection;
 import android.text.TextUtils;
 import android.util.SparseBooleanArray;
 
@@ -167,6 +168,7 @@
         private CustomTabsCallback mCustomTabsCallback;
         public final DisconnectCallback disconnectCallback;
         public final PostMessageHandler postMessageHandler;
+        public final PostMessageServiceConnection serviceConnection;
         public final Set<Origin> mLinkedOrigins = new HashSet<>();
         public OriginVerifier originVerifier;
         public boolean mIgnoreFragments;
@@ -186,13 +188,15 @@
         private boolean mShouldGetPageLoadMetrics;
 
         public SessionParams(Context context, int uid, CustomTabsCallback customTabsCallback,
-                             DisconnectCallback callback, PostMessageHandler postMessageHandler) {
+                DisconnectCallback callback, PostMessageHandler postMessageHandler,
+                PostMessageServiceConnection serviceConnection) {
             this.uid = uid;
             mPackageName = getPackageName(context, uid);
             mCustomTabsCallback = customTabsCallback;
             disconnectCallback = callback;
             this.postMessageHandler = postMessageHandler;
-            if (postMessageHandler != null) this.postMessageHandler.setPackageName(mPackageName);
+            this.serviceConnection = serviceConnection;
+            if (postMessageHandler != null) this.serviceConnection.setPackageName(mPackageName);
         }
 
         /**
@@ -297,13 +301,14 @@
      * @return true for success.
      */
     public synchronized boolean newSession(CustomTabsSessionToken session, int uid,
-            DisconnectCallback onDisconnect, @NonNull PostMessageHandler postMessageHandler) {
+            DisconnectCallback onDisconnect, @NonNull PostMessageHandler postMessageHandler,
+            @NonNull PostMessageServiceConnection serviceConnection) {
         if (session == null || session.getCallback() == null) return false;
         if (mSessionParams.containsKey(session)) {
             mSessionParams.get(session).setCustomTabsCallback(session.getCallback());
         } else {
             SessionParams params = new SessionParams(ContextUtils.getApplicationContext(), uid,
-                    session.getCallback(), onDisconnect, postMessageHandler);
+                    session.getCallback(), onDisconnect, postMessageHandler, serviceConnection);
             mSessionParams.put(session, params);
         }
 
@@ -427,12 +432,13 @@
     }
 
     /**
-     * See {@link PostMessageHandler#bindSessionToPostMessageService(Context, String)}.
+     * See {@link PostMessageServiceConnection#bindSessionToPostMessageService(Context, String)}.
      */
     public synchronized boolean bindToPostMessageServiceForSession(CustomTabsSessionToken session) {
         SessionParams params = mSessionParams.get(session);
         if (params == null) return false;
-        return params.postMessageHandler.bindSessionToPostMessageService();
+        return params.serviceConnection.bindSessionToPostMessageService(
+                ContextUtils.getApplicationContext());
     }
 
     /**
@@ -791,8 +797,8 @@
         SessionParams params = mSessionParams.get(session);
         if (params == null) return;
         mSessionParams.remove(session);
-        if (params.postMessageHandler != null) {
-            params.postMessageHandler.cleanup(ContextUtils.getApplicationContext());
+        if (params.serviceConnection != null) {
+            params.serviceConnection.cleanup(ContextUtils.getApplicationContext());
         }
         if (params.originVerifier != null) params.originVerifier.cleanUp();
         if (params.disconnectCallback != null) params.disconnectCallback.run(session);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index f6405fd..de04d9e6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -23,6 +23,7 @@
 import android.support.customtabs.CustomTabsIntent;
 import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsSessionToken;
+import android.support.customtabs.PostMessageServiceConnection;
 import android.text.TextUtils;
 import android.widget.RemoteViews;
 
@@ -359,8 +360,10 @@
                 cancelSpeculation(session);
             }
         };
-        PostMessageHandler handler = new PostMessageHandler(session);
-        return mClientManager.newSession(session, Binder.getCallingUid(), onDisconnect, handler);
+        PostMessageServiceConnection serviceConnection = new PostMessageServiceConnection(session);
+        PostMessageHandler handler = new PostMessageHandler(serviceConnection);
+        return mClientManager.newSession(
+                session, Binder.getCallingUid(), onDisconnect, handler, serviceConnection);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
index 87fca8d..a40b2292 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
@@ -156,11 +156,6 @@
     void updateMicButtonState();
 
     /**
-     * Signal to hide the omnibox suggestions.
-     */
-    void hideSuggestions();
-
-    /**
      * Sets the callback to be used by default for text editing action bar.
      * @param callback The callback to use.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 6497299..4f1ad60 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -46,7 +46,6 @@
 import org.chromium.chrome.browser.omnibox.UrlBarCoordinator.SelectionState;
 import org.chromium.chrome.browser.omnibox.geo.GeolocationHeader;
 import org.chromium.chrome.browser.omnibox.status.StatusViewCoordinator;
-import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController;
 import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator;
 import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator.AutocompleteDelegate;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion;
@@ -203,6 +202,7 @@
                 };
         mAutocompleteCoordinator =
                 new AutocompleteCoordinator(this, this, embedder, mUrlCoordinator);
+        addUrlFocusChangeListener(mAutocompleteCoordinator);
         mUrlCoordinator.setUrlTextChangeListener(mAutocompleteCoordinator);
 
         mMicButton = (AppCompatImageButton) findViewById(R.id.mic_button);
@@ -350,6 +350,7 @@
         if (shouldBeFocused) {
             mUrlBar.requestFocus();
         } else {
+            hideKeyboard();
             mUrlBar.clearFocus();
         }
     }
@@ -376,7 +377,6 @@
                 setUrlBarText(mToolbarDataProvider.getUrlBarData(), UrlBar.ScrollType.NO_SCROLL,
                         SelectionState.SELECT_ALL);
             }
-            hideSuggestions();
             hideKeyboard();
         }
     }
@@ -464,8 +464,6 @@
                 });
             }
         }
-
-        mAutocompleteCoordinator.onUrlFocusChanged(hasFocus);
     }
 
     /**
@@ -478,7 +476,6 @@
             listener.onUrlFocusChange(hasFocus);
         }
 
-        mAutocompleteCoordinator.maybeShowOmniboxResultsContainer();
         updateFadingBackgroundView(hasFocus, false);
     }
 
@@ -697,19 +694,6 @@
         mDeleteButton.setVisibility(shouldShowDeleteButton() ? VISIBLE : GONE);
     }
 
-    /**
-     * Hides the omnibox suggestion popup.
-     *
-     * <p>
-     * Signals the autocomplete controller to stop generating omnibox suggestions.
-     *
-     * @see AutocompleteController#stop(boolean)
-     */
-    @Override
-    public final void hideSuggestions() {
-        mAutocompleteCoordinator.hideSuggestions();
-    }
-
     @Override
     public void onSuggestionsHidden() {
         updateNavigationButton();
@@ -808,13 +792,9 @@
     @Override
     public void onClick(View v) {
         if (v == mDeleteButton) {
-            if (!TextUtils.isEmpty(mUrlCoordinator.getTextWithAutocomplete())) {
-                setUrlBarTextEmpty();
-                hideSuggestions();
-                updateButtonVisibility();
-            }
+            setUrlBarTextEmpty();
+            updateButtonVisibility();
 
-            mAutocompleteCoordinator.startZeroSuggest();
             RecordUserAction.record("MobileOmniboxDeleteUrl");
             return;
         } else if (v == mMicButton && mVoiceRecognitionHandler != null) {
@@ -827,8 +807,6 @@
     @Override
     public void backKeyPressed() {
         setUrlBarFocus(false);
-        hideSuggestions();
-        hideKeyboard();
         // Revert the URL to match the current page.
         setUrlToPageUrl();
         focusCurrentTab();
@@ -911,8 +889,10 @@
      * @return Whether this changed the existing text.
      */
     private boolean setUrlBarTextEmpty() {
-        return mUrlCoordinator.setUrlBarData(
+        boolean textChanged = mUrlCoordinator.setUrlBarData(
                 UrlBarData.EMPTY, UrlBar.ScrollType.SCROLL_TO_BEGINNING, SelectionState.SELECT_ALL);
+        mAutocompleteCoordinator.onTextChangedForAutocomplete();
+        return textChanged;
     }
 
     @Override
@@ -963,9 +943,6 @@
         LocaleManager.getInstance().recordLocaleBasedSearchMetrics(false, url, transition);
 
         focusCurrentTab();
-        // Prevent any upcoming omnibox suggestions from showing. We have to do this after we load
-        // the URL as this will hide the suggestions and trigger a cancel of the prerendered page.
-        mAutocompleteCoordinator.stopAutocomplete(true);
     }
 
     /**
@@ -1015,7 +992,6 @@
             chromeActivity.addViewObscuringAllTabs(mScrim);
         } else {
             chromeActivity.removeViewObscuringAllTabs(mScrim);
-            mAutocompleteCoordinator.updateOmniboxResultsContainerVisibility(false);
         }
     }
 
@@ -1067,23 +1043,6 @@
     }
 
     @Override
-    public void onWindowFocusChanged(boolean hasWindowFocus) {
-        super.onWindowFocusChanged(hasWindowFocus);
-        if (!hasWindowFocus && !mAutocompleteCoordinator.isSuggestionModalShown()) {
-            hideSuggestions();
-        } else if (hasWindowFocus && mUrlHasFocus && mNativeInitialized) {
-            String currentUrlBarText = mUrlCoordinator.getTextWithAutocomplete();
-            if (TextUtils.isEmpty(currentUrlBarText)
-                    || TextUtils.equals(currentUrlBarText,
-                               mToolbarDataProvider.getUrlBarData().getEditingOrDisplayText())) {
-                mAutocompleteCoordinator.startZeroSuggest();
-            } else {
-                mAutocompleteCoordinator.onTextChangedForAutocomplete();
-            }
-        }
-    }
-
-    @Override
     protected void onWindowVisibilityChanged(int visibility) {
         super.onWindowVisibilityChanged(visibility);
         if (visibility == View.VISIBLE) updateMicButtonState();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
index 2a7da64..2658ebaf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -26,6 +26,7 @@
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
 import org.chromium.chrome.browser.omnibox.UrlBar.UrlTextChangeListener;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
+import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
 import org.chromium.chrome.browser.omnibox.VoiceSuggestionProvider.VoiceResult;
 import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxResultsAdapter.OmniboxResultItem;
@@ -46,7 +47,7 @@
  * Coordinator that handles the interactions with the autocomplete system.
  */
 public class AutocompleteCoordinator
-        implements OnSuggestionsReceivedListener, UrlTextChangeListener {
+        implements OnSuggestionsReceivedListener, UrlFocusChangeListener, UrlTextChangeListener {
     private static final String TAG = "cr_Autocomplete";
 
     // Delay triggering the omnibox results upon key press to allow the location bar to repaint
@@ -178,6 +179,33 @@
         mAutocomplete = new AutocompleteController(this);
     }
 
+    @Override
+    public void onUrlFocusChange(boolean hasFocus) {
+        if (hasFocus) {
+            if (mNativeInitialized) {
+                startZeroSuggest();
+            } else {
+                mDeferredNativeRunnables.add(() -> {
+                    if (TextUtils.isEmpty(mUrlBarEditingTextProvider.getTextWithAutocomplete())) {
+                        startZeroSuggest();
+                    }
+                });
+            }
+            maybeShowOmniboxResultsContainer();
+        } else {
+            // Prevent any upcoming omnibox suggestions from showing once a URL is loaded (and as
+            // a consequence the omnibox is unfocused).
+            stopAutocomplete(true);
+
+            updateOmniboxResultsContainerVisibility(false);
+
+            mHasStartedNewOmniboxEditSession = false;
+            mNewOmniboxEditSessionTimestamp = -1;
+            hideSuggestions();
+            mAnswersImageFetcher.clearCache();
+        }
+    }
+
     /**
      * Provides data and state for the toolbar component.
      * @param toolbarDataProvider The data provider.
@@ -321,7 +349,6 @@
                         updateSuggestionUrlIfNeeded(suggestion, position, false);
                 loadUrlFromOmniboxMatch(
                         suggestionMatchUrl, position, suggestion, mLastActionUpTimestamp);
-                hideSuggestions();
                 mDelegate.hideKeyboard();
             }
 
@@ -465,7 +492,7 @@
     /**
      * Conditionally show the omnibox suggestions container.
      */
-    public void maybeShowOmniboxResultsContainer() {
+    private void maybeShowOmniboxResultsContainer() {
         if (isSuggestionsListShown() || mDelegate.isUrlBarFocused()) {
             initOmniboxResultsContainer();
             updateOmniboxResultsContainerVisibility(true);
@@ -475,7 +502,7 @@
     /**
      * Update whether the omnibox suggestions container is visible.
      */
-    public void updateOmniboxResultsContainerVisibility(boolean visible) {
+    private void updateOmniboxResultsContainerVisibility(boolean visible) {
         if (mOmniboxResultsContainer == null) return;
 
         boolean currentlyVisible = mOmniboxResultsContainer.getVisibility() == View.VISIBLE;
@@ -851,7 +878,7 @@
      * - The URL bar has focus.
      * - The current tab is not incognito.
      */
-    public void startZeroSuggest() {
+    private void startZeroSuggest() {
         // hasWindowFocus() can return true before onWindowFocusChanged has been called, so this
         // is an optimization, but not entirely reliable.  The underlying controller needs to also
         // ensure we do not double trigger zero query.
@@ -917,7 +944,7 @@
      *
      * @see AutocompleteController#stop(boolean)
      */
-    public void hideSuggestions() {
+    private void hideSuggestions() {
         if (mAutocomplete == null || !mNativeInitialized) return;
 
         if (mShowSuggestions != null) mParent.removeCallbacks(mShowSuggestions);
@@ -934,7 +961,7 @@
      *
      * @param clear Whether to clear the most recent autocomplete results.
      */
-    public void stopAutocomplete(boolean clear) {
+    private void stopAutocomplete(boolean clear) {
         if (mAutocomplete != null) mAutocomplete.stop(clear);
         cancelPendingAutocompleteStart();
     }
@@ -966,28 +993,6 @@
     }
 
     /**
-     * Notifies autocomplete that the URL focus state has changed.
-     */
-    public void onUrlFocusChanged(boolean hasFocus) {
-        if (!hasFocus) {
-            mHasStartedNewOmniboxEditSession = false;
-            mNewOmniboxEditSessionTimestamp = -1;
-            hideSuggestions();
-            mAnswersImageFetcher.clearCache();
-        }
-
-        if (mNativeInitialized) {
-            startZeroSuggest();
-        } else {
-            mDeferredNativeRunnables.add(() -> {
-                if (TextUtils.isEmpty(mUrlBarEditingTextProvider.getTextWithAutocomplete())) {
-                    startZeroSuggest();
-                }
-            });
-        }
-    }
-
-    /**
      * Sets the autocomplete controller for the location bar.
      *
      * @param controller The controller that will handle autocomplete/omnibox suggestions.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
index 192f028..1f95261 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
@@ -776,9 +776,6 @@
     public void revertChanges() {}
 
     @Override
-    public void hideSuggestions() {}
-
-    @Override
     public void updateMicButtonState() {}
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
index 5d2ebd8..aaaeeef4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -765,7 +765,7 @@
      * @return Whether or not the current Tab did go back.
      */
     protected boolean back() {
-        getLocationBar().hideSuggestions();
+        if (getLocationBar() != null) getLocationBar().setUrlBarFocus(false);
         return mToolbarTabController != null ? mToolbarTabController.back() : false;
     }
 
@@ -774,7 +774,7 @@
      * @return Whether or not the current Tab did go forward.
      */
     protected boolean forward() {
-        getLocationBar().hideSuggestions();
+        if (getLocationBar() != null) getLocationBar().setUrlBarFocus(false);
         return mToolbarTabController != null ? mToolbarTabController.forward() : false;
     }
 
@@ -785,7 +785,7 @@
      * <p>The buttons of the toolbar will be updated as a result of making this call.
      */
     protected void stopOrReloadCurrentTab() {
-        getLocationBar().hideSuggestions();
+        if (getLocationBar() != null) getLocationBar().setUrlBarFocus(false);
         if (mToolbarTabController != null) mToolbarTabController.stopOrReloadCurrentTab();
     }
 
@@ -793,6 +793,7 @@
      * Opens hompage in the current tab.
      */
     protected void openHomepage() {
+        if (getLocationBar() != null) getLocationBar().setUrlBarFocus(false);
         if (mToolbarTabController != null) mToolbarTabController.openHomepage();
     }
 
@@ -800,7 +801,6 @@
      * Opens the Memex UI in the current tab.
      */
     protected void openMemexUI() {
-        getLocationBar().hideSuggestions();
         if (mToolbarTabController != null) mToolbarTabController.openMemexUI();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 29eb5f2..060a9bd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -1364,7 +1364,6 @@
     public void openHomepage() {
         RecordUserAction.record("Home");
 
-        mLocationBar.hideSuggestions();
         Tab currentTab = mToolbarModel.getTab();
         if (currentTab == null) return;
         String homePageUrl = HomepageManager.getHomepageUri();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/SilenceLintErrors.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/SilenceLintErrors.java
index 4f48faf..4ee896eb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/SilenceLintErrors.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/SilenceLintErrors.java
@@ -16,7 +16,8 @@
             R.string.vr_services_check_infobar_update_text,
             R.string.vr_services_check_infobar_install_button,
             R.string.vr_services_check_infobar_update_button, R.anim.stay_hidden,
-            R.drawable.vr_services, R.string.vr_module_title,
+            R.drawable.vr_services, R.string.vr_module_title, R.string.vr_module_install_start_text,
+            R.string.vr_module_install_success_text, R.string.vr_module_install_failure_text,
     };
 
     private SilenceLintErrors() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java
index b5e8d00..6ba6418 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java
@@ -4,12 +4,7 @@
 
 package org.chromium.chrome.browser.vr;
 
-import org.chromium.base.ContextUtils;
-import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
-import org.chromium.chrome.R;
-import org.chromium.components.module_installer.ModuleInstaller;
-import org.chromium.ui.widget.Toast;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -23,13 +18,6 @@
     private static VrDelegateProvider sDelegateProvider;
     private static final List<VrModeObserver> sVrModeObservers = new ArrayList<>();
 
-    private long mNativeVrModuleProvider;
-
-    /** Need to be called after native libraries are available. */
-    public static void init() {
-        nativeInit();
-    }
-
     public static VrDelegate getDelegate() {
         return getDelegateProvider().getDelegate();
     }
@@ -72,8 +60,6 @@
 
     private static VrDelegateProvider getDelegateProvider() {
         if (sDelegateProvider == null) {
-            // Need to be called before trying to access the VR module.
-            ModuleInstaller.init();
             try {
                 sDelegateProvider =
                         (VrDelegateProvider) Class
@@ -87,54 +73,7 @@
         return sDelegateProvider;
     }
 
-    @CalledByNative
-    private static VrModuleProvider create(long nativeVrModuleProvider) {
-        return new VrModuleProvider(nativeVrModuleProvider);
-    }
+    private VrModuleProvider() {}
 
-    @CalledByNative
-    private static boolean isModuleInstalled() {
-        return !(getDelegateProvider() instanceof VrDelegateProviderFallback);
-    }
-
-    private VrModuleProvider(long nativeVrModuleProvider) {
-        mNativeVrModuleProvider = nativeVrModuleProvider;
-    }
-
-    @CalledByNative
-    private void onNativeDestroy() {
-        mNativeVrModuleProvider = 0;
-    }
-
-    @CalledByNative
-    private void installModule() {
-        assert !isModuleInstalled();
-
-        // TODO(crbug.com/863064): This is a placeholder UI. Replace once proper UI is spec'd.
-        Toast.makeText(ContextUtils.getApplicationContext(), R.string.vr_module_install_start_text,
-                     Toast.LENGTH_SHORT)
-                .show();
-
-        ModuleInstaller.install("vr", (success) -> {
-            if (success) {
-                // Re-create delegate provider.
-                sDelegateProvider = null;
-                VrDelegate delegate = getDelegate();
-                assert !(delegate instanceof VrDelegateFallback);
-                delegate.onNativeLibraryAvailable();
-            }
-            // TODO(crbug.com/863064): This is a placeholder UI. Replace once proper UI is spec'd.
-            int mToastTextRes = success ? R.string.vr_module_install_success_text
-                                        : R.string.vr_module_install_failure_text;
-            Toast.makeText(ContextUtils.getApplicationContext(), mToastTextRes, Toast.LENGTH_SHORT)
-                    .show();
-            if (mNativeVrModuleProvider != 0) {
-                nativeOnInstalledModule(mNativeVrModuleProvider, success);
-            }
-        });
-    }
-
-    private static native void nativeInit();
     private static native void nativeRegisterJni();
-    private native void nativeOnInstalledModule(long nativeVrModuleProvider, boolean success);
 }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 4e6db8e6..2d5844d 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -3719,19 +3719,17 @@
         <message name="IDS_VR_MODULE_TITLE" desc="Title of the Virtual Reality (VR) dynamic feature module. Used, for instance, in the text of dialogs confirming to download the module.">
           VR
         </message>
+        <message name="IDS_VR_MODULE_INSTALL_START_TEXT" desc="Text shown on a toast when Chrome starts to download the VR dynamic feature module.">
+          Installing VR module...
+        </message>
+        <message name="IDS_VR_MODULE_INSTALL_SUCCESS_TEXT" desc="Text shown on a toast when Chrome successfully installed the VR dynamic feature module.">
+          Installed VR module
+        </message>
+        <message name="IDS_VR_MODULE_INSTALL_FAILURE_TEXT" desc="Text shown on a toast when Chrome failed to install the VR dynamic feature module.">
+          Failed to install VR module
+        </message>
       </if>
 
-      <!-- VR module -->
-      <message name="IDS_VR_MODULE_INSTALL_START_TEXT" desc="Text shown on a toast when Chrome starts to download the VR dynamic feature module.">
-        Installing VR module...
-      </message>
-      <message name="IDS_VR_MODULE_INSTALL_SUCCESS_TEXT" desc="Text shown on a toast when Chrome successfully installed the VR dynamic feature module.">
-        Installed VR module
-      </message>
-      <message name="IDS_VR_MODULE_INSTALL_FAILURE_TEXT" desc="Text shown on a toast when Chrome failed to install the VR dynamic feature module.">
-        Failed to install VR module
-      </message>
-
       <if expr="enable_arcore">
         <!-- ARCore check infobar -->
         <message name="IDS_AR_CORE_CHECK_INFOBAR_INSTALL_TEXT" desc="Text to be displayed in the ARCore check infobar. When a WebXR page is loaded, if ARCore is needed to display AR content and it is not installed, an infobar will be shown to the user prompting them to install ARCore.">
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
index 5654eef..573c3d9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
@@ -9,6 +9,7 @@
 import android.os.Process;
 import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsSessionToken;
+import android.support.customtabs.PostMessageServiceConnection;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 
@@ -94,7 +95,7 @@
     @Test
     @SmallTest
     public void testValidSessionNoWarmup() {
-        mClientManager.newSession(mSession, mUid, null, null);
+        mClientManager.newSession(mSession, mUid, null, null, null);
         Assert.assertEquals(ClientManager.CalledWarmup.SESSION_NO_WARMUP_NOT_CALLED,
                 mClientManager.getWarmupState(mSession));
     }
@@ -103,7 +104,7 @@
     @SmallTest
     public void testValidSessionOtherWarmup() {
         mClientManager.recordUidHasCalledWarmup(mUid + 1);
-        mClientManager.newSession(mSession, mUid, null, null);
+        mClientManager.newSession(mSession, mUid, null, null, null);
         Assert.assertEquals(ClientManager.CalledWarmup.SESSION_NO_WARMUP_ALREADY_CALLED,
                 mClientManager.getWarmupState(mSession));
     }
@@ -112,7 +113,7 @@
     @SmallTest
     public void testValidSessionWarmup() {
         mClientManager.recordUidHasCalledWarmup(mUid);
-        mClientManager.newSession(mSession, mUid, null, null);
+        mClientManager.newSession(mSession, mUid, null, null, null);
         Assert.assertEquals(
                 ClientManager.CalledWarmup.SESSION_WARMUP, mClientManager.getWarmupState(mSession));
     }
@@ -121,12 +122,12 @@
     @SmallTest
     public void testValidSessionWarmupSeveralCalls() {
         mClientManager.recordUidHasCalledWarmup(mUid);
-        mClientManager.newSession(mSession, mUid, null, null);
+        mClientManager.newSession(mSession, mUid, null, null, null);
         Assert.assertEquals(
                 ClientManager.CalledWarmup.SESSION_WARMUP, mClientManager.getWarmupState(mSession));
 
         CustomTabsSessionToken token = CustomTabsSessionToken.createMockSessionTokenForTesting();
-        mClientManager.newSession(token, mUid, null, null);
+        mClientManager.newSession(token, mUid, null, null, null);
         Assert.assertEquals(
                 ClientManager.CalledWarmup.SESSION_WARMUP, mClientManager.getWarmupState(token));
     }
@@ -135,7 +136,7 @@
     @SmallTest
     @RetryOnFailure
     public void testPredictionOutcomeSuccess() {
-        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null));
+        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null, null));
         Assert.assertTrue(
                 mClientManager.updateStatsAndReturnWhetherAllowed(mSession, mUid, URL, false));
         Assert.assertEquals(ClientManager.PredictionStatus.GOOD,
@@ -145,7 +146,7 @@
     @Test
     @SmallTest
     public void testPredictionOutcomeNoPrediction() {
-        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null));
+        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null, null));
         mClientManager.recordUidHasCalledWarmup(mUid);
         Assert.assertEquals(ClientManager.PredictionStatus.NONE,
                 mClientManager.getPredictionOutcome(mSession, URL));
@@ -154,7 +155,7 @@
     @Test
     @SmallTest
     public void testPredictionOutcomeBadPrediction() {
-        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null));
+        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null, null));
         Assert.assertTrue(
                 mClientManager.updateStatsAndReturnWhetherAllowed(mSession, mUid, URL, false));
         Assert.assertEquals(ClientManager.PredictionStatus.BAD,
@@ -164,7 +165,7 @@
     @Test
     @SmallTest
     public void testPredictionOutcomeIgnoreFragment() {
-        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null));
+        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null, null));
         Assert.assertTrue(
                 mClientManager.updateStatsAndReturnWhetherAllowed(mSession, mUid, URL, false));
         mClientManager.setIgnoreFragmentsForSession(mSession, true);
@@ -176,7 +177,9 @@
     @SmallTest
     public void testPostMessageOriginVerification() {
         final ClientManager cm = mClientManager;
-        Assert.assertTrue(cm.newSession(mSession, mUid, null, new PostMessageHandler(mSession)));
+        PostMessageServiceConnection serviceConnection = new PostMessageServiceConnection(mSession);
+        Assert.assertTrue(cm.newSession(mSession, mUid, null,
+                new PostMessageHandler(serviceConnection), serviceConnection));
         // Should always start with no origin.
         Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession));
 
@@ -223,7 +226,9 @@
     @SmallTest
     public void testPostMessageOriginDifferentRelations() {
         final ClientManager cm = mClientManager;
-        Assert.assertTrue(cm.newSession(mSession, mUid, null, new PostMessageHandler(mSession)));
+        PostMessageServiceConnection serviceConnection = new PostMessageServiceConnection(mSession);
+        Assert.assertTrue(cm.newSession(mSession, mUid, null,
+                new PostMessageHandler(serviceConnection), serviceConnection));
         // Should always start with no origin.
         Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession));
 
@@ -260,7 +265,9 @@
     @SmallTest
     public void testPostMessageOriginHttpNotAllowed() {
         final ClientManager cm = mClientManager;
-        Assert.assertTrue(cm.newSession(mSession, mUid, null, new PostMessageHandler(mSession)));
+        PostMessageServiceConnection serviceConnection = new PostMessageServiceConnection(mSession);
+        Assert.assertTrue(cm.newSession(mSession, mUid, null,
+                new PostMessageHandler(serviceConnection), serviceConnection));
         // Should always start with no origin.
         Assert.assertNull(cm.getPostMessageOriginForSessionForTesting(mSession));
 
@@ -291,7 +298,7 @@
         Context context = InstrumentationRegistry.getInstrumentation()
                                   .getTargetContext()
                                   .getApplicationContext();
-        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null));
+        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null, null));
 
         // Two low confidence in a row is OK.
         Assert.assertTrue(
@@ -334,7 +341,7 @@
         MetricsUtils.HistogramDelta bothDelta =
                 new MetricsUtils.HistogramDelta(name, ClientManager.MayLaunchUrlType.BOTH);
 
-        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null));
+        Assert.assertTrue(mClientManager.newSession(mSession, mUid, null, null, null));
 
         // No prediction;
         mClientManager.registerLaunch(mSession, URL);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
index 0ae589ed..bdcf867 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -298,59 +298,6 @@
         }));
     }
 
-    @Test
-    @MediumTest
-    @Feature("Omnibox")
-    public void testSuggestionsTriggeredOnWindowFocusGained() {
-        final LocationBarLayout locationBar =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        final UrlBar urlBar = (UrlBar) mActivityTestRule.getActivity().findViewById(R.id.url_bar);
-
-        OmniboxTestUtils.toggleUrlBarFocus(urlBar, true);
-
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            TestAutocompleteController controller = new TestAutocompleteController(locationBar,
-                    sEmptySuggestionListener, new HashMap<String, List<SuggestionsResult>>());
-            locationBar.getAutocompleteCoordinator().setAutocompleteController(controller);
-            locationBar.onWindowFocusChanged(false);
-            locationBar.onWindowFocusChanged(true);
-            Assert.assertEquals("Zero suggest not triggered when URL focused but unchanged", 1,
-                    controller.numZeroSuggestRequests());
-        });
-
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            urlBar.setText("");
-
-            TestAutocompleteController controller = new TestAutocompleteController(locationBar,
-                    sEmptySuggestionListener, new HashMap<String, List<SuggestionsResult>>());
-            locationBar.getAutocompleteCoordinator().setAutocompleteController(controller);
-            locationBar.onWindowFocusChanged(false);
-            locationBar.onWindowFocusChanged(true);
-            Assert.assertEquals("Zero suggest not triggered when URL focused but empty", 1,
-                    controller.numZeroSuggestRequests());
-        });
-
-        final TestAutocompleteController controller = new TestAutocompleteController(locationBar,
-                sEmptySuggestionListener, new HashMap<String, List<SuggestionsResult>>());
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            urlBar.setText("cows");
-
-            locationBar.getAutocompleteCoordinator().setAutocompleteController(controller);
-            locationBar.onWindowFocusChanged(false);
-            locationBar.onWindowFocusChanged(true);
-            Assert.assertEquals("Zero suggest incorrectly triggered when URL has changed", 0,
-                    controller.numZeroSuggestRequests());
-        });
-        // Autocomplete is triggered async, so we need to poll to see that it is eventually
-        // requested.
-        CriteriaHelper.pollUiThread(Criteria.equals(true, new Callable<Boolean>() {
-            @Override
-            public Boolean call() throws Exception {
-                return controller.isStartAutocompleteCalled();
-            }
-        }));
-    }
-
     // Sanity check that no text is displayed in the omnibox when on the NTP page and that the hint
     // text is correct.
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrDeviceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrDeviceTest.java
index 9341e8a..9eb65c3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrDeviceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrDeviceTest.java
@@ -22,7 +22,6 @@
 import org.chromium.base.test.params.ParameterSet;
 import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -71,7 +70,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     public void testDeviceCapabilitiesMatchExpectations() throws InterruptedException {
         mWebVrTestFramework.loadUrlAndAwaitInitialization(
@@ -89,7 +87,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags.Add("enable-features=WebXROrientationSensorDevice")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     @Restriction(RESTRICTION_TYPE_SVR)
@@ -113,7 +110,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
index 39dfd08..e2bde6a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
@@ -34,7 +34,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -97,7 +96,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @DisableIf.
     Build(message = "Flaky on K/L crbug.com/762126", sdk_is_less_than = Build.VERSION_CODES.M)
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@@ -112,7 +110,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @DisableIf
             .Build(message = "Flaky on K/L crbug.com/762126",
                     sdk_is_less_than = Build.VERSION_CODES.M)
@@ -261,7 +258,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @Restriction(RESTRICTION_TYPE_VIEWER_NON_DAYDREAM)
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     public void testScreenTapsRegisteredOnCardboard() throws InterruptedException {
@@ -292,7 +288,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @Restriction(RESTRICTION_TYPE_VIEWER_NON_DAYDREAM)
     @CommandLineFlags
             .Remove({"enable-webvr"})
@@ -332,7 +327,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     public void testPresentationLocksFocus() throws InterruptedException {
         presentationLocksFocusImpl(
@@ -346,7 +340,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
@@ -571,7 +564,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
     @CommandLineFlags
             .Remove({"enable-webvr"})
@@ -590,7 +582,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @Restriction(RESTRICTION_TYPE_VIEWER_NON_DAYDREAM)
     @CommandLineFlags
             .Remove({"enable-webvr"})
@@ -608,7 +599,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
     @CommandLineFlags
             .Remove({"enable-webvr"})
@@ -625,7 +615,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @Restriction(RESTRICTION_TYPE_VIEWER_NON_DAYDREAM)
     @CommandLineFlags
             .Remove({"enable-webvr"})
@@ -644,7 +633,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
     @CommandLineFlags.Remove({"enable-webvr"})
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@@ -659,7 +647,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @Restriction(RESTRICTION_TYPE_VIEWER_NON_DAYDREAM)
     @CommandLineFlags.Remove({"enable-webvr"})
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
index f6145476..fefb638 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
@@ -37,7 +37,6 @@
 import org.chromium.base.test.params.ParameterSet;
 import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -94,7 +93,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     public void testRequestPresentEntersVr() throws InterruptedException {
         testPresentationEntryImpl(
@@ -107,7 +105,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
@@ -165,7 +162,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags.Remove({"enable-webvr"})
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     public void testWebVrDisabledWithoutFlagSet() throws InterruptedException {
@@ -182,7 +178,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags.Remove({"enable-webvr"})
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     public void testWebXrDisabledWithoutFlagSet() throws InterruptedException {
@@ -370,7 +365,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     public void testWindowRafStopsFiringWhilePresenting() throws InterruptedException {
         windowRafStopsFiringWhilePresentingImpl(
@@ -385,7 +379,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
@@ -457,7 +450,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
@@ -477,7 +469,6 @@
      */
     @Test
     @MediumTest
-    @FlakyTest(message = "https://crbug.com/894796")
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
diff --git a/chrome/android/modules/vr/AndroidManifest.xml b/chrome/android/modules/vr/AndroidManifest.xml
index 02e07a6..4be5316 100644
--- a/chrome/android/modules/vr/AndroidManifest.xml
+++ b/chrome/android/modules/vr/AndroidManifest.xml
@@ -7,13 +7,15 @@
     xmlns:dist="http://schemas.android.com/apk/distribution"
     package="{{manifest_package}}">
 
-    <!-- The VR module is only supported on Android L+. -->
+    <!-- Chrome VR is only supported on Android L+. -->
     <uses-sdk
         android:minSdkVersion="21"
         android:targetSdkVersion="{{target_sdk_version}}" />
 
+    <!-- TODO(crbug.com/862689): Set dist:onDemand="true" once we can on-demand
+         install modules. -->
     <dist:module
-        dist:onDemand="true"
+        dist:onDemand="false"
         dist:title="@string/vr_module_title">
         <dist:fusing dist:include="false" />
     </dist:module>
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index da6d638..ad5d5bc 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -3637,9 +3637,6 @@
   <message name="IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_LOCKED_AND_RSSI_TOO_LOW" desc="Tooltip for an icon on a user's lock screen pod shown by Easy Unlock when a phone eligible to unlock the Chromebook is detected, but it's both (a) locked and (b) not in the Chromebook's proximity (> 1 foot away).">
     Unlock your phone and bring it closer to unlock your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>.
   </message>
-  <message name="IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_INITIAL_AUTHENTICATED" desc="Tooltip text shown on lock screen when a phone eligible to unlock the Chromebook via Easy Unlock is detected and authenticated for the first time.">
-    When your phone is unlocked and nearby, just select to unlock. Otherwise, enter your password or PIN.
-  </message>
   <message name="IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_INSTRUCTIONS" desc="Tooltip for an icon on user's lock screen pod shown by Easy Unlock when a phone eligible to unlock the Chromebook is detected and authenticated. The tooltip shows instructions for hard-locking the Chromebook.">
     If you click this icon, you will manually lock this <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. Next time, you’ll need to type your password to enter.
   </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7ba7a9a..28ee98d 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2549,9 +2549,9 @@
       "//components/feed:feature_list",
       "//components/invalidation/impl:feature_list",
       "//components/language/android:language_bridge",
+      "//components/omnibox/browser",
       "//components/payments/content/android",
       "//components/resources:components_resources",
-      "//components/toolbar",
       "//media/mojo/clients",
       "//media/mojo/interfaces:constants",
       "//rlz:rlz_utils",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 9e71fdb..844cf52 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -78,6 +78,7 @@
 #include "components/offline_pages/core/offline_page_feature.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/omnibox_switches.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/payments/core/features.h"
 #include "components/previews/core/previews_features.h"
@@ -97,7 +98,6 @@
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "components/suggestions/features.h"
 #include "components/sync/driver/sync_driver_switches.h"
-#include "components/toolbar/toolbar_field_trial.h"
 #include "components/tracing/common/tracing_switches.h"
 #include "components/translate/core/browser/translate_prefs.h"
 #include "components/translate/core/browser/translate_ranker_impl.h"
@@ -4107,6 +4107,14 @@
      flag_descriptions::kEnableAppShortcutSearchDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(app_list_features::kEnableAppShortcutSearch)},
 
+    {"enable-play-store-search", flag_descriptions::kEnablePlayStoreSearchName,
+     flag_descriptions::kEnablePlayStoreSearchDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(app_list_features::kEnablePlayStoreAppSearch)},
+
+    {"enable-app-data-search", flag_descriptions::kEnableAppDataSearchName,
+     flag_descriptions::kEnableAppDataSearchDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(app_list_features::kEnableAppDataSearch)},
+
     {"enable-drag-tabs-in-tablet-mode",
      flag_descriptions::kEnableDragTabsInTabletModeName,
      flag_descriptions::kEnableDragTabsInTabletModeDescription, kOsCrOS,
@@ -4336,6 +4344,12 @@
      flag_descriptions::kEnableHomeLauncherGesturesDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(app_list_features::kEnableHomeLauncherGestures)},
 #endif
+#if defined(OS_WIN)
+    {"calculate-native-win-occlusion",
+     flag_descriptions::kCalculateNativeWinOcclusionName,
+     flag_descriptions::kCalculateNativeWinOcclusionDescription, kOsWin,
+     FEATURE_VALUE_TYPE(features::kCalculateNativeWinOcclusion)},
+#endif  // OS_WIN
 
 #if !defined(OS_ANDROID)
     {"happiness-tarcking-surveys-for-desktop",
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index b101234..04bdd90 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -23,11 +23,11 @@
 #include "components/ntp_tiles/constants.h"
 #include "components/offline_pages/core/offline_page_feature.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/payments/core/features.h"
 #include "components/safe_browsing/features.h"
 #include "components/subresource_filter/core/browser/subresource_filter_features.h"
-#include "components/toolbar/toolbar_field_trial.h"
 #include "components/translate/core/browser/translate_prefs.h"
 #include "components/unified_consent/feature.h"
 #include "content/public/common/content_features.h"
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.cc b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
index d2f54991..07b4e43 100644
--- a/chrome/browser/android/omnibox/autocomplete_controller_android.cc
+++ b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
@@ -43,10 +43,10 @@
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/omnibox_log.h"
 #include "components/omnibox/browser/search_provider.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/open_from_clipboard/clipboard_recent_content.h"
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/template_url_service.h"
-#include "components/toolbar/toolbar_model.h"
 #include "components/url_formatter/url_formatter.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h
index 14b58e4..f37a21f7 100644
--- a/chrome/browser/android/tab_android.h
+++ b/chrome/browser/android/tab_android.h
@@ -21,8 +21,8 @@
 #include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h"
 #include "components/favicon/core/favicon_driver_observer.h"
 #include "components/infobars/core/infobar_manager.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/sessions/core/session_id.h"
-#include "components/toolbar/toolbar_model.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn
index 4a563ae6..127c2ae 100644
--- a/chrome/browser/android/vr/BUILD.gn
+++ b/chrome/browser/android/vr/BUILD.gn
@@ -51,7 +51,6 @@
     "vr_input_connection.cc",
     "vr_input_connection.h",
     "vr_module_provider.cc",
-    "vr_module_provider.h",
     "vr_shell.cc",
     "vr_shell.h",
     "vr_shell_delegate.cc",
diff --git a/chrome/browser/android/vr/vr_module_provider.cc b/chrome/browser/android/vr/vr_module_provider.cc
index 738d156..15e49ba 100644
--- a/chrome/browser/android/vr/vr_module_provider.cc
+++ b/chrome/browser/android/vr/vr_module_provider.cc
@@ -2,64 +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/android/vr/vr_module_provider.h"
-
 #include "chrome/browser/android/vr/register_jni.h"
-#include "chrome/browser/android/vr/vr_module_provider.h"
-#include "device/vr/android/gvr/vr_module_delegate.h"
 #include "jni/VrModuleProvider_jni.h"
 
 namespace vr {
 
-VrModuleProvider::VrModuleProvider() = default;
-
-VrModuleProvider::~VrModuleProvider() {
-  if (!j_vr_module_provider_.obj()) {
-    return;
-  }
-  Java_VrModuleProvider_onNativeDestroy(base::android::AttachCurrentThread(),
-                                        j_vr_module_provider_);
-}
-
-bool VrModuleProvider::ModuleInstalled() {
-  return Java_VrModuleProvider_isModuleInstalled(
-      base::android::AttachCurrentThread());
-}
-
-void VrModuleProvider::InstallModule(
-    base::OnceCallback<void(bool)> on_finished) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  on_finished_callbacks_.push(std::move(on_finished));
-  // Don't request VR module multiple times in parallel.
-  if (on_finished_callbacks_.size() > 1) {
-    return;
-  }
-  DCHECK(!j_vr_module_provider_.obj());
-  j_vr_module_provider_.Reset(Java_VrModuleProvider_create(
-      base::android::AttachCurrentThread(), (jlong) this));
-  Java_VrModuleProvider_installModule(base::android::AttachCurrentThread(),
-                                      j_vr_module_provider_);
-}
-
-void VrModuleProvider::OnInstalledModule(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj,
-    bool success) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(on_finished_callbacks_.size() > 0);
-  while (!on_finished_callbacks_.empty()) {
-    std::move(on_finished_callbacks_.front()).Run(success);
-    on_finished_callbacks_.pop();
-  }
-  j_vr_module_provider_ = nullptr;
-}
-
-static void JNI_VrModuleProvider_Init(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jclass>& clazz) {
-  device::VrModuleDelegate::Set(std::make_unique<VrModuleProvider>());
-}
-
 static void JNI_VrModuleProvider_RegisterJni(
     JNIEnv* env,
     const base::android::JavaParamRef<jclass>& clazz) {
diff --git a/chrome/browser/android/vr/vr_module_provider.h b/chrome/browser/android/vr/vr_module_provider.h
deleted file mode 100644
index f70c42f..0000000
--- a/chrome/browser/android/vr/vr_module_provider.h
+++ /dev/null
@@ -1,37 +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 CHROME_BROWSER_ANDROID_VR_VR_MODULE_PROVIDER_H_
-#define CHROME_BROWSER_ANDROID_VR_VR_MODULE_PROVIDER_H_
-
-#include <jni.h>
-#include <queue>
-
-#include "base/android/jni_android.h"
-#include "device/vr/android/gvr/vr_module_delegate.h"
-
-namespace vr {
-
-// Installs the VR module.
-class VrModuleProvider : public device::VrModuleDelegate {
- public:
-  VrModuleProvider();
-  ~VrModuleProvider() override;
-  bool ModuleInstalled() override;
-  void InstallModule(base::OnceCallback<void(bool)> on_finished) override;
-
-  // Called by Java.
-  void OnInstalledModule(JNIEnv* env,
-                         const base::android::JavaParamRef<jobject>& obj,
-                         bool success);
-
- private:
-  std::queue<base::OnceCallback<void(bool)>> on_finished_callbacks_;
-  base::android::ScopedJavaGlobalRef<jobject> j_vr_module_provider_;
-  SEQUENCE_CHECKER(sequence_checker_);
-};
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_ANDROID_VR_VR_MODULE_PROVIDER_H_
diff --git a/chrome/browser/browser_switcher/browser_switcher_prefs.cc b/chrome/browser/browser_switcher/browser_switcher_prefs.cc
index 5ddefde..066f956 100644
--- a/chrome/browser/browser_switcher/browser_switcher_prefs.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_prefs.cc
@@ -25,11 +25,15 @@
 // List of hosts that should not trigger a transition in either browser.
 const char kUrlGreylist[] = "browser_switcher.url_greylist";
 
+// If set to true, use the IE Enterprise Mode Sitelist policy.
+const char kUseIeSitelist[] = "browser_switcher.use_ie_sitelist";
+
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
   registry->RegisterStringPref(prefs::kAlternativeBrowserPath, "");
   registry->RegisterListPref(prefs::kAlternativeBrowserParameters);
   registry->RegisterListPref(prefs::kUrlList);
   registry->RegisterListPref(prefs::kUrlGreylist);
+  registry->RegisterBooleanPref(prefs::kUseIeSitelist, false);
 }
 
 }  // namespace prefs
diff --git a/chrome/browser/browser_switcher/browser_switcher_prefs.h b/chrome/browser/browser_switcher/browser_switcher_prefs.h
index 4d83d4a..9accf10 100644
--- a/chrome/browser/browser_switcher/browser_switcher_prefs.h
+++ b/chrome/browser/browser_switcher/browser_switcher_prefs.h
@@ -16,6 +16,7 @@
 extern const char kAlternativeBrowserParameters[];
 extern const char kUrlList[];
 extern const char kUrlGreylist[];
+extern const char kUseIeSitelist[];
 
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
diff --git a/chrome/browser/browser_switcher/browser_switcher_service.cc b/chrome/browser/browser_switcher/browser_switcher_service.cc
index b735a333..878a17a6 100644
--- a/chrome/browser/browser_switcher/browser_switcher_service.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_service.cc
@@ -4,17 +4,96 @@
 
 #include "chrome/browser/browser_switcher/browser_switcher_service.h"
 
+#include "build/build_config.h"
 #include "chrome/browser/browser_switcher/alternative_browser_launcher.h"
+#include "chrome/browser/browser_switcher/browser_switcher_prefs.h"
 #include "chrome/browser/browser_switcher/browser_switcher_sitelist.h"
+#include "chrome/browser/browser_switcher/ieem_sitelist_parser.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "net/base/load_flags.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+
+#if defined(OS_WIN)
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/registry.h"
+#endif
 
 namespace browser_switcher {
 
-BrowserSwitcherService::BrowserSwitcherService(PrefService* prefs)
-    : launcher_(nullptr), sitelist_(nullptr), prefs_(prefs) {
+namespace {
+
+#if defined(OS_WIN)
+const wchar_t kIeSiteListKey[] =
+    L"SOFTWARE\\Policies\\Microsoft\\Internet Explorer\\Main\\EnterpriseMode";
+const wchar_t kIeSiteListValue[] = L"SiteList";
+
+// How long to wait after |BrowserSwitcherService| is created before initiating
+// the sitelist fetch.
+const base::TimeDelta kFetchSitelistDelay = base::TimeDelta::FromSeconds(60);
+
+// How many times to re-try fetching the XML file for the sitelist.
+const int kFetchNumRetries = 1;
+
+// TODO(nicolaso): Add chrome_policy for this annotation once the policy is
+// implemented.
+constexpr net::NetworkTrafficAnnotationTag traffic_annotation =
+    net::DefineNetworkTrafficAnnotation("browser_switcher_ieem_sitelist", R"(
+        semantics {
+          sender: "Browser Switcher"
+          description:
+            "BrowserSwitcher may download Internet Explorer's Enterprise Mode "
+            "SiteList XML, to load the list of URLs to open in an alternative "
+            "browser. This is often on the organization's intranet. For more "
+            "information on Internet Explorer's Enterprise Mode, see: "
+            "https://docs.microsoft.com/internet-explorer/ie11-deploy-guide"
+            "/what-is-enterprise-mode"
+          trigger:
+            "This happens only once per profile, 60s after the first page "
+            "starts loading. The request may be retried once if it failed the "
+            "first time."
+          data:
+            "An HTTP or HTTPS GET request to the URL configured in Internet "
+            "Explorer's SiteList policy."
+          destination: OTHER
+          destination_other:
+            "URL configured in Internet Explorer's SiteList policy."
+        }
+        policy {
+          cookies_allowed: NO
+          setting: "This feature cannot be disabled by settings."
+          policy_exception_justification:
+            "This feature is still in development, and is disabled by default."
+        })");
+#endif
+
+}  // namespace
+
+BrowserSwitcherService::BrowserSwitcherService(Profile* profile)
+    : launcher_(nullptr), sitelist_(nullptr), prefs_(profile->GetPrefs()) {
+  DCHECK(profile);
   DCHECK(prefs_);
+#if defined(OS_WIN)
+  if (prefs_->GetBoolean(prefs::kUseIeSitelist)) {
+    GURL sitelist_url = GetIeemSitelistUrl();
+    if (sitelist_url.is_valid()) {
+      auto factory =
+          content::BrowserContext::GetDefaultStoragePartition(profile)
+              ->GetURLLoaderFactoryForBrowserProcess();
+      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+          FROM_HERE,
+          base::BindOnce(&BrowserSwitcherService::FetchIeemSitelist,
+                         base::Unretained(this), std::move(sitelist_url),
+                         std::move(factory)),
+          fetch_sitelist_delay_);
+    }
+  } else {
+    DoneLoadingIeemSitelist();
+  }
+#endif
 }
 
 BrowserSwitcherService::~BrowserSwitcherService() {}
@@ -41,4 +120,92 @@
   sitelist_ = std::move(sitelist);
 }
 
+#if defined(OS_WIN)
+base::TimeDelta BrowserSwitcherService::fetch_sitelist_delay_ =
+    kFetchSitelistDelay;
+
+// static
+void BrowserSwitcherService::SetIeemFetchDelayForTesting(
+    base::TimeDelta delay) {
+  fetch_sitelist_delay_ = delay;
+}
+
+base::OnceCallback<void()>
+    BrowserSwitcherService::xml_parsed_callback_for_testing_;
+
+// static
+void BrowserSwitcherService::SetXmlParsedCallbackForTesting(
+    base::OnceCallback<void()> callback) {
+  xml_parsed_callback_for_testing_ = std::move(callback);
+}
+
+GURL BrowserSwitcherService::ieem_sitelist_url_for_testing_;
+
+// static
+void BrowserSwitcherService::SetIeemSitelistUrlForTesting(const GURL& url) {
+  ieem_sitelist_url_for_testing_ = url;
+}
+
+GURL BrowserSwitcherService::GetIeemSitelistUrl() {
+  if (!ieem_sitelist_url_for_testing_.is_empty())
+    return ieem_sitelist_url_for_testing_;
+
+  base::win::RegKey key;
+  if (ERROR_SUCCESS != key.Open(HKEY_LOCAL_MACHINE, kIeSiteListKey, KEY_READ) &&
+      ERROR_SUCCESS != key.Open(HKEY_CURRENT_USER, kIeSiteListKey, KEY_READ)) {
+    return GURL();
+  }
+  std::wstring url_string;
+  if (ERROR_SUCCESS != key.ReadValue(kIeSiteListValue, &url_string))
+    return GURL();
+  return GURL(base::UTF16ToUTF8(url_string));
+}
+
+void BrowserSwitcherService::FetchIeemSitelist(
+    GURL url,
+    scoped_refptr<network::SharedURLLoaderFactory> factory) {
+  DCHECK(factory);
+  DCHECK(!url_loader_);
+  auto request = std::make_unique<network::ResourceRequest>();
+  request->url = url;
+  request->load_flags =
+      (net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
+       net::LOAD_DISABLE_CACHE);
+  url_loader_ =
+      network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
+  url_loader_->SetRetryOptions(
+      kFetchNumRetries,
+      network::SimpleURLLoader::RetryMode::RETRY_ON_NETWORK_CHANGE);
+  url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+      factory.get(), base::BindOnce(&BrowserSwitcherService::ParseXml,
+                                    base::Unretained(this)));
+}
+
+void BrowserSwitcherService::ParseXml(std::unique_ptr<std::string> bytes) {
+  if (!bytes) {
+    DoneLoadingIeemSitelist();
+    return;
+  }
+  ParseIeemXml(*bytes,
+               base::BindOnce(&BrowserSwitcherService::OnIeemSitelistXmlParsed,
+                              base::Unretained(this)));
+}
+
+void BrowserSwitcherService::OnIeemSitelistXmlParsed(ParsedXml xml) {
+  if (xml.error) {
+    LOG(ERROR) << "Unable to parse IEEM SiteList: " << *xml.error;
+  } else {
+    VLOG(2) << "Done parsing IEEM SiteList. "
+            << "Applying rules to future navigations.";
+    sitelist()->SetIeemSitelist(std::move(xml));
+  }
+  DoneLoadingIeemSitelist();
+}
+
+void BrowserSwitcherService::DoneLoadingIeemSitelist() {
+  if (xml_parsed_callback_for_testing_)
+    std::move(xml_parsed_callback_for_testing_).Run();
+}
+#endif
+
 }  // namespace browser_switcher
diff --git a/chrome/browser/browser_switcher/browser_switcher_service.h b/chrome/browser/browser_switcher/browser_switcher_service.h
index ab3a1bb..0ba5de33 100644
--- a/chrome/browser/browser_switcher/browser_switcher_service.h
+++ b/chrome/browser/browser_switcher/browser_switcher_service.h
@@ -5,22 +5,33 @@
 #ifndef CHROME_BROWSER_BROWSER_SWITCHER_BROWSER_SWITCHER_SERVICE_H_
 #define CHROME_BROWSER_BROWSER_SWITCHER_BROWSER_SWITCHER_SERVICE_H_
 
+#include "base/callback.h"
 #include "base/macros.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "url/gurl.h"
 
 #include <memory>
 
+namespace network {
+class SimpleURLLoader;
+class SharedURLLoaderFactory;
+}  // namespace network
+
 class PrefService;
+class Profile;
 
 namespace browser_switcher {
 
 class AlternativeBrowserLauncher;
 class BrowserSwitcherSitelist;
+class ParsedXml;
 
-// Manages resources that can be accessed from a |BrowserSwitcherTabHelper|.
+// Manages per-profile resources for BrowserSwitcher.
 class BrowserSwitcherService : public KeyedService {
  public:
-  explicit BrowserSwitcherService(PrefService* prefs);
+  explicit BrowserSwitcherService(Profile* profile);
   ~BrowserSwitcherService() override;
 
   AlternativeBrowserLauncher* launcher();
@@ -30,7 +41,43 @@
       std::unique_ptr<AlternativeBrowserLauncher> launcher);
   void SetSitelistForTesting(std::unique_ptr<BrowserSwitcherSitelist> sitelist);
 
+#if defined(OS_WIN)
+  static void SetIeemFetchDelayForTesting(base::TimeDelta delay);
+  static void SetXmlParsedCallbackForTesting(
+      base::OnceCallback<void()> callback);
+  static void SetIeemSitelistUrlForTesting(const GURL& url);
+#endif
+
  private:
+#if defined(OS_WIN)
+  // Returns the URL to fetch to get Internet Explorer's Enterprise Mode
+  // sitelist, based on policy. Returns an empty (invalid) URL if IE's SiteList
+  // policy is unset.
+  GURL GetIeemSitelistUrl();
+
+  // Steps to process the IEEM sitelist rules: fetch, parse, apply.
+  void FetchIeemSitelist(
+      GURL url,
+      scoped_refptr<network::SharedURLLoaderFactory> factory);
+  void ParseXml(std::unique_ptr<std::string> bytes);
+  void OnIeemSitelistXmlParsed(ParsedXml xml);
+  void DoneLoadingIeemSitelist();
+
+  // Delay for the IEEM XML fetch task, launched from the constructor.
+  static base::TimeDelta fetch_sitelist_delay_;
+
+  // URL to fetch the IEEM sitelist from. Only used for testing.
+  static GURL ieem_sitelist_url_for_testing_;
+
+  // If set, gets called once the IEEM sitelist rules are applied. Also gets
+  // called if any step of the process fails.
+  static base::OnceCallback<void()> xml_parsed_callback_for_testing_;
+
+  // Used to fetch the IEEM XML.
+  std::unique_ptr<network::SimpleURLLoader> url_loader_;
+#endif
+
+  // Per-profile helpers.
   std::unique_ptr<AlternativeBrowserLauncher> launcher_;
   std::unique_ptr<BrowserSwitcherSitelist> sitelist_;
 
diff --git a/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc b/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc
new file mode 100644
index 0000000..5a5ff97
--- /dev/null
+++ b/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc
@@ -0,0 +1,141 @@
+// 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 "chrome/browser/browser_switcher/browser_switcher_service.h"
+
+#include "base/run_loop.h"
+#include "base/test/test_timeouts.h"
+#include "chrome/browser/browser_switcher/browser_switcher_prefs.h"
+#include "chrome/browser/browser_switcher/browser_switcher_service_factory.h"
+#include "chrome/browser/browser_switcher/browser_switcher_sitelist.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/test/url_loader_interceptor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace browser_switcher {
+
+namespace {
+
+const char kAValidUrl[] = "http://example.com/";
+const char kAnInvalidUrl[] = "the quick brown fox jumps over the lazy dog";
+
+bool ReturnValidXml(content::URLLoaderInterceptor::RequestParams* params) {
+  std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";
+  std::string xml =
+      "<rules version=\"1\"><docMode><domain docMode=\"9\">"
+      "docs.google.com</domain></docMode></rules>";
+  content::URLLoaderInterceptor::WriteResponse(headers, xml,
+                                               params->client.get());
+  return true;
+}
+
+bool FailToDownload(content::URLLoaderInterceptor::RequestParams* params) {
+  std::string headers = "HTTP/1.1 500 Internal Server Error\n\n";
+  content::URLLoaderInterceptor::WriteResponse(headers, "",
+                                               params->client.get());
+  return true;
+}
+
+}  // namespace
+
+class BrowserSwitcherServiceTest : public InProcessBrowserTest {
+ public:
+  BrowserSwitcherServiceTest() = default;
+  ~BrowserSwitcherServiceTest() override = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BrowserSwitcherServiceTest);
+};
+
+IN_PROC_BROWSER_TEST_F(BrowserSwitcherServiceTest, NotEnabledByPolicy) {
+  // Only load the IEEM sitelist if the 'use_ie_sitelist' pref is set to true.
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kUseIeSitelist, false);
+  base::RunLoop run_loop;
+  BrowserSwitcherService::SetIeemFetchDelayForTesting(base::TimeDelta());
+  BrowserSwitcherService::SetXmlParsedCallbackForTesting(
+      run_loop.QuitClosure());
+  BrowserSwitcherService::SetIeemSitelistUrlForTesting(GURL(kAValidUrl));
+
+  bool fetch_happened = false;
+  content::URLLoaderInterceptor interceptor(base::BindRepeating(
+      [](bool* happened, content::URLLoaderInterceptor::RequestParams*) {
+        *happened = true;
+        return false;
+      },
+      &fetch_happened));
+
+  // Execute everything and make sure we didn't get to the fetch step.
+  BrowserSwitcherServiceFactory::GetForBrowserContext(browser()->profile());
+  run_loop.Run();
+  EXPECT_FALSE(fetch_happened);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserSwitcherServiceTest, IeemSitelistInvalidUrl) {
+  // Only load the IEEM sitelist if the 'use_ie_sitelist' pref is set to true.
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kUseIeSitelist, false);
+  base::RunLoop run_loop;
+  BrowserSwitcherService::SetIeemFetchDelayForTesting(base::TimeDelta());
+  BrowserSwitcherService::SetXmlParsedCallbackForTesting(
+      run_loop.QuitClosure());
+  BrowserSwitcherService::SetIeemSitelistUrlForTesting(GURL(kAnInvalidUrl));
+
+  bool fetch_happened = false;
+  content::URLLoaderInterceptor interceptor(base::BindRepeating(
+      [](bool* happened, content::URLLoaderInterceptor::RequestParams*) {
+        *happened = true;
+        return false;
+      },
+      &fetch_happened));
+
+  // Execute everything and make sure we didn't get to the fetch step.
+  BrowserSwitcherServiceFactory::GetForBrowserContext(browser()->profile());
+  run_loop.Run();
+  EXPECT_FALSE(fetch_happened);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserSwitcherServiceTest, FetchAndParseAfterStartup) {
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kUseIeSitelist, true);
+  base::RunLoop run_loop;
+  BrowserSwitcherService::SetIeemFetchDelayForTesting(base::TimeDelta());
+  BrowserSwitcherService::SetXmlParsedCallbackForTesting(
+      run_loop.QuitClosure());
+  BrowserSwitcherService::SetIeemSitelistUrlForTesting(GURL(kAValidUrl));
+
+  content::URLLoaderInterceptor interceptor(
+      base::BindRepeating(ReturnValidXml));
+
+  // Execute everything and make sure the rules are applied correctly.
+  auto* service =
+      BrowserSwitcherServiceFactory::GetForBrowserContext(browser()->profile());
+  run_loop.Run();
+  EXPECT_FALSE(service->sitelist()->ShouldSwitch(GURL("http://google.com/")));
+  EXPECT_TRUE(
+      service->sitelist()->ShouldSwitch(GURL("http://docs.google.com/")));
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserSwitcherServiceTest, IgnoresFailedDownload) {
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kUseIeSitelist, true);
+  base::RunLoop run_loop;
+  BrowserSwitcherService::SetIeemFetchDelayForTesting(base::TimeDelta());
+  BrowserSwitcherService::SetXmlParsedCallbackForTesting(
+      run_loop.QuitClosure());
+  BrowserSwitcherService::SetIeemSitelistUrlForTesting(GURL(kAValidUrl));
+
+  content::URLLoaderInterceptor interceptor(
+      base::BindRepeating(FailToDownload));
+
+  // Execute everything and make sure no rules are applied.
+  auto* service =
+      BrowserSwitcherServiceFactory::GetForBrowserContext(browser()->profile());
+  run_loop.Run();
+  EXPECT_FALSE(service->sitelist()->ShouldSwitch(GURL("http://google.com/")));
+  EXPECT_FALSE(
+      service->sitelist()->ShouldSwitch(GURL("http://docs.google.com/")));
+}
+
+}  // namespace browser_switcher
diff --git a/chrome/browser/browser_switcher/browser_switcher_service_factory.cc b/chrome/browser/browser_switcher/browser_switcher_service_factory.cc
index fdab6cb..727e3b7 100644
--- a/chrome/browser/browser_switcher/browser_switcher_service_factory.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_service_factory.cc
@@ -35,8 +35,7 @@
 
 KeyedService* BrowserSwitcherServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-  return new BrowserSwitcherService(
-      Profile::FromBrowserContext(context)->GetPrefs());
+  return new BrowserSwitcherService(Profile::FromBrowserContext(context));
 }
 
 content::BrowserContext* BrowserSwitcherServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/browser_switcher/ieem_sitelist_parser.cc b/chrome/browser/browser_switcher/ieem_sitelist_parser.cc
index 4ba28b5..5c6889d 100644
--- a/chrome/browser/browser_switcher/ieem_sitelist_parser.cc
+++ b/chrome/browser/browser_switcher/ieem_sitelist_parser.cc
@@ -127,7 +127,7 @@
   }
 }
 
-void RawXmlParsed(ParseIeemXmlCallback callback,
+void RawXmlParsed(base::OnceCallback<void(ParsedXml)> callback,
                   std::unique_ptr<base::Value> xml,
                   const base::Optional<std::string>& error) {
   if (error) {
@@ -163,7 +163,8 @@
       error(std::move(error_)) {}
 ParsedXml::~ParsedXml() = default;
 
-void ParseIeemXml(const std::string& xml, ParseIeemXmlCallback callback) {
+void ParseIeemXml(const std::string& xml,
+                  base::OnceCallback<void(ParsedXml)> callback) {
   data_decoder::ParseXml(
       content::ServiceManagerConnection::GetForProcess()->GetConnector(), xml,
       base::BindOnce(&RawXmlParsed, std::move(callback)));
diff --git a/chrome/browser/browser_switcher/ieem_sitelist_parser.h b/chrome/browser/browser_switcher/ieem_sitelist_parser.h
index 96c5193..dabf81f5 100644
--- a/chrome/browser/browser_switcher/ieem_sitelist_parser.h
+++ b/chrome/browser/browser_switcher/ieem_sitelist_parser.h
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/optional.h"
+#include "url/gurl.h"
 
 namespace browser_switcher {
 
@@ -29,12 +30,9 @@
   DISALLOW_COPY_AND_ASSIGN(ParsedXml);
 };
 
-// Callback type for the |ParseIeemXml()| method.
-using ParseIeemXmlCallback = base::OnceCallback<void(ParsedXml)>;
-
 // Parses the XML contained in |xml|, and calls |callback| with the parsed XML
 // result.
-void ParseIeemXml(const std::string& xml, ParseIeemXmlCallback callback);
+void ParseIeemXml(const std::string& xml, base::OnceCallback<void(ParsedXml)>);
 
 }  // namespace browser_switcher
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index f24c232..95c24e9 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -4365,7 +4365,8 @@
     io_data = ProfileIOData::FromResourceContext(resource_context);
   }
 
-  if (io_data && data_reduction_proxy::params::IsEnabledWithNetworkService()) {
+  if (io_data && io_data->data_reduction_proxy_io_data() &&
+      data_reduction_proxy::params::IsEnabledWithNetworkService()) {
     net::HttpRequestHeaders headers;
     data_reduction_proxy::DataReductionProxyRequestOptions* request_options =
         io_data->data_reduction_proxy_io_data()->request_options();
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 2aaf22f..e7de6bf 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -135,6 +135,7 @@
     "//components/language/core/common",
     "//components/login",
     "//components/metrics:serialization",
+    "//components/omnibox/browser",
     "//components/onc",
     "//components/ownership",
     "//components/pairing",
@@ -156,7 +157,6 @@
     "//components/startup_metric_utils/browser:lib",
     "//components/storage_monitor",
     "//components/sync_preferences",
-    "//components/toolbar",
     "//components/tracing:startup_tracing",
     "//components/translate/core/browser:browser",
     "//components/ukm/content",
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
index 0bc42bdd..c7a07af 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -916,6 +916,11 @@
       test_context_handler.last_update_composition_arg().composition_text.text);
   EXPECT_EQ(1, test_context_handler.commit_text_call_count());
 
+  // CommitText should clear the composing text.
+  connection->FinishComposingText();
+  // commit_text_call_count() doesn't change.
+  EXPECT_EQ(1, test_context_handler.commit_text_call_count());
+
   test_context_handler.Reset();
   connection->SetComposingText(text, 0, base::make_optional<gfx::Range>(1, 3));
   EXPECT_EQ(1u, test_context_handler.last_update_composition_arg()
diff --git a/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc b/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
index 280e86a..f7a84765 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
@@ -108,6 +108,7 @@
   if (!ime_engine_->CommitText(input_context_id_,
                                base::UTF16ToUTF8(text).c_str(), &error))
     LOG(ERROR) << "CommitText failed: error=\"" << error << "\"";
+  composing_text_.clear();
 }
 
 void InputConnectionImpl::DeleteSurroundingText(int before, int after) {
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_metrics.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_metrics.cc
index 1182260..bfca555 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_metrics.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_metrics.cc
@@ -34,10 +34,4 @@
                             EASY_UNLOCK_AUTH_EVENT_COUNT);
 }
 
-void RecordEasyUnlockTrialRunEvent(EasyUnlockTrialRunEvent event) {
-  DCHECK_LT(event, EASY_UNLOCK_TRIAL_RUN_EVENT_COUNT);
-  UMA_HISTOGRAM_ENUMERATION("EasyUnlock.TrialRun.Events", event,
-                            EASY_UNLOCK_TRIAL_RUN_EVENT_COUNT);
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_metrics.h b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_metrics.h
index aedbbb1a..5403e69 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_metrics.h
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_metrics.h
@@ -74,20 +74,11 @@
   EASY_UNLOCK_AUTH_EVENT_COUNT  // Must be the last entry.
 };
 
-enum EasyUnlockTrialRunEvent {
-  // A trial run was initiated from the Easy Unlock setup app.
-  EASY_UNLOCK_TRIAL_RUN_EVENT_LAUNCHED = 0,
-  // The user clicked on the lock icon during the trial run.
-  EASY_UNLOCK_TRIAL_RUN_EVENT_CLICKED_LOCK_ICON = 1,
-  EASY_UNLOCK_TRIAL_RUN_EVENT_COUNT  // Must be the last entry.
-};
-
 void RecordEasyUnlockDidUserManuallyUnlockPhone(bool did_unlock);
 void RecordEasyUnlockSigninDuration(const base::TimeDelta& duration);
 void RecordEasyUnlockSigninEvent(EasyUnlockAuthEvent event);
 void RecordEasyUnlockScreenUnlockDuration(const base::TimeDelta& duration);
 void RecordEasyUnlockScreenUnlockEvent(EasyUnlockAuthEvent event);
-void RecordEasyUnlockTrialRunEvent(EasyUnlockTrialRunEvent event);
 
 }  // namespace chromeos
 
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.cc
index a2ff7f5..5c631de 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.cc
@@ -154,8 +154,7 @@
   if (IsLockedState(state_))
     did_see_locked_phone_ = true;
 
-  // No hardlock UI for trial run.
-  if (!is_trial_run_ && hardlock_state_ != NO_HARDLOCK) {
+  if (hardlock_state_ != NO_HARDLOCK) {
     ShowHardlockUI();
     return;
   }
@@ -173,10 +172,7 @@
   proximity_auth::ScreenlockBridge::UserPodCustomIconOptions icon_options;
   icon_options.SetIcon(icon);
 
-  // Don't hardlock on trial run.
-  if (is_trial_run_)
-    icon_options.SetTrialRun();
-  else if (HardlockOnClick(state_))
+  if (HardlockOnClick(state_))
     icon_options.SetHardlockOnClick();
 
   UpdateTooltipOptions(&icon_options);
@@ -215,20 +211,6 @@
     ShowHardlockUI();
 }
 
-void EasyUnlockScreenlockStateHandler::SetTrialRun() {
-  if (is_trial_run_)
-    return;
-  is_trial_run_ = true;
-  RefreshScreenlockState();
-  RecordEasyUnlockTrialRunEvent(EASY_UNLOCK_TRIAL_RUN_EVENT_LAUNCHED);
-}
-
-void EasyUnlockScreenlockStateHandler::RecordClickOnLockIcon() {
-  if (!is_trial_run_)
-    return;
-  RecordEasyUnlockTrialRunEvent(EASY_UNLOCK_TRIAL_RUN_EVENT_CLICKED_LOCK_ICON);
-}
-
 void EasyUnlockScreenlockStateHandler::OnScreenDidLock(
     proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) {
   did_see_locked_phone_ = IsLockedState(state_);
@@ -240,7 +222,6 @@
   if (hardlock_state_ == LOGIN_FAILED)
     hardlock_state_ = NO_HARDLOCK;
   hardlock_ui_shown_ = false;
-  is_trial_run_ = false;
 
   // Upon a successful unlock event, record whether the user's phone was locked
   // at any point while the lock screen was up.
@@ -332,13 +313,9 @@
     proximity_auth::ScreenlockBridge::UserPodCustomIconOptions* icon_options) {
   size_t resource_id = 0;
   base::string16 device_name;
-  if (is_trial_run_ && state_ == ScreenlockState::AUTHENTICATED) {
-    resource_id = IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_INITIAL_AUTHENTICATED;
-  } else {
-    resource_id = GetTooltipResourceId(state_);
-    if (TooltipContainsDeviceType(state_))
-      device_name = GetDeviceName();
-  }
+  resource_id = GetTooltipResourceId(state_);
+  if (TooltipContainsDeviceType(state_))
+    device_name = GetDeviceName();
 
   if (!resource_id)
     return;
@@ -353,8 +330,7 @@
   if (tooltip.empty())
     return;
 
-  bool autoshow_tooltip =
-      is_trial_run_ || state_ != ScreenlockState::AUTHENTICATED;
+  bool autoshow_tooltip = state_ != ScreenlockState::AUTHENTICATED;
   icon_options->SetTooltip(tooltip, autoshow_tooltip);
 }
 
@@ -363,7 +339,7 @@
 }
 
 void EasyUnlockScreenlockStateHandler::UpdateScreenlockAuthType() {
-  if (!is_trial_run_ && hardlock_state_ != NO_HARDLOCK)
+  if (hardlock_state_ != NO_HARDLOCK)
     return;
 
   // Do not override online signin.
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.h b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.h
index d4bd62cf..4398b65 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.h
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.h
@@ -62,13 +62,6 @@
   // Shows the hardlock UI if the hardlock_state_ is not NO_HARDLOCK.
   void MaybeShowHardlockUI();
 
-  // Marks the current screenlock state as the one for trial Easy Unlock run.
-  void SetTrialRun();
-
-  // Records that the user clicked on the lock icon during the trial run
-  // initiated by the Easy Unlock app.
-  void RecordClickOnLockIcon();
-
   proximity_auth::ScreenlockState state() const { return state_; }
 
  private:
@@ -104,11 +97,6 @@
   HardlockState hardlock_state_;
   bool hardlock_ui_shown_ = false;
 
-  // Whether this is the trial Easy Unlock run. If this is the case, a
-  // tutorial message should be shown and hard-locking be disabled. The trial
-  // run should be set if the screen was locked by the Easy Unlock setup app.
-  bool is_trial_run_ = false;
-
   // Whether the user's phone was ever locked while on the current lock screen.
   bool did_see_locked_phone_ = false;
 
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler_unittest.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler_unittest.cc
index 30013ef..bd39a71 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler_unittest.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler_unittest.cc
@@ -246,25 +246,6 @@
   std::unique_ptr<TestLockHandler> lock_handler_;
 };
 
-TEST_F(EasyUnlockScreenlockStateHandlerTest, AuthenticatedTrialRun) {
-  state_handler_->SetTrialRun();
-  state_handler_->ChangeState(ScreenlockState::AUTHENTICATED);
-
-  EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount());
-  EXPECT_EQ(proximity_auth::mojom::AuthType::USER_CLICK,
-            lock_handler_->GetAuthType(account_id_));
-
-  ASSERT_TRUE(lock_handler_->HasCustomIcon());
-  EXPECT_EQ(kUnlockedIconId, lock_handler_->GetCustomIconId());
-  EXPECT_TRUE(lock_handler_->CustomIconHasTooltip());
-  EXPECT_TRUE(lock_handler_->IsCustomIconTooltipAutoshown());
-  EXPECT_FALSE(lock_handler_->CustomIconHardlocksOnClick());
-
-  state_handler_->ChangeState(ScreenlockState::AUTHENTICATED);
-  // Duplicated state change should be ignored.
-  EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount());
-}
-
 TEST_F(EasyUnlockScreenlockStateHandlerTest, AuthenticatedNotInitialRun) {
   state_handler_->ChangeState(ScreenlockState::AUTHENTICATED);
 
@@ -376,26 +357,6 @@
   }
 }
 
-TEST_F(EasyUnlockScreenlockStateHandlerTest, SettingTrialRunUpdatesUI) {
-  state_handler_->ChangeState(ScreenlockState::AUTHENTICATED);
-
-  EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount());
-  EXPECT_EQ(proximity_auth::mojom::AuthType::USER_CLICK,
-            lock_handler_->GetAuthType(account_id_));
-
-  ASSERT_TRUE(lock_handler_->HasCustomIcon());
-  ASSERT_FALSE(lock_handler_->IsCustomIconTooltipAutoshown());
-
-  state_handler_->SetTrialRun();
-
-  EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount());
-  EXPECT_EQ(proximity_auth::mojom::AuthType::USER_CLICK,
-            lock_handler_->GetAuthType(account_id_));
-
-  ASSERT_TRUE(lock_handler_->HasCustomIcon());
-  ASSERT_TRUE(lock_handler_->IsCustomIconTooltipAutoshown());
-}
-
 TEST_F(EasyUnlockScreenlockStateHandlerTest,
        LockScreenClearedOnStateHandlerDestruction) {
   state_handler_->ChangeState(ScreenlockState::AUTHENTICATED);
@@ -457,40 +418,6 @@
   EXPECT_EQ(kSpinnerIconId, lock_handler_->GetCustomIconId());
 }
 
-TEST_F(EasyUnlockScreenlockStateHandlerTest,
-       HardlockEnabledAfterInitialUnlock) {
-  state_handler_->SetTrialRun();
-
-  std::vector<ScreenlockState> states;
-  states.push_back(ScreenlockState::BLUETOOTH_CONNECTING);
-  states.push_back(ScreenlockState::PHONE_NOT_AUTHENTICATED);
-  states.push_back(ScreenlockState::NO_BLUETOOTH);
-  states.push_back(ScreenlockState::NO_PHONE);
-  states.push_back(ScreenlockState::PHONE_UNSUPPORTED);
-  states.push_back(ScreenlockState::PHONE_NOT_LOCKABLE);
-  // This one should go last as changing state to AUTHENTICATED enables hard
-  // locking.
-  states.push_back(ScreenlockState::AUTHENTICATED);
-
-  for (size_t i = 0; i < states.size(); ++i) {
-    SCOPED_TRACE(base::NumberToString(i));
-    state_handler_->ChangeState(states[i]);
-    ASSERT_TRUE(lock_handler_->HasCustomIcon());
-    EXPECT_FALSE(lock_handler_->CustomIconHardlocksOnClick());
-  }
-
-  proximity_auth::ScreenlockBridge::Get()->SetLockHandler(NULL);
-  lock_handler_.reset(new TestLockHandler(account_id_));
-  proximity_auth::ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get());
-
-  for (size_t i = 0; i < states.size(); ++i) {
-    SCOPED_TRACE(base::NumberToString(i));
-    state_handler_->ChangeState(states[i]);
-    ASSERT_TRUE(lock_handler_->HasCustomIcon());
-    EXPECT_TRUE(lock_handler_->CustomIconHardlocksOnClick());
-  }
-}
-
 TEST_F(EasyUnlockScreenlockStateHandlerTest, NoPairingHardlockClearsIcon) {
   state_handler_->ChangeState(ScreenlockState::PHONE_LOCKED);
 
@@ -526,24 +453,6 @@
   EXPECT_EQ(kLockedToBeActivatedIconId, lock_handler_->GetCustomIconId());
 }
 
-TEST_F(EasyUnlockScreenlockStateHandlerTest,
-       PairingChangedHardlockIneffectiveOnInitialRun) {
-  state_handler_->SetTrialRun();
-
-  state_handler_->ChangeState(ScreenlockState::PHONE_LOCKED);
-
-  EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount());
-  ASSERT_TRUE(lock_handler_->HasCustomIcon());
-  EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId());
-
-  state_handler_->SetHardlockState(
-      EasyUnlockScreenlockStateHandler::PAIRING_CHANGED);
-
-  EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount());
-  ASSERT_TRUE(lock_handler_->HasCustomIcon());
-  EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId());
-}
-
 TEST_F(EasyUnlockScreenlockStateHandlerTest, InactiveStateHidesIcon) {
   state_handler_->ChangeState(ScreenlockState::AUTHENTICATED);
 
@@ -719,27 +628,5 @@
   }
 }
 
-TEST_F(EasyUnlockScreenlockStateHandlerTest, TrialRunMetrics) {
-  base::HistogramTester histogram_tester;
-
-  // Simulate the user clicking on the lock icon twice outside of a trial run.
-  // No trial run metrics should be recorded.
-  state_handler_->RecordClickOnLockIcon();
-  state_handler_->RecordClickOnLockIcon();
-  histogram_tester.ExpectTotalCount("EasyUnlock.TrialRun.Events", 0);
-
-  // Simulate the user clicking on the lock icon three times during a trial run.
-  state_handler_->SetTrialRun();
-  state_handler_->RecordClickOnLockIcon();
-  state_handler_->RecordClickOnLockIcon();
-  state_handler_->RecordClickOnLockIcon();
-  histogram_tester.ExpectTotalCount("EasyUnlock.TrialRun.Events", 4);
-  histogram_tester.ExpectBucketCount("EasyUnlock.TrialRun.Events",
-                                     EASY_UNLOCK_TRIAL_RUN_EVENT_LAUNCHED, 1);
-  histogram_tester.ExpectBucketCount(
-      "EasyUnlock.TrialRun.Events",
-      EASY_UNLOCK_TRIAL_RUN_EVENT_CLICKED_LOCK_ICON, 3);
-}
-
 }  // namespace
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
index 496e927e..e98eb24 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
@@ -494,19 +494,6 @@
                  weak_ptr_factory_.GetWeakPtr(), account_id, paired_devices));
 }
 
-void EasyUnlockService::SetTrialRun() {
-  DCHECK_EQ(GetType(), TYPE_REGULAR);
-
-  EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
-  if (handler)
-    handler->SetTrialRun();
-}
-
-void EasyUnlockService::RecordClickOnLockIcon() {
-  if (screenlock_state_handler_)
-    screenlock_state_handler_->RecordClickOnLockIcon();
-}
-
 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h
index 9211746..801ba9a1 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h
@@ -183,14 +183,6 @@
   // hardlock state if the two do not match.
   void CheckCryptohomeKeysAndMaybeHardlock();
 
-  // Marks the Easy Unlock screen lock state as the one associated with the
-  // trial run initiated by Easy Unlock app.
-  void SetTrialRun();
-
-  // Records that the user clicked on the lock icon during the trial run
-  // initiated by the Easy Unlock app.
-  void RecordClickOnLockIcon();
-
   // Called when the user reauths (e.g. in chrome://settings) so we can cache
   // the user context for the setup flow.
   virtual void HandleUserReauth(const UserContext& user_context);
diff --git a/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc b/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
index f0b68ad5..487b42a 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
@@ -63,6 +63,7 @@
         .WillRepeatedly(Return(mock_user_manager_->CreatePublicAccountUser(
             auto_login_account_id_)));
 
+    settings_helper_.ReplaceDeviceSettingsProviderWithStub();
     settings_helper_.SetFakeSessionManager();
 
     std::unique_ptr<base::DictionaryValue> account(new base::DictionaryValue);
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.cc b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
index 92e1857..30d922b 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
@@ -252,11 +252,6 @@
   user_selection_screen_->HardLockPod(account_id);
 }
 
-void ViewsScreenLocker::HandleRecordClickOnLockIcon(
-    const AccountId& account_id) {
-  user_selection_screen_->RecordClickOnLockIcon(account_id);
-}
-
 void ViewsScreenLocker::HandleOnFocusPod(const AccountId& account_id) {
   proximity_auth::ScreenlockBridge::Get()->SetFocusedUser(account_id);
   if (user_selection_screen_)
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.h b/chrome/browser/chromeos/login/lock/views_screen_locker.h
index d292646..e330bd2 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.h
@@ -68,7 +68,6 @@
   void HandleAuthenticateUserWithEasyUnlock(
       const AccountId& account_id) override;
   void HandleHardlockPod(const AccountId& account_id) override;
-  void HandleRecordClickOnLockIcon(const AccountId& account_id) override;
   void HandleOnFocusPod(const AccountId& account_id) override;
   void HandleOnNoPodFocused() override;
   bool HandleFocusLockScreenApps(bool reverse) override;
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
index 533ff0d9..bdc13b52 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -752,13 +752,6 @@
   service->AttemptAuth(account_id);
 }
 
-void UserSelectionScreen::RecordClickOnLockIcon(const AccountId& account_id) {
-  EasyUnlockService* service = GetEasyUnlockServiceForUser(account_id);
-  if (!service)
-    return;
-  service->RecordClickOnLockIcon();
-}
-
 std::unique_ptr<base::ListValue>
 UserSelectionScreen::UpdateAndReturnUserListForWebUI() {
   std::unique_ptr<base::ListValue> users_list =
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.h b/chrome/browser/chromeos/login/screens/user_selection_screen.h
index 44685ab..83cd0700 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.h
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.h
@@ -63,7 +63,6 @@
   // Methods for easy unlock support.
   void HardLockPod(const AccountId& account_id);
   void AttemptEasyUnlock(const AccountId& account_id);
-  void RecordClickOnLockIcon(const AccountId& account_id);
 
   // ui::UserActivityDetector implementation:
   void OnUserActivity(const ui::Event* event) override;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
index c661f18..dfc84bd 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -395,11 +395,6 @@
   user_selection_screen_->HardLockPod(account_id);
 }
 
-void LoginDisplayHostMojo::HandleRecordClickOnLockIcon(
-    const AccountId& account_id) {
-  user_selection_screen_->RecordClickOnLockIcon(account_id);
-}
-
 void LoginDisplayHostMojo::HandleOnFocusPod(const AccountId& account_id) {
   // TODO(jdufault): Share common code between this and
   // ViewsScreenLocker::HandleOnFocusPod See https://crbug.com/831787.
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
index 05ed24fd..01b220f 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
@@ -111,7 +111,6 @@
   void HandleAuthenticateUserWithEasyUnlock(
       const AccountId& account_id) override;
   void HandleHardlockPod(const AccountId& account_id) override;
-  void HandleRecordClickOnLockIcon(const AccountId& account_id) override;
   void HandleOnFocusPod(const AccountId& account_id) override;
   void HandleOnNoPodFocused() override;
   bool HandleFocusLockScreenApps(bool reverse) override;
diff --git a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
index a5f08f7..4e8798e 100644
--- a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
+++ b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
@@ -21,9 +21,9 @@
 #include "chrome/browser/ui/views/toolbar/reload_button.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/toolbar_model_impl.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/chromeos/login/user_board_view_mojo.cc b/chrome/browser/chromeos/login/user_board_view_mojo.cc
index 3622ada..c3a8fd3 100644
--- a/chrome/browser/chromeos/login/user_board_view_mojo.cc
+++ b/chrome/browser/chromeos/login/user_board_view_mojo.cc
@@ -56,9 +56,6 @@
   if (icon_options.hardlock_on_click())
     options->hardlock_on_click = true;
 
-  if (icon_options.is_trial_run())
-    options->is_trial_run = true;
-
   return options;
 }
 
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index 7180637..1de6b520f 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -165,6 +165,7 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(switches::kOobeSkipPostLogin);
     command_line->AppendSwitch(::switches::kUseFakeDeviceForMediaStream);
+    command_line->AppendSwitch(switches::kStubCrosSettings);
     OobeBaseTest::SetUpCommandLine(command_line);
   }
 
diff --git a/chrome/browser/chromeos/settings/cros_settings.cc b/chrome/browser/chromeos/settings/cros_settings.cc
index c10eae3..a278583 100644
--- a/chrome/browser/chromeos/settings/cros_settings.cc
+++ b/chrome/browser/chromeos/settings/cros_settings.cc
@@ -68,9 +68,14 @@
       base::Bind(&CrosSettings::FireObservers,
                  // This is safe since |this| is never deleted.
                  base::Unretained(this)));
+
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kStubCrosSettings)) {
-    AddSettingsProvider(std::make_unique<StubCrosSettingsProvider>(notify_cb));
+    std::unique_ptr<StubCrosSettingsProvider> stubbed_provider =
+        std::make_unique<StubCrosSettingsProvider>(notify_cb);
+    stubbed_provider_ptr_ = stubbed_provider.get();
+    AddSettingsProvider(std::move(stubbed_provider));
+
   } else {
     AddSettingsProvider(std::make_unique<DeviceSettingsProvider>(
         notify_cb, device_settings_service, local_state));
diff --git a/chrome/browser/chromeos/settings/cros_settings.h b/chrome/browser/chromeos/settings/cros_settings.h
index ff37ea6..c982df8 100644
--- a/chrome/browser/chromeos/settings/cros_settings.h
+++ b/chrome/browser/chromeos/settings/cros_settings.h
@@ -28,6 +28,7 @@
 namespace chromeos {
 
 class DeviceSettingsService;
+class StubCrosSettingsProvider;
 
 // This class manages per-device/global settings.
 class CrosSettings {
@@ -129,6 +130,12 @@
   // Returns the provider that handles settings with the |path| or prefix.
   CrosSettingsProvider* GetProvider(const std::string& path) const;
 
+  // Returns the StubCrosSettingsProvider. Returns |nullptr| unless the
+  // kStubCrosSettings switch is set, which is only true during testing.
+  StubCrosSettingsProvider* stubbed_provider_for_test() const {
+    return stubbed_provider_ptr_;
+  }
+
  private:
   friend class CrosSettingsTest;
 
@@ -138,6 +145,9 @@
   // List of ChromeOS system settings providers.
   std::vector<std::unique_ptr<CrosSettingsProvider>> providers_;
 
+  // A stubbed provider - only used if the kStubCrosSettings switch is set.
+  StubCrosSettingsProvider* stubbed_provider_ptr_ = nullptr;
+
   // A map from settings names to a list of observers. Observers get fired in
   // the order they are added.
   std::map<std::string, std::unique_ptr<base::CallbackList<void(void)>>>
diff --git a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.cc b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.cc
index 5c226052..0a051387 100644
--- a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.cc
+++ b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.cc
@@ -41,10 +41,15 @@
 }
 
 void ScopedCrosSettingsTestHelper::ReplaceDeviceSettingsProviderWithStub() {
-  CHECK(!real_settings_provider_);
-  // Swap out the DeviceSettingsProvider with our settings provider.
+  CHECK(CrosSettings::IsInitialized());
   CrosSettings* const cros_settings = CrosSettings::Get();
 
+  // If CrosSettings is already using a stub, then we shouldn't be replacing it
+  // with a different stub - that would be confusing and unnecessary.
+  CHECK(!cros_settings->stubbed_provider_for_test());
+  // And, this function shouldn't be called twice either, for the same reason:
+  CHECK(!real_settings_provider_);
+
   // TODO(olsen): This could be simplified if DeviceSettings and CrosSettings
   // were the same thing, which they nearly are, except for 3 timezone settings.
   CrosSettingsProvider* real_settings_provider =
@@ -68,31 +73,30 @@
   real_settings_provider_.reset();
 }
 
-bool ScopedCrosSettingsTestHelper::IsDeviceSettingsProviderStubbed() {
-  return !!real_settings_provider_;
+StubCrosSettingsProvider* ScopedCrosSettingsTestHelper::GetStubbedProvider() {
+  // If CrosSettings was already initialized with kStubCrosSettings, then
+  // we use the StubCrosSettingsProvider that was already initialized:
+  if (CrosSettings::IsInitialized() &&
+      CrosSettings::Get()->stubbed_provider_for_test()) {
+    return CrosSettings::Get()->stubbed_provider_for_test();
+  }
+  // Otherwise, we use this one - it has to be explicitly swapped in using
+  // ReplaceDeviceSettingsProviderWithStub() however.
+  return stub_settings_provider_ptr_;
 }
 
 void ScopedCrosSettingsTestHelper::SetTrustedStatus(
     CrosSettingsProvider::TrustedStatus status) {
-  stub_settings_provider_ptr_->SetTrustedStatus(status);
+  GetStubbedProvider()->SetTrustedStatus(status);
 }
 
 void ScopedCrosSettingsTestHelper::SetCurrentUserIsOwner(bool owner) {
-  stub_settings_provider_ptr_->SetCurrentUserIsOwner(owner);
+  GetStubbedProvider()->SetCurrentUserIsOwner(owner);
 }
 
 void ScopedCrosSettingsTestHelper::Set(const std::string& path,
                                        const base::Value& in_value) {
-  CHECK(DeviceSettingsProvider::IsDeviceSetting(path));
-  if (IsDeviceSettingsProviderStubbed()) {
-    // Set in the stub settings provider.
-    stub_settings_provider_ptr_->Set(path, in_value);
-  } else {
-    // Set in the real settings provider.
-    // TODO(olsen): Separate the write path (OwnerSettingsService) away from the
-    // read path (CrosSettings) - http://crbug.com/433840
-    CrosSettings::Get()->Set(path, in_value);
-  }
+  GetStubbedProvider()->Set(path, in_value);
 }
 
 void ScopedCrosSettingsTestHelper::SetBoolean(const std::string& path,
diff --git a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
index a675692..52d5249 100644
--- a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
+++ b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
@@ -46,7 +46,20 @@
   std::unique_ptr<FakeOwnerSettingsService> CreateOwnerSettingsService(
       Profile* profile);
 
-  // These methods simply call the according |stub_settings_provider_| method.
+  // Returns the stubbed CrosSettingsProvider - either the one that was
+  // initialized by |CrosSettings::Initialize()| (that is, if the switch
+  // |kStubCrosSettings| is set). Or, if CrosSettings was not initialized with
+  // a stub, this returns a stub that is only swapped into |CrosSettings| once
+  // |ReplaceDeviceSettingsProviderWithStub()| is called.
+  // Note that if you want to test the real DeviceSettingsProvider in your test
+  // (not a stub), you should set the settings using the OwnerSettingsService
+  // which uses the current user's private key to sign the settings.
+  StubCrosSettingsProvider* GetStubbedProvider();
+
+  // These methods simply call the appropriate method on |GetStubbedProvider()|.
+  // So if you use them, you need to make sure that a stubbed provider is used
+  // in your test - either by setting |kStubCrosSettings| switch or by calling
+  // |ReplaceDeviceSettingsProviderWithStub()|.
   void SetTrustedStatus(CrosSettingsProvider::TrustedStatus status);
   void SetCurrentUserIsOwner(bool owner);
   void Set(const std::string& path, const base::Value& in_value);
diff --git a/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc b/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
index 340f2a8..3f97252c 100644
--- a/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
@@ -65,7 +65,7 @@
 
 class DevToolsManagerDelegateTest : public InProcessBrowserTest {
  public:
-  void SendCommand(std::string state) {
+  void SendCommand(const std::string& state) {
     auto window_bounds =
         protocol::Browser::Bounds::Create().SetWindowState(state).Build();
     BrowserHandler handler(nullptr);
diff --git a/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc b/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
index 843f3fbb..3712535 100644
--- a/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
+++ b/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
@@ -72,15 +72,6 @@
   chromeos::EasyUnlockService* service =
       chromeos::EasyUnlockService::Get(GetProfile());
   if (params->locked) {
-    if (extension()->id() == extension_misc::kEasyUnlockAppId &&
-        AppWindowRegistry::Get(browser_context())
-            ->GetAppWindowForAppAndKey(extension()->id(),
-                                       "easy_unlock_pairing")) {
-      // Mark the Easy Unlock behaviour on the lock screen as the one initiated
-      // by the Easy Unlock setup app as a trial one.
-      // TODO(tbarzic): Move this logic to a new easyUnlockPrivate function.
-      service->SetTrialRun();
-    }
     proximity_auth::ScreenlockBridge::Get()->Lock();
   } else {
     proximity_auth::ScreenlockBridge::Get()->Unlock(AccountId::FromUserEmail(
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index f57e804c6..7b8a83fe 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2858,6 +2858,12 @@
 
 #if defined(OS_WIN)
 
+const char kCalculateNativeWinOcclusionName[] =
+    "Calculate window occlusion on Windows";
+const char kCalculateNativeWinOcclusionDescription[] =
+    "Calculate window occlusion on Windows will be used in the future "
+    "to throttle and potentially unload foreground tabs in occluded windows";
+
 const char kCloudPrintXpsName[] = "XPS in Google Cloud Print";
 const char kCloudPrintXpsDescription[] =
     "XPS enables advanced options for classic printers connected to the Cloud "
@@ -3173,6 +3179,11 @@
 const char kEnableAppShortcutSearchDescription[] =
     "Enables app shortcut search in launcher";
 
+const char kEnableAppDataSearchName[] = "Enable app data search in launcher";
+const char kEnableAppDataSearchDescription[] =
+    "Allow launcher search to access data available through Firebase App "
+    "Indexing";
+
 const char kEnableAppsGridGapFeatureName[] =
     "Enable apps grid gap feature in launcher.";
 const char kEnableAppsGridGapFeatureDescription[] =
@@ -3275,6 +3286,10 @@
     "Chrome OS system timezone preference is stored and handled for each user "
     "individually.";
 
+const char kEnablePlayStoreSearchName[] = "Enable Play Store search";
+const char kEnablePlayStoreSearchDescription[] =
+    "Enable Play Store search in launcher.";
+
 const char kEnableSettingsShortcutSearchName[] =
     "Enable Settings shortcut search";
 const char kEnableSettingsShortcutSearchDescription[] =
@@ -3309,7 +3324,7 @@
 const char kEnableZeroStateSuggestionsName[] = "Enable Zero State Suggetions";
 const char kEnableZeroStateSuggestionsDescription[] =
     "Enable Zero State Suggestions feature in Launcher, which will show "
-    "suggetions when launcher search box is active with an empty query";
+    "suggestions when launcher search box is active with an empty query";
 
 const char kEolNotificationName[] = "Disable Device End of Life notification.";
 const char kEolNotificationDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 9de89c4..58c69d73 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1720,6 +1720,9 @@
 
 #if defined(OS_WIN)
 
+extern const char kCalculateNativeWinOcclusionName[];
+extern const char kCalculateNativeWinOcclusionDescription[];
+
 extern const char kCloudPrintXpsName[];
 extern const char kCloudPrintXpsDescription[];
 
@@ -1933,6 +1936,9 @@
 extern const char kEnableAppShortcutSearchName[];
 extern const char kEnableAppShortcutSearchDescription[];
 
+extern const char kEnableAppDataSearchName[];
+extern const char kEnableAppDataSearchDescription[];
+
 extern const char kEnableAppsGridGapFeatureName[];
 extern const char kEnableAppsGridGapFeatureDescription[];
 
@@ -1993,6 +1999,9 @@
 extern const char kEnablePerUserTimezoneName[];
 extern const char kEnablePerUserTimezoneDescription[];
 
+extern const char kEnablePlayStoreSearchName[];
+extern const char kEnablePlayStoreSearchDescription[];
+
 extern const char kEnableSettingsShortcutSearchName[];
 extern const char kEnableSettingsShortcutSearchDescription[];
 
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc
index 16935711..2aa6bef0 100644
--- a/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc
+++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc
@@ -150,10 +150,12 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  std::string GetBody() {
+  std::string GetBody() { return GetBody(browser()); }
+
+  std::string GetBody(Browser* browser) {
     std::string body;
     EXPECT_TRUE(content::ExecuteScriptAndExtractString(
-        browser()->tab_strip_model()->GetActiveWebContents(),
+        browser->tab_strip_model()->GetActiveWebContents(),
         "window.domAutomationController.send(document.body.textContent);",
         &body));
     return body;
@@ -245,6 +247,35 @@
   EXPECT_THAT(body, HasSubstr("pid="));
 }
 
+IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest, DisabledOnIncognito) {
+  net::EmbeddedTestServer test_server;
+  test_server.RegisterRequestHandler(
+      base::BindRepeating(&BasicResponse, kDummyBody));
+  ASSERT_TRUE(test_server.Start());
+
+  Browser* incognito = CreateIncognitoBrowser();
+  ui_test_utils::NavigateToURL(
+      incognito, GetURLWithMockHost(test_server, "/echoheader?Chrome-Proxy"));
+  EXPECT_EQ(GetBody(incognito), kDummyBody);
+
+  // Make sure subresource doesn't use DRP either.
+  std::string script = R"((url => {
+    var xhr = new XMLHttpRequest();
+    xhr.open('GET', url, true);
+    xhr.onload = () => domAutomationController.send(xhr.responseText);
+    xhr.send();
+  }))";
+  std::string result;
+  ASSERT_TRUE(ExecuteScriptAndExtractString(
+      incognito->tab_strip_model()->GetActiveWebContents(),
+      script + "('" +
+          GetURLWithMockHost(test_server, "/echoheader?Chrome-Proxy").spec() +
+          "')",
+      &result));
+
+  EXPECT_EQ(result, kDummyBody);
+}
+
 IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest,
                        ChromeProxyHeaderSetForSubresource) {
   net::EmbeddedTestServer test_server;
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
index 83d4f7e..e6186ae 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
@@ -93,6 +93,10 @@
     "PageLoad.Experimental.PaintTiming.NavigationToLargestImagePaint";
 const char kHistogramLastImagePaint[] =
     "PageLoad.Experimental.PaintTiming.NavigationToLastImagePaint";
+const char kHistogramLargestTextPaint[] =
+    "PageLoad.Experimental.PaintTiming.NavigationToLargestTextPaint";
+const char kHistogramLastTextPaint[] =
+    "PageLoad.Experimental.PaintTiming.NavigationToLastTextPaint";
 const char kHistogramTimeToInteractive[] =
     "PageLoad.Experimental.NavigationToInteractive";
 const char kHistogramInteractiveToInteractiveDetection[] =
@@ -547,6 +551,31 @@
   }
 }
 
+void CorePageLoadMetricsObserver::OnLargestTextPaintInMainFrameDocument(
+    const page_load_metrics::mojom::PageLoadTiming& timing,
+    const page_load_metrics::PageLoadExtraInfo& info) {
+  base::Optional<base::TimeDelta>& largest_text_paint =
+      timing.paint_timing->largest_text_paint;
+  if (largest_text_paint.has_value() &&
+      WasStartedInForegroundOptionalEventInForeground(largest_text_paint,
+                                                      info)) {
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramLargestTextPaint,
+                        largest_text_paint.value());
+  }
+}
+
+void CorePageLoadMetricsObserver::OnLastTextPaintInMainFrameDocument(
+    const page_load_metrics::mojom::PageLoadTiming& timing,
+    const page_load_metrics::PageLoadExtraInfo& info) {
+  base::Optional<base::TimeDelta>& last_text_paint =
+      timing.paint_timing->last_text_paint;
+  if (last_text_paint.has_value() &&
+      WasStartedInForegroundOptionalEventInForeground(last_text_paint, info)) {
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramLastTextPaint,
+                        last_text_paint.value());
+  }
+}
+
 void CorePageLoadMetricsObserver::OnPageInteractive(
     const page_load_metrics::mojom::PageLoadTiming& timing,
     const page_load_metrics::PageLoadExtraInfo& info) {
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
index 1dfe1f2..76e3752 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
@@ -27,6 +27,8 @@
 extern const char kHistogramFirstMeaningfulPaint[];
 extern const char kHistogramLargestImagePaint[];
 extern const char kHistogramLastImagePaint[];
+extern const char kHistogramLargestTextPaint[];
+extern const char kHistogramLastTextPaint[];
 extern const char kHistogramTimeToInteractive[];
 extern const char kHistogramParseDuration[];
 extern const char kHistogramParseBlockedOnScriptLoad[];
@@ -218,6 +220,12 @@
   void OnLastImagePaintInMainFrameDocument(
       const page_load_metrics::mojom::PageLoadTiming& timing,
       const page_load_metrics::PageLoadExtraInfo& info) override;
+  void OnLargestTextPaintInMainFrameDocument(
+      const page_load_metrics::mojom::PageLoadTiming& timing,
+      const page_load_metrics::PageLoadExtraInfo& info) override;
+  void OnLastTextPaintInMainFrameDocument(
+      const page_load_metrics::mojom::PageLoadTiming& timing,
+      const page_load_metrics::PageLoadExtraInfo& info) override;
 
  private:
   void RecordTimingHistograms(
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
index 16bf154..4db79d7 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
@@ -826,6 +826,44 @@
   histogram_tester().ExpectTotalCount(internal::kHistogramLastImagePaint, 0);
 }
 
+TEST_F(CorePageLoadMetricsObserverTest, LargestTextPaint) {
+  page_load_metrics::mojom::PageLoadTiming timing;
+  page_load_metrics::InitPageLoadTimingForTest(&timing);
+  timing.navigation_start = base::Time::FromDoubleT(1);
+  // Pick a value that lines up with a histogram bucket.
+  timing.paint_timing->largest_text_paint =
+      base::TimeDelta::FromMilliseconds(4780);
+  PopulateRequiredTimingFields(&timing);
+
+  NavigateAndCommit(GURL(kDefaultTestUrl));
+  SimulateTimingUpdate(timing);
+  // Navigate again to force histogram recording.
+  NavigateAndCommit(GURL(kDefaultTestUrl2));
+
+  EXPECT_THAT(
+      histogram_tester().GetAllSamples(internal::kHistogramLargestTextPaint),
+      testing::ElementsAre(base::Bucket(4780, 1)));
+}
+
+TEST_F(CorePageLoadMetricsObserverTest, LastTextPaint) {
+  page_load_metrics::mojom::PageLoadTiming timing;
+  page_load_metrics::InitPageLoadTimingForTest(&timing);
+  timing.navigation_start = base::Time::FromDoubleT(1);
+  // Pick a value that lines up with a histogram bucket.
+  timing.paint_timing->last_text_paint =
+      base::TimeDelta::FromMilliseconds(4780);
+  PopulateRequiredTimingFields(&timing);
+
+  NavigateAndCommit(GURL(kDefaultTestUrl));
+  SimulateTimingUpdate(timing);
+  // Navigate again to force histogram recording.
+  NavigateAndCommit(GURL(kDefaultTestUrl2));
+
+  EXPECT_THAT(
+      histogram_tester().GetAllSamples(internal::kHistogramLastTextPaint),
+      testing::ElementsAre(base::Bucket(4780, 1)));
+}
+
 TEST_F(CorePageLoadMetricsObserverTest, ForegroundToFirstMeaningfulPaint) {
   page_load_metrics::mojom::PageLoadTiming timing;
   page_load_metrics::InitPageLoadTimingForTest(&timing);
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
index 33ccc6ba..72bf521 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
@@ -177,6 +177,18 @@
     builder.SetExperimental_PaintTiming_NavigationToLastImagePaint(
         timing.paint_timing->last_image_paint.value().InMilliseconds());
   }
+  if (timing.paint_timing->largest_text_paint.has_value() &&
+      WasStartedInForegroundOptionalEventInForeground(
+          timing.paint_timing->largest_text_paint, info)) {
+    builder.SetExperimental_PaintTiming_NavigationToLargestTextPaint(
+        timing.paint_timing->largest_text_paint.value().InMilliseconds());
+  }
+  if (timing.paint_timing->last_text_paint.has_value() &&
+      WasStartedInForegroundOptionalEventInForeground(
+          timing.paint_timing->last_text_paint, info)) {
+    builder.SetExperimental_PaintTiming_NavigationToLastTextPaint(
+        timing.paint_timing->last_text_paint.value().InMilliseconds());
+  }
   if (timing.interactive_timing->interactive) {
     base::TimeDelta time_to_interactive =
         timing.interactive_timing->interactive.value();
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
index 0beaf8a3..4bfc962 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
@@ -316,7 +316,7 @@
   }
 }
 
-TEST_F(UkmPageLoadMetricsObserverTest, LastImagePaint_DiscardBackgroundResult) {
+TEST_F(UkmPageLoadMetricsObserverTest, FCPPlusPlus_DiscardBackgroundResult) {
   page_load_metrics::mojom::PageLoadTiming timing;
   page_load_metrics::InitPageLoadTimingForTest(&timing);
 
@@ -325,7 +325,10 @@
   web_contents()->WasHidden();
   // Set a large enough value to make sure it will be larger than background
   // time, so that the result will be discarded.
+  timing.paint_timing->largest_image_paint = base::TimeDelta::FromSeconds(10);
   timing.paint_timing->last_image_paint = base::TimeDelta::FromSeconds(10);
+  timing.paint_timing->last_text_paint = base::TimeDelta::FromSeconds(10);
+  timing.paint_timing->largest_text_paint = base::TimeDelta::FromSeconds(10);
   NavigateAndCommit(GURL(kTestUrl1));
   SimulateTimingUpdate(timing);
 
@@ -337,7 +340,7 @@
   EXPECT_EQ(0ul, merged_entries.size());
 }
 
-TEST_F(UkmPageLoadMetricsObserverTest, LastImagePaint_ReportLastCandidate) {
+TEST_F(UkmPageLoadMetricsObserverTest, FCPPlusPlus_ReportLastCandidate) {
   page_load_metrics::mojom::PageLoadTiming timing;
   page_load_metrics::InitPageLoadTimingForTest(&timing);
   timing.navigation_start = base::Time::FromDoubleT(1);
@@ -346,10 +349,20 @@
 
   NavigateAndCommit(GURL(kTestUrl1));
   timing.paint_timing->last_image_paint = base::TimeDelta::FromMilliseconds(60);
+  timing.paint_timing->largest_image_paint =
+      base::TimeDelta::FromMilliseconds(60);
+  timing.paint_timing->last_text_paint = base::TimeDelta::FromMilliseconds(60);
+  timing.paint_timing->largest_text_paint =
+      base::TimeDelta::FromMilliseconds(60);
   SimulateTimingUpdate(timing);
 
   timing.paint_timing->last_image_paint =
       base::TimeDelta::FromMilliseconds(600);
+  timing.paint_timing->largest_image_paint =
+      base::TimeDelta::FromMilliseconds(600);
+  timing.paint_timing->last_text_paint = base::TimeDelta::FromMilliseconds(600);
+  timing.paint_timing->largest_text_paint =
+      base::TimeDelta::FromMilliseconds(600);
   SimulateTimingUpdate(timing);
 
   // Simulate closing the tab.
@@ -366,6 +379,75 @@
         kv.second.get(),
         PageLoad::kExperimental_PaintTiming_NavigationToLastImagePaintName,
         600);
+    test_ukm_recorder().ExpectEntryMetric(
+        kv.second.get(),
+        PageLoad::kExperimental_PaintTiming_NavigationToLargestImagePaintName,
+        600);
+    test_ukm_recorder().ExpectEntryMetric(
+        kv.second.get(),
+        PageLoad::kExperimental_PaintTiming_NavigationToLastTextPaintName, 600);
+    test_ukm_recorder().ExpectEntryMetric(
+        kv.second.get(),
+        PageLoad::kExperimental_PaintTiming_NavigationToLargestTextPaintName,
+        600);
+    EXPECT_TRUE(test_ukm_recorder().EntryHasMetric(
+        kv.second.get(), PageLoad::kPageTiming_ForegroundDurationName));
+  }
+}
+
+TEST_F(UkmPageLoadMetricsObserverTest, LargestTextPaint) {
+  page_load_metrics::mojom::PageLoadTiming timing;
+  page_load_metrics::InitPageLoadTimingForTest(&timing);
+  timing.navigation_start = base::Time::FromDoubleT(1);
+  timing.paint_timing->largest_text_paint =
+      base::TimeDelta::FromMilliseconds(600);
+  PopulateRequiredTimingFields(&timing);
+
+  NavigateAndCommit(GURL(kTestUrl1));
+  SimulateTimingUpdate(timing);
+
+  // Simulate closing the tab.
+  DeleteContents();
+
+  std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+      test_ukm_recorder().GetMergedEntriesByName(PageLoad::kEntryName);
+  EXPECT_EQ(1ul, merged_entries.size());
+
+  for (const auto& kv : merged_entries) {
+    test_ukm_recorder().ExpectEntrySourceHasUrl(kv.second.get(),
+                                                GURL(kTestUrl1));
+    test_ukm_recorder().ExpectEntryMetric(
+        kv.second.get(),
+        PageLoad::kExperimental_PaintTiming_NavigationToLargestTextPaintName,
+        600);
+    EXPECT_TRUE(test_ukm_recorder().EntryHasMetric(
+        kv.second.get(), PageLoad::kPageTiming_ForegroundDurationName));
+  }
+}
+
+TEST_F(UkmPageLoadMetricsObserverTest, LastTextPaint) {
+  page_load_metrics::mojom::PageLoadTiming timing;
+  page_load_metrics::InitPageLoadTimingForTest(&timing);
+  timing.navigation_start = base::Time::FromDoubleT(1);
+  timing.paint_timing->last_text_paint = base::TimeDelta::FromMilliseconds(600);
+  PopulateRequiredTimingFields(&timing);
+
+  NavigateAndCommit(GURL(kTestUrl1));
+  SimulateTimingUpdate(timing);
+
+  // Simulate closing the tab.
+  DeleteContents();
+
+  std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+      test_ukm_recorder().GetMergedEntriesByName(PageLoad::kEntryName);
+  EXPECT_EQ(1ul, merged_entries.size());
+
+  for (const auto& kv : merged_entries) {
+    test_ukm_recorder().ExpectEntrySourceHasUrl(kv.second.get(),
+                                                GURL(kTestUrl1));
+    test_ukm_recorder().ExpectEntryMetric(
+        kv.second.get(),
+        PageLoad::kExperimental_PaintTiming_NavigationToLastTextPaintName, 600);
     EXPECT_TRUE(test_ukm_recorder().EntryHasMetric(
         kv.second.get(), PageLoad::kPageTiming_ForegroundDurationName));
   }
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
index 8c69b7f..e1cda828 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -422,6 +422,12 @@
   virtual void OnLastImagePaintInMainFrameDocument(
       const mojom::PageLoadTiming& last_candidate,
       const page_load_metrics::PageLoadExtraInfo& info) {}
+  virtual void OnLargestTextPaintInMainFrameDocument(
+      const mojom::PageLoadTiming& last_candidate,
+      const page_load_metrics::PageLoadExtraInfo& info) {}
+  virtual void OnLastTextPaintInMainFrameDocument(
+      const mojom::PageLoadTiming& last_candidate,
+      const page_load_metrics::PageLoadExtraInfo& info) {}
 
   virtual void OnPageInteractive(const mojom::PageLoadTiming& timing,
                                  const PageLoadExtraInfo& extra_info) {}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
index 91780eb..68e148b59 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
@@ -441,6 +441,21 @@
     should_dispatch = true;
   }
 
+  if (largest_text_paint_) {
+    pending_merged_page_timing_->paint_timing->largest_text_paint.swap(
+        largest_text_paint_);
+    // Reset it so multiple shutdowns will have only one dispatch.
+    largest_text_paint_.reset();
+    should_dispatch = true;
+  }
+  if (last_text_paint_) {
+    pending_merged_page_timing_->paint_timing->last_text_paint.swap(
+        last_text_paint_);
+    // Reset it so multiple shutdowns will have only one dispatch.
+    last_text_paint_.reset();
+    should_dispatch = true;
+  }
+
   if (should_dispatch) {
     DispatchTimingUpdates();
   }
@@ -573,6 +588,10 @@
   new_timing.paint_timing->largest_image_paint.reset();
   last_image_paint_.swap(new_timing.paint_timing->last_image_paint);
   new_timing.paint_timing->last_image_paint.reset();
+  largest_text_paint_.swap(new_timing.paint_timing->largest_text_paint);
+  new_timing.paint_timing->largest_text_paint.reset();
+  last_text_paint_.swap(new_timing.paint_timing->last_text_paint);
+  new_timing.paint_timing->last_text_paint.reset();
 
   // Update the pending_merged_page_timing_, making sure to merge the previously
   // observed |paint_timing| and |interactive_timing|, which are tracked across
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
index 00d3c29..33debbdf 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
@@ -176,6 +176,8 @@
   // current_merged_page_timing_ at the end of the pageload life time.
   base::Optional<base::TimeDelta> largest_image_paint_;
   base::Optional<base::TimeDelta> last_image_paint_;
+  base::Optional<base::TimeDelta> largest_text_paint_;
+  base::Optional<base::TimeDelta> last_text_paint_;
 
   // PageLoadTiming for the currently tracked page. The fields in |paint_timing|
   // are merged across all frames in the document. All other fields are from the
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc
index c4d63acf..75272a56 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.cc
+++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -157,6 +157,12 @@
   if (new_timing.paint_timing->last_image_paint &&
       !last_timing.paint_timing->last_image_paint)
     observer->OnLastImagePaintInMainFrameDocument(new_timing, extra_info);
+  if (new_timing.paint_timing->largest_text_paint &&
+      !last_timing.paint_timing->largest_text_paint)
+    observer->OnLargestTextPaintInMainFrameDocument(new_timing, extra_info);
+  if (new_timing.paint_timing->last_text_paint &&
+      !last_timing.paint_timing->last_text_paint)
+    observer->OnLastTextPaintInMainFrameDocument(new_timing, extra_info);
   if (new_timing.interactive_timing->interactive &&
       !last_timing.interactive_timing->interactive)
     observer->OnPageInteractive(new_timing, extra_info);
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
index 27fbd9de..5dadfc6 100644
--- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
+++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/views/overlay/overlay_window_views.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
@@ -190,7 +189,7 @@
   EXPECT_TRUE(window_controller()->GetWindowForTesting()->IsVisible());
 }
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#if (defined(OS_MACOSX) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
 class PictureInPicturePixelComparisonBrowserTest
     : public PictureInPictureWindowControllerBrowserTest {
  public:
@@ -233,8 +232,7 @@
             base::BindOnce(
                 &PictureInPicturePixelComparisonBrowserTest::ReadbackResult,
                 base::Unretained(this), run_loop.QuitClosure()));
-    overlay_window_views->GetNativeWindow()->layer()->RequestCopyOfOutput(
-        std::move(request));
+    overlay_window_views->GetLayer()->RequestCopyOfOutput(std::move(request));
     run_loop.Run();
   }
 
@@ -271,8 +269,7 @@
   std::unique_ptr<SkBitmap> result_bitmap_;
 };
 
-// TODO(cliffordcheng): enable this tests on other platforms when
-// Windows and Mac capture screen problem is solved.
+// TODO(cliffordcheng): enable on Windows when compile errors are resolved.
 // Plays a video and then trigger Picture-in-Picture. Grabs a screenshot of
 // Picture-in-Picture window and verifies it's as expected.
 IN_PROC_BROWSER_TEST_F(PictureInPicturePixelComparisonBrowserTest, VideoPlay) {
@@ -320,7 +317,7 @@
   ASSERT_TRUE(SaveBitmap(test_image_path, GetResultBitmap()));
   EXPECT_TRUE(CompareImages(GetResultBitmap()));
 }
-#endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#endif  // (defined(OS_MACOSX) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
 
 // Tests that when an active WebContents accurately tracks whether a video
 // is in Picture-in-Picture.
diff --git a/chrome/browser/printing/print_preview_message_handler.cc b/chrome/browser/printing/print_preview_message_handler.cc
index 37b7d6d..e78e6348 100644
--- a/chrome/browser/printing/print_preview_message_handler.cc
+++ b/chrome/browser/printing/print_preview_message_handler.cc
@@ -90,8 +90,8 @@
     return nullptr;
   PrintPreviewUI* preview_ui =
       static_cast<PrintPreviewUI*>(dialog->GetWebUI()->GetController());
-  return preview_ui->GetIDForPrintPreviewUI() == preview_ui_id ? preview_ui
-                                                               : nullptr;
+  base::Optional<int32_t> id = preview_ui->GetIDForPrintPreviewUI();
+  return (id && *id == preview_ui_id) ? preview_ui : nullptr;
 }
 
 void PrintPreviewMessageHandler::OnRequestPrintPreview(
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
index 9cc1eb3..f6de05aba 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -60,6 +60,9 @@
   /** @private {boolean} */
   this.shouldIgnoreDocumentSelectionFromAction_ = false;
 
+  /** @private {number?} */
+  this.delayedAttributeOutputId_;
+
   this.addListener_(
       EventType.ACTIVEDESCENDANTCHANGED, this.onActiveDescendantChanged);
   this.addListener_(EventType.ALERT, this.onAlert);
@@ -109,6 +112,13 @@
 DesktopAutomationHandler.VMIN_VALUE_CHANGE_DELAY_MS = 50;
 
 /**
+ * Time to wait before announcing attribute changes that are otherwise too
+ * disruptive.
+ * @const {number}
+ */
+DesktopAutomationHandler.ATTRIBUTE_DELAY_MS = 1500;
+
+/**
  * Controls announcement of non-user-initiated events.
  * @type {boolean}
  */
@@ -187,6 +197,21 @@
           prevOutput.equals(this.lastAttributeOutput_))
         return;
 
+      // If the target or an ancestor is controlled by another control, we may
+      // want to delay the output.
+      var maybeControlledBy = evt.target;
+      while (maybeControlledBy) {
+        if (maybeControlledBy.controlledBy.length &&
+            maybeControlledBy.controlledBy.find((n) => !!n.autoComplete)) {
+          clearTimeout(this.delayedAttributeOutputId_);
+          this.delayedAttributeOutputId_ = setTimeout(() => {
+            this.lastAttributeOutput_.go();
+          }, DesktopAutomationHandler.ATTRIBUTE_DELAY_MS);
+          return;
+        }
+        maybeControlledBy = maybeControlledBy.parent;
+      }
+
       this.lastAttributeOutput_.go();
     }
   },
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions_test.extjs
index cf247dd..fd26ae0 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions_test.extjs
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions_test.extjs
@@ -46,6 +46,14 @@
       CommandHandler.onCommand(cmd);
     };
   },
+
+  /**
+   * Simulates work done when users interact using keyboard, braille, or
+   * touch.
+ */
+  simulateUserInteraction: function() {
+    Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH);
+  },
 };
 
 TEST_F('ChromeVoxLiveRegionsTest', 'LiveRegionAddElement', function() {
@@ -183,9 +191,10 @@
     */},
     function(rootNode) {
       var go = rootNode.find({ role: RoleType.BUTTON });
-      mockFeedback.call(go.doDefault.bind(go))
-          .expectCategoryFlushSpeech('Live')
-          .expectCategoryFlushSpeech('Focus');
+      mockFeedback.call(this.simulateUserInteraction.bind(this))
+          .call(go.doDefault.bind(go))
+          .expectFlushingSpeech('Live')
+          .expectQueuedSpeech('Focus');
       mockFeedback.replay();
     });
 });
@@ -208,8 +217,9 @@
     */},
     function(rootNode) {
       var go = rootNode.find({ role: RoleType.BUTTON });
-      mockFeedback.call(go.doDefault.bind(go))
-          .expectCategoryFlushSpeech('Focus')
+      mockFeedback.call(this.simulateUserInteraction.bind(this))
+          .call(go.doDefault.bind(go))
+          .expectFlushingSpeech('Focus')
           .expectCategoryFlushSpeech('Live');
       mockFeedback.replay();
     });
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
index edbc048..97db4ad 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -1002,7 +1002,7 @@
    */
   go: function() {
     // Speech.
-    var queueMode = cvox.QueueMode.CATEGORY_FLUSH;
+    var queueMode = cvox.QueueMode.QUEUE;
     if (Output.forceModeForNextSpeechUtterance_ !== undefined) {
       queueMode = /** @type{cvox.QueueMode} */ (
           Output.forceModeForNextSpeechUtterance_);
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index dc507566..56199a15 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -24,7 +24,7 @@
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/user_event_service_factory.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -50,7 +50,6 @@
 #include "components/safe_browsing/web_ui/safe_browsing_ui.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/signin_manager.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/sync/protocol/user_event_specifics.pb.h"
 #include "components/sync/user_events/user_event_service.h"
@@ -62,6 +61,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "google_apis/gaia/gaia_auth_util.h"
+#include "services/identity/public/cpp/identity_manager.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
@@ -975,12 +975,11 @@
 }
 
 AccountInfo ChromePasswordProtectionService::GetAccountInfo() const {
-  SigninManagerBase* signin_manager =
-      SigninManagerFactory::GetForProfileIfExists(
-          profile_->GetOriginalProfile());
+  auto* identity_manager = IdentityManagerFactory::GetForProfileIfExists(
+      profile_->GetOriginalProfile());
 
-  return signin_manager ? signin_manager->GetAuthenticatedAccountInfo()
-                        : AccountInfo();
+  return identity_manager ? identity_manager->GetPrimaryAccountInfo()
+                          : AccountInfo();
 }
 
 GURL ChromePasswordProtectionService::GetEnterpriseChangePasswordURL() const {
diff --git a/chrome/browser/ssl/security_state_tab_helper.cc b/chrome/browser/ssl/security_state_tab_helper.cc
index aebdb13..4044932 100644
--- a/chrome/browser/ssl/security_state_tab_helper.cc
+++ b/chrome/browser/ssl/security_state_tab_helper.cc
@@ -20,10 +20,10 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/secure_origin_whitelist.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/features.h"
 #include "components/security_state/content/content_utils.h"
-#include "components/toolbar/toolbar_field_trial.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
index cf1102fd..e877da7 100644
--- a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
@@ -6,7 +6,6 @@
 
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/bookmark_app_helper.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -95,13 +94,7 @@
 // Install some apps on both clients, some on only one client, some on only the
 // other, and sync.  Both clients should end up with all apps, and the app and
 // page ordinals should be identical.
-// Flakily crashes on Windows, see crbug.com/434438.
-#if defined(OS_WIN)
-#define MAYBE_StartWithDifferentApps DISABLED_StartWithDifferentApps
-#else
-#define MAYBE_StartWithDifferentApps StartWithDifferentApps
-#endif
-IN_PROC_BROWSER_TEST_P(TwoClientAppsSyncTest, MAYBE_StartWithDifferentApps) {
+IN_PROC_BROWSER_TEST_P(TwoClientAppsSyncTest, StartWithDifferentApps) {
   ASSERT_TRUE(SetupClients());
 
   int i = 0;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 03c5004..594acb53 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -439,6 +439,7 @@
     "//components/ntp_tiles",
     "//components/offline_pages/buildflags",
     "//components/omnibox/browser",
+    "//components/omnibox/browser:vector_icons",
     "//components/onc",
     "//components/password_manager/content/browser",
     "//components/password_manager/core/browser",
@@ -478,8 +479,6 @@
     "//components/sync",
     "//components/sync_preferences",
     "//components/sync_sessions",
-    "//components/toolbar",
-    "//components/toolbar:vector_icons",
     "//components/tracing:startup_tracing",
     "//components/ui_devtools",
     "//components/ukm:ukm",
@@ -1233,7 +1232,6 @@
       "//components/network_session_configurator/common",
       "//components/ui_metrics",
       "//components/vector_icons",
-      "//components/vector_icons",
       "//components/web_modal",
       "//components/zoom",
       "//device/bluetooth",
@@ -3568,9 +3566,9 @@
     "//chrome/app/theme:theme_resources",
     "//chrome/browser",
     "//chrome/browser/devtools",
+    "//components/omnibox/browser",
     "//components/password_manager/core/browser",
     "//components/sessions",
-    "//components/toolbar",
     "//components/translate/content/browser",
     "//content/public/browser",
     "//content/public/common",
diff --git a/chrome/browser/ui/android/tab_model/tab_model.cc b/chrome/browser/ui/android/tab_model/tab_model.cc
index 9939172..d3ce012 100644
--- a/chrome/browser/ui/android/tab_model/tab_model.cc
+++ b/chrome/browser/ui/android/tab_model/tab_model.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/sync/glue/synced_window_delegate_android.h"
 #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router.h"
 #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h"
-#include "components/toolbar/toolbar_model_impl.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 #include "content/public/browser/notification_service.h"
 
 using content::NotificationService;
diff --git a/chrome/browser/ui/android/tab_model/tab_model.h b/chrome/browser/ui/android/tab_model/tab_model.h
index 5be70637..2fa081b 100644
--- a/chrome/browser/ui/android/tab_model/tab_model.h
+++ b/chrome/browser/ui/android/tab_model/tab_model.h
@@ -9,10 +9,10 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/android/tab_model/android_live_tab_context.h"
+#include "components/omnibox/browser/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model_delegate.h"
 #include "components/sessions/core/session_id.h"
 #include "components/sync_sessions/synced_window_delegate.h"
-#include "components/toolbar/toolbar_model.h"
-#include "components/toolbar/toolbar_model_delegate.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 
diff --git a/chrome/browser/ui/android/toolbar/toolbar_model_android.cc b/chrome/browser/ui/android/toolbar/toolbar_model_android.cc
index 533aba6..429f8c21 100644
--- a/chrome/browser/ui/android/toolbar/toolbar_model_android.cc
+++ b/chrome/browser/ui/android/toolbar/toolbar_model_android.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/android/toolbar/toolbar_model_android.h"
 
 #include "base/android/jni_string.h"
-#include "components/toolbar/toolbar_model_impl.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/android/toolbar/toolbar_model_android.h b/chrome/browser/ui/android/toolbar/toolbar_model_android.h
index f36a996e..515a525 100644
--- a/chrome/browser/ui/android/toolbar/toolbar_model_android.h
+++ b/chrome/browser/ui/android/toolbar/toolbar_model_android.h
@@ -11,7 +11,7 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 
 namespace content {
 class WebContents;
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc
index 68746891..87fc590 100644
--- a/chrome/browser/ui/app_list/search/search_controller_factory.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -48,7 +48,7 @@
 constexpr size_t kMaxPlayStoreResults = 12;
 
 // TODO(warx): Need UX spec.
-constexpr size_t kMaxAppDataResults = 6;
+constexpr size_t kMaxAppDataResults = 4;
 constexpr size_t kMaxAppShortcutResults = 4;
 
 // TODO(wutao): Need UX spec.
@@ -116,11 +116,13 @@
                                                      profile, list_controller));
   }
 
-  size_t app_data_api_group_id =
-      controller->AddGroup(kMaxAppDataResults, 1.0, kBoostOfApps);
-  controller->AddProvider(app_data_api_group_id,
-                          std::make_unique<ArcAppDataSearchProvider>(
-                              kMaxAppDataResults, list_controller));
+  if (app_list_features::IsAppDataSearchEnabled()) {
+    size_t app_data_api_group_id =
+        controller->AddGroup(kMaxAppDataResults, 1.0, kBoostOfApps);
+    controller->AddProvider(app_data_api_group_id,
+                            std::make_unique<ArcAppDataSearchProvider>(
+                                kMaxAppDataResults, list_controller));
+  }
 
   if (app_list_features::IsSettingsShortcutSearchEnabled()) {
     size_t settings_shortcut_group_id = controller->AddGroup(
diff --git a/chrome/browser/ui/ash/login_screen_client.cc b/chrome/browser/ui/ash/login_screen_client.cc
index c4f7990..fb9c741 100644
--- a/chrome/browser/ui/ash/login_screen_client.cc
+++ b/chrome/browser/ui/ash/login_screen_client.cc
@@ -125,11 +125,6 @@
     delegate_->HandleHardlockPod(account_id);
 }
 
-void LoginScreenClient::RecordClickOnLockIcon(const AccountId& account_id) {
-  if (delegate_)
-    delegate_->HandleRecordClickOnLockIcon(account_id);
-}
-
 void LoginScreenClient::OnFocusPod(const AccountId& account_id) {
   if (delegate_)
     delegate_->HandleOnFocusPod(account_id);
diff --git a/chrome/browser/ui/ash/login_screen_client.h b/chrome/browser/ui/ash/login_screen_client.h
index 195ec050..f0d6ee86 100644
--- a/chrome/browser/ui/ash/login_screen_client.h
+++ b/chrome/browser/ui/ash/login_screen_client.h
@@ -43,7 +43,6 @@
     virtual void HandleAuthenticateUserWithEasyUnlock(
         const AccountId& account_id) = 0;
     virtual void HandleHardlockPod(const AccountId& account_id) = 0;
-    virtual void HandleRecordClickOnLockIcon(const AccountId& account_id) = 0;
     virtual void HandleOnFocusPod(const AccountId& account_id) = 0;
     virtual void HandleOnNoPodFocused() = 0;
     // Handles request to focus a lock screen app window. Returns whether the
@@ -86,7 +85,6 @@
       EnrollUserWithExternalBinaryCallback callback) override;
   void AuthenticateUserWithEasyUnlock(const AccountId& account_id) override;
   void HardlockPod(const AccountId& account_id) override;
-  void RecordClickOnLockIcon(const AccountId& account_id) override;
   void OnFocusPod(const AccountId& account_id) override;
   void OnNoPodFocused() override;
   void LoadWallpaper(const AccountId& account_id) override;
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
index f092da30..0261909 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
@@ -30,7 +30,7 @@
 
 #if !defined(OS_ANDROID)
 #include "chrome/app/vector_icons/vector_icons.h"
-#include "components/toolbar/vector_icons.h"  // nogncheck
+#include "components/omnibox/browser/vector_icons.h"  // nogncheck
 #endif
 
 namespace autofill {
@@ -221,11 +221,11 @@
   // For http warning message, get icon images from VectorIcon, which is the
   // same as security indicator icons in location bar.
   if (icon_str == base::ASCIIToUTF16("httpWarning")) {
-    return gfx::CreateVectorIcon(toolbar::kHttpIcon, kIconSize,
+    return gfx::CreateVectorIcon(omnibox::kHttpIcon, kIconSize,
                                  gfx::kChromeIconGrey);
   }
   if (icon_str == base::ASCIIToUTF16("httpsInvalid")) {
-    return gfx::CreateVectorIcon(toolbar::kHttpsInvalidIcon, kIconSize,
+    return gfx::CreateVectorIcon(omnibox::kHttpsInvalidIcon, kIconSize,
                                  gfx::kGoogleRed700);
   }
   if (icon_str == base::ASCIIToUTF16("keyIcon"))
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 288241b8..51bd0a1 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -166,6 +166,7 @@
 #include "components/keep_alive_registry/keep_alive_registry.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 #include "components/prefs/pref_service.h"
 #include "components/search/search.h"
 #include "components/security_state/content/content_utils.h"
@@ -173,7 +174,6 @@
 #include "components/sessions/core/session_types.h"
 #include "components/sessions/core/tab_restore_service.h"
 #include "components/startup_metric_utils/browser/startup_metric_utils.h"
-#include "components/toolbar/toolbar_model_impl.h"
 #include "components/translate/core/browser/language_state.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 68f8f0bd..dd4c877 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -33,9 +33,9 @@
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/sessions/core/session_id.h"
-#include "components/toolbar/toolbar_model.h"
 #include "components/translate/content/browser/content_translate_driver.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
index 59ccef8..2bcd809 100644
--- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
+++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
@@ -29,7 +29,6 @@
 #include "components/prefs/pref_member.h"
 #include "components/search_engines/util.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/vector_icons.h"
 #include "components/url_formatter/url_formatter.h"
 #include "components/vector_icons/vector_icons.h"
 #include "content/public/browser/web_contents.h"
@@ -469,7 +468,7 @@
 
 - (void)updateStarredButton {
   const gfx::VectorIcon& icon =
-      isStarred_ ? toolbar::kStarActiveIcon : toolbar::kStarIcon;
+      isStarred_ ? omnibox::kStarActiveIcon : omnibox::kStarIcon;
   SkColor iconColor =
       isStarred_ ? kTouchBarStarActiveColor : kTouchBarDefaultIconColor;
   int tooltipId = isStarred_ ? IDS_TOOLTIP_STARRED : IDS_TOOLTIP_STAR;
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
index d89fb48..4b9b3e1 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -58,11 +58,11 @@
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_result.h"
 #include "components/omnibox/browser/search_provider.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/prefs/pref_service.h"
 #include "components/search/search.h"
 #include "components/search_engines/search_engines_pref_names.h"
 #include "components/search_engines/template_url_service.h"
-#include "components/toolbar/toolbar_model.h"
 #include "components/translate/core/browser/translate_manager.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc b/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc
index c9671ca..71955519 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "extensions/buildflags/buildflags.h"
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index 5134694..d88091f 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -42,11 +42,11 @@
 #include "components/omnibox/browser/history_quick_provider.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/browser/omnibox_view.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_service.h"
-#include "components/toolbar/test_toolbar_model.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
 #include "net/dns/mock_host_resolver.h"
diff --git a/chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.cc b/chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.cc
index 5a607362..7afe700 100644
--- a/chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.cc
+++ b/chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.cc
@@ -25,8 +25,7 @@
 #include "extensions/common/constants.h"
 
 #if !defined(OS_ANDROID)
-#include "components/omnibox/browser/vector_icons.h" // nogncheck
-#include "components/toolbar/vector_icons.h"  // nogncheck
+#include "components/omnibox/browser/vector_icons.h"  // nogncheck
 #endif  // !defined(OS_ANDROID)
 
 #if BUILDFLAG(ENABLE_OFFLINE_PAGES)
@@ -146,7 +145,7 @@
   GetURL(&url);
 
   if (url.SchemeIs(content::kChromeUIScheme))
-    return &toolbar::kProductIcon;
+    return &omnibox::kProductIcon;
 
   if (url.SchemeIs(extensions::kExtensionScheme))
     return &omnibox::kExtensionAppIcon;
diff --git a/chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.h b/chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.h
index ec6e7f32..70a4491 100644
--- a/chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.h
+++ b/chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_TOOLBAR_CHROME_TOOLBAR_MODEL_DELEGATE_H_
 
 #include "base/macros.h"
-#include "components/toolbar/toolbar_model_delegate.h"
+#include "components/omnibox/browser/toolbar_model_delegate.h"
 
 class Profile;
 
diff --git a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
index b07f6322..88d4333 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model_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 "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 
 #include <stddef.h>
 
@@ -16,8 +16,8 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
-#include "components/toolbar/toolbar_field_trial.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/common/content_constants.h"
diff --git a/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc b/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc
index 7f5854b0..083c49b 100644
--- a/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc
+++ b/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc
@@ -4,29 +4,32 @@
 
 #include "chrome/browser/ui/views/crostini/crostini_browser_test_util.h"
 
+#include <utility>
+
 #include "base/path_service.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_browser_main.h"
 #include "chrome/browser/chrome_browser_main_extra_parts.h"
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
-#include "chrome/browser/component_updater/cros_component_installer_chromeos.h"
+#include "chrome/browser/component_updater/fake_cros_component_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_features.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_image_loader_client.h"
 #include "components/component_updater/component_updater_paths.h"
 #include "components/prefs/pref_service.h"
 #include "net/base/mock_network_change_notifier.h"
 #include "net/base/network_change_notifier_factory.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-// ChromeBrowserMainExtraParts used to install a MockNetworkChangeNotifier.
-class ChromeBrowserMainExtraPartsNetFactoryInstaller
+// ChromeBrowserMainExtraParts used to install a MockNetworkChangeNotifier and
+// FakeCrOSComponentManager.
+class CrostiniBrowserTestChromeBrowserMainExtraParts
     : public ChromeBrowserMainExtraParts {
  public:
-  ChromeBrowserMainExtraPartsNetFactoryInstaller() = default;
-  ~ChromeBrowserMainExtraPartsNetFactoryInstaller() override {
+  explicit CrostiniBrowserTestChromeBrowserMainExtraParts(bool register_termina)
+      : register_termina_(register_termina) {}
+
+  ~CrostiniBrowserTestChromeBrowserMainExtraParts() override {
     // |network_change_notifier_| needs to be destroyed before |net_installer_|.
     network_change_notifier_.reset();
   }
@@ -35,8 +38,34 @@
     return network_change_notifier_.get();
   }
 
+  component_updater::FakeCrOSComponentManager* cros_component_manager() {
+    return cros_component_manager_ptr_;
+  }
+
   // ChromeBrowserMainExtraParts:
-  void PreEarlyInitialization() override {}
+  void PostEarlyInitialization() override {
+    auto cros_component_manager =
+        std::make_unique<component_updater::FakeCrOSComponentManager>();
+    cros_component_manager->set_supported_components(
+        {imageloader::kTerminaComponentName});
+
+    if (register_termina_) {
+      cros_component_manager->set_registered_components(
+          {imageloader::kTerminaComponentName});
+      cros_component_manager->ResetComponentState(
+          imageloader::kTerminaComponentName,
+          component_updater::FakeCrOSComponentManager::ComponentInfo(
+              component_updater::CrOSComponentManager::Error::NONE,
+              base::FilePath("/dev/null"), base::FilePath("/dev/null")));
+    }
+    cros_component_manager_ptr_ = cros_component_manager.get();
+
+    browser_process_platform_part_test_api_ =
+        std::make_unique<BrowserProcessPlatformPartTestApi>(
+            g_browser_process->platform_part());
+    browser_process_platform_part_test_api_->InitializeCrosComponentManager(
+        std::move(cros_component_manager));
+  }
   void PostMainMessageLoopStart() override {
     ASSERT_TRUE(net::NetworkChangeNotifier::HasNetworkChangeNotifier());
     net_installer_ =
@@ -46,34 +75,42 @@
     network_change_notifier_->SetConnectionType(
         net::NetworkChangeNotifier::CONNECTION_WIFI);
   }
+  void PostMainMessageLoopRun() override {
+    cros_component_manager_ptr_ = nullptr;
+    browser_process_platform_part_test_api_->ShutdownCrosComponentManager();
+    browser_process_platform_part_test_api_.reset();
+  }
 
  private:
+  const bool register_termina_;
+
+  std::unique_ptr<BrowserProcessPlatformPartTestApi>
+      browser_process_platform_part_test_api_;
+  component_updater::FakeCrOSComponentManager* cros_component_manager_ptr_ =
+      nullptr;
+
   std::unique_ptr<net::test::MockNetworkChangeNotifier>
       network_change_notifier_;
   std::unique_ptr<net::NetworkChangeNotifier::DisableForTest> net_installer_;
 
-  DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsNetFactoryInstaller);
+  DISALLOW_COPY_AND_ASSIGN(CrostiniBrowserTestChromeBrowserMainExtraParts);
 };
 
-CrostiniDialogBrowserTest::CrostiniDialogBrowserTest()
-    : dir_component_user_override_(component_updater::DIR_COMPONENT_USER) {
-  auto image_loader_client =
-      std::make_unique<chromeos::FakeImageLoaderClient>();
-  image_loader_client_ = image_loader_client.get();
-  chromeos::DBusThreadManager::GetSetterForTesting()->SetImageLoaderClient(
-      std::move(image_loader_client));
-}
+CrostiniDialogBrowserTest::CrostiniDialogBrowserTest(bool register_termina)
+    : register_termina_(register_termina) {}
+
+CrostiniDialogBrowserTest::~CrostiniDialogBrowserTest() = default;
 
 void CrostiniDialogBrowserTest::CreatedBrowserMainParts(
     content::BrowserMainParts* browser_main_parts) {
   ChromeBrowserMainParts* chrome_browser_main_parts =
       static_cast<ChromeBrowserMainParts*>(browser_main_parts);
-  extra_parts_ = new ChromeBrowserMainExtraPartsNetFactoryInstaller();
+  extra_parts_ =
+      new CrostiniBrowserTestChromeBrowserMainExtraParts(register_termina_);
   chrome_browser_main_parts->AddParts(extra_parts_);
 }
 
 void CrostiniDialogBrowserTest::SetUp() {
-  InitCrosTermina();
   crostini::SetCrostiniUIAllowedForTesting(true);
   DialogBrowserTest::SetUp();
 }
@@ -81,25 +118,6 @@
 void CrostiniDialogBrowserTest::SetUpOnMainThread() {
   browser()->profile()->GetPrefs()->SetBoolean(
       crostini::prefs::kCrostiniEnabled, true);
-  auto* cros_component_manager =
-      g_browser_process->platform_part()->cros_component_manager();
-  cros_component_manager->RegisterCompatiblePath(
-      imageloader::kTerminaComponentName, cros_termina_resources_.GetPath());
-  image_loader_client_->RegisterComponent(
-      imageloader::kTerminaComponentName, "1.1",
-      cros_termina_resources_.GetPath().value(), base::DoNothing());
-}
-
-void CrostiniDialogBrowserTest::InitCrosTermina() {
-  base::FilePath component_user_dir;
-  ASSERT_TRUE(base::PathService::Get(component_updater::DIR_COMPONENT_USER,
-                                     &component_user_dir));
-  ASSERT_TRUE(cros_termina_resources_.Set(
-      component_user_dir.Append("cros-components")
-          .Append(imageloader::kTerminaComponentName)));
-
-  image_loader_client_->SetMountPathForComponent(
-      imageloader::kTerminaComponentName, cros_termina_resources_.GetPath());
 }
 
 void CrostiniDialogBrowserTest::SetConnectionType(
@@ -108,8 +126,9 @@
 }
 
 void CrostiniDialogBrowserTest::UnregisterTermina() {
-  auto* cros_component_manager =
-      g_browser_process->platform_part()->cros_component_manager();
-  cros_component_manager->UnregisterCompatiblePath(
-      imageloader::kTerminaComponentName);
+  extra_parts_->cros_component_manager()->ResetComponentState(
+      imageloader::kTerminaComponentName,
+      component_updater::FakeCrOSComponentManager::ComponentInfo(
+          component_updater::CrOSComponentManager::Error::INSTALL_FAILURE,
+          base::FilePath(), base::FilePath()));
 }
diff --git a/chrome/browser/ui/views/crostini/crostini_browser_test_util.h b/chrome/browser/ui/views/crostini/crostini_browser_test_util.h
index 734f646d..f935f16 100644
--- a/chrome/browser/ui/views/crostini/crostini_browser_test_util.h
+++ b/chrome/browser/ui/views/crostini/crostini_browser_test_util.h
@@ -5,29 +5,26 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_CROSTINI_CROSTINI_BROWSER_TEST_UTIL_H_
 #define CHROME_BROWSER_UI_VIEWS_CROSTINI_CROSTINI_BROWSER_TEST_UTIL_H_
 
-#include "base/files/scoped_temp_dir.h"
-#include "base/test/scoped_path_override.h"
+#include <memory>
+
 #include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h"
 #include "net/base/network_change_notifier.h"
 
-class ChromeBrowserMainExtraPartsNetFactoryInstaller;
-
-namespace chromeos {
-class FakeImageLoaderClient;
-}  // namespace chromeos
+class CrostiniBrowserTestChromeBrowserMainExtraParts;
 
 // Common base for Crostini dialog broswer tests. Allows tests to set network
 // connection type.
 class CrostiniDialogBrowserTest : public DialogBrowserTest {
  public:
-  CrostiniDialogBrowserTest();
+  explicit CrostiniDialogBrowserTest(bool register_termina);
+  ~CrostiniDialogBrowserTest() override;
 
   // BrowserTestBase:
   void CreatedBrowserMainParts(
       content::BrowserMainParts* browser_main_parts) override;
   void SetUp() override;
   void SetUpOnMainThread() override;
-  virtual void InitCrosTermina();
 
   void SetConnectionType(
       net::NetworkChangeNotifier::ConnectionType connection_type);
@@ -35,12 +32,10 @@
   void UnregisterTermina();
 
  protected:
+  const bool register_termina_;
+
   // Owned by content::Browser
-  ChromeBrowserMainExtraPartsNetFactoryInstaller* extra_parts_ = nullptr;
-  // Image loader client injected into, and owned by DBusThreadManager.
-  chromeos::FakeImageLoaderClient* image_loader_client_ = nullptr;
-  base::ScopedPathOverride dir_component_user_override_;
-  base::ScopedTempDir cros_termina_resources_;
+  CrostiniBrowserTestChromeBrowserMainExtraParts* extra_parts_ = nullptr;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(CrostiniDialogBrowserTest);
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
index 10ba78ba..cbbf1e5 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
@@ -76,7 +76,8 @@
   };
 
   CrostiniInstallerViewBrowserTest()
-      : waiting_fake_concierge_client_(new WaitingFakeConciergeClient()),
+      : CrostiniDialogBrowserTest(true /*register_termina*/),
+        waiting_fake_concierge_client_(new WaitingFakeConciergeClient()),
         waiting_disk_mount_manager_observer_(
             new WaitingDiskMountManagerObserver) {
     chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
diff --git a/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
index 4b8f1d9b..c5bc47dc 100644
--- a/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
@@ -52,7 +52,11 @@
   };
 
   CrostiniUninstallerViewBrowserTest()
-      : waiting_fake_concierge_client_(new WaitingFakeConciergeClient()) {
+      : CrostiniUninstallerViewBrowserTest(true /*register_termina*/) {}
+
+  explicit CrostiniUninstallerViewBrowserTest(bool register_termina)
+      : CrostiniDialogBrowserTest(register_termina),
+        waiting_fake_concierge_client_(new WaitingFakeConciergeClient()) {
     chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
         base::WrapUnique(waiting_fake_concierge_client_));
   }
@@ -91,17 +95,8 @@
 class CrostiniUninstalledUninstallerViewBrowserTest
     : public CrostiniUninstallerViewBrowserTest {
  public:
-  CrostiniUninstalledUninstallerViewBrowserTest() = default;
-
-  void SetUpOnMainThread() override {
-    browser()->profile()->GetPrefs()->SetBoolean(
-        crostini::prefs::kCrostiniEnabled, true);
-    // Skips installing the Cros-Termina component.
-  }
-
-  void InitCrosTermina() override {
-    // Skips setting up the Cros-Termina component.
-  }
+  CrostiniUninstalledUninstallerViewBrowserTest()
+      : CrostiniUninstallerViewBrowserTest(false /*register_termina*/) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(CrostiniUninstalledUninstallerViewBrowserTest);
diff --git a/chrome/browser/ui/views/crostini/crostini_upgrade_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_upgrade_view_browsertest.cc
index 4b3e41a..576ddc85 100644
--- a/chrome/browser/ui/views/crostini/crostini_upgrade_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_upgrade_view_browsertest.cc
@@ -22,7 +22,8 @@
 
 class CrostiniUpgradeViewBrowserTest : public CrostiniDialogBrowserTest {
  public:
-  CrostiniUpgradeViewBrowserTest() = default;
+  CrostiniUpgradeViewBrowserTest()
+      : CrostiniDialogBrowserTest(true /*register_termina*/) {}
 
   // DialogBrowserTest:
   void ShowUi(const std::string& name) override {
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc
index 11bf9f5..07aabb42 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -390,6 +390,16 @@
       ++i;
     }
   }
+
+  // If we had keyboard focus, calling SetVisible(false) causes keyboard focus
+  // to be completely lost. To prevent this, we focus another view: the web
+  // contents. TODO(collinbaker): https://crbug.com/846466 Fix
+  // AccessiblePaneView::SetVisible or FocusManager to make this unnecessary.
+  auto* focus_manager = GetFocusManager();
+  if (focus_manager && Contains(focus_manager->GetFocusedView())) {
+    get_parent()->contents_web_view()->RequestFocus();
+  }
+
   SetVisible(false);
 }
 
diff --git a/chrome/browser/ui/views/location_bar/find_bar_icon.cc b/chrome/browser/ui/views/location_bar/find_bar_icon.cc
index ddc1bd9..93177959 100644
--- a/chrome/browser/ui/views/location_bar/find_bar_icon.cc
+++ b/chrome/browser/ui/views/location_bar/find_bar_icon.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/ui/find_bar/find_bar.h"
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/toolbar/vector_icons.h"
+#include "components/omnibox/browser/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/animation/ink_drop.h"
 
@@ -46,7 +46,7 @@
 }
 
 const gfx::VectorIcon& FindBarIcon::GetVectorIcon() const {
-  return toolbar::kFindInPageIcon;
+  return omnibox::kFindInPageIcon;
 }
 
 bool FindBarIcon::Update() {
diff --git a/chrome/browser/ui/views/location_bar/intent_picker_view.cc b/chrome/browser/ui/views/location_bar/intent_picker_view.cc
index 0adda3de..2009a54 100644
--- a/chrome/browser/ui/views/location_bar/intent_picker_view.cc
+++ b/chrome/browser/ui/views/location_bar/intent_picker_view.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/intent_picker_bubble_view.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/toolbar/vector_icons.h"
+#include "components/omnibox/browser/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace content {
@@ -65,7 +65,7 @@
 }
 
 const gfx::VectorIcon& IntentPickerView::GetVectorIcon() const {
-  return toolbar::kOpenInNewIcon;
+  return omnibox::kOpenInNewIcon;
 }
 
 base::string16 IntentPickerView::GetTextForTooltipAndAccessibleName() const {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index c26a4bf9..9507163 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -64,14 +64,13 @@
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/browser/omnibox_popup_view.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/omnibox/browser/vector_icons.h"
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/toolbar_model.h"
-#include "components/toolbar/vector_icons.h"
 #include "components/translate/core/browser/language_state.h"
 #include "components/variations/variations_associated_data.h"
 #include "content/public/browser/navigation_entry.h"
@@ -112,6 +111,16 @@
 #include "chrome/browser/ui/views/location_bar/intent_picker_view.h"
 #endif
 
+namespace {
+
+// This feature shows the full URL when the user focuses the omnibox via
+// keyboard shortcut. This feature flag only exists so we have a remote
+// killswitch for this behavior.
+base::Feature kOmniboxShowFullUrlOnKeyboardShortcut{
+    "OmniboxShowFullUrlOnKeyboardShortcut", base::FEATURE_ENABLED_BY_DEFAULT};
+
+}  // namespace
+
 using content::WebContents;
 using views::View;
 
@@ -369,7 +378,7 @@
   // We are currently gating this behavior on the Query in Omnibox flag, since
   // it's still under active experimentation.
   if (base::FeatureList::IsEnabled(omnibox::kQueryInOmnibox))
-    omnibox_view()->model()->SetUserTextToURLForEditing();
+    omnibox_view()->model()->Unelide(true /* exit_query_in_omnibox */);
 
   return true;
 }
@@ -378,7 +387,10 @@
 // LocationBarView, public LocationBar implementation:
 
 void LocationBarView::FocusLocation(bool select_all) {
-  bool already_focused = omnibox_view_->HasFocus();
+  // Only exit Query in Omnibox mode on focus command if the location bar was
+  // already focused to begin with, i.e. user presses Ctrl+L twice.
+  bool exit_query_in_omnibox = omnibox_view_->HasFocus();
+
   omnibox_view_->SetFocus();
 
   if (!select_all)
@@ -386,12 +398,8 @@
 
   omnibox_view_->SelectAll(true);
 
-  // If the location bar is already focused, a second command to focus it
-  // should expose the full URL, temporarily disabling Steady State Elisions
-  // and Query in Omnibox. This behavior is currently gated on the Query in
-  // Omnibox flag, as it's still under active experimentation.
-  if (already_focused && base::FeatureList::IsEnabled(omnibox::kQueryInOmnibox))
-    omnibox_view()->model()->SetUserTextToURLForEditing();
+  if (base::FeatureList::IsEnabled(kOmniboxShowFullUrlOnKeyboardShortcut))
+    omnibox_view()->model()->Unelide(exit_query_in_omnibox);
 }
 
 void LocationBarView::Revert() {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
index ed4c8f8c4..00f6d16e 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
@@ -21,9 +21,9 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 #include "components/security_state/core/security_state.h"
-#include "components/toolbar/toolbar_field_trial.h"
-#include "components/toolbar/toolbar_model_impl.h"
 #include "components/zoom/zoom_controller.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/page_zoom.h"
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc
index 839a07d..41a579f 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -11,8 +11,8 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/toolbar_model.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc
index b73b7ce..5cd2cc73 100644
--- a/chrome/browser/ui/views/location_bar/star_view.cc
+++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -13,8 +13,8 @@
 #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h"
 #include "chrome/browser/ui/views/feature_promos/bookmark_promo_bubble_view.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/omnibox/browser/vector_icons.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -79,7 +79,7 @@
 }
 
 const gfx::VectorIcon& StarView::GetVectorIcon() const {
-  return active() ? toolbar::kStarActiveIcon : toolbar::kStarIcon;
+  return active() ? omnibox::kStarActiveIcon : omnibox::kStarIcon;
 }
 
 base::string16 StarView::GetTextForTooltipAndAccessibleName() const {
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
index 4bd8ec9..25960497 100644
--- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
+++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
@@ -25,7 +25,7 @@
 #include "chrome/browser/ui/views/accelerator_table.h"
 #include "chrome/browser/ui/views/exclusive_access_bubble_views.h"
 #include "chrome/browser/ui/views/media_router/presentation_receiver_window_frame.h"
-#include "components/toolbar/toolbar_model_impl.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_constants.h"
 #include "ui/base/accelerators/accelerator_manager.h"
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 3ffaa3b..b76aab3 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -33,10 +33,10 @@
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/toolbar_field_trial.h"
-#include "components/toolbar/toolbar_model.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/escape.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -318,11 +318,14 @@
   // Temporarily reveal the top-of-window views (if not already revealed) so
   // that the location bar view is visible and is considered focusable. When it
   // actually receives focus, ImmersiveFocusWatcher will add another lock to
-  // keep it revealed.
-  std::unique_ptr<ImmersiveRevealedLock> focus_reveal_lock(
-      BrowserView::GetBrowserViewForBrowser(location_bar_view_->browser())
-          ->immersive_mode_controller()
-          ->GetRevealedLock(ImmersiveModeController::ANIMATE_REVEAL_YES));
+  // keep it revealed. |location_bar_view_| can be nullptr in unit tests.
+  std::unique_ptr<ImmersiveRevealedLock> focus_reveal_lock;
+  if (location_bar_view_) {
+    focus_reveal_lock.reset(
+        BrowserView::GetBrowserViewForBrowser(location_bar_view_->browser())
+            ->immersive_mode_controller()
+            ->GetRevealedLock(ImmersiveModeController::ANIMATE_REVEAL_YES));
+  }
 
   RequestFocus();
   // Restore caret visibility if focus is explicitly requested. This is
@@ -650,7 +653,8 @@
   if (model()->user_input_in_progress())
     return false;
 
-  // Don't unelide if we are currently displaying Query in Omnibox search terms.
+  // Don't unelide if we are currently displaying Query in Omnibox search terms,
+  // as otherwise, it would be impossible to refine query terms.
   if (model()->GetQueryInOmniboxSearchTerms(nullptr /* search_terms */))
     return false;
 
@@ -692,7 +696,8 @@
     OffsetDoubleClickWord(offset);
   }
 
-  model()->SetUserTextToURLForEditing();
+  // We have already early-exited if Query in Omnibox is active.
+  model()->Unelide(false /* exit_query_in_omnibox */);
   SelectRange(gfx::Range(start, end));
   return true;
 }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
index 8edd65e..3482f5b 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -27,8 +27,8 @@
 #include "chrome/test/views/chrome_views_test_base.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
-#include "components/toolbar/test_toolbar_model.h"
-#include "components/toolbar/toolbar_field_trial.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ime/input_method.h"
@@ -479,17 +479,11 @@
 }
 
 TEST_F(OmniboxViewViewsTest, RevertOnBlur) {
-  // Since this test is not focused on steady state elisions, set the full
-  // formatted URL and the url for display to the same value.
-  toolbar_model()->set_formatted_full_url(
-      base::ASCIIToUTF16("https://permanent-text.com"));
-  toolbar_model()->set_url_for_display(
-      base::ASCIIToUTF16("https://permanent-text.com"));
-
+  toolbar_model()->set_url(GURL("https://permanent-text.com/"));
   omnibox_view()->model()->ResetDisplayTexts();
   omnibox_view()->RevertAll();
 
-  EXPECT_EQ(base::ASCIIToUTF16("https://permanent-text.com"),
+  EXPECT_EQ(base::ASCIIToUTF16("https://permanent-text.com/"),
             omnibox_view()->text());
   EXPECT_FALSE(omnibox_view()->model()->user_input_in_progress());
 
@@ -505,10 +499,11 @@
 
   // Expect that on blur, if the text is the same as the
   // https://permanent-text.com, exit user input mode.
-  omnibox_view()->SetUserText(base::ASCIIToUTF16("https://permanent-text.com"));
+  omnibox_view()->SetUserText(
+      base::ASCIIToUTF16("https://permanent-text.com/"));
   EXPECT_TRUE(omnibox_view()->model()->user_input_in_progress());
   omnibox_textfield()->OnBlur();
-  EXPECT_EQ(base::ASCIIToUTF16("https://permanent-text.com"),
+  EXPECT_EQ(base::ASCIIToUTF16("https://permanent-text.com/"),
             omnibox_view()->text());
   EXPECT_FALSE(omnibox_view()->model()->user_input_in_progress());
 }
@@ -548,7 +543,7 @@
       : OmniboxViewViewsTest(enabled_features) {}
 
   const int kCharacterWidth = 10;
-  const base::string16 kFullUrl = base::ASCIIToUTF16("https://www.example.com");
+  const GURL kFullUrl = GURL("https://www.example.com/");
 
   void SetUp() override {
     OmniboxViewViewsTest::SetUp();
@@ -557,7 +552,7 @@
     clock_.Advance(base::TimeDelta::FromSeconds(5));
     ui::SetEventTickClockForTesting(&clock_);
 
-    toolbar_model()->set_formatted_full_url(kFullUrl);
+    toolbar_model()->set_url(kFullUrl);
     toolbar_model()->set_url_for_display(base::ASCIIToUTF16("example.com"));
 
     gfx::test::RenderTextTestApi render_text_test_api(
@@ -580,13 +575,14 @@
   }
 
   void ExpectFullUrlDisplayed() {
-    EXPECT_EQ(kFullUrl, omnibox_view()->text());
+    EXPECT_EQ(base::UTF8ToUTF16(kFullUrl.spec()), omnibox_view()->text());
     EXPECT_TRUE(omnibox_view()->model()->user_input_in_progress());
 
     // We test the user text stored in the model has been updated as well. The
     // model user text is used to populate the text in the Omnibox after some
     // state transitions, such as the ZeroSuggest popup opening.
-    EXPECT_EQ(kFullUrl, omnibox_view()->model()->GetUserTextForTesting());
+    EXPECT_EQ(base::UTF8ToUTF16(kFullUrl.spec()),
+              omnibox_view()->model()->GetUserTextForTesting());
   }
 
   bool IsElidedUrlDisplayed() {
@@ -768,7 +764,7 @@
   size_t start, end;
   omnibox_view()->GetSelectionBounds(&start, &end);
   EXPECT_EQ(0U, start);
-  EXPECT_EQ(23U, end);
+  EXPECT_EQ(24U, end);
 }
 
 TEST_F(OmniboxViewViewsSteadyStateElisionsTest, MouseClickDrag) {
@@ -892,12 +888,12 @@
                           ui::DomKey::FromCharacter('a'),
                           ui::EventTimeForNow());
   omnibox_textfield()->InsertChar(char_event);
-  EXPECT_EQ(base::ASCIIToUTF16("https://www.a.com"), omnibox_view()->text());
+  EXPECT_EQ(base::ASCIIToUTF16("https://www.a.com/"), omnibox_view()->text());
   EXPECT_TRUE(omnibox_view()->model()->user_input_in_progress());
 
   // Now that we've edited the text, blurring should not re-elide the URL.
   BlurOmnibox();
-  EXPECT_EQ(base::ASCIIToUTF16("https://www.a.com"), omnibox_view()->text());
+  EXPECT_EQ(base::ASCIIToUTF16("https://www.a.com/"), omnibox_view()->text());
   EXPECT_TRUE(omnibox_view()->model()->user_input_in_progress());
 }
 
@@ -935,6 +931,18 @@
   EXPECT_TRUE(omnibox_view()->IsSelectAll());
 }
 
+TEST_F(OmniboxViewViewsSteadyStateElisionsTest, UnelideFromModel) {
+  EXPECT_TRUE(IsElidedUrlDisplayed());
+
+  omnibox_view()->model()->Unelide(false /* exit_query_in_omnibox */);
+  EXPECT_TRUE(omnibox_view()->IsSelectAll());
+  size_t start, end;
+  omnibox_view()->GetSelectionBounds(&start, &end);
+  EXPECT_EQ(24U, start);
+  EXPECT_EQ(0U, end);
+  ExpectFullUrlDisplayed();
+}
+
 class OmniboxViewViewsSteadyStateElisionsAndQueryInOmniboxTest
     : public OmniboxViewViewsSteadyStateElisionsTest {
  public:
@@ -944,24 +952,30 @@
             toolbar::features::kHideSteadyStateUrlTrivialSubdomains,
             omnibox::kQueryInOmnibox,
         }) {}
+
+ protected:
+  const GURL kValidSearchResultsPage =
+      GURL("https://www.google.com/search?q=foo+query");
+
+  void SetUp() override {
+    OmniboxViewViewsSteadyStateElisionsTest::SetUp();
+
+    toolbar_model()->set_url(kValidSearchResultsPage);
+    toolbar_model()->set_security_level(security_state::SecurityLevel::SECURE);
+
+    omnibox_view()->model()->ResetDisplayTexts();
+    omnibox_view()->RevertAll();
+
+    // Sanity check that Query in Omnibox is working with Steady State Elisions.
+    EXPECT_EQ(base::ASCIIToUTF16("foo query"), omnibox_view()->text());
+
+    // Focus the Omnibox.
+    SendMouseClick(0);
+  }
 };
 
 TEST_F(OmniboxViewViewsSteadyStateElisionsAndQueryInOmniboxTest,
        DontUnelideQueryInOmniboxSearchTerms) {
-  const GURL kValidSearchResultsPage =
-      GURL("https://www.google.com/search?q=foo+query");
-  toolbar_model()->set_url(kValidSearchResultsPage);
-  toolbar_model()->set_security_level(security_state::SecurityLevel::SECURE);
-
-  omnibox_view()->model()->ResetDisplayTexts();
-  omnibox_view()->RevertAll();
-
-  // Sanity check that Query in Omnibox is working with Steady State Elisions.
-  EXPECT_EQ(base::ASCIIToUTF16("foo query"), omnibox_view()->text());
-
-  // Focus the Omnibox.
-  SendMouseClick(0);
-
   // Right key should NOT unelide, and should correctly place the cursor at the
   // end of the search query.
   omnibox_textfield_view()->OnKeyPressed(
@@ -974,3 +988,27 @@
   EXPECT_EQ(9U, start);
   EXPECT_EQ(9U, end);
 }
+
+TEST_F(OmniboxViewViewsSteadyStateElisionsAndQueryInOmniboxTest,
+       UnelideFromModel) {
+  // Uneliding without exiting Query in Omnibox should do nothing.
+  omnibox_view()->model()->Unelide(false /* exit_query_in_omnibox */);
+  EXPECT_EQ(base::ASCIIToUTF16("foo query"), omnibox_view()->text());
+  {
+    size_t start, end;
+    omnibox_view()->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(9U, start);
+    EXPECT_EQ(0U, end);
+  }
+
+  // Uneliding and exiting Query in Omnibox should reveal the full URL.
+  omnibox_view()->model()->Unelide(true /* exit_query_in_omnibox */);
+  EXPECT_EQ(base::ASCIIToUTF16(kValidSearchResultsPage.spec()),
+            omnibox_view()->text());
+  {
+    size_t start, end;
+    omnibox_view()->GetSelectionBounds(&start, &end);
+    EXPECT_EQ(41U, start);
+    EXPECT_EQ(0U, end);
+  }
+}
diff --git a/chrome/browser/ui/views/page_action/zoom_view.cc b/chrome/browser/ui/views/page_action/zoom_view.cc
index 373b186..769166a 100644
--- a/chrome/browser/ui/views/page_action/zoom_view.cc
+++ b/chrome/browser/ui/views/page_action/zoom_view.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/zoom/zoom_controller.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.cc
index 4add2987..c2f1c73d 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.cc
@@ -22,8 +22,6 @@
 void UserBoardScreenHandler::RegisterMessages() {
   AddCallback("attemptUnlock", &UserBoardScreenHandler::HandleAttemptUnlock);
   AddCallback("hardlockPod", &UserBoardScreenHandler::HandleHardlockPod);
-  AddCallback("recordClickOnLockIcon",
-              &UserBoardScreenHandler::HandleRecordClickOnLockIcon);
 }
 
 void UserBoardScreenHandler::Initialize() {
@@ -41,12 +39,6 @@
   screen_->AttemptEasyUnlock(account_id);
 }
 
-void UserBoardScreenHandler::HandleRecordClickOnLockIcon(
-    const AccountId& account_id) {
-  CHECK(screen_);
-  screen_->RecordClickOnLockIcon(account_id);
-}
-
 //----------------- API
 
 void UserBoardScreenHandler::SetPublicSessionDisplayName(
diff --git a/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h
index 0d3ee1cf..453793f1 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h
@@ -36,7 +36,6 @@
   // Handlers
   void HandleHardlockPod(const AccountId& account_id);
   void HandleAttemptUnlock(const AccountId& account_id);
-  void HandleRecordClickOnLockIcon(const AccountId& account_id);
 
   // UserBoardView implementation:
   void SetPublicSessionDisplayName(const AccountId& account_id,
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
index c9eacc5f..03e57126 100644
--- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
@@ -22,16 +22,17 @@
 
 namespace {
 
-std::pair<std::vector<base::FilePath>, int> ExecuteCancelledSelectFileDialog(
+void ExecuteCancelledSelectFileDialog(
     ui::SelectFileDialog::Type type,
     const base::string16& title,
     const base::FilePath& default_path,
     const std::vector<ui::FileFilterSpec>& filter,
     int file_type_index,
     const base::string16& default_extension,
-    HWND owner) {
-  // Return an empty result to simulate a cancelled dialog.
-  return {{}, 0};
+    HWND owner,
+    ui::OnSelectFileExecutedCallback on_select_file_executed_callback) {
+  // Send an empty result to simulate a cancelled dialog.
+  std::move(on_select_file_executed_callback).Run({}, 0);
 }
 
 class FakePdfPrinterHandler : public PdfPrinterHandler {
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index dc351ccc0..afcad591 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -628,6 +628,7 @@
 }
 
 void PrintPreviewHandler::OnJavascriptAllowed() {
+  print_preview_ui()->SetPreviewUIId();
   // Now that the UI is initialized, any future account changes will require
   // a printer list refresh.
   RegisterForGaiaCookieChanges();
@@ -637,6 +638,7 @@
   // Normally the handler and print preview will be destroyed together, but
   // this is necessary for refresh or navigation from the chrome://print page.
   weak_factory_.InvalidateWeakPtrs();
+  print_preview_ui()->ClearPreviewUIId();
   preview_callbacks_.clear();
   preview_failures_.clear();
   UnregisterForGaiaCookieChanges();
@@ -773,7 +775,7 @@
   // Add an additional key in order to identify |print_preview_ui| later on
   // when calling PrintPreviewUI::ShouldCancelRequest() on the IO thread.
   settings->SetInteger(printing::kPreviewUIID,
-                       print_preview_ui()->GetIDForPrintPreviewUI());
+                       print_preview_ui()->GetIDForPrintPreviewUI().value());
 
   // Increment request count.
   ++regenerate_preview_request_count_;
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index c3c6f489..97fb289 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -584,17 +584,13 @@
                                std::unique_ptr<PrintPreviewHandler> handler)
     : ConstrainedWebDialogUI(web_ui),
       initial_preview_start_time_(base::TimeTicks::Now()),
-      id_(g_print_preview_ui_id_map.Get().Add(this)),
       handler_(handler.get()) {
   web_ui->AddMessageHandler(std::move(handler));
-
-  g_print_preview_request_id_map.Get().Set(id_, -1);
 }
 
 PrintPreviewUI::PrintPreviewUI(content::WebUI* web_ui)
     : ConstrainedWebDialogUI(web_ui),
       initial_preview_start_time_(base::TimeTicks::Now()),
-      id_(g_print_preview_ui_id_map.Get().Add(this)),
       handler_(CreatePrintPreviewHandlers(web_ui)) {
   // Set up the chrome://print/ data source.
   Profile* profile = Profile::FromWebUI(web_ui);
@@ -611,31 +607,37 @@
 
   // Set up the chrome://theme/ source.
   content::URLDataSource::Add(profile, std::make_unique<ThemeSource>(profile));
-
-  g_print_preview_request_id_map.Get().Set(id_, -1);
 }
 
 PrintPreviewUI::~PrintPreviewUI() {
-  PrintPreviewDataService::GetInstance()->RemoveEntry(id_);
-  g_print_preview_request_id_map.Get().Erase(id_);
-  g_print_preview_ui_id_map.Get().Remove(id_);
+  ClearPreviewUIId();
+}
+
+void PrintPreviewUI::ClearPreviewUIId() {
+  if (!id_)
+    return;
+
+  PrintPreviewDataService::GetInstance()->RemoveEntry(*id_);
+  g_print_preview_request_id_map.Get().Erase(*id_);
+  g_print_preview_ui_id_map.Get().Remove(*id_);
+  id_.reset();
 }
 
 void PrintPreviewUI::GetPrintPreviewDataForIndex(
     int index,
     scoped_refptr<base::RefCountedMemory>* data) const {
-  PrintPreviewDataService::GetInstance()->GetDataEntry(id_, index, data);
+  PrintPreviewDataService::GetInstance()->GetDataEntry(*id_, index, data);
 }
 
 void PrintPreviewUI::SetPrintPreviewDataForIndex(
     int index,
     scoped_refptr<base::RefCountedMemory> data) {
-  PrintPreviewDataService::GetInstance()->SetDataEntry(id_, index,
+  PrintPreviewDataService::GetInstance()->SetDataEntry(*id_, index,
                                                        std::move(data));
 }
 
 void PrintPreviewUI::ClearAllPreviewData() {
-  PrintPreviewDataService::GetInstance()->RemoveEntry(id_);
+  PrintPreviewDataService::GetInstance()->RemoveEntry(*id_);
 }
 
 void PrintPreviewUI::SetInitiatorTitle(
@@ -689,7 +691,7 @@
   return ids.request_id != current_id;
 }
 
-int32_t PrintPreviewUI::GetIDForPrintPreviewUI() const {
+base::Optional<int32_t> PrintPreviewUI::GetIDForPrintPreviewUI() const {
   return id_;
 }
 
@@ -728,7 +730,7 @@
     UMA_HISTOGRAM_TIMES("PrintPreview.InitializationTime",
                         base::TimeTicks::Now() - initial_preview_start_time_);
   }
-  g_print_preview_request_id_map.Get().Set(id_, request_id);
+  g_print_preview_request_id_map.Get().Set(*id_, request_id);
 }
 
 void PrintPreviewUI::OnDidStartPreview(
@@ -799,7 +801,7 @@
 
   if (g_testing_delegate)
     g_testing_delegate->DidRenderPreviewPage(web_ui()->GetWebContents());
-  handler_->SendPagePreviewReady(page_number, id_, preview_request_id);
+  handler_->SendPagePreviewReady(page_number, *id_, preview_request_id);
 }
 
 void PrintPreviewUI::OnPreviewDataIsAvailable(
@@ -823,11 +825,11 @@
   SetPrintPreviewDataForIndex(printing::COMPLETE_PREVIEW_DOCUMENT_INDEX,
                               std::move(data));
 
-  handler_->OnPrintPreviewReady(id_, preview_request_id);
+  handler_->OnPrintPreviewReady(*id_, preview_request_id);
 }
 
 void PrintPreviewUI::OnCancelPendingPreviewRequest() {
-  g_print_preview_request_id_map.Get().Set(id_, -1);
+  g_print_preview_request_id_map.Get().Set(*id_, -1);
 }
 
 void PrintPreviewUI::OnPrintPreviewFailed(int request_id) {
@@ -906,3 +908,9 @@
 void PrintPreviewUI::ClearAllPreviewDataForTest() {
   ClearAllPreviewData();
 }
+
+void PrintPreviewUI::SetPreviewUIId() {
+  DCHECK(!id_);
+  id_ = g_print_preview_ui_id_map.Get().Add(this);
+  g_print_preview_request_id_map.Get().Set(*id_, -1);
+}
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.h b/chrome/browser/ui/webui/print_preview/print_preview_ui.h
index 5135daa..7a5c43e63 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.h
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.h
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/read_only_shared_memory_region.h"
 #include "base/memory/ref_counted.h"
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
 #include "ui/gfx/geometry/rect.h"
@@ -94,7 +95,7 @@
   static bool ShouldCancelRequest(const PrintHostMsg_PreviewIds& ids);
 
   // Returns an id to uniquely identify this PrintPreviewUI.
-  int32_t GetIDForPrintPreviewUI() const;
+  base::Optional<int32_t> GetIDForPrintPreviewUI() const;
 
   // Notifies the Web UI of a print preview request with |request_id|.
   virtual void OnPrintPreviewRequest(int request_id);
@@ -194,6 +195,14 @@
   // See ClearAllPreviewData().
   void ClearAllPreviewDataForTest();
 
+  // Sets a new valid Print Preview UI ID for this instance. Called by
+  // PrintPreviewHandler in OnJavascriptAllowed().
+  void SetPreviewUIId();
+
+  // Clears the UI ID. Called by PrintPreviewHandler in
+  // OnJavascriptDisallowed().
+  void ClearPreviewUIId();
+
  protected:
   // Alternate constructor for tests
   PrintPreviewUI(content::WebUI* web_ui,
@@ -217,7 +226,7 @@
 
   // The unique ID for this class instance. Stored here to avoid calling
   // GetIDForPrintPreviewUI() everywhere.
-  const int32_t id_;
+  base::Optional<int32_t> id_;
 
   // Weak pointer to the WebUI handler.
   PrintPreviewHandler* const handler_;
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
index eca9387..c385a358 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
@@ -87,6 +87,7 @@
   PrintPreviewUI* preview_ui = static_cast<PrintPreviewUI*>(
       preview_dialog->GetWebUI()->GetController());
   ASSERT_TRUE(preview_ui);
+  preview_ui->SetPreviewUIId();
 
   scoped_refptr<base::RefCountedMemory> data;
   preview_ui->GetPrintPreviewDataForIndex(
@@ -134,6 +135,7 @@
   PrintPreviewUI* preview_ui = static_cast<PrintPreviewUI*>(
       preview_dialog->GetWebUI()->GetController());
   ASSERT_TRUE(preview_ui);
+  preview_ui->SetPreviewUIId();
 
   scoped_refptr<base::RefCountedMemory> data;
   preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX, &data);
@@ -194,6 +196,7 @@
   PrintPreviewUI* preview_ui = static_cast<PrintPreviewUI*>(
       preview_dialog->GetWebUI()->GetController());
   ASSERT_TRUE(preview_ui);
+  preview_ui->SetPreviewUIId();
 
   // Test with invalid UI ID.
   const int32_t kInvalidId = -5;
@@ -201,7 +204,7 @@
 
   const int kFirstRequestId = 1000;
   const int kSecondRequestId = 1001;
-  const int32_t preview_id = preview_ui->GetIDForPrintPreviewUI();
+  const int32_t preview_id = preview_ui->GetIDForPrintPreviewUI().value();
 
   // Test with kFirstRequestId.
   preview_ui->OnPrintPreviewRequest(kFirstRequestId);
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn
index cd0f342..0872602 100644
--- a/chrome/browser/vr/BUILD.gn
+++ b/chrome/browser/vr/BUILD.gn
@@ -189,7 +189,7 @@
     "//chrome/app:generated_resources",
     "//chrome/browser/vr/vector_icons",
     "//chrome/common:constants",
-    "//components/toolbar:vector_icons",
+    "//components/omnibox/browser:vector_icons",
     "//components/url_formatter",
     "//components/vector_icons",
     "//media",
@@ -275,9 +275,9 @@
     "//chrome/browser/vr/vector_icons",
     "//chrome/common:constants",
     "//components/omnibox/browser",
+    "//components/omnibox/browser",
+    "//components/omnibox/browser:vector_icons",
     "//components/rappor/public:public",
-    "//components/toolbar",
-    "//components/toolbar:vector_icons",
     "//components/ukm/content",
     "//components/vector_icons",
     "//content/public/browser",
@@ -574,8 +574,8 @@
     "//base/test:test_support",
     "//cc:test_support",
     "//components/omnibox/browser:browser",
+    "//components/omnibox/browser:vector_icons",
     "//components/security_state/core",
-    "//components/toolbar:vector_icons",
     "//content/test:test_support",
     "//mojo/core/embedder",
     "//skia",
diff --git a/chrome/browser/vr/testapp/BUILD.gn b/chrome/browser/vr/testapp/BUILD.gn
index f0c114a..9585f28 100644
--- a/chrome/browser/vr/testapp/BUILD.gn
+++ b/chrome/browser/vr/testapp/BUILD.gn
@@ -29,8 +29,8 @@
     "//chrome/browser/vr:vr_test_support",
     "//chrome/browser/vr:vr_ui",
     "//components:components_tests_pak",
+    "//components/omnibox/browser:vector_icons",
     "//components/security_state/core",
-    "//components/toolbar:vector_icons",
     "//components/tracing:startup_tracing",
     "//components/vector_icons:vector_icons",
     "//ui/display/types",
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc
index 585e1bc..87a4aee 100644
--- a/chrome/browser/vr/testapp/vr_test_context.cc
+++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -36,7 +36,6 @@
 #include "chrome/grit/vr_testapp_resources.h"
 #include "components/omnibox/browser/vector_icons.h"
 #include "components/security_state/core/security_state.h"
-#include "components/toolbar/vector_icons.h"
 #include "components/vector_icons/vector_icons.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkSurface.h"
@@ -581,7 +580,7 @@
 
 void VrTestContext::Navigate(GURL gurl, NavigationMethod method) {
   ToolbarState state(gurl, security_state::SecurityLevel::HTTP_SHOW_WARNING,
-                     &toolbar::kHttpIcon, true, false);
+                     &omnibox::kHttpIcon, true, false);
   ui_->GetBrowserUiWeakPtr()->SetToolbarState(state);
   page_load_start_ = base::TimeTicks::Now();
 }
@@ -742,52 +741,52 @@
 void VrTestContext::CycleOrigin() {
   const std::vector<ToolbarState> states = {
       {GURL("http://domain.com"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("https://www.domain.com/path/segment/directory/file.html"),
-       security_state::SecurityLevel::SECURE, &toolbar::kHttpsValidIcon, true,
+       security_state::SecurityLevel::SECURE, &omnibox::kHttpsValidIcon, true,
        false},
       {GURL("https://www.domain.com/path/segment/directory/file.html"),
-       security_state::SecurityLevel::DANGEROUS, &toolbar::kHttpsInvalidIcon,
+       security_state::SecurityLevel::DANGEROUS, &omnibox::kHttpsInvalidIcon,
        true, false},
       // Do not show URL
       {GURL(), security_state::SecurityLevel::HTTP_SHOW_WARNING,
-       &toolbar::kHttpIcon, false, false},
-      {GURL(), security_state::SecurityLevel::SECURE, &toolbar::kHttpsValidIcon,
+       &omnibox::kHttpIcon, false, false},
+      {GURL(), security_state::SecurityLevel::SECURE, &omnibox::kHttpsValidIcon,
        true, false},
       {GURL("file://very-very-very-long-file-hostname/path/path/path/path"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("file:///path/path/path/path/path/path/path/path/path"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       // Elision-related cases.
       {GURL("http://domaaaaaaaaaaain.com"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("http://domaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaain.com"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("http://domain.com/a/"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("http://domain.com/aaaaaaa/"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("http://domain.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("http://domaaaaaaaaaaaaaaaaain.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("http://domaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaain.com/aaaaaaaaaa/"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("http://www.domain.com/path/segment/directory/file.html"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
       {GURL("http://subdomain.domain.com/"),
-       security_state::SecurityLevel::HTTP_SHOW_WARNING, &toolbar::kHttpIcon,
+       security_state::SecurityLevel::HTTP_SHOW_WARNING, &omnibox::kHttpIcon,
        true, false},
   };
 
diff --git a/chrome/browser/vr/toolbar_helper.cc b/chrome/browser/vr/toolbar_helper.cc
index 612caaf..baf59f8 100644
--- a/chrome/browser/vr/toolbar_helper.cc
+++ b/chrome/browser/vr/toolbar_helper.cc
@@ -6,7 +6,7 @@
 
 #include <memory>
 
-#include "components/toolbar/toolbar_model_impl.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 
 class ToolbarModelDelegate;
 
diff --git a/chrome/browser/vr/ui_pixeltest.cc b/chrome/browser/vr/ui_pixeltest.cc
index 64c15d3..3b24fabb 100644
--- a/chrome/browser/vr/ui_pixeltest.cc
+++ b/chrome/browser/vr/ui_pixeltest.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/vr/model/toolbar_state.h"
 #include "chrome/browser/vr/test/constants.h"
 #include "chrome/browser/vr/test/ui_pixel_test.h"
-#include "components/toolbar/vector_icons.h"
+#include "components/omnibox/browser/vector_icons.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace vr {
@@ -25,7 +25,7 @@
   ui_initial_state.web_vr_autopresentation_expected = false;
   MakeUi(ui_initial_state,
          ToolbarState(GURL("https://example.com"), security_state::SECURE,
-                      &toolbar::kHttpsValidIcon, true, false));
+                      &omnibox::kHttpsValidIcon, true, false));
 
   // Draw UI.
   DrawUi(gfx::Vector3dF(0.0f, 0.0f, -1.0f), gfx::Point3F(0.5f, -0.5f, 0.0f),
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc
index 400361d..f746b54 100644
--- a/chrome/browser/vr/ui_scene_creator.cc
+++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -76,8 +76,8 @@
 #include "chrome/browser/vr/ui_scene_constants.h"
 #include "chrome/browser/vr/vector_icons/vector_icons.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/omnibox/browser/vector_icons.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/vector_icons.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/paint_vector_icon.h"
diff --git a/chrome/browser/win/chrome_select_file_dialog_factory.cc b/chrome/browser/win/chrome_select_file_dialog_factory.cc
index 1449717..5888ebe 100644
--- a/chrome/browser/win/chrome_select_file_dialog_factory.cc
+++ b/chrome/browser/win/chrome_select_file_dialog_factory.cc
@@ -7,11 +7,196 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/task/post_task.h"
+#include "base/win/win_util.h"
+#include "chrome/services/util_win/public/mojom/constants.mojom.h"
+#include "chrome/services/util_win/public/mojom/shell_util_win.mojom.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/common/service_manager_connection.h"
+#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "ui/shell_dialogs/execute_select_file_win.h"
 #include "ui/shell_dialogs/select_file_dialog_win.h"
 #include "ui/shell_dialogs/select_file_policy.h"
 
+namespace {
+
+// This feature controls whether or not file dialogs are executed in a utility
+// process on Windows.
+base::Feature kWinOOPSelectFileDialog{"WinOOPSelectFileDialog",
+                                      base::FEATURE_DISABLED_BY_DEFAULT};
+}  // namespace
+
+std::unique_ptr<service_manager::Connector> GetConnectorOnUIThread() {
+  return content::ServiceManagerConnection::GetForProcess()
+      ->GetConnector()
+      ->Clone();
+}
+// static
+
+// Helper class to execute a select file operation on a utility process. It
+// hides the complexity of managing the lifetime of the connection to the
+// ChromeWinUtil service.
+class ShellUtilWinHelper {
+ public:
+  // Executes the select file operation and returns the result via
+  // |on_select_file_executed_callback|.
+  static void ExecuteSelectFile(
+      ui::SelectFileDialog::Type type,
+      const base::string16& title,
+      const base::FilePath& default_path,
+      const std::vector<ui::FileFilterSpec>& filter,
+      int file_type_index,
+      const base::string16& default_extension,
+      HWND owner,
+      ui::OnSelectFileExecutedCallback on_select_file_executed_callback);
+
+ private:
+  ShellUtilWinHelper(
+      ui::SelectFileDialog::Type type,
+      const base::string16& title,
+      const base::FilePath& default_path,
+      const std::vector<ui::FileFilterSpec>& filter,
+      int file_type_index,
+      const base::string16& default_extension,
+      HWND owner,
+      ui::OnSelectFileExecutedCallback on_select_file_executed_callback);
+
+  // Invoked back on the sequence this instance was created on when the
+  // connector is received from the UI thread.
+  void OnConnectorReceived(
+      ui::SelectFileDialog::Type type,
+      const base::string16& title,
+      const base::FilePath& default_path,
+      const std::vector<ui::FileFilterSpec>& filter,
+      int file_type_index,
+      const base::string16& default_extension,
+      HWND owner,
+      std::unique_ptr<service_manager::Connector> connector);
+
+  // Connection error handler for the interface pipe.
+  void OnConnectionError();
+
+  // Forwards the result of the file operation to the
+  // |on_select_file_executed_callback_|.
+  void OnSelectFileExecuted(const std::vector<base::FilePath>& paths,
+                            int index);
+
+  // The pointer to the ShellUtilWin interface. This must be kept alive while
+  // waiting for the response.
+  chrome::mojom::ShellUtilWinPtr shell_util_win_ptr_;
+
+  // The callback that is invoked when the file operation is finished.
+  ui::OnSelectFileExecutedCallback on_select_file_executed_callback_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(ShellUtilWinHelper);
+};
+
+// static
+void ShellUtilWinHelper::ExecuteSelectFile(
+    ui::SelectFileDialog::Type type,
+    const base::string16& title,
+    const base::FilePath& default_path,
+    const std::vector<ui::FileFilterSpec>& filter,
+    int file_type_index,
+    const base::string16& default_extension,
+    HWND owner,
+    ui::OnSelectFileExecutedCallback on_select_file_executed_callback) {
+  // Self-deleting when the select file operation completes.
+  new ShellUtilWinHelper(type, title, default_path, filter, file_type_index,
+                         default_extension, owner,
+                         std::move(on_select_file_executed_callback));
+}
+
+ShellUtilWinHelper::ShellUtilWinHelper(
+    ui::SelectFileDialog::Type type,
+    const base::string16& title,
+    const base::FilePath& default_path,
+    const std::vector<ui::FileFilterSpec>& filter,
+    int file_type_index,
+    const base::string16& default_extension,
+    HWND owner,
+    ui::OnSelectFileExecutedCallback on_select_file_executed_callback)
+    : on_select_file_executed_callback_(
+          std::move(on_select_file_executed_callback)) {
+  // A valid connector is required to create the interface pointer.
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {content::BrowserThread::UI},
+      base::BindOnce(&GetConnectorOnUIThread),
+      base::BindOnce(&ShellUtilWinHelper::OnConnectorReceived,
+                     base::Unretained(this), type, title, default_path, filter,
+                     file_type_index, default_extension, owner));
+}
+
+void ShellUtilWinHelper::OnConnectorReceived(
+    ui::SelectFileDialog::Type type,
+    const base::string16& title,
+    const base::FilePath& default_path,
+    const std::vector<ui::FileFilterSpec>& filter,
+    int file_type_index,
+    const base::string16& default_extension,
+    HWND owner,
+    std::unique_ptr<service_manager::Connector> connector) {
+  connector->BindInterface(chrome::mojom::kUtilWinServiceName,
+                           &shell_util_win_ptr_);
+
+  // |shell_util_win_ptr_| owns the callbacks and is guaranteed to be destroyed
+  // before |this|, therefore making base::Unretained() safe to use.
+  shell_util_win_ptr_.set_connection_error_handler(base::BindOnce(
+      &ShellUtilWinHelper::OnConnectionError, base::Unretained(this)));
+
+  shell_util_win_ptr_->CallExecuteSelectFile(
+      type, base::win::HandleToUint32(owner), title, default_path, filter,
+      file_type_index, default_extension,
+      base::BindOnce(&ShellUtilWinHelper::OnSelectFileExecuted,
+                     base::Unretained(this)));
+}
+
+void ShellUtilWinHelper::OnConnectionError() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  std::move(on_select_file_executed_callback_).Run({}, 0);
+
+  base::UmaHistogramBoolean("Windows.OOPSelectFileDialog.ProcessError", true);
+
+  delete this;
+}
+
+void ShellUtilWinHelper::OnSelectFileExecuted(
+    const std::vector<base::FilePath>& paths,
+    int index) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  base::UmaHistogramBoolean("Windows.OOPSelectFileDialog.ProcessError", false);
+
+  std::move(on_select_file_executed_callback_).Run(paths, index);
+  delete this;
+}
+
+void ExecuteSelectFileImpl(
+    ui::SelectFileDialog::Type type,
+    const base::string16& title,
+    const base::FilePath& default_path,
+    const std::vector<ui::FileFilterSpec>& filter,
+    int file_type_index,
+    const base::string16& default_extension,
+    HWND owner,
+    ui::OnSelectFileExecutedCallback on_select_file_executed_callback) {
+  if (!base::FeatureList::IsEnabled(kWinOOPSelectFileDialog)) {
+    ui::ExecuteSelectFile(type, title, default_path, filter, file_type_index,
+                          default_extension, owner,
+                          std::move(on_select_file_executed_callback));
+    return;
+  }
+
+  ShellUtilWinHelper::ExecuteSelectFile(
+      type, title, default_path, filter, file_type_index, default_extension,
+      owner, std::move(on_select_file_executed_callback));
+}
+
 ChromeSelectFileDialogFactory::ChromeSelectFileDialogFactory() = default;
 
 ChromeSelectFileDialogFactory::~ChromeSelectFileDialogFactory() = default;
@@ -19,8 +204,6 @@
 ui::SelectFileDialog* ChromeSelectFileDialogFactory::Create(
     ui::SelectFileDialog::Listener* listener,
     std::unique_ptr<ui::SelectFilePolicy> policy) {
-  // TODO(pmonette): Re-implement the OOP file dialogs using the ShellUtilWin
-  // interface.
   return ui::CreateWinSelectFileDialog(
-      listener, std::move(policy), base::BindRepeating(&ui::ExecuteSelectFile));
+      listener, std::move(policy), base::BindRepeating(&ExecuteSelectFileImpl));
 }
diff --git a/chrome/common/page_load_metrics/page_load_metrics.mojom b/chrome/common/page_load_metrics/page_load_metrics.mojom
index 1786a84..1fd19480 100644
--- a/chrome/common/page_load_metrics/page_load_metrics.mojom
+++ b/chrome/common/page_load_metrics/page_load_metrics.mojom
@@ -41,6 +41,12 @@
 
   // (Experimental) Time when the page's last image is painted.
   mojo_base.mojom.TimeDelta? last_image_paint;
+
+  // (Experimental) Time when the page's largest text is painted.
+  mojo_base.mojom.TimeDelta? largest_text_paint;
+
+  // (Experimental) Time when the page's last text is painted.
+  mojo_base.mojom.TimeDelta? last_text_paint;
 };
 
 // TimeDeltas below represent durations of time during the page load.
diff --git a/chrome/common/page_load_metrics/page_load_timing.cc b/chrome/common/page_load_metrics/page_load_timing.cc
index 16bc248..357cc80 100644
--- a/chrome/common/page_load_metrics/page_load_timing.cc
+++ b/chrome/common/page_load_metrics/page_load_timing.cc
@@ -29,7 +29,8 @@
   return !timing.first_paint && !timing.first_text_paint &&
          !timing.first_image_paint && !timing.first_contentful_paint &&
          !timing.first_meaningful_paint && !timing.largest_image_paint &&
-         !timing.last_image_paint;
+         !timing.last_image_paint && !timing.largest_text_paint &&
+         !timing.last_text_paint;
 }
 
 bool IsEmpty(const page_load_metrics::mojom::ParseTiming& timing) {
diff --git a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
index 548fe783..2cf3adc 100644
--- a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
+++ b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
@@ -330,6 +330,14 @@
     timing->paint_timing->last_image_paint =
         ClampDelta(perf.LastImagePaint(), start);
   }
+  if (perf.LargestTextPaint() > 0.0) {
+    timing->paint_timing->largest_text_paint =
+        ClampDelta(perf.LargestTextPaint(), start);
+  }
+  if (perf.LastTextPaint() > 0.0) {
+    timing->paint_timing->last_text_paint =
+        ClampDelta(perf.LastTextPaint(), start);
+  }
   if (perf.ParseStart() > 0.0)
     timing->parse_timing->parse_start = ClampDelta(perf.ParseStart(), start);
   if (perf.ParseStop() > 0.0)
diff --git a/chrome/services/util_win/public/mojom/OWNERS b/chrome/services/util_win/public/mojom/OWNERS
index d28aad2..743855d2 100644
--- a/chrome/services/util_win/public/mojom/OWNERS
+++ b/chrome/services/util_win/public/mojom/OWNERS
@@ -3,3 +3,6 @@
 
 per-file *.typemap=set noparent
 per-file *.typemap=file://ipc/SECURITY_OWNERS
+
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chrome/services/util_win/public/mojom/shell_util_mojom_traits.cc b/chrome/services/util_win/public/mojom/shell_util_mojom_traits.cc
new file mode 100644
index 0000000..544bdb8
--- /dev/null
+++ b/chrome/services/util_win/public/mojom/shell_util_mojom_traits.cc
@@ -0,0 +1,74 @@
+// 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 "chrome/services/util_win/public/mojom/shell_util_mojom_traits.h"
+
+#include "mojo/public/cpp/base/string16_mojom_traits.h"
+
+namespace mojo {
+
+// static
+chrome::mojom::SelectFileDialogType EnumTraits<
+    chrome::mojom::SelectFileDialogType,
+    ui::SelectFileDialog::Type>::ToMojom(ui::SelectFileDialog::Type input) {
+  switch (input) {
+    case ui::SelectFileDialog::Type::SELECT_NONE:
+      return chrome::mojom::SelectFileDialogType::kNone;
+    case ui::SelectFileDialog::Type::SELECT_FOLDER:
+      return chrome::mojom::SelectFileDialogType::kFolder;
+    case ui::SelectFileDialog::Type::SELECT_UPLOAD_FOLDER:
+      return chrome::mojom::SelectFileDialogType::kUploadFolder;
+    case ui::SelectFileDialog::Type::SELECT_EXISTING_FOLDER:
+      return chrome::mojom::SelectFileDialogType::kExistingFolder;
+    case ui::SelectFileDialog::Type::SELECT_SAVEAS_FILE:
+      return chrome::mojom::SelectFileDialogType::kSaveAsFile;
+    case ui::SelectFileDialog::Type::SELECT_OPEN_FILE:
+      return chrome::mojom::SelectFileDialogType::kOpenFile;
+    case ui::SelectFileDialog::Type::SELECT_OPEN_MULTI_FILE:
+      return chrome::mojom::SelectFileDialogType::kOpenMultiFile;
+  }
+  NOTREACHED();
+  return chrome::mojom::SelectFileDialogType::kNone;
+}
+
+// static
+bool EnumTraits<chrome::mojom::SelectFileDialogType,
+                ui::SelectFileDialog::Type>::
+    FromMojom(chrome::mojom::SelectFileDialogType input,
+              ui::SelectFileDialog::Type* output) {
+  switch (input) {
+    case chrome::mojom::SelectFileDialogType::kNone:
+      *output = ui::SelectFileDialog::Type::SELECT_NONE;
+      return true;
+    case chrome::mojom::SelectFileDialogType::kFolder:
+      *output = ui::SelectFileDialog::Type::SELECT_FOLDER;
+      return true;
+    case chrome::mojom::SelectFileDialogType::kUploadFolder:
+      *output = ui::SelectFileDialog::Type::SELECT_UPLOAD_FOLDER;
+      return true;
+    case chrome::mojom::SelectFileDialogType::kExistingFolder:
+      *output = ui::SelectFileDialog::Type::SELECT_EXISTING_FOLDER;
+      return true;
+    case chrome::mojom::SelectFileDialogType::kSaveAsFile:
+      *output = ui::SelectFileDialog::Type::SELECT_SAVEAS_FILE;
+      return true;
+    case chrome::mojom::SelectFileDialogType::kOpenFile:
+      *output = ui::SelectFileDialog::Type::SELECT_OPEN_FILE;
+      return true;
+    case chrome::mojom::SelectFileDialogType::kOpenMultiFile:
+      *output = ui::SelectFileDialog::Type::SELECT_OPEN_MULTI_FILE;
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
+// static
+bool StructTraits<chrome::mojom::FileFilterSpecDataView, ui::FileFilterSpec>::
+    Read(chrome::mojom::FileFilterSpecDataView input, ui::FileFilterSpec* out) {
+  return input.ReadDescription(&out->description) &&
+         input.ReadExtensionSpec(&out->extension_spec);
+}
+
+}  // namespace mojo
diff --git a/chrome/services/util_win/public/mojom/shell_util_mojom_traits.h b/chrome/services/util_win/public/mojom/shell_util_mojom_traits.h
new file mode 100644
index 0000000..222d5389d
--- /dev/null
+++ b/chrome/services/util_win/public/mojom/shell_util_mojom_traits.h
@@ -0,0 +1,38 @@
+// 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 CHROME_SERVICES_UTIL_WIN_PUBLIC_MOJOM_SHELL_UTIL_MOJOM_TRAITS_H_
+#define CHROME_SERVICES_UTIL_WIN_PUBLIC_MOJOM_SHELL_UTIL_MOJOM_TRAITS_H_
+
+#include "base/strings/string16.h"
+#include "chrome/services/util_win/public/mojom/shell_util_win.mojom.h"
+#include "ui/shell_dialogs/execute_select_file_win.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<chrome::mojom::SelectFileDialogType,
+                  ui::SelectFileDialog::Type> {
+  static chrome::mojom::SelectFileDialogType ToMojom(
+      ui::SelectFileDialog::Type input);
+  static bool FromMojom(chrome::mojom::SelectFileDialogType input,
+                        ui::SelectFileDialog::Type* output);
+};
+
+template <>
+struct StructTraits<chrome::mojom::FileFilterSpecDataView, ui::FileFilterSpec> {
+  static const base::string16& description(const ui::FileFilterSpec& input) {
+    return input.description;
+  }
+  static const base::string16& extension_spec(const ui::FileFilterSpec& input) {
+    return input.extension_spec;
+  }
+
+  static bool Read(chrome::mojom::FileFilterSpecDataView data,
+                   ui::FileFilterSpec* output);
+};
+
+}  // namespace mojo
+
+#endif  // CHROME_SERVICES_UTIL_WIN_PUBLIC_MOJOM_SHELL_UTIL_MOJOM_TRAITS_H_
diff --git a/chrome/services/util_win/public/mojom/shell_util_win.mojom b/chrome/services/util_win/public/mojom/shell_util_win.mojom
index f402e64..98c6e51 100644
--- a/chrome/services/util_win/public/mojom/shell_util_win.mojom
+++ b/chrome/services/util_win/public/mojom/shell_util_win.mojom
@@ -10,51 +10,66 @@
 import "mojo/public/mojom/base/file_path.mojom";
 import "mojo/public/mojom/base/string16.mojom";
 
+enum SelectFileDialogType {
+  kNone,
+
+  // For opening a folder.
+  kFolder,
+
+  // Like kFolder, but the dialog UI should explicitly show it's
+  // specifically for "upload".
+  kUploadFolder,
+
+  // Like kFolder, but folder creation is disabled, if possible.
+  kExistingFolder,
+
+  // For saving into a file, allowing a nonexistent file to be selected.
+  kSaveAsFile,
+
+  // For opening a file.
+  kOpenFile,
+
+  // Like kOpenFile, but allowing multiple files to open.
+  kOpenMultiFile,
+};
+
+struct FileFilterSpec {
+  mojo_base.mojom.String16 description;
+  mojo_base.mojom.String16 extension_spec;
+};
+
 interface ShellUtilWin {
   // Returns the pinned state of the current executable.
   IsPinnedToTaskbar() => (bool succeeded, bool is_pinned_to_taskbar);
 
-  // Calls OS_WIN ::GetOpenFileName() with parameters:
-  // |owner| HWND to use as the parent of the modal dialog.
-  // |flags| OFN_* flags to use with OPENFILENAME.
-  // |filters| constrains the user's file type selections.
-  // |initial_directory| initial directory to be displayed.
-  // |initial_filename| file name initially selected.
+  // Executes a select file operation that can be executed on a utility process.
+  // |owner|:
+  //   The HWND that owns the file dialog.
+  // |title|:
+  //   The title of the file dialog.
+  // |default_path|:
+  //   The path that is selected by default when the dialog is opened.
+  // |filter|:
+  //   Filters which files are shown based on the file extension. Ignored for
+  //   folder selection dialogs (kFolder, kUploadFolder, kExistingFolder).
+  // |file_type_index|:
+  //   The index of the file extension filter that should be selected when the
+  //   dialog is first opened. Ignored for folder selection dialogs (kFolder,
+  //   kUploadFolder, kExistingFolder).
+  // |default_extension|:
+  //   The extension that should automatically be appended to a filename if it
+  //   doesn't have one. This is only used for kSaveAsFile dialogs.
   //
-  // Returns the list of selected |files| from |directory|. On cancelation
-  // or failure, |files| will be empty.
-  [Sync]
-  CallGetOpenFileName(uint32 owner,
-                      uint32 flags,
-                      FileExtensionFilters filters,
-                      mojo_base.mojom.FilePath initial_directory,
-                      mojo_base.mojom.FilePath initial_filename) =>
-      (mojo_base.mojom.FilePath directory,
-       array<mojo_base.mojom.FilePath> files);
-
-  // Calls OS_WIN ::GetSaveFileName() with parameters:
-  // |owner| HWND to use as the parent of the modal dialog.
-  // |flags| OFN_* flags to use with OPENFILENAME.
-  // |filters| constrains the user's file type selections.
-  // |one_based_filter_index| index of the selected filter in |filters|.
-  // |initial_directory| initial directory to be displayed.
-  // |suggested_filename| save file name to suggest.
-  // |default_extension| file extension to use if the user doesn't type one.
-  //
-  // Returns the save file |path| selected, and the |filter_index| of the
-  // filter selected, by the user. On cancelation or failure, |path| will
-  // be empty.
-  [Sync]
-  CallGetSaveFileName(uint32 owner,
-                      uint32 flags,
-                      FileExtensionFilters filters,
-                      uint32 one_based_filter_index,
-                      mojo_base.mojom.FilePath initial_directory,
-                      mojo_base.mojom.FilePath suggested_filename,
-                      mojo_base.mojom.String16 default_extension) =>
-      (mojo_base.mojom.FilePath path,
-       uint32 filter_index);
+  // Returns the selected file |paths| and the |file_type_index| of the filter
+  // selected by the user. The |file_type_index| return value is meaningless on
+  // folder selection dialogs. On cancelation or failure, |paths| will be empty.
+  CallExecuteSelectFile(SelectFileDialogType type,
+                        uint32 owner,
+                        mojo_base.mojom.String16 title,
+                        mojo_base.mojom.FilePath default_path,
+                        array<FileFilterSpec> filter,
+                        int32 file_type_index,
+                        mojo_base.mojom.String16 default_extension) =>
+      (array<mojo_base.mojom.FilePath> paths,
+       int32 file_type_index);
 };
-
-[Native]
-struct FileExtensionFilters;
diff --git a/chrome/services/util_win/public/mojom/shell_util_win.typemap b/chrome/services/util_win/public/mojom/shell_util_win.typemap
index dcbf2a0..7511a5c 100644
--- a/chrome/services/util_win/public/mojom/shell_util_win.typemap
+++ b/chrome/services/util_win/public/mojom/shell_util_win.typemap
@@ -4,12 +4,25 @@
 
 mojom = "//chrome/services/util_win/public/mojom/shell_util_win.mojom"
 
-public_headers = [ "//base/strings/string16.h" ]
-traits_headers = [ "//ipc/ipc_message_utils.h" ]
+public_headers = [
+  "//base/strings/string16.h",
+  "//ui/shell_dialogs/execute_select_file_win.h",
+  "//ui/shell_dialogs/select_file_dialog.h",
+]
+traits_headers = [
+  "//ipc/ipc_message_utils.h",
+  "//chrome/services/util_win/public/mojom/shell_util_mojom_traits.h",
+]
+sources = [
+  "//chrome/services/util_win/public/mojom/shell_util_mojom_traits.cc",
+]
 
 deps = [
   "//base",
+  "//ui/shell_dialogs",
 ]
 
-type_mappings = [ "chrome.mojom.FileExtensionFilters=" +
-                  "std::vector<std::tuple<base::string16, base::string16>>" ]
+type_mappings = [
+  "chrome.mojom.FileFilterSpec=ui::FileFilterSpec",
+  "chrome.mojom.SelectFileDialogType=ui::SelectFileDialog::Type",
+]
diff --git a/chrome/services/util_win/shell_util_win_impl.cc b/chrome/services/util_win/shell_util_win_impl.cc
index c6ecc65..ca6a636 100644
--- a/chrome/services/util_win/shell_util_win_impl.cc
+++ b/chrome/services/util_win/shell_util_win_impl.cc
@@ -8,6 +8,8 @@
 #include <shldisp.h>
 #include <wrl/client.h>
 
+#include <utility>
+
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/path_service.h"
@@ -20,6 +22,7 @@
 #include "base/win/win_util.h"
 #include "chrome/installer/util/install_util.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "ui/shell_dialogs/execute_select_file_win.h"
 
 namespace {
 
@@ -224,24 +227,19 @@
   std::move(callback).Run(!helper.error_occured(), is_pinned_to_taskbar);
 }
 
-void ShellUtilWinImpl::CallGetOpenFileName(
+void ShellUtilWinImpl::CallExecuteSelectFile(
+    ui::SelectFileDialog::Type type,
     uint32_t owner,
-    uint32_t flags,
-    const std::vector<std::tuple<base::string16, base::string16>>& filters,
-    const base::FilePath& initial_directory,
-    const base::FilePath& initial_filename,
-    CallGetOpenFileNameCallback callback) {
-  std::move(callback).Run(base::FilePath(), std::vector<base::FilePath>());
-}
-
-void ShellUtilWinImpl::CallGetSaveFileName(
-    uint32_t owner,
-    uint32_t flags,
-    const std::vector<std::tuple<base::string16, base::string16>>& filters,
-    uint32_t one_based_filter_index,
-    const base::FilePath& initial_directory,
-    const base::FilePath& suggested_filename,
+    const base::string16& title,
+    const base::FilePath& default_path,
+    const std::vector<ui::FileFilterSpec>& filter,
+    int32_t file_type_index,
     const base::string16& default_extension,
-    CallGetSaveFileNameCallback callback) {
-  std::move(callback).Run(base::FilePath(), 0);
+    CallExecuteSelectFileCallback callback) {
+  base::win::ScopedCOMInitializer scoped_com_initializer;
+
+  ui::ExecuteSelectFile(
+      type, title, default_path, filter, file_type_index, default_extension,
+      reinterpret_cast<HWND>(base::win::Uint32ToHandle(owner)),
+      base::BindOnce(std::move(callback)));
 }
diff --git a/chrome/services/util_win/shell_util_win_impl.h b/chrome/services/util_win/shell_util_win_impl.h
index 7bed780..679ce549 100644
--- a/chrome/services/util_win/shell_util_win_impl.h
+++ b/chrome/services/util_win/shell_util_win_impl.h
@@ -5,7 +5,12 @@
 #ifndef CHROME_SERVICES_UTIL_WIN_SHELL_UTIL_WIN_IMPL_H_
 #define CHROME_SERVICES_UTIL_WIN_SHELL_UTIL_WIN_IMPL_H_
 
+#include <memory>
+#include <vector>
+
+#include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/strings/string16.h"
 #include "chrome/services/util_win/public/mojom/shell_util_win.mojom.h"
 #include "services/service_manager/public/cpp/service_context_ref.h"
 
@@ -18,24 +23,14 @@
  private:
   // chrome::mojom::ShellUtilWin:
   void IsPinnedToTaskbar(IsPinnedToTaskbarCallback callback) override;
-
-  void CallGetOpenFileName(
-      uint32_t owner,
-      uint32_t flags,
-      const std::vector<std::tuple<base::string16, base::string16>>& filters,
-      const base::FilePath& initial_directory,
-      const base::FilePath& initial_filename,
-      CallGetOpenFileNameCallback callback) override;
-
-  void CallGetSaveFileName(
-      uint32_t owner,
-      uint32_t flags,
-      const std::vector<std::tuple<base::string16, base::string16>>& filters,
-      uint32_t one_based_filter_index,
-      const base::FilePath& initial_directory,
-      const base::FilePath& suggested_filename,
-      const base::string16& default_extension,
-      CallGetSaveFileNameCallback callback) override;
+  void CallExecuteSelectFile(ui::SelectFileDialog::Type type,
+                             uint32_t owner,
+                             const base::string16& title,
+                             const base::FilePath& default_path,
+                             const std::vector<ui::FileFilterSpec>& filter,
+                             int32_t file_type_index,
+                             const base::string16& default_extension,
+                             CallExecuteSelectFileCallback callback) override;
 
   const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 4ed6bd7..322c649 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -166,7 +166,6 @@
     "//components/sync:test_support_driver",
     "//components/sync_preferences:test_support",
     "//components/sync_sessions:test_support",
-    "//components/toolbar:test_support",
     "//components/unified_consent:test_support",
     "//components/update_client:test_support",
     "//components/variations:test_support",
@@ -1988,6 +1987,7 @@
     }
     if (is_win) {
       sources += [
+        "../browser/browser_switcher/browser_switcher_service_browsertest.cc",
         "../browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc",
         "../browser/printing/pdf_to_emf_converter_browsertest.cc",
         "../browser/ui/views/accessibility/invert_bubble_view_browsertest.cc",
@@ -4803,6 +4803,7 @@
 
     if (use_aura) {
       sources += [ "../browser/ui/views/drag_and_drop_interactive_uitest.cc" ]
+      deps += [ "//ui/aura:aura_interactive_ui_tests" ]
     } else {
       sources -= [
         "base/interactive_test_utils_aura.cc",
diff --git a/chromecast/browser/cast_media_blocker_unittest.cc b/chromecast/browser/cast_media_blocker_unittest.cc
index 4bb1a53..ee7d25e 100644
--- a/chromecast/browser/cast_media_blocker_unittest.cc
+++ b/chromecast/browser/cast_media_blocker_unittest.cc
@@ -44,6 +44,8 @@
   MOCK_METHOD1(RemoveObserver, void(content::MediaSessionObserver*));
   MOCK_METHOD1(GetMediaSessionInfo, void(GetMediaSessionInfoCallback));
   MOCK_METHOD1(GetDebugInfo, void(GetDebugInfoCallback));
+  MOCK_METHOD0(PreviousTrack, void());
+  MOCK_METHOD0(NextTrack, void());
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockMediaSession);
diff --git a/chromeos/components/proximity_auth/screenlock_bridge.cc b/chromeos/components/proximity_auth/screenlock_bridge.cc
index 7dbff991..97ec95c 100644
--- a/chromeos/components/proximity_auth/screenlock_bridge.cc
+++ b/chromeos/components/proximity_auth/screenlock_bridge.cc
@@ -54,9 +54,7 @@
 }  // namespace
 
 ScreenlockBridge::UserPodCustomIconOptions::UserPodCustomIconOptions()
-    : autoshow_tooltip_(false),
-      hardlock_on_click_(false),
-      is_trial_run_(false) {}
+    : autoshow_tooltip_(false), hardlock_on_click_(false) {}
 
 ScreenlockBridge::UserPodCustomIconOptions::~UserPodCustomIconOptions() {}
 
@@ -78,9 +76,6 @@
   if (hardlock_on_click_)
     result->SetBoolean("hardlockOnClick", true);
 
-  if (is_trial_run_)
-    result->SetBoolean("isTrialRun", true);
-
   return result;
 }
 
@@ -105,10 +100,6 @@
   hardlock_on_click_ = true;
 }
 
-void ScreenlockBridge::UserPodCustomIconOptions::SetTrialRun() {
-  is_trial_run_ = true;
-}
-
 std::string ScreenlockBridge::UserPodCustomIconOptions::GetIDString() const {
   return GetIdForIcon(icon_);
 }
diff --git a/chromeos/components/proximity_auth/screenlock_bridge.h b/chromeos/components/proximity_auth/screenlock_bridge.h
index 7ce128d..d4641aa 100644
--- a/chromeos/components/proximity_auth/screenlock_bridge.h
+++ b/chromeos/components/proximity_auth/screenlock_bridge.h
@@ -68,10 +68,6 @@
     // go to state where password is required for unlock.
     void SetHardlockOnClick();
 
-    // If the current lock screen is a trial run to introduce users to Easy
-    // Unlock, the icon will record metrics upon click.
-    void SetTrialRun();
-
     std::string GetIDString() const;
 
     UserPodCustomIcon icon() const { return icon_; }
@@ -84,8 +80,6 @@
 
     bool hardlock_on_click() const { return hardlock_on_click_; }
 
-    bool is_trial_run() const { return is_trial_run_; }
-
    private:
     UserPodCustomIcon icon_;
 
@@ -96,8 +90,6 @@
 
     bool hardlock_on_click_;
 
-    bool is_trial_run_;
-
     DISALLOW_COPY_AND_ASSIGN(UserPodCustomIconOptions);
   };
 
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index f322e8f..fbb5f24 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -57,6 +57,9 @@
 constexpr char kQueryDeeplinkPrefix[] = "googleassistant://send-query?q=";
 constexpr base::Feature kAssistantTimerNotificationFeature{
     "ChromeOSAssistantTimerNotification", base::FEATURE_ENABLED_BY_DEFAULT};
+constexpr base::Feature kChromeOSAssistantDogfood{
+    "ChromeOSAssistantDogfood", base::FEATURE_DISABLED_BY_DEFAULT};
+constexpr char kServersideDogfoodExperimentId[] = "20347368";
 
 constexpr float kDefaultSliderStep = 0.1f;
 }  // namespace
@@ -777,6 +780,12 @@
   assistant_manager_->AddConversationStateListener(this);
   assistant_manager_->AddDeviceStateListener(this);
 
+  std::vector<std::string> server_experiment_ids;
+  FillServerExperimentIds(server_experiment_ids);
+
+  if (server_experiment_ids.size() > 0)
+    assistant_manager_internal_->AddExtraExperimentIds(server_experiment_ids);
+
   SetAccessToken(access_token);
 
   assistant_manager_->Start();
@@ -1162,5 +1171,13 @@
   last_search_source_ = std::string();
   return search_source;
 }
+
+void AssistantManagerServiceImpl::FillServerExperimentIds(
+    std::vector<std::string>& server_experiment_ids) {
+  if (base::FeatureList::IsEnabled(kChromeOSAssistantDogfood)) {
+    server_experiment_ids.emplace_back(kServersideDogfoodExperimentId);
+  }
+}
+
 }  // namespace assistant
 }  // namespace chromeos
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h
index 950d5142..8c5c31ab0 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.h
+++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -210,6 +210,8 @@
       std::unique_ptr<ui::AssistantTree> assistant_tree,
       const std::vector<uint8_t>& assistant_screenshot);
 
+  void FillServerExperimentIds(std::vector<std::string>& server_experiment_ids);
+
   State state_ = State::STOPPED;
   std::unique_ptr<PlatformApiImpl> platform_api_;
   bool enable_hotword_;
diff --git a/components/BUILD.gn b/components/BUILD.gn
index c1f38af..2ef826b 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -157,7 +157,6 @@
     "//components/sync_sessions:unit_tests",
     "//components/task_scheduler_util:unit_tests",
     "//components/test:run_all_unittests",
-    "//components/toolbar:unit_tests",
     "//components/translate/core/browser:unit_tests",
     "//components/translate/core/common:unit_tests",
     "//components/translate/core/language_detection:unit_tests",
@@ -340,7 +339,10 @@
   }
 
   if (is_win) {
-    deps += [ "//components/browser_watcher:unit_tests" ]
+    deps += [
+      "//components/browser_watcher:unit_tests",
+      "//components/gwp_asan/common:unit_tests",
+    ]
   }
 
   if (enable_basic_printing) {
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index e2f3aa9..ed4587b 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -1445,6 +1445,111 @@
   return s.Succeeded();
 }
 
+void AutofillTable::SetServerCardsData(
+    const std::vector<CreditCard>& credit_cards) {
+  sql::Transaction transaction(db_);
+  if (!transaction.Begin())
+    return;
+
+  // Delete all old values.
+  sql::Statement masked_delete(
+      db_->GetUniqueStatement("DELETE FROM masked_credit_cards"));
+  masked_delete.Run();
+
+  // Add all the masked cards.
+  sql::Statement masked_insert(
+      db_->GetUniqueStatement("INSERT INTO masked_credit_cards("
+                              "id,"            // 0
+                              "network,"       // 1
+                              "type,"          // 2
+                              "status,"        // 3
+                              "name_on_card,"  // 4
+                              "last_four,"     // 5
+                              "exp_month,"     // 6
+                              "exp_year,"      // 7
+                              "bank_name)"     // 8
+                              "VALUES (?,?,?,?,?,?,?,?,?)"));
+  for (const CreditCard& card : credit_cards) {
+    DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type());
+    masked_insert.BindString(0, card.server_id());
+    masked_insert.BindString(1, card.network());
+    masked_insert.BindInt(2, card.card_type());
+    masked_insert.BindString(3,
+                             ServerStatusEnumToString(card.GetServerStatus()));
+    masked_insert.BindString16(4, card.GetRawInfo(CREDIT_CARD_NAME_FULL));
+    masked_insert.BindString16(5, card.LastFourDigits());
+    masked_insert.BindString16(6, card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
+    masked_insert.BindString16(7,
+                               card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+    masked_insert.BindString(8, card.bank_name());
+    masked_insert.Run();
+    masked_insert.Reset(true);
+  }
+
+  // Delete all items in the unmasked table that aren't in the new set.
+  sql::Statement unmasked_delete(db_->GetUniqueStatement(
+      "DELETE FROM unmasked_credit_cards WHERE id NOT IN "
+      "(SELECT id FROM masked_credit_cards)"));
+  unmasked_delete.Run();
+
+  transaction.Commit();
+}
+
+void AutofillTable::SetServerAddressesData(
+    const std::vector<AutofillProfile>& profiles) {
+  sql::Transaction transaction(db_);
+  if (!transaction.Begin())
+    return;
+
+  // Delete existing server addresses.
+  sql::Statement delete_old(
+      db_->GetUniqueStatement("DELETE FROM server_addresses"));
+  delete_old.Run();
+
+  // Add the new server addresses.
+  sql::Statement insert(db_->GetUniqueStatement(
+      "INSERT INTO server_addresses("
+      "id,"
+      "recipient_name,"
+      "company_name,"
+      "street_address,"
+      "address_1,"     // ADDRESS_HOME_STATE
+      "address_2,"     // ADDRESS_HOME_CITY
+      "address_3,"     // ADDRESS_HOME_DEPENDENT_LOCALITY
+      "address_4,"     // Not supported in AutofillProfile yet.
+      "postal_code,"   // ADDRESS_HOME_ZIP
+      "sorting_code,"  // ADDRESS_HOME_SORTING_CODE
+      "country_code,"  // ADDRESS_HOME_COUNTRY
+      "phone_number,"  // PHONE_HOME_WHOLE_NUMBER
+      "language_code) "
+      "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+  for (const auto& profile : profiles) {
+    DCHECK(profile.record_type() == AutofillProfile::SERVER_PROFILE);
+
+    int index = 0;
+    insert.BindString(index++, profile.server_id());
+    insert.BindString16(index++, profile.GetRawInfo(NAME_FULL));
+    insert.BindString16(index++, profile.GetRawInfo(COMPANY_NAME));
+    insert.BindString16(index++,
+                        profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_STATE));
+    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_CITY));
+    insert.BindString16(index++,
+                        profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
+    index++;  // SKip address_4 which we haven't added to AutofillProfile yet.
+    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_ZIP));
+    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE));
+    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
+    insert.BindString16(index++, profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
+    insert.BindString(index++, profile.language_code());
+
+    insert.Run();
+    insert.Reset(true);
+  }
+
+  transaction.Commit();
+}
+
 void AutofillTable::SetPaymentsCustomerData(
     const PaymentsCustomerData* customer_data) {
   sql::Transaction transaction(db_);
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h
index 51adbdd..8af3e21 100644
--- a/components/autofill/core/browser/webdata/autofill_table.h
+++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -418,6 +418,11 @@
   bool GetServerAddressesMetadata(
       std::map<std::string, AutofillMetadata>* addresses_metadata) const;
 
+  // Methods to add the server cards and addresses data independently from the
+  // metadata.
+  void SetServerCardsData(const std::vector<CreditCard>& credit_cards);
+  void SetServerAddressesData(const std::vector<AutofillProfile>& profiles);
+
   // Setters and getters related to the Google Payments customer data.
   // Passing null to the setter will clear the data.
   void SetPaymentsCustomerData(const PaymentsCustomerData* customer_data);
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index d51108a..6b20deb 100644
--- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -2002,6 +2002,131 @@
   ASSERT_EQ(1U, outputs.size());
 }
 
+TEST_F(AutofillTableTest, SetServerCardsData) {
+  // Set a card data.
+  std::vector<CreditCard> inputs;
+  inputs.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "card1"));
+  inputs[0].SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Rick Roman"));
+  inputs[0].SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("12"));
+  inputs[0].SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("1997"));
+  inputs[0].SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("1111"));
+  inputs[0].SetNetworkForMaskedCard(kVisaCard);
+  inputs[0].SetServerStatus(CreditCard::EXPIRED);
+  table_->SetServerCardsData(inputs);
+
+  // Make sure the card was added correctly.
+  std::vector<std::unique_ptr<CreditCard>> outputs;
+  ASSERT_TRUE(table_->GetServerCreditCards(&outputs));
+  ASSERT_EQ(inputs.size(), outputs.size());
+
+  // GUIDs for server cards are dynamically generated so will be different
+  // after reading from the DB. Check they're valid, but otherwise don't count
+  // them in the comparison.
+  inputs[0].set_guid(std::string());
+  outputs[0]->set_guid(std::string());
+
+  EXPECT_EQ(inputs[0], *outputs[0]);
+  EXPECT_EQ(CreditCard::EXPIRED, outputs[0]->GetServerStatus());
+
+  // Make sure no metadata was added.
+  std::map<std::string, AutofillMetadata> metadata_map;
+  ASSERT_TRUE(table_->GetServerCardsMetadata(&metadata_map));
+  ASSERT_EQ(0U, metadata_map.size());
+
+  // Set a different card.
+  inputs[0] = CreditCard(CreditCard::MASKED_SERVER_CARD, "card2");
+  table_->SetServerCardsData(inputs);
+
+  // The original one should have been replaced.
+  ASSERT_TRUE(table_->GetServerCreditCards(&outputs));
+  ASSERT_EQ(1U, outputs.size());
+  EXPECT_EQ("card2", outputs[0]->server_id());
+
+  // Make sure no metadata was added.
+  ASSERT_TRUE(table_->GetServerCardsMetadata(&metadata_map));
+  ASSERT_EQ(0U, metadata_map.size());
+}
+
+// Tests that adding server cards data does not delete the existing metadata.
+TEST_F(AutofillTableTest, SetServerCardsData_ExistingMetadata) {
+  // Create and set some metadata.
+  AutofillMetadata input;
+  input.id = "server id";
+  input.use_count = 50;
+  input.use_date = Time::Now();
+  input.billing_address_id = "billing id";
+  table_->AddServerCardMetadata(input);
+
+  // Set a card data.
+  std::vector<CreditCard> inputs;
+  inputs.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "server id"));
+  table_->SetServerCardsData(inputs);
+
+  // Make sure the metadata is still intact.
+  std::map<std::string, AutofillMetadata> outputs;
+  ASSERT_TRUE(table_->GetServerCardsMetadata(&outputs));
+  ASSERT_EQ(1U, outputs.size());
+  EXPECT_EQ(input, outputs[input.id]);
+}
+
+TEST_F(AutofillTableTest, SetServerAddressesData) {
+  AutofillProfile one(AutofillProfile::SERVER_PROFILE, "a123");
+  std::vector<AutofillProfile> inputs;
+  inputs.push_back(one);
+  table_->SetServerAddressesData(inputs);
+
+  // Make sure the address was added correctly.
+  std::vector<std::unique_ptr<AutofillProfile>> outputs;
+  table_->GetServerProfiles(&outputs);
+  ASSERT_EQ(1u, outputs.size());
+  EXPECT_EQ(one.server_id(), outputs[0]->server_id());
+
+  outputs.clear();
+
+  // Make sure no metadata was added.
+  std::map<std::string, AutofillMetadata> metadata_map;
+  ASSERT_TRUE(table_->GetServerAddressesMetadata(&metadata_map));
+  ASSERT_EQ(0U, metadata_map.size());
+
+  // Set a different profile.
+  AutofillProfile two(AutofillProfile::SERVER_PROFILE, "b456");
+  inputs[0] = two;
+  table_->SetServerAddressesData(inputs);
+
+  // The original one should have been replaced.
+  table_->GetServerProfiles(&outputs);
+  ASSERT_EQ(1u, outputs.size());
+  EXPECT_EQ(two.server_id(), outputs[0]->server_id());
+
+  // Make sure no metadata was added.
+  ASSERT_TRUE(table_->GetServerAddressesMetadata(&metadata_map));
+  ASSERT_EQ(0U, metadata_map.size());
+}
+
+// Tests that adding server addresses data does not delete the existing
+// metadata.
+TEST_F(AutofillTableTest, SetServerAddressesData_ExistingMetadata) {
+  // Create and set some metadata.
+  AutofillMetadata input;
+  input.id = "server id";
+  input.use_count = 50;
+  input.use_date = Time::Now();
+  input.has_converted = true;
+  table_->AddServerAddressMetadata(input);
+
+  // Set an address data.
+  std::vector<AutofillProfile> inputs;
+  inputs.push_back(
+      AutofillProfile(AutofillProfile::SERVER_PROFILE, "server id"));
+  table_->SetServerAddressesData(inputs);
+
+  // Make sure the metadata is still intact.
+  std::map<std::string, AutofillMetadata> outputs;
+  ASSERT_TRUE(table_->GetServerAddressesMetadata(&outputs));
+  ASSERT_EQ(1U, outputs.size());
+  EXPECT_EQ(input, outputs[input.id]);
+}
+
 TEST_F(AutofillTableTest, RemoveWrongServerAddressMetadata) {
   // Crete and set some metadata.
   AutofillMetadata input;
diff --git a/components/autofill_assistant/browser/actions/wait_for_dom_action.cc b/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
index b5162a03..92a877ad 100644
--- a/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
+++ b/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
@@ -29,8 +29,9 @@
                                              ProcessActionCallback callback) {
   DCHECK_GT(proto_.wait_for_dom().selectors_size(), 0);
   batch_element_checker_ = delegate->CreateBatchElementChecker();
-  batch_element_checker_->AddElementExistenceCheck(
-      ExtractSelectors(proto_.wait_for_dom().selectors()), base::DoNothing());
+  batch_element_checker_->AddElementCheck(
+      kVisibilityCheck, ExtractSelectors(proto_.wait_for_dom().selectors()),
+      base::DoNothing());
 
   base::TimeDelta duration = kDefaultCheckDuration;
   int timeout_ms = proto_.wait_for_dom().timeout_ms();
diff --git a/components/autofill_assistant/browser/batch_element_checker.cc b/components/autofill_assistant/browser/batch_element_checker.cc
index 9817afb..99b56c3 100644
--- a/components/autofill_assistant/browser/batch_element_checker.cc
+++ b/components/autofill_assistant/browser/batch_element_checker.cc
@@ -21,7 +21,7 @@
 
 BatchElementChecker::BatchElementChecker(WebController* web_controller)
     : web_controller_(web_controller),
-      pending_preconditions_to_check_count_(0),
+      pending_checks_count_(0),
       all_found_(false),
       stopped_(false),
       weak_ptr_factory_(this) {
@@ -30,22 +30,22 @@
 
 BatchElementChecker::~BatchElementChecker() {}
 
-void BatchElementChecker::AddElementExistenceCheck(
+void BatchElementChecker::AddElementCheck(
+    ElementCheckType check_type,
     const std::vector<std::string>& selectors,
-    base::OnceCallback<void(bool)> callback) {
+    ElementCheckCallback callback) {
   DCHECK(!try_done_callback_);
 
-  element_callback_map_[selectors].element_exists_callbacks.emplace_back(
+  element_check_callbacks_[std::make_pair(check_type, selectors)].emplace_back(
       std::move(callback));
 }
 
 void BatchElementChecker::AddFieldValueCheck(
     const std::vector<std::string>& selectors,
-    base::OnceCallback<void(bool, const std::string&)> callback) {
+    GetFieldValueCallback callback) {
   DCHECK(!try_done_callback_);
 
-  element_callback_map_[selectors].get_field_value_callbacks.emplace_back(
-      std::move(callback));
+  get_field_value_callbacks_[selectors].emplace_back(std::move(callback));
 }
 
 void BatchElementChecker::Run(const base::TimeDelta& duration,
@@ -62,9 +62,6 @@
       base::Unretained(this), try_count, try_done, std::move(all_done)));
 }
 
-BatchElementChecker::ElementCallbacks::ElementCallbacks() {}
-BatchElementChecker::ElementCallbacks::~ElementCallbacks() {}
-
 void BatchElementChecker::Try(base::OnceCallback<void()> try_done_callback) {
   DCHECK(!try_done_callback_);
 
@@ -74,43 +71,53 @@
   }
   try_done_callback_ = std::move(try_done_callback);
 
-  DCHECK_EQ(pending_preconditions_to_check_count_, 0);
-  pending_preconditions_to_check_count_ = element_callback_map_.size();
-  // Done the check if there is nothing to check.
-  if (!pending_preconditions_to_check_count_) {
-    CheckTryDone();
-    return;
-  }
+  DCHECK_EQ(pending_checks_count_, 0);
+  pending_checks_count_ =
+      element_check_callbacks_.size() + get_field_value_callbacks_.size() + 1;
 
-  size_t total_number_of_loops = pending_preconditions_to_check_count_;
-  for (auto iter = element_callback_map_.begin();
-       iter != element_callback_map_.end(); iter++) {
-    if (!iter->second.get_field_value_callbacks.empty()) {
-      web_controller_->GetFieldValue(
-          iter->first, base::BindOnce(&BatchElementChecker::OnGetFieldValue,
-                                      weak_ptr_factory_.GetWeakPtr(), iter));
-    } else if (!iter->second.element_exists_callbacks.empty()) {
-      web_controller_->ElementExists(
-          iter->first, base::BindOnce(&BatchElementChecker::OnElementExists,
-                                      weak_ptr_factory_.GetWeakPtr(), iter));
-    } else {
-      // Uninteresting entries
-      pending_preconditions_to_check_count_--;
-      CheckTryDone();
+  for (auto& entry : element_check_callbacks_) {
+    if (entry.second.empty()) {
+      pending_checks_count_--;
+      continue;
     }
 
-    // This is an ugly workaround for unit tests. 'all_done' callback will be
-    // called synchronously since mocked web_controller is synchronous. And we
-    // can not simply make it asynchronous since a lot of unit tests rely on
-    // synchronous callback. During the callback consumer may destruct this
-    // class which causes crash since 'element_callback_map_' is deleted.
-    //
-    // TODO(crbug.com/806868): make sure 'all_done' callback is called
-    // asynchronously and fix unit tests accordingly.
-    total_number_of_loops--;
-    if (!total_number_of_loops)
-      return;
+    const auto& call_arguments = entry.first;
+    web_controller_->ElementCheck(
+        call_arguments.first, call_arguments.second,
+        base::BindOnce(
+            &BatchElementChecker::OnElementChecked,
+            weak_ptr_factory_.GetWeakPtr(),
+            // Guaranteed to exist for the lifetime of this instance, because
+            // the map isn't modified after Run has been called.
+            base::Unretained(&entry.second)));
   }
+
+  for (auto& entry : get_field_value_callbacks_) {
+    if (entry.second.empty()) {
+      pending_checks_count_--;
+      continue;
+    }
+
+    web_controller_->GetFieldValue(
+        entry.first,
+        base::BindOnce(
+            &BatchElementChecker::OnGetFieldValue,
+            weak_ptr_factory_.GetWeakPtr(),
+            // Guaranteed to exist for the lifetime of this instance, because
+            // the map isn't modified after Run has been called.
+            base::Unretained(&entry.second)));
+  }
+
+  // The extra +1 of pending_check_count and this check happening last
+  // guarantees that all_done cannot be called before the end of this function.
+  // Without this, callbacks could be called synchronously by the web
+  // controller, the call all_done, which could delete this instance and all its
+  // datastructures while the function is still going through them.
+  //
+  // TODO(crbug.com/806868): make sure 'all_done' callback is called
+  // asynchronously and fix unit tests accordingly.
+  pending_checks_count_--;
+  CheckTryDone();
 }
 
 void BatchElementChecker::OnTryDone(int64_t remaining_attempts,
@@ -144,68 +151,71 @@
 }
 
 void BatchElementChecker::GiveUp() {
-  for (auto& entry : element_callback_map_) {
-    ElementCallbacks* callbacks = &entry.second;
-    RunElementExistsCallbacks(callbacks, false);
-    RunGetFieldValueCallbacks(callbacks, false, "");
+  for (auto& entry : element_check_callbacks_) {
+    RunCallbacks(&entry.second, false);
+  }
+  for (auto& entry : get_field_value_callbacks_) {
+    RunCallbacks(&entry.second, false, "");
   }
 }
 
-void BatchElementChecker::OnElementExists(ElementCallbackMap::iterator iter,
-                                          bool exists) {
-  pending_preconditions_to_check_count_--;
+void BatchElementChecker::OnElementChecked(
+    std::vector<ElementCheckCallback>* callbacks,
+    bool exists) {
+  pending_checks_count_--;
   if (exists)
-    RunElementExistsCallbacks(&iter->second, true);
+    RunCallbacks(callbacks, true);
 
   CheckTryDone();
 }
 
-void BatchElementChecker::OnGetFieldValue(ElementCallbackMap::iterator iter,
-                                          bool exists,
-                                          const std::string& value) {
-  pending_preconditions_to_check_count_--;
-  if (exists) {
-    RunElementExistsCallbacks(&iter->second, exists);
-    RunGetFieldValueCallbacks(&iter->second, exists, value);
-  }
+void BatchElementChecker::OnGetFieldValue(
+    std::vector<GetFieldValueCallback>* callbacks,
+    bool exists,
+    const std::string& value) {
+  pending_checks_count_--;
+  if (exists)
+    RunCallbacks(callbacks, exists, value);
 
   CheckTryDone();
 }
 
 void BatchElementChecker::CheckTryDone() {
-  DCHECK_GE(pending_preconditions_to_check_count_, 0);
-  if (pending_preconditions_to_check_count_ <= 0 && try_done_callback_) {
+  DCHECK_GE(pending_checks_count_, 0);
+  if (pending_checks_count_ <= 0 && try_done_callback_) {
     all_found_ = !HasMoreChecksToRun();
     std::move(try_done_callback_).Run();
   }
 }
 
-bool BatchElementChecker::HasMoreChecksToRun() {
-  for (const auto& entry : element_callback_map_) {
-    if (!entry.second.element_exists_callbacks.empty())
-      return true;
+void BatchElementChecker::RunCallbacks(
+    std::vector<ElementCheckCallback>* callbacks,
+    bool result) {
+  for (auto& callback : *callbacks) {
+    std::move(callback).Run(result);
+  }
+  callbacks->clear();
+}
 
-    if (!entry.second.get_field_value_callbacks.empty())
+void BatchElementChecker::RunCallbacks(
+    std::vector<GetFieldValueCallback>* callbacks,
+    bool exists,
+    const std::string& value) {
+  for (auto& callback : *callbacks) {
+    std::move(callback).Run(exists, value);
+  }
+  callbacks->clear();
+}
+
+bool BatchElementChecker::HasMoreChecksToRun() {
+  for (const auto& entry : element_check_callbacks_) {
+    if (!entry.second.empty())
+      return true;
+  }
+  for (const auto& entry : get_field_value_callbacks_) {
+    if (!entry.second.empty())
       return true;
   }
   return false;
 }
-
-void BatchElementChecker::RunElementExistsCallbacks(ElementCallbacks* callbacks,
-                                                    bool result) {
-  for (auto& callback : callbacks->element_exists_callbacks) {
-    std::move(callback).Run(result);
-  }
-  callbacks->element_exists_callbacks.clear();
-}
-
-void BatchElementChecker::RunGetFieldValueCallbacks(ElementCallbacks* callbacks,
-                                                    bool exists,
-                                                    const std::string& value) {
-  for (auto& callback : callbacks->get_field_value_callbacks) {
-    std::move(callback).Run(exists, value);
-  }
-  callbacks->get_field_value_callbacks.clear();
-}
-
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/batch_element_checker.h b/components/autofill_assistant/browser/batch_element_checker.h
index 70bd904..b33ec13 100644
--- a/components/autofill_assistant/browser/batch_element_checker.h
+++ b/components/autofill_assistant/browser/batch_element_checker.h
@@ -19,6 +19,9 @@
 namespace autofill_assistant {
 class WebController;
 
+// Types of element checks.
+enum ElementCheckType { kExistenceCheck, kVisibilityCheck };
+
 // Helper for checking a set of elements at the same time. It avoids duplicate
 // checks and supports retries.
 //
@@ -27,12 +30,12 @@
 // The simplest way of using a BatchElementChecker is to:
 // - create an instance, using WebController::CreateBatchElementChecker or
 //   ActionDelegate::CreateBatchElementChecker
-// - call AddElementExistenceCheck() and AddFieldValueCheck()
+// - call AddElementCheck() and AddFieldValueCheck()
 // - call Run() with duration set to 0.
 //
 // The result of the checks is reported to the callbacks passed to
-// AddElementExistenceCheck() and AddFieldValueCheck(), then the callback passed
-// to Run() is called, to report the end of the a run.
+// AddElementCheck(kExistenceCheck, ) and AddFieldValueCheck(), then the
+// callback passed to Run() is called, to report the end of the a run.
 //
 // Check with retries:
 //
@@ -46,19 +49,34 @@
   explicit BatchElementChecker(WebController* web_controller);
   virtual ~BatchElementChecker();
 
-  // Checks whether the element given by |selectors| exists on the web page.
+  // Callback for AddElementCheck. Argument is true if the check passed.
+  using ElementCheckCallback = base::OnceCallback<void(bool)>;
+
+  // Callback for AddFieldValueCheck. Argument is true is the element exists.
+  // The string contains the field value, or an empty string if accessing the
+  // value failed.
+  using GetFieldValueCallback =
+      base::OnceCallback<void(bool, const std::string&)>;
+
+  // Checks an an element.
   //
-  // New element existence checks cannot be added once Run has been called.
-  void AddElementExistenceCheck(const std::vector<std::string>& selectors,
-                                base::OnceCallback<void(bool)> callback);
+  // kElementCheck checks whether at least one element given by |selectors|
+  // exists on the web page.
+  //
+  // kVisibilityCheck checks whether at least one element given by |selectors|
+  // is visible on the page.
+  //
+  // New element checks cannot be added once Run has been called.
+  void AddElementCheck(ElementCheckType check_type,
+                       const std::vector<std::string>& selectors,
+                       ElementCheckCallback callback);
 
   // Gets the value of |selectors| and return the result through |callback|. The
   // returned value will be the empty string in case of error or empty value.
   //
   // New field checks cannot be added once Run has been called.
-  void AddFieldValueCheck(
-      const std::vector<std::string>& selectors,
-      base::OnceCallback<void(bool, const std::string&)> callback);
+  void AddFieldValueCheck(const std::vector<std::string>& selectors,
+                          GetFieldValueCallback callback);
 
   // Runs the checks until all elements exist or for |duration|, whichever one
   // comes first. Elements found are reported as soon as they're founds.
@@ -78,58 +96,52 @@
   bool all_found() { return all_found_; }
 
  private:
-  // Checks to run on a specific element, and the callbacks to report them to.
-  struct ElementCallbacks {
-    ElementCallbacks();
-    ~ElementCallbacks();
-
-    // All the callbacks registered for that element by separate calls to
-    // AddElementExistenceCheck with the same selector.
-    std::vector<base::OnceCallback<void(bool)>> element_exists_callbacks;
-
-    // All the callbacks registered for that field by separate calls to
-    // AddFieldValueCheck with the same selector.
-    std::vector<base::OnceCallback<void(bool, const std::string&)>>
-        get_field_value_callbacks;
-  };
-
-  using ElementCallbackMap =
-      std::map<std::vector<std::string>, ElementCallbacks>;
-
   // Tries running the checks, reporting only successes.
   //
   // Calls |try_done_callback| at the end of the run.
   void Try(base::OnceCallback<void()> try_done_callback);
 
+  void OnTryDone(int64_t remaining_attempts,
+                 base::RepeatingCallback<void()> try_done,
+                 base::OnceCallback<void()> all_done);
+
   // If there are still callbacks not called by a previous call to Try, call
   // them now. When this method returns, all callbacks are guaranteed to have
   // been run.
   void GiveUp();
 
-  void OnTryDone(int64_t remaining_attempts,
-                 base::RepeatingCallback<void()> try_done,
-                 base::OnceCallback<void()> all_done);
-  bool HasMoreChecksToRun();
-  void OnElementExists(ElementCallbackMap::iterator iter, bool exists);
-  void OnGetFieldValue(ElementCallbackMap::iterator iter,
+  void OnElementChecked(std::vector<ElementCheckCallback>* callbacks,
+                        bool exists);
+  void OnGetFieldValue(std::vector<GetFieldValueCallback>* callbacks,
                        bool exists,
                        const std::string& value);
   void CheckTryDone();
-  void RunElementExistsCallbacks(ElementCallbacks* element, bool result);
-  void RunGetFieldValueCallbacks(ElementCallbacks* element,
-                                 bool exists,
-                                 const std::string& value);
+  void RunCallbacks(std::vector<ElementCheckCallback>* callbacks, bool result);
+  void RunCallbacks(std::vector<GetFieldValueCallback>* callbacks,
+                    bool result,
+                    const std::string& value);
+  bool HasMoreChecksToRun();
 
   WebController* const web_controller_;
-  ElementCallbackMap element_callback_map_;
-  int pending_preconditions_to_check_count_;
+
+  // A map of ElementCheck arguments (check_type, selectors) to callbacks that
+  // take the result of the check.
+  std::map<std::pair<ElementCheckType, std::vector<std::string>>,
+           std::vector<ElementCheckCallback>>
+      element_check_callbacks_;
+
+  // A map of GetFieldValue arguments (selectors) to callbacks that take the
+  // field value.
+  std::map<std::vector<std::string>, std::vector<GetFieldValueCallback>>
+      get_field_value_callbacks_;
+  int pending_checks_count_;
   bool all_found_;
   bool stopped_;
 
-  // The callback built for Try(). It is kept around while going through
-  // |element_callback_map_| and called once all selectors in that map have been
-  // looked up once, whether that lookup was successful or not. Also used to
-  // guarantee that only one Try runs at a time.
+  // The callback built for Try(). It is kept around while going through the
+  // maps and called once all selectors in that map have been looked up once,
+  // whether that lookup was successful or not. Also used to guarantee that only
+  // one Try runs at a time.
   base::OnceCallback<void()> try_done_callback_;
 
   base::WeakPtrFactory<BatchElementChecker> weak_ptr_factory_;
diff --git a/components/autofill_assistant/browser/batch_element_checker_unittest.cc b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
index f157d488..dbe6607 100644
--- a/components/autofill_assistant/browser/batch_element_checker_unittest.cc
+++ b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
@@ -39,19 +39,29 @@
     element_exists_results_[name] = result;
   }
 
-  base::OnceCallback<void(bool)> ElementExistenceCallback(
+  BatchElementChecker::ElementCheckCallback ElementExistenceCallback(
       const std::string& name) {
     return base::BindOnce(&BatchElementCheckerTest::OnElementExistenceCheck,
                           base::Unretained(this), name);
   }
 
+  void OnElementVisibilityCheck(const std::string& name, bool result) {
+    element_visible_results_[name] = result;
+  }
+
+  BatchElementChecker::ElementCheckCallback ElementVisibilityCallback(
+      const std::string& name) {
+    return base::BindOnce(&BatchElementCheckerTest::OnElementVisibilityCheck,
+                          base::Unretained(this), name);
+  }
+
   void OnFieldValueCheck(const std::string& name,
                          bool exists,
                          const std::string& value) {
     get_field_value_results_[name] = value;
   }
 
-  base::OnceCallback<void(bool, const std::string&)> FieldValueCallback(
+  BatchElementChecker::GetFieldValueCallback FieldValueCallback(
       const std::string& name) {
     return base::BindOnce(&BatchElementCheckerTest::OnFieldValueCheck,
                           base::Unretained(this), name);
@@ -85,16 +95,18 @@
   MockWebController mock_web_controller_;
   BatchElementChecker checks_;
   std::map<std::string, bool> element_exists_results_;
+  std::map<std::string, bool> element_visible_results_;
   std::map<std::string, std::string> get_field_value_results_;
   std::set<std::string> all_done_;
   std::map<std::string, int> try_done_;
 };
 
 TEST_F(BatchElementCheckerTest, OneElementFound) {
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("exists"), _))
-      .WillOnce(RunOnceCallback<1>(true));
-  checks_.AddElementExistenceCheck({"exists"},
-                                   ElementExistenceCallback("exists"));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("exists"), _))
+      .WillOnce(RunOnceCallback<2>(true));
+  checks_.AddElementCheck(kExistenceCheck, {"exists"},
+                          ElementExistenceCallback("exists"));
   RunOnce("run_once");
 
   EXPECT_THAT(element_exists_results_, Contains(Pair("exists", true)));
@@ -104,10 +116,10 @@
 
 TEST_F(BatchElementCheckerTest, OneElementNotFound) {
   EXPECT_CALL(mock_web_controller_,
-              OnElementExists(ElementsAre("does_not_exist"), _))
-      .WillOnce(RunOnceCallback<1>(false));
-  checks_.AddElementExistenceCheck({"does_not_exist"},
-                                   ElementExistenceCallback("does_not_exist"));
+              OnElementCheck(kExistenceCheck, ElementsAre("does_not_exist"), _))
+      .WillOnce(RunOnceCallback<2>(false));
+  checks_.AddElementCheck(kExistenceCheck, {"does_not_exist"},
+                          ElementExistenceCallback("does_not_exist"));
   RunOnce("run_once");
 
   EXPECT_THAT(element_exists_results_, Contains(Pair("does_not_exist", false)));
@@ -149,20 +161,26 @@
 }
 
 TEST_F(BatchElementCheckerTest, MultipleElements) {
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("1"), _))
-      .WillOnce(RunOnceCallback<1>(true));
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("2"), _))
-      .WillOnce(RunOnceCallback<1>(true));
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("3"), _))
-      .WillOnce(RunOnceCallback<1>(false));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("1"), _))
+      .WillOnce(RunOnceCallback<2>(true));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("2"), _))
+      .WillOnce(RunOnceCallback<2>(true));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("3"), _))
+      .WillOnce(RunOnceCallback<2>(false));
   EXPECT_CALL(mock_web_controller_, OnGetFieldValue(ElementsAre("4"), _))
       .WillOnce(RunOnceCallback<1>(true, "value"));
   EXPECT_CALL(mock_web_controller_, OnGetFieldValue(ElementsAre("5"), _))
       .WillOnce(RunOnceCallback<1>(false, ""));
 
-  checks_.AddElementExistenceCheck({"1"}, ElementExistenceCallback("1"));
-  checks_.AddElementExistenceCheck({"2"}, ElementExistenceCallback("2"));
-  checks_.AddElementExistenceCheck({"3"}, ElementExistenceCallback("3"));
+  checks_.AddElementCheck(kExistenceCheck, {"1"},
+                          ElementExistenceCallback("1"));
+  checks_.AddElementCheck(kExistenceCheck, {"2"},
+                          ElementExistenceCallback("2"));
+  checks_.AddElementCheck(kExistenceCheck, {"3"},
+                          ElementExistenceCallback("3"));
   checks_.AddFieldValueCheck({"4"}, FieldValueCallback("4"));
   checks_.AddFieldValueCheck({"5"}, FieldValueCallback("5"));
   RunOnce("run_once");
@@ -176,50 +194,70 @@
   EXPECT_FALSE(checks_.all_found());
 }
 
-TEST_F(BatchElementCheckerTest, Deduplicate) {
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("1"), _))
-      .WillOnce(RunOnceCallback<1>(true));
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(ElementsAre("2"), _))
-      .WillOnce(RunOnceCallback<1>(true, "value2"));
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(ElementsAre("3"), _))
-      .WillOnce(RunOnceCallback<1>(true, "value3"));
+TEST_F(BatchElementCheckerTest, DeduplicateElementExists) {
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("1"), _))
+      .WillOnce(RunOnceCallback<2>(true));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("2"), _))
+      .WillOnce(RunOnceCallback<2>(true));
 
-  // Deduplicate two AddElementExistenceCheck for the same element:
-  checks_.AddElementExistenceCheck({"1"}, ElementExistenceCallback("first 1"));
-  checks_.AddElementExistenceCheck({"1"}, ElementExistenceCallback("second 1"));
-
-  // Deduplicate an AddElementExistenceCheck and a AddFieldValueCheck for the
-  // same element:
-  checks_.AddElementExistenceCheck({"2"}, ElementExistenceCallback("first 2"));
-  checks_.AddFieldValueCheck({"2"}, FieldValueCallback("second 2"));
-
-  // Deduplicate two AddFieldValueCheck for the same element:
-  checks_.AddFieldValueCheck({"3"}, FieldValueCallback("first 3"));
-  checks_.AddFieldValueCheck({"3"}, FieldValueCallback("second 3"));
+  checks_.AddElementCheck(kExistenceCheck, {"1"},
+                          ElementExistenceCallback("first 1"));
+  checks_.AddElementCheck(kExistenceCheck, {"1"},
+                          ElementExistenceCallback("second 1"));
+  checks_.AddElementCheck(kExistenceCheck, {"2"},
+                          ElementExistenceCallback("2"));
 
   RunOnce("run_once");
 
   EXPECT_THAT(element_exists_results_, Contains(Pair("first 1", true)));
   EXPECT_THAT(element_exists_results_, Contains(Pair("second 1", true)));
-  EXPECT_THAT(element_exists_results_, Contains(Pair("first 2", true)));
-  EXPECT_THAT(get_field_value_results_, Contains(Pair("second 2", "value2")));
-  EXPECT_THAT(get_field_value_results_, Contains(Pair("first 3", "value3")));
-  EXPECT_THAT(get_field_value_results_, Contains(Pair("second 3", "value3")));
+  EXPECT_THAT(element_exists_results_, Contains(Pair("2", true)));
   EXPECT_THAT(all_done_, Contains("run_once"));
 }
 
+TEST_F(BatchElementCheckerTest, DeduplicateElementVisible) {
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kVisibilityCheck, ElementsAre("1"), _))
+      .WillOnce(RunOnceCallback<2>(true));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kVisibilityCheck, ElementsAre("2"), _))
+      .WillOnce(RunOnceCallback<2>(true));
+
+  checks_.AddElementCheck(kVisibilityCheck, {"1"},
+                          ElementVisibilityCallback("first 1"));
+  checks_.AddElementCheck(kVisibilityCheck, {"1"},
+                          ElementVisibilityCallback("second 1"));
+  checks_.AddElementCheck(kVisibilityCheck, {"2"},
+                          ElementVisibilityCallback("2"));
+
+  RunOnce("run_once");
+
+  EXPECT_THAT(element_visible_results_, Contains(Pair("first 1", true)));
+  EXPECT_THAT(element_visible_results_, Contains(Pair("second 1", true)));
+  EXPECT_THAT(element_visible_results_, Contains(Pair("2", true)));
+  EXPECT_THAT(all_done_, Contains("run_once"));
+}
+
+// Deduplicate get field
+
 TEST_F(BatchElementCheckerTest, EventuallyFindAll) {
   {
     InSequence seq;
 
-    EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("1"), _))
-        .WillOnce(RunOnceCallback<1>(true));
-    EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("2"), _))
-        .WillOnce(RunOnceCallback<1>(false))
-        .WillOnce(RunOnceCallback<1>(true));
+    EXPECT_CALL(mock_web_controller_,
+                OnElementCheck(kExistenceCheck, ElementsAre("1"), _))
+        .WillOnce(RunOnceCallback<2>(true));
+    EXPECT_CALL(mock_web_controller_,
+                OnElementCheck(kExistenceCheck, ElementsAre("2"), _))
+        .WillOnce(RunOnceCallback<2>(false))
+        .WillOnce(RunOnceCallback<2>(true));
   }
-  checks_.AddElementExistenceCheck({"1"}, ElementExistenceCallback("1"));
-  checks_.AddElementExistenceCheck({"2"}, ElementExistenceCallback("2"));
+  checks_.AddElementCheck(kExistenceCheck, {"1"},
+                          ElementExistenceCallback("1"));
+  checks_.AddElementCheck(kExistenceCheck, {"2"},
+                          ElementExistenceCallback("2"));
   checks_.Run(base::TimeDelta::FromSeconds(1), base::DoNothing(),
               DoneCallback("all_done"));
 
@@ -243,14 +281,18 @@
   {
     InSequence seq;
 
-    EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("1"), _))
-        .WillOnce(RunOnceCallback<1>(true));
-    EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("2"), _))
+    EXPECT_CALL(mock_web_controller_,
+                OnElementCheck(kExistenceCheck, ElementsAre("1"), _))
+        .WillOnce(RunOnceCallback<2>(true));
+    EXPECT_CALL(mock_web_controller_,
+                OnElementCheck(kExistenceCheck, ElementsAre("2"), _))
         .Times(3)
-        .WillRepeatedly(RunOnceCallback<1>(false));
+        .WillRepeatedly(RunOnceCallback<2>(false));
   }
-  checks_.AddElementExistenceCheck({"1"}, ElementExistenceCallback("1"));
-  checks_.AddElementExistenceCheck({"2"}, ElementExistenceCallback("2"));
+  checks_.AddElementCheck(kExistenceCheck, {"1"},
+                          ElementExistenceCallback("1"));
+  checks_.AddElementCheck(kExistenceCheck, {"2"},
+                          ElementExistenceCallback("2"));
   checks_.Run(3 * kTimeUnit, base::DoNothing(), DoneCallback("all_done"));
 
   // The first try should have run, not fully successful, and should now be
@@ -274,11 +316,12 @@
 }
 
 TEST_F(BatchElementCheckerTest, TryDoneCallback) {
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("element"), _))
-      .WillOnce(RunOnceCallback<1>(false))
-      .WillOnce(RunOnceCallback<1>(true));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("element"), _))
+      .WillOnce(RunOnceCallback<2>(false))
+      .WillOnce(RunOnceCallback<2>(true));
 
-  checks_.AddElementExistenceCheck({"element"}, base::DoNothing());
+  checks_.AddElementCheck(kExistenceCheck, {"element"}, base::DoNothing());
   checks_.Run(base::TimeDelta::FromSeconds(1), TryCallback("try"),
               DoneCallback("all_done"));
 
@@ -294,10 +337,10 @@
 
 TEST_F(BatchElementCheckerTest, TryOnceGivenSmallDuration) {
   EXPECT_CALL(mock_web_controller_,
-              OnElementExists(ElementsAre("does_not_exist"), _))
-      .WillOnce(RunOnceCallback<1>(false));
-  checks_.AddElementExistenceCheck({"does_not_exist"},
-                                   ElementExistenceCallback("does_not_exist"));
+              OnElementCheck(kExistenceCheck, ElementsAre("does_not_exist"), _))
+      .WillOnce(RunOnceCallback<2>(false));
+  checks_.AddElementCheck(kExistenceCheck, {"does_not_exist"},
+                          ElementExistenceCallback("does_not_exist"));
 
   checks_.Run(base::TimeDelta::FromMilliseconds(10), base::DoNothing(),
               DoneCallback("all_done"));
@@ -309,10 +352,11 @@
 }
 
 TEST_F(BatchElementCheckerTest, StopTrying) {
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("element"), _))
-      .WillRepeatedly(RunOnceCallback<1>(false));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("element"), _))
+      .WillRepeatedly(RunOnceCallback<2>(false));
 
-  checks_.AddElementExistenceCheck({"element"}, base::DoNothing());
+  checks_.AddElementCheck(kExistenceCheck, {"element"}, base::DoNothing());
   checks_.Run(base::TimeDelta::FromSeconds(1), TryCallback("try"),
               DoneCallback("all_done"));
 
diff --git a/components/autofill_assistant/browser/mock_web_controller.h b/components/autofill_assistant/browser/mock_web_controller.h
index 660c7d21d..02bb175 100644
--- a/components/autofill_assistant/browser/mock_web_controller.h
+++ b/components/autofill_assistant/browser/mock_web_controller.h
@@ -41,12 +41,14 @@
                void(const std::vector<std::string>& selectors,
                     base::OnceCallback<void(bool)>& callback));
 
-  void ElementExists(const std::vector<std::string>& selectors,
-                     base::OnceCallback<void(bool)> callback) override {
-    OnElementExists(selectors, callback);
+  void ElementCheck(ElementCheckType check_type,
+                    const std::vector<std::string>& selectors,
+                    base::OnceCallback<void(bool)> callback) override {
+    OnElementCheck(check_type, selectors, callback);
   }
-  MOCK_METHOD2(OnElementExists,
-               void(const std::vector<std::string>& selectors,
+  MOCK_METHOD3(OnElementCheck,
+               void(ElementCheckType check_type,
+                    const std::vector<std::string>& selectors,
                     base::OnceCallback<void(bool)>& callback));
 
   void GetFieldValue(
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 3558f04..82eedb3 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -64,7 +64,7 @@
 void ScriptExecutor::WaitForElement(const std::vector<std::string>& selectors,
                                     base::OnceCallback<void(bool)> callback) {
   std::unique_ptr<BatchElementChecker> checker = CreateBatchElementChecker();
-  checker->AddElementExistenceCheck(selectors, base::DoNothing());
+  checker->AddElementCheck(kVisibilityCheck, selectors, base::DoNothing());
   checker->Run(kWaitForSelectorDeadline,
                /* try_done= */ base::DoNothing(),
                /* all_done= */
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc
index d55edf86..aac823d 100644
--- a/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -43,8 +43,8 @@
 
     // In this test, "tell" actions always succeed and "click" actions always
     // fail. The following makes a click action fail immediately
-    ON_CALL(mock_web_controller_, OnElementExists(_, _))
-        .WillByDefault(RunOnceCallback<1>(true));
+    ON_CALL(mock_web_controller_, OnElementCheck(_, _, _))
+        .WillByDefault(RunOnceCallback<2>(true));
     ON_CALL(mock_web_controller_, OnClickElement(_, _))
         .WillByDefault(RunOnceCallback<1>(false));
     ON_CALL(mock_web_controller_, OnFocusElement(_, _))
diff --git a/components/autofill_assistant/browser/script_precondition.cc b/components/autofill_assistant/browser/script_precondition.cc
index 8cfad9c9..9342cc2 100644
--- a/components/autofill_assistant/browser/script_precondition.cc
+++ b/components/autofill_assistant/browser/script_precondition.cc
@@ -98,7 +98,8 @@
     base::OnceCallback<void(bool)> callback =
         base::BindOnce(&ScriptPrecondition::OnCheckElementExists,
                        weak_ptr_factory_.GetWeakPtr());
-    batch_checks->AddElementExistenceCheck(selector, std::move(callback));
+    batch_checks->AddElementCheck(kExistenceCheck, selector,
+                                  std::move(callback));
   }
   for (const auto& value_match : form_value_match_) {
     DCHECK(!value_match.element().selectors().empty());
diff --git a/components/autofill_assistant/browser/script_precondition_unittest.cc b/components/autofill_assistant/browser/script_precondition_unittest.cc
index 4ec840b..656a199 100644
--- a/components/autofill_assistant/browser/script_precondition_unittest.cc
+++ b/components/autofill_assistant/browser/script_precondition_unittest.cc
@@ -55,11 +55,12 @@
 class ScriptPreconditionTest : public testing::Test {
  public:
   void SetUp() override {
-    ON_CALL(mock_web_controller_, OnElementExists(ElementsAre("exists"), _))
-        .WillByDefault(RunOnceCallback<1>(true));
     ON_CALL(mock_web_controller_,
-            OnElementExists(ElementsAre("does_not_exist"), _))
-        .WillByDefault(RunOnceCallback<1>(false));
+            OnElementCheck(kExistenceCheck, ElementsAre("exists"), _))
+        .WillByDefault(RunOnceCallback<2>(true));
+    ON_CALL(mock_web_controller_,
+            OnElementCheck(kExistenceCheck, ElementsAre("does_not_exist"), _))
+        .WillByDefault(RunOnceCallback<2>(false));
 
     SetUrl("http://www.example.com/path");
     ON_CALL(mock_web_controller_, OnGetFieldValue(ElementsAre("exists"), _))
@@ -177,8 +178,9 @@
 }
 
 TEST_F(ScriptPreconditionTest, IgnoreEmptyElementsExist) {
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("exists"), _))
-      .WillOnce(RunOnceCallback<1>(true));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("exists"), _))
+      .WillOnce(RunOnceCallback<2>(true));
 
   ScriptPreconditionProto proto;
   proto.add_elements_exist()->add_selectors("exists");
diff --git a/components/autofill_assistant/browser/script_tracker_unittest.cc b/components/autofill_assistant/browser/script_tracker_unittest.cc
index eebcb6a..40113704 100644
--- a/components/autofill_assistant/browser/script_tracker_unittest.cc
+++ b/components/autofill_assistant/browser/script_tracker_unittest.cc
@@ -32,11 +32,12 @@
                           public ScriptExecutorDelegate {
  public:
   void SetUp() override {
-    ON_CALL(mock_web_controller_, OnElementExists(ElementsAre("exists"), _))
-        .WillByDefault(RunOnceCallback<1>(true));
     ON_CALL(mock_web_controller_,
-            OnElementExists(ElementsAre("does_not_exist"), _))
-        .WillByDefault(RunOnceCallback<1>(false));
+            OnElementCheck(kExistenceCheck, ElementsAre("exists"), _))
+        .WillByDefault(RunOnceCallback<2>(true));
+    ON_CALL(mock_web_controller_,
+            OnElementCheck(kExistenceCheck, ElementsAre("does_not_exist"), _))
+        .WillByDefault(RunOnceCallback<2>(false));
     ON_CALL(mock_web_controller_, GetUrl()).WillByDefault(ReturnRef(url_));
 
     // Scripts run, but have no actions.
@@ -250,8 +251,8 @@
 
 TEST_F(ScriptTrackerTest, CheckScriptsAfterDOMChange) {
   EXPECT_CALL(mock_web_controller_,
-              OnElementExists(ElementsAre("maybe_exists"), _))
-      .WillOnce(RunOnceCallback<1>(false));
+              OnElementCheck(kExistenceCheck, ElementsAre("maybe_exists"), _))
+      .WillOnce(RunOnceCallback<2>(false));
 
   SupportsScriptResponseProto scripts;
   AddScript(&scripts, "script name", "script path", "maybe_exists");
@@ -262,8 +263,8 @@
 
   // DOM has changed; OnElementExists now returns true.
   EXPECT_CALL(mock_web_controller_,
-              OnElementExists(ElementsAre("maybe_exists"), _))
-      .WillOnce(RunOnceCallback<1>(true));
+              OnElementCheck(kExistenceCheck, ElementsAre("maybe_exists"), _))
+      .WillOnce(RunOnceCallback<2>(true));
   tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
 
   // The script can now run
@@ -275,9 +276,10 @@
   AddScript(&scripts, "runnable name", "runnable path", "exists");
 
   base::OnceCallback<void(bool)> captured_callback;
-  EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("exists"), _))
-      .WillOnce(CaptureOnceCallback<1>(&captured_callback))
-      .WillOnce(RunOnceCallback<1>(false));
+  EXPECT_CALL(mock_web_controller_,
+              OnElementCheck(kExistenceCheck, ElementsAre("exists"), _))
+      .WillOnce(CaptureOnceCallback<2>(&captured_callback))
+      .WillOnce(RunOnceCallback<2>(false));
   SetAndCheckScripts(scripts);
 
   // At this point, since the callback hasn't been run, there's still a check in
diff --git a/components/autofill_assistant/browser/web_controller.cc b/components/autofill_assistant/browser/web_controller.cc
index af2c7fc..0560024 100644
--- a/components/autofill_assistant/browser/web_controller.cc
+++ b/components/autofill_assistant/browser/web_controller.cc
@@ -238,32 +238,39 @@
   OnResult(true, std::move(callback));
 }
 
-void WebController::ElementExists(const std::vector<std::string>& selectors,
-                                  base::OnceCallback<void(bool)> callback) {
+void WebController::ElementCheck(ElementCheckType check_type,
+                                 const std::vector<std::string>& selectors,
+                                 base::OnceCallback<void(bool)> callback) {
   DCHECK(!selectors.empty());
-  // We don't use strict_mode because we only check for the existence of an
-  // element and we don't act on it.
-  FindElement(
-      selectors, /* strict_mode= */ false,
-      base::BindOnce(&WebController::OnFindElementForExist,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  // We don't use strict_mode because we only check for the existence of at
+  // least one such element and we don't act on it.
+  FindElement(selectors, /* strict_mode= */ false,
+              base::BindOnce(&WebController::OnFindElementForCheck,
+                             weak_ptr_factory_.GetWeakPtr(), check_type,
+                             std::move(callback)));
 }
 
-void WebController::OnFindElementForExist(
+void WebController::OnFindElementForCheck(
+    ElementCheckType check_type,
     base::OnceCallback<void(bool)> callback,
     std::unique_ptr<FindElementResult> result) {
   if (result->object_id.empty()) {
     OnResult(false, std::move(callback));
     return;
   }
+  if (check_type == kExistenceCheck) {
+    OnResult(true, std::move(callback));
+    return;
+  }
+  DCHECK_EQ(check_type, kVisibilityCheck);
 
   devtools_client_->GetDOM()->GetBoxModel(
       dom::GetBoxModelParams::Builder().SetObjectId(result->object_id).Build(),
-      base::BindOnce(&WebController::OnGetBoxModelForExist,
+      base::BindOnce(&WebController::OnGetBoxModelForVisible,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void WebController::OnGetBoxModelForExist(
+void WebController::OnGetBoxModelForVisible(
     base::OnceCallback<void(bool)> callback,
     std::unique_ptr<dom::GetBoxModelResult> result) {
   OnResult(result && result->GetModel() && result->GetModel()->GetContent(),
diff --git a/components/autofill_assistant/browser/web_controller.h b/components/autofill_assistant/browser/web_controller.h
index 4a0182d..3123769 100644
--- a/components/autofill_assistant/browser/web_controller.h
+++ b/components/autofill_assistant/browser/web_controller.h
@@ -115,13 +115,18 @@
  protected:
   friend class BatchElementChecker;
 
-  // Check whether at least one element given by |selectors| exists on the web
-  // page. The element must have a valid BoxModel (i.e. it must be visible and
-  // have a size greater than 0).
+  // Checks an element for:
+  //
+  // kExistenceCheck: Checks whether at least one element given by |selectors|
+  // exists on the web page.
+  //
+  // kVisibilityCheck: Checks whether at least on element given by |selectors|
+  // is visible on the web page.
   //
   // Normally done through BatchElementChecker.
-  virtual void ElementExists(const std::vector<std::string>& selectors,
-                             base::OnceCallback<void(bool)> callback);
+  virtual void ElementCheck(ElementCheckType type,
+                            const std::vector<std::string>& selectors,
+                            base::OnceCallback<void(bool)> callback);
 
   // Get the value of |selectors| and return the result through |callback|. The
   // returned value might be false, if the element cannot be found, true and the
@@ -183,10 +188,11 @@
   void OnDispatchReleaseMouseEvent(
       base::OnceCallback<void(bool)> callback,
       std::unique_ptr<input::DispatchMouseEventResult> result);
-  void OnFindElementForExist(base::OnceCallback<void(bool)> callback,
+  void OnFindElementForCheck(ElementCheckType check_type,
+                             base::OnceCallback<void(bool)> callback,
                              std::unique_ptr<FindElementResult> result);
-  void OnGetBoxModelForExist(base::OnceCallback<void(bool)> callback,
-                             std::unique_ptr<dom::GetBoxModelResult> result);
+  void OnGetBoxModelForVisible(base::OnceCallback<void(bool)> callback,
+                               std::unique_ptr<dom::GetBoxModelResult> result);
 
   // Find the element given by |selectors|. If multiple elements match
   // |selectors| and if |strict_mode| is false, return the first one that is
diff --git a/components/autofill_assistant/browser/web_controller_browsertest.cc b/components/autofill_assistant/browser/web_controller_browsertest.cc
index 516dfec..07703e4 100644
--- a/components/autofill_assistant/browser/web_controller_browsertest.cc
+++ b/components/autofill_assistant/browser/web_controller_browsertest.cc
@@ -34,25 +34,26 @@
         WebController::CreateForWebContents(shell()->web_contents());
   }
 
-  void AreElementsExist(const std::vector<std::vector<std::string>>& selectors,
+  void RunElementChecks(ElementCheckType check_type,
+                        const std::vector<std::vector<std::string>>& selectors,
                         const std::vector<bool> results) {
     base::RunLoop run_loop;
     ASSERT_EQ(selectors.size(), results.size());
     size_t pending_number_of_checks = selectors.size();
     for (size_t i = 0; i < selectors.size(); i++) {
-      web_controller_->ElementExists(
-          selectors[i],
-          base::BindOnce(&WebControllerBrowserTest::CheckElementExistCallback,
+      web_controller_->ElementCheck(
+          check_type, selectors[i],
+          base::BindOnce(&WebControllerBrowserTest::CheckElementVisibleCallback,
                          base::Unretained(this), run_loop.QuitClosure(),
                          &pending_number_of_checks, results[i]));
     }
     run_loop.Run();
   }
 
-  void CheckElementExistCallback(const base::Closure& done_callback,
-                                 size_t* pending_number_of_checks_output,
-                                 bool expected_result,
-                                 bool result) {
+  void CheckElementVisibleCallback(const base::Closure& done_callback,
+                                   size_t* pending_number_of_checks_output,
+                                   bool expected_result,
+                                   bool result) {
     ASSERT_EQ(expected_result, result);
     *pending_number_of_checks_output -= 1;
     if (*pending_number_of_checks_output == 0) {
@@ -77,8 +78,8 @@
 
   void WaitForElementRemove(const std::vector<std::string>& selectors) {
     base::RunLoop run_loop;
-    web_controller_->ElementExists(
-        selectors,
+    web_controller_->ElementCheck(
+        kExistenceCheck, selectors,
         base::BindOnce(&WebControllerBrowserTest::OnWaitForElementRemove,
                        base::Unretained(this), run_loop.QuitClosure(),
                        selectors));
@@ -255,7 +256,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebControllerBrowserTest);
 };
 
-IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ConcurrentElementsExist) {
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ConcurrentElementsVisible) {
   std::vector<std::vector<std::string>> selectors;
   std::vector<bool> results;
 
@@ -315,7 +316,33 @@
   selectors.emplace_back(a_selector);
   results.emplace_back(false);
 
-  AreElementsExist(selectors, results);
+  RunElementChecks(kVisibilityCheck, selectors, results);
+}
+
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ElementExists) {
+  std::vector<std::vector<std::string>> selectors;
+  std::vector<bool> results;
+
+  std::vector<std::string> a_selector;
+
+  // A visible element
+  a_selector.emplace_back("#button");
+  selectors.emplace_back(a_selector);
+  results.emplace_back(true);
+
+  // A hidden element.
+  a_selector.clear();
+  a_selector.emplace_back("#hidden");
+  selectors.emplace_back(a_selector);
+  results.emplace_back(true);
+
+  // A nonexistent element.
+  a_selector.clear();
+  a_selector.emplace_back("#doesnotexist");
+  selectors.emplace_back(a_selector);
+  results.emplace_back(false);
+
+  RunElementChecks(kExistenceCheck, selectors, results);
 }
 
 IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ClickElement) {
diff --git a/components/cbor/BUILD.gn b/components/cbor/BUILD.gn
index c44e464..b0d8024 100644
--- a/components/cbor/BUILD.gn
+++ b/components/cbor/BUILD.gn
@@ -6,13 +6,13 @@
 
 component("cbor") {
   sources = [
-    "cbor_constants.h",
-    "cbor_reader.cc",
-    "cbor_reader.h",
-    "cbor_values.cc",
-    "cbor_values.h",
-    "cbor_writer.cc",
-    "cbor_writer.h",
+    "constants.h",
+    "reader.cc",
+    "reader.h",
+    "values.cc",
+    "values.h",
+    "writer.cc",
+    "writer.h",
   ]
 
   defines = [ "CBOR_IMPLEMENTATION" ]
@@ -25,9 +25,9 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "cbor_reader_unittest.cc",
-    "cbor_values_unittest.cc",
-    "cbor_writer_unittest.cc",
+    "reader_unittest.cc",
+    "values_unittest.cc",
+    "writer_unittest.cc",
   ]
 
   deps = [
@@ -38,14 +38,14 @@
   ]
 }
 
-fuzzer_test("cbor_reader_fuzzer") {
+fuzzer_test("reader_fuzzer") {
   sources = [
-    "cbor_reader_fuzzer.cc",
+    "reader_fuzzer.cc",
   ]
   deps = [
     ":cbor",
     "//base",
   ]
-  seed_corpus = "cbor_reader_fuzzer_corpus/"
+  seed_corpus = "reader_fuzzer_corpus/"
   libfuzzer_options = [ "max_len=65535" ]
 }
diff --git a/components/cbor/cbor_constants.h b/components/cbor/constants.h
similarity index 91%
rename from components/cbor/cbor_constants.h
rename to components/cbor/constants.h
index 69a6364c..2df971d 100644
--- a/components/cbor/cbor_constants.h
+++ b/components/cbor/constants.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 COMPONENTS_CBOR_CBOR_CONSTANTS_H_
-#define COMPONENTS_CBOR_CBOR_CONSTANTS_H_
+#ifndef COMPONENTS_CBOR_CONSTANTS_H_
+#define COMPONENTS_CBOR_CONSTANTS_H_
 
 #include <stdint.h>
 
@@ -34,4 +34,4 @@
 }  // namespace constants
 }  // namespace cbor
 
-#endif  // COMPONENTS_CBOR_CBOR_CONSTANTS_H_
+#endif  // COMPONENTS_CBOR_CONSTANTS_H_
diff --git a/components/cbor/cbor_reader.cc b/components/cbor/reader.cc
similarity index 98%
rename from components/cbor/cbor_reader.cc
rename to components/cbor/reader.cc
index 7205ed9f..dbab268 100644
--- a/components/cbor/cbor_reader.cc
+++ b/components/cbor/reader.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 "components/cbor/cbor_reader.h"
+#include "components/cbor/reader.h"
 
 #include <math.h>
 
@@ -12,7 +12,7 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
-#include "components/cbor/cbor_constants.h"
+#include "components/cbor/constants.h"
 
 namespace cbor {
 
@@ -33,7 +33,7 @@
 }
 
 // Error messages that correspond to each of the error codes. There is 1
-// exception: we declare |kUnsupportedMajorType| in cbor_constants.h in the
+// exception: we declare |kUnsupportedMajorType| in constants.h in the
 // `constants` namespace, because we use it in several files.
 const char kNoError[] = "Successfully deserialized to a CBOR value.";
 const char kUnknownAdditionalInfo[] =
diff --git a/components/cbor/cbor_reader.h b/components/cbor/reader.h
similarity index 97%
rename from components/cbor/cbor_reader.h
rename to components/cbor/reader.h
index 6463fed0..6cf58873b 100644
--- a/components/cbor/cbor_reader.h
+++ b/components/cbor/reader.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 COMPONENTS_CBOR_CBOR_READER_H_
-#define COMPONENTS_CBOR_CBOR_READER_H_
+#ifndef COMPONENTS_CBOR_READER_H_
+#define COMPONENTS_CBOR_READER_H_
 
 #include <stddef.h>
 
@@ -13,7 +13,7 @@
 #include "base/containers/span.h"
 #include "base/optional.h"
 #include "components/cbor/cbor_export.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 
 // Concise Binary Object Representation (CBOR) decoder as defined by
 // https://tools.ietf.org/html/rfc7049. This decoder only accepts canonical CBOR
@@ -158,4 +158,4 @@
 
 }  // namespace cbor
 
-#endif  // COMPONENTS_CBOR_CBOR_READER_H_
+#endif  // COMPONENTS_CBOR_READER_H_
diff --git a/components/cbor/cbor_reader_fuzzer.cc b/components/cbor/reader_fuzzer.cc
similarity index 88%
rename from components/cbor/cbor_reader_fuzzer.cc
rename to components/cbor/reader_fuzzer.cc
index a3b8594..3a1e045 100644
--- a/components/cbor/cbor_reader_fuzzer.cc
+++ b/components/cbor/reader_fuzzer.cc
@@ -5,8 +5,8 @@
 #include <stdint.h>
 #include <algorithm>
 
-#include "components/cbor/cbor_reader.h"  // nogncheck
-#include "components/cbor/cbor_writer.h"  // nogncheck
+#include "components/cbor/reader.h"  // nogncheck
+#include "components/cbor/writer.h"  // nogncheck
 
 namespace cbor {
 
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor0 b/components/cbor/reader_fuzzer_corpus/cbor0
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor0
rename to components/cbor/reader_fuzzer_corpus/cbor0
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor1 b/components/cbor/reader_fuzzer_corpus/cbor1
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor1
rename to components/cbor/reader_fuzzer_corpus/cbor1
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor10 b/components/cbor/reader_fuzzer_corpus/cbor10
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor10
rename to components/cbor/reader_fuzzer_corpus/cbor10
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor11 b/components/cbor/reader_fuzzer_corpus/cbor11
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor11
rename to components/cbor/reader_fuzzer_corpus/cbor11
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor12 b/components/cbor/reader_fuzzer_corpus/cbor12
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor12
rename to components/cbor/reader_fuzzer_corpus/cbor12
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor13 b/components/cbor/reader_fuzzer_corpus/cbor13
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor13
rename to components/cbor/reader_fuzzer_corpus/cbor13
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor14 b/components/cbor/reader_fuzzer_corpus/cbor14
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor14
rename to components/cbor/reader_fuzzer_corpus/cbor14
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor15 b/components/cbor/reader_fuzzer_corpus/cbor15
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor15
rename to components/cbor/reader_fuzzer_corpus/cbor15
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor16 b/components/cbor/reader_fuzzer_corpus/cbor16
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor16
rename to components/cbor/reader_fuzzer_corpus/cbor16
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor17 b/components/cbor/reader_fuzzer_corpus/cbor17
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor17
rename to components/cbor/reader_fuzzer_corpus/cbor17
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor18 b/components/cbor/reader_fuzzer_corpus/cbor18
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor18
rename to components/cbor/reader_fuzzer_corpus/cbor18
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor19 b/components/cbor/reader_fuzzer_corpus/cbor19
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor19
rename to components/cbor/reader_fuzzer_corpus/cbor19
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor2 b/components/cbor/reader_fuzzer_corpus/cbor2
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor2
rename to components/cbor/reader_fuzzer_corpus/cbor2
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor20 b/components/cbor/reader_fuzzer_corpus/cbor20
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor20
rename to components/cbor/reader_fuzzer_corpus/cbor20
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor21 b/components/cbor/reader_fuzzer_corpus/cbor21
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor21
rename to components/cbor/reader_fuzzer_corpus/cbor21
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor22 b/components/cbor/reader_fuzzer_corpus/cbor22
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor22
rename to components/cbor/reader_fuzzer_corpus/cbor22
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor23 b/components/cbor/reader_fuzzer_corpus/cbor23
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor23
rename to components/cbor/reader_fuzzer_corpus/cbor23
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor24 b/components/cbor/reader_fuzzer_corpus/cbor24
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor24
rename to components/cbor/reader_fuzzer_corpus/cbor24
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor25 b/components/cbor/reader_fuzzer_corpus/cbor25
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor25
rename to components/cbor/reader_fuzzer_corpus/cbor25
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor26 b/components/cbor/reader_fuzzer_corpus/cbor26
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor26
rename to components/cbor/reader_fuzzer_corpus/cbor26
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor27 b/components/cbor/reader_fuzzer_corpus/cbor27
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor27
rename to components/cbor/reader_fuzzer_corpus/cbor27
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor28 b/components/cbor/reader_fuzzer_corpus/cbor28
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor28
rename to components/cbor/reader_fuzzer_corpus/cbor28
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor29 b/components/cbor/reader_fuzzer_corpus/cbor29
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor29
rename to components/cbor/reader_fuzzer_corpus/cbor29
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor3 b/components/cbor/reader_fuzzer_corpus/cbor3
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor3
rename to components/cbor/reader_fuzzer_corpus/cbor3
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor30 b/components/cbor/reader_fuzzer_corpus/cbor30
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor30
rename to components/cbor/reader_fuzzer_corpus/cbor30
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor31 b/components/cbor/reader_fuzzer_corpus/cbor31
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor31
rename to components/cbor/reader_fuzzer_corpus/cbor31
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor32 b/components/cbor/reader_fuzzer_corpus/cbor32
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor32
rename to components/cbor/reader_fuzzer_corpus/cbor32
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor33 b/components/cbor/reader_fuzzer_corpus/cbor33
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor33
rename to components/cbor/reader_fuzzer_corpus/cbor33
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor34 b/components/cbor/reader_fuzzer_corpus/cbor34
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor34
rename to components/cbor/reader_fuzzer_corpus/cbor34
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor35 b/components/cbor/reader_fuzzer_corpus/cbor35
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor35
rename to components/cbor/reader_fuzzer_corpus/cbor35
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor36 b/components/cbor/reader_fuzzer_corpus/cbor36
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor36
rename to components/cbor/reader_fuzzer_corpus/cbor36
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor37 b/components/cbor/reader_fuzzer_corpus/cbor37
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor37
rename to components/cbor/reader_fuzzer_corpus/cbor37
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor38 b/components/cbor/reader_fuzzer_corpus/cbor38
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor38
rename to components/cbor/reader_fuzzer_corpus/cbor38
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor39 b/components/cbor/reader_fuzzer_corpus/cbor39
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor39
rename to components/cbor/reader_fuzzer_corpus/cbor39
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor4 b/components/cbor/reader_fuzzer_corpus/cbor4
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor4
rename to components/cbor/reader_fuzzer_corpus/cbor4
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor40 b/components/cbor/reader_fuzzer_corpus/cbor40
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor40
rename to components/cbor/reader_fuzzer_corpus/cbor40
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor41 b/components/cbor/reader_fuzzer_corpus/cbor41
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor41
rename to components/cbor/reader_fuzzer_corpus/cbor41
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor42 b/components/cbor/reader_fuzzer_corpus/cbor42
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor42
rename to components/cbor/reader_fuzzer_corpus/cbor42
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor43 b/components/cbor/reader_fuzzer_corpus/cbor43
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor43
rename to components/cbor/reader_fuzzer_corpus/cbor43
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor44 b/components/cbor/reader_fuzzer_corpus/cbor44
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor44
rename to components/cbor/reader_fuzzer_corpus/cbor44
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor45 b/components/cbor/reader_fuzzer_corpus/cbor45
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor45
rename to components/cbor/reader_fuzzer_corpus/cbor45
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor46 b/components/cbor/reader_fuzzer_corpus/cbor46
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor46
rename to components/cbor/reader_fuzzer_corpus/cbor46
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor47 b/components/cbor/reader_fuzzer_corpus/cbor47
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor47
rename to components/cbor/reader_fuzzer_corpus/cbor47
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor48 b/components/cbor/reader_fuzzer_corpus/cbor48
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor48
rename to components/cbor/reader_fuzzer_corpus/cbor48
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor49 b/components/cbor/reader_fuzzer_corpus/cbor49
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor49
rename to components/cbor/reader_fuzzer_corpus/cbor49
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor5 b/components/cbor/reader_fuzzer_corpus/cbor5
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor5
rename to components/cbor/reader_fuzzer_corpus/cbor5
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor50 b/components/cbor/reader_fuzzer_corpus/cbor50
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor50
rename to components/cbor/reader_fuzzer_corpus/cbor50
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor51 b/components/cbor/reader_fuzzer_corpus/cbor51
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor51
rename to components/cbor/reader_fuzzer_corpus/cbor51
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor52 b/components/cbor/reader_fuzzer_corpus/cbor52
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor52
rename to components/cbor/reader_fuzzer_corpus/cbor52
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor53 b/components/cbor/reader_fuzzer_corpus/cbor53
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor53
rename to components/cbor/reader_fuzzer_corpus/cbor53
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor54 b/components/cbor/reader_fuzzer_corpus/cbor54
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor54
rename to components/cbor/reader_fuzzer_corpus/cbor54
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor55 b/components/cbor/reader_fuzzer_corpus/cbor55
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor55
rename to components/cbor/reader_fuzzer_corpus/cbor55
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor56 b/components/cbor/reader_fuzzer_corpus/cbor56
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor56
rename to components/cbor/reader_fuzzer_corpus/cbor56
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor57 b/components/cbor/reader_fuzzer_corpus/cbor57
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor57
rename to components/cbor/reader_fuzzer_corpus/cbor57
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor58 b/components/cbor/reader_fuzzer_corpus/cbor58
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor58
rename to components/cbor/reader_fuzzer_corpus/cbor58
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor59 b/components/cbor/reader_fuzzer_corpus/cbor59
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor59
rename to components/cbor/reader_fuzzer_corpus/cbor59
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor6 b/components/cbor/reader_fuzzer_corpus/cbor6
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor6
rename to components/cbor/reader_fuzzer_corpus/cbor6
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor60 b/components/cbor/reader_fuzzer_corpus/cbor60
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor60
rename to components/cbor/reader_fuzzer_corpus/cbor60
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor61 b/components/cbor/reader_fuzzer_corpus/cbor61
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor61
rename to components/cbor/reader_fuzzer_corpus/cbor61
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor62 b/components/cbor/reader_fuzzer_corpus/cbor62
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor62
rename to components/cbor/reader_fuzzer_corpus/cbor62
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor63 b/components/cbor/reader_fuzzer_corpus/cbor63
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor63
rename to components/cbor/reader_fuzzer_corpus/cbor63
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor64 b/components/cbor/reader_fuzzer_corpus/cbor64
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor64
rename to components/cbor/reader_fuzzer_corpus/cbor64
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor65 b/components/cbor/reader_fuzzer_corpus/cbor65
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor65
rename to components/cbor/reader_fuzzer_corpus/cbor65
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor66 b/components/cbor/reader_fuzzer_corpus/cbor66
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor66
rename to components/cbor/reader_fuzzer_corpus/cbor66
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor67 b/components/cbor/reader_fuzzer_corpus/cbor67
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor67
rename to components/cbor/reader_fuzzer_corpus/cbor67
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor68 b/components/cbor/reader_fuzzer_corpus/cbor68
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor68
rename to components/cbor/reader_fuzzer_corpus/cbor68
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor69 b/components/cbor/reader_fuzzer_corpus/cbor69
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor69
rename to components/cbor/reader_fuzzer_corpus/cbor69
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor7 b/components/cbor/reader_fuzzer_corpus/cbor7
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor7
rename to components/cbor/reader_fuzzer_corpus/cbor7
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor70 b/components/cbor/reader_fuzzer_corpus/cbor70
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor70
rename to components/cbor/reader_fuzzer_corpus/cbor70
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor71 b/components/cbor/reader_fuzzer_corpus/cbor71
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor71
rename to components/cbor/reader_fuzzer_corpus/cbor71
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor72 b/components/cbor/reader_fuzzer_corpus/cbor72
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor72
rename to components/cbor/reader_fuzzer_corpus/cbor72
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor73 b/components/cbor/reader_fuzzer_corpus/cbor73
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor73
rename to components/cbor/reader_fuzzer_corpus/cbor73
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor74 b/components/cbor/reader_fuzzer_corpus/cbor74
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor74
rename to components/cbor/reader_fuzzer_corpus/cbor74
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor75 b/components/cbor/reader_fuzzer_corpus/cbor75
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor75
rename to components/cbor/reader_fuzzer_corpus/cbor75
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor76 b/components/cbor/reader_fuzzer_corpus/cbor76
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor76
rename to components/cbor/reader_fuzzer_corpus/cbor76
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor77 b/components/cbor/reader_fuzzer_corpus/cbor77
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor77
rename to components/cbor/reader_fuzzer_corpus/cbor77
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor78 b/components/cbor/reader_fuzzer_corpus/cbor78
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor78
rename to components/cbor/reader_fuzzer_corpus/cbor78
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor79 b/components/cbor/reader_fuzzer_corpus/cbor79
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor79
rename to components/cbor/reader_fuzzer_corpus/cbor79
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor8 b/components/cbor/reader_fuzzer_corpus/cbor8
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor8
rename to components/cbor/reader_fuzzer_corpus/cbor8
Binary files differ
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor80 b/components/cbor/reader_fuzzer_corpus/cbor80
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor80
rename to components/cbor/reader_fuzzer_corpus/cbor80
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor81 b/components/cbor/reader_fuzzer_corpus/cbor81
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor81
rename to components/cbor/reader_fuzzer_corpus/cbor81
diff --git a/components/cbor/cbor_reader_fuzzer_corpus/cbor9 b/components/cbor/reader_fuzzer_corpus/cbor9
similarity index 100%
rename from components/cbor/cbor_reader_fuzzer_corpus/cbor9
rename to components/cbor/reader_fuzzer_corpus/cbor9
Binary files differ
diff --git a/components/cbor/cbor_reader_unittest.cc b/components/cbor/reader_unittest.cc
similarity index 99%
rename from components/cbor/cbor_reader_unittest.cc
rename to components/cbor/reader_unittest.cc
index 2d72860..6af8d600 100644
--- a/components/cbor/cbor_reader_unittest.cc
+++ b/components/cbor/reader_unittest.cc
@@ -5,7 +5,7 @@
 #include <limits>
 #include <utility>
 
-#include "components/cbor/cbor_reader.h"
+#include "components/cbor/reader.h"
 
 #include "base/containers/span.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/components/cbor/cbor_values.cc b/components/cbor/values.cc
similarity index 98%
rename from components/cbor/cbor_values.cc
rename to components/cbor/values.cc
index 7f37a422..f495a7f 100644
--- a/components/cbor/cbor_values.cc
+++ b/components/cbor/values.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 
 #include <new>
 #include <utility>
 
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_util.h"
-#include "components/cbor/cbor_constants.h"
+#include "components/cbor/constants.h"
 
 namespace cbor {
 
diff --git a/components/cbor/cbor_values.h b/components/cbor/values.h
similarity index 97%
rename from components/cbor/cbor_values.h
rename to components/cbor/values.h
index abed1520..ed9aae2 100644
--- a/components/cbor/cbor_values.h
+++ b/components/cbor/values.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 COMPONENTS_CBOR_CBOR_VALUES_H_
-#define COMPONENTS_CBOR_CBOR_VALUES_H_
+#ifndef COMPONENTS_CBOR_VALUES_H_
+#define COMPONENTS_CBOR_VALUES_H_
 
 #include <stdint.h>
 
@@ -187,4 +187,4 @@
 };
 }  // namespace cbor
 
-#endif  // COMPONENTS_CBOR_CBOR_VALUES_H_
+#endif  // COMPONENTS_CBOR_VALUES_H_
diff --git a/components/cbor/cbor_values_unittest.cc b/components/cbor/values_unittest.cc
similarity index 99%
rename from components/cbor/cbor_values_unittest.cc
rename to components/cbor/values_unittest.cc
index d303fe1..1276b99 100644
--- a/components/cbor/cbor_values_unittest.cc
+++ b/components/cbor/values_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 "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 
 #include <string>
 #include <utility>
diff --git a/components/cbor/cbor_writer.cc b/components/cbor/writer.cc
similarity index 98%
rename from components/cbor/cbor_writer.cc
rename to components/cbor/writer.cc
index d5fddd5..a522eff 100644
--- a/components/cbor/cbor_writer.cc
+++ b/components/cbor/writer.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 "components/cbor/cbor_writer.h"
+#include "components/cbor/writer.h"
 
 #include <string>
 
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_piece.h"
-#include "components/cbor/cbor_constants.h"
+#include "components/cbor/constants.h"
 
 namespace cbor {
 
diff --git a/components/cbor/cbor_writer.h b/components/cbor/writer.h
similarity index 95%
rename from components/cbor/cbor_writer.h
rename to components/cbor/writer.h
index 0515adbd..39cd430a 100644
--- a/components/cbor/cbor_writer.h
+++ b/components/cbor/writer.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 COMPONENTS_CBOR_CBOR_WRITER_H_
-#define COMPONENTS_CBOR_CBOR_WRITER_H_
+#ifndef COMPONENTS_CBOR_WRITER_H_
+#define COMPONENTS_CBOR_WRITER_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -11,7 +11,7 @@
 
 #include "base/optional.h"
 #include "components/cbor/cbor_export.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 
 // A basic Concise Binary Object Representation (CBOR) encoder as defined by
 // https://tools.ietf.org/html/rfc7049. This is a generic encoder that supplies
@@ -97,4 +97,4 @@
 
 }  // namespace cbor
 
-#endif  // COMPONENTS_CBOR_CBOR_WRITER_H_
+#endif  // COMPONENTS_CBOR_WRITER_H_
diff --git a/components/cbor/cbor_writer_unittest.cc b/components/cbor/writer_unittest.cc
similarity index 99%
rename from components/cbor/cbor_writer_unittest.cc
rename to components/cbor/writer_unittest.cc
index 3067aad..3fb96884 100644
--- a/components/cbor/cbor_writer_unittest.cc
+++ b/components/cbor/writer_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 "components/cbor/cbor_writer.h"
+#include "components/cbor/writer.h"
 
 #include <limits>
 #include <string>
diff --git a/components/gwp_asan/OWNERS b/components/gwp_asan/OWNERS
new file mode 100644
index 0000000..57999e8
--- /dev/null
+++ b/components/gwp_asan/OWNERS
@@ -0,0 +1,2 @@
+vitalybuka@chromium.org
+vtsyrklevich@chromium.org
diff --git a/components/gwp_asan/README b/components/gwp_asan/README
new file mode 100644
index 0000000..80bce31a
--- /dev/null
+++ b/components/gwp_asan/README
@@ -0,0 +1,4 @@
+GWP-ASan is a sampling debug allocator, similar to ElectricFence or Page Heap,
+intended to detect heap memory errors in the wild. When crashes in a GWP-ASan
+allocation are detected in the crash handler, additional debug information about
+the allocation/deallocation context is added to the crash minidump.
diff --git a/components/gwp_asan/common/BUILD.gn b/components/gwp_asan/common/BUILD.gn
new file mode 100644
index 0000000..82d0ff8
--- /dev/null
+++ b/components/gwp_asan/common/BUILD.gn
@@ -0,0 +1,29 @@
+# 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.
+
+assert(is_win, "GWP-ASan currently only supports Windows.")
+
+static_library("common") {
+  sources = [
+    "guarded_page_allocator.cc",
+    "guarded_page_allocator.h",
+    "guarded_page_allocator_win.cc",
+  ]
+
+  deps = [
+    "//base",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "guarded_page_allocator_unittest.cc",
+  ]
+  deps = [
+    ":common",
+    "//base/test:test_support",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/gwp_asan/common/guarded_page_allocator.cc b/components/gwp_asan/common/guarded_page_allocator.cc
new file mode 100644
index 0000000..b06f4c2fd
--- /dev/null
+++ b/components/gwp_asan/common/guarded_page_allocator.cc
@@ -0,0 +1,272 @@
+// 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/gwp_asan/common/guarded_page_allocator.h"
+
+#include "base/bits.h"
+#include "base/no_destructor.h"
+#include "base/process/process_metrics.h"
+#include "base/rand_util.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+
+using base::debug::StackTrace;
+
+namespace gwp_asan {
+namespace internal {
+
+// TODO: Delete out-of-line constexpr defininitons once C++17 is in use.
+constexpr size_t GuardedPageAllocator::kGpaMaxPages;
+constexpr size_t GuardedPageAllocator::kGpaAllocAlignment;
+constexpr size_t GuardedPageAllocator::kFreePagesNumBits;
+
+GuardedPageAllocator& GuardedPageAllocator::InitializeSingleton(
+    size_t num_pages) {
+  static base::NoDestructor<GuardedPageAllocator> gpa(num_pages);
+  return *gpa;
+}
+
+GuardedPageAllocator& GuardedPageAllocator::Get() {
+  // The constructor will fail if it is called with num_pages = 0, forcing
+  // InitializeSingleton() to be called first.
+  return InitializeSingleton(0);
+}
+
+GuardedPageAllocator::GuardedPageAllocator(size_t num_pages) {
+  CHECK_GT(num_pages, 0U);
+  CHECK_LE(num_pages, kFreePagesNumBits);
+  num_pages_ = num_pages;
+
+  page_size_ = base::GetPageSize();
+  CHECK(MapPages());
+
+  free_pages_ =
+      (num_pages_ == kFreePagesNumBits) ? ~0ULL : (1ULL << num_pages_) - 1;
+
+  for (size_t i = 0; i < num_pages_; i++)
+    data_[i].Init();
+}
+
+GuardedPageAllocator::~GuardedPageAllocator() {
+  UnmapPages();
+}
+
+void* GuardedPageAllocator::Allocate(size_t size) {
+  size_t free_slot = ReserveSlot();
+  if (free_slot == SIZE_MAX)
+    return nullptr;  // All slots are reserved.
+
+  uintptr_t free_page = SlotToAddr(free_slot);
+  MarkPageReadWrite(reinterpret_cast<void*>(free_page));
+
+  size_t offset;
+  if (base::RandInt(0, 1)) {
+    // Return right-aligned allocation to detect overflows.
+    size_t alignment =
+        std::min(size_t{1} << base::bits::Log2Floor(size), kGpaAllocAlignment);
+    offset = page_size_ - base::bits::Align(size, alignment);
+  } else {
+    // Return left-aligned allocation to detect underflows.
+    offset = 0;
+  }
+
+  // Initialize slot metadata.
+  data_[free_slot].RecordAllocation(size, offset);
+
+  return reinterpret_cast<void*>(free_page + offset);
+}
+
+void GuardedPageAllocator::Deallocate(void* ptr) {
+  CHECK(PointerIsMine(ptr));
+
+  const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
+  MarkPageInaccessible(reinterpret_cast<void*>(GetPageAddr(addr)));
+
+  size_t slot = AddrToSlot(GetPageAddr(addr));
+  DCHECK_EQ(addr, GetPageAddr(addr) + data_[slot].alloc_offset);
+  // Check for double free.
+  if (data_[slot].dealloc_trace_addr) {
+    double_free_detected_ = true;
+    *reinterpret_cast<char*>(ptr) = 'X';  // Trigger exception.
+    __builtin_trap();
+  }
+
+  // Record deallocation stack trace/thread id.
+  data_[slot].RecordDeallocation();
+
+  FreeSlot(slot);
+}
+
+size_t GuardedPageAllocator::GetRequestedSize(const void* ptr) const {
+  DCHECK(PointerIsMine(ptr));
+  const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
+  size_t slot = AddrToSlot(GetPageAddr(addr));
+  DCHECK_EQ(addr, GetPageAddr(addr) + data_[slot].alloc_offset);
+  return data_[slot].alloc_size;
+}
+
+bool GuardedPageAllocator::PointerIsMine(const void* ptr) const {
+  uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
+  return pages_base_addr_ <= addr && addr < pages_end_addr_;
+}
+
+// Selects a random slot in O(1) time by rotating the free_pages bitmap by a
+// random amount, using an intrinsic to get the least-significant 1-bit after
+// the rotation, and then computing the position of the bit before the rotation.
+// Picking a random slot is useful for randomizing allocator behavior across
+// different runs, so certain bits being more heavily biased is not a concern.
+size_t GuardedPageAllocator::ReserveSlot() {
+  base::AutoLock lock(lock_);
+  if (!free_pages_)
+    return SIZE_MAX;
+
+  // Disable allocations after a double free is detected so that the double
+  // freed allocation is not reallocated while the crash handler could be
+  // concurrently inspecting the metadata.
+  if (double_free_detected_)
+    return SIZE_MAX;
+
+  uint64_t rot = base::RandGenerator(kFreePagesNumBits);
+  BitMap rotated_bitmap =
+      (free_pages_ << rot) | (free_pages_ >> (kFreePagesNumBits - rot));
+  int rotated_selection = CountTrailingZeroBits64(rotated_bitmap);
+  size_t selection =
+      (rotated_selection - rot + kFreePagesNumBits) % kFreePagesNumBits;
+  DCHECK_LT(selection, kFreePagesNumBits);
+  DCHECK(free_pages_ & (1ULL << selection));
+  free_pages_ &= ~(1ULL << selection);
+  return selection;
+}
+
+void GuardedPageAllocator::FreeSlot(size_t slot) {
+  DCHECK_LT(slot, kFreePagesNumBits);
+
+  BitMap bit = 1ULL << slot;
+  base::AutoLock lock(lock_);
+  DCHECK_EQ((free_pages_ & bit), 0ULL);
+  free_pages_ |= bit;
+}
+
+uintptr_t GuardedPageAllocator::GetPageAddr(uintptr_t addr) const {
+  const uintptr_t addr_mask = ~(page_size_ - 1ULL);
+  return addr & addr_mask;
+}
+
+uintptr_t GuardedPageAllocator::GetNearestValidPage(uintptr_t addr) const {
+  if (addr < first_page_addr_)
+    return first_page_addr_;
+  const uintptr_t last_page_addr = pages_end_addr_ - 2 * page_size_;
+  if (addr > last_page_addr)
+    return last_page_addr;
+
+  uintptr_t offset = addr - first_page_addr_;
+  // If addr is already on a valid page, just return addr.
+  if ((offset / page_size_) % 2 == 0)
+    return addr;
+
+  // ptr points to a guard page, so get nearest valid page.
+  const size_t kHalfPageSize = page_size_ / 2;
+  if ((offset / kHalfPageSize) % 2 == 0) {
+    return addr - kHalfPageSize;  // Round down.
+  }
+  return addr + kHalfPageSize;  // Round up.
+}
+
+size_t GuardedPageAllocator::GetNearestSlot(uintptr_t addr) const {
+  return AddrToSlot(GetPageAddr(GetNearestValidPage(addr)));
+}
+
+GuardedPageAllocator::ErrorType GuardedPageAllocator::GetErrorType(
+    uintptr_t addr,
+    bool allocated,
+    bool deallocated) const {
+  if (!allocated)
+    return ErrorType::kUnknown;
+  if (double_free_detected_)
+    return ErrorType::kDoubleFree;
+  if (deallocated)
+    return ErrorType::kUseAfterFree;
+  if (addr < first_page_addr_)
+    return ErrorType::kBufferUnderflow;
+  const uintptr_t last_page_addr = pages_end_addr_ - 2 * page_size_;
+  if (addr > last_page_addr)
+    return ErrorType::kBufferOverflow;
+  const uintptr_t offset = addr - first_page_addr_;
+  DCHECK_NE((offset / page_size_) % 2, 0ULL);
+  const size_t kHalfPageSize = page_size_ / 2;
+  return (offset / kHalfPageSize) % 2 == 0 ? ErrorType::kBufferOverflow
+                                           : ErrorType::kBufferUnderflow;
+}
+
+uintptr_t GuardedPageAllocator::SlotToAddr(size_t slot) const {
+  DCHECK_LT(slot, kFreePagesNumBits);
+  return first_page_addr_ + 2 * slot * page_size_;
+}
+
+size_t GuardedPageAllocator::AddrToSlot(uintptr_t addr) const {
+  DCHECK_EQ(addr % page_size_, 0ULL);
+  uintptr_t offset = addr - first_page_addr_;
+  DCHECK_EQ((offset / page_size_) % 2, 0ULL);
+  size_t slot = offset / page_size_ / 2;
+  DCHECK_LT(slot, kFreePagesNumBits);
+  return slot;
+}
+
+GuardedPageAllocator::SlotMetadata::SlotMetadata() {}
+
+GuardedPageAllocator::SlotMetadata::~SlotMetadata() {
+  if (!stacktrace_alloc)
+    return;
+
+  Reset();
+
+  free(stacktrace_alloc);
+  free(stacktrace_dealloc);
+}
+
+void GuardedPageAllocator::SlotMetadata::Init() {
+  // new is not used so that we can explicitly call the constructor when we
+  // want to collect a stack trace.
+  stacktrace_alloc =
+      static_cast<StackTrace*>(malloc(sizeof(*stacktrace_alloc)));
+  CHECK(stacktrace_alloc);
+  stacktrace_dealloc =
+      static_cast<StackTrace*>(malloc(sizeof(*stacktrace_dealloc)));
+  CHECK(stacktrace_dealloc);
+}
+
+void GuardedPageAllocator::SlotMetadata::Reset() {
+  // Destruct previous allocation/deallocation traces. The constructor was only
+  // called if (de)alloc_trace_addr is non-null.
+  if (alloc_trace_addr)
+    stacktrace_alloc->~StackTrace();
+  if (dealloc_trace_addr)
+    stacktrace_dealloc->~StackTrace();
+}
+
+void GuardedPageAllocator::SlotMetadata::RecordAllocation(size_t size,
+                                                          size_t offset) {
+  Reset();
+
+  alloc_size = size;
+  alloc_offset = offset;
+
+  alloc_tid = base::PlatformThread::CurrentId();
+  new (stacktrace_alloc) StackTrace();
+  alloc_trace_addr = stacktrace_alloc->Addresses(&alloc_trace_len);
+
+  dealloc_tid = base::kInvalidThreadId;
+  dealloc_trace_addr = nullptr;
+  dealloc_trace_len = 0;
+}
+
+void GuardedPageAllocator::SlotMetadata::RecordDeallocation() {
+  dealloc_tid = base::PlatformThread::CurrentId();
+  new (stacktrace_dealloc) StackTrace();
+  dealloc_trace_addr = stacktrace_dealloc->Addresses(&dealloc_trace_len);
+}
+
+}  // namespace internal
+}  // namespace gwp_asan
diff --git a/components/gwp_asan/common/guarded_page_allocator.h b/components/gwp_asan/common/guarded_page_allocator.h
new file mode 100644
index 0000000..624757c
--- /dev/null
+++ b/components/gwp_asan/common/guarded_page_allocator.h
@@ -0,0 +1,202 @@
+// Copyright (c) 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_GWP_ASAN_COMMON_GUARDED_PAGE_ALLOCATOR_H_
+#define COMPONENTS_GWP_ASAN_COMMON_GUARDED_PAGE_ALLOCATOR_H_
+
+#include <atomic>
+
+#include "base/debug/stack_trace.h"
+#include "base/gtest_prod_util.h"
+#include "base/no_destructor.h"
+#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
+#include "base/threading/platform_thread.h"
+
+namespace gwp_asan {
+namespace internal {
+
+// Method to count trailing zero bits in a uint64_t (identical to
+// base::bits::CountTrailingZeroBits64 except that it also works on 32-bit
+// platforms.)
+unsigned CountTrailingZeroBits64(uint64_t x);
+
+class GuardedPageAllocator {
+ public:
+  // Maximum number of pages this class can allocate.
+  static constexpr size_t kGpaMaxPages = 64;
+
+  // Maximum alignment for all returned allocations.
+  static constexpr size_t kGpaAllocAlignment = 16;
+
+  enum class ErrorType {
+    kUseAfterFree = 0,
+    kBufferUnderflow = 1,
+    kBufferOverflow = 2,
+    kDoubleFree = 3,
+    kUnknown = 4,
+  };
+
+  // Initialize the singleton. Used to configure the allocator to map memory
+  // for num_pages pages (excluding guard pages). num_pages must be in the range
+  // [1, kGpaMaxPages].
+  static GuardedPageAllocator& InitializeSingleton(size_t num_pages);
+
+  // Returns the global allocator singleton.
+  static GuardedPageAllocator& Get();
+
+  // On success, returns a pointer to size bytes of page-guarded memory. On
+  // failure, returns nullptr. The allocation is not guaranteed to be
+  // zero-filled. Failure can occur if memory could not be mapped or protected,
+  // or if all guarded pages are already allocated.
+  //
+  // Precondition: size <= page_size_
+  void* Allocate(size_t size);
+
+  // Deallocates memory pointed to by ptr. ptr must have been previously
+  // returned by a call to Allocate.
+  void Deallocate(void* ptr);
+
+  // Returns the size requested when ptr was allocated. ptr must have been
+  // previously returned by a call to Allocate.
+  size_t GetRequestedSize(const void* ptr) const;
+
+  // Returns true if ptr points to memory managed by this class.
+  bool PointerIsMine(const void* ptr) const;
+
+ private:
+  using BitMap = uint64_t;
+
+  // Structure for storing data about a slot.
+  struct SlotMetadata {
+    SlotMetadata();
+    ~SlotMetadata();
+
+    // Allocate internal data (StackTraces) for this slot. StackTrace objects
+    // are large so we only allocate them if they're required (instead of
+    // having them be statically allocated in the SlotMetadata itself.)
+    void Init();
+
+    // Update slot metadata on an allocation with the given size and offset.
+    void RecordAllocation(size_t size, size_t offset);
+
+    // Update slot metadata on a deallocation.
+    void RecordDeallocation();
+
+    // Size of the allocation
+    size_t alloc_size = 0;
+    // How far into the page is the returned allocation.
+    size_t alloc_offset = 0;
+
+    // (De)allocation thread id or base::kInvalidThreadId if no (de)allocation
+    // occurred.
+    base::PlatformThreadId alloc_tid = base::kInvalidThreadId;
+    base::PlatformThreadId dealloc_tid = base::kInvalidThreadId;
+
+    // Pointer to stack trace addresses or null if no (de)allocation occurred.
+    const void* const* alloc_trace_addr = nullptr;
+    const void* const* dealloc_trace_addr = nullptr;
+
+    // Stack trace length or 0 if no (de)allocation occurred.
+    size_t alloc_trace_len = 0;
+    size_t dealloc_trace_len = 0;
+
+   private:
+    // Call destructors on stacktrace_alloc and stacktrace_dealloc if
+    // constructors for them have previously been called.
+    void Reset();
+
+    // StackTrace objects for this slot, they are allocated by Init() and only
+    // used internally, (de)alloc_trace_addr/len should be used by external
+    // consumers of the stack trace data.
+    base::debug::StackTrace* stacktrace_alloc = nullptr;
+    base::debug::StackTrace* stacktrace_dealloc = nullptr;
+  };
+
+  // Number of bits in the free_pages_ bitmap.
+  static constexpr size_t kFreePagesNumBits = sizeof(BitMap) * 8;
+
+  // Configures this allocator to map memory for num_pages pages (excluding
+  // guard pages). num_pages must be in the range [1, kGpaMaxPages].
+  //
+  // Marked private so that the singleton Get() method is the only way to obtain
+  // an instance.
+  explicit GuardedPageAllocator(size_t num_pages);
+
+  // Unmaps memory allocated by this class.
+  //
+  // This method should be called only once to complete destruction.
+  ~GuardedPageAllocator();
+
+  // Maps pages into memory and sets pages_base_addr_, first_page_addr_, and
+  // pages_end_addr on success. Returns true on success, false on failure.
+  bool MapPages();
+
+  // Unmaps pages.
+  void UnmapPages();
+
+  // Mark page read-write or inaccessible.
+  void MarkPageReadWrite(void*);
+  void MarkPageInaccessible(void*);
+
+  // Reserves and returns a slot randomly selected from the free slots in
+  // free_pages_. Returns SIZE_MAX if no slots available.
+  size_t ReserveSlot() LOCKS_EXCLUDED(lock_);
+
+  // Marks the specified slot as unreserved.
+  void FreeSlot(size_t slot) LOCKS_EXCLUDED(lock_);
+
+  // Returns the address of the page that addr resides on.
+  uintptr_t GetPageAddr(uintptr_t addr) const;
+
+  // Returns an address somewhere on the valid page nearest to addr.
+  uintptr_t GetNearestValidPage(uintptr_t addr) const;
+
+  // Returns the slot number for the page nearest to addr.
+  size_t GetNearestSlot(uintptr_t addr) const;
+
+  // Returns the likely error type given an exception address and whether its
+  // previously been allocated and deallocated.
+  ErrorType GetErrorType(uintptr_t addr,
+                         bool allocated,
+                         bool deallocated) const;
+
+  uintptr_t SlotToAddr(size_t slot) const;
+  size_t AddrToSlot(uintptr_t addr) const;
+
+  // Allocator lock that protects free_pages_.
+  base::Lock lock_;
+
+  // Maps each bit to one page.
+  // Bit=1: Free. Bit=0: Reserved.
+  BitMap free_pages_ GUARDED_BY(lock_) = 0;
+
+  // Information about every allocation, including its size, offset, and
+  // pointers to the allocation/deallocation stack traces (if present.)
+  SlotMetadata data_[kFreePagesNumBits] = {};
+
+  uintptr_t pages_base_addr_ = 0;  // Points to start of mapped region.
+  uintptr_t pages_end_addr_ = 0;   // Points to the end of mapped region.
+  uintptr_t first_page_addr_ = 0;  // Points to first allocatable page.
+  size_t num_pages_ = 0;  // Number of pages mapped (excluding guard pages).
+  size_t page_size_ = 0;  // Page size.
+
+  // Set to true if a double free has occurred.
+  std::atomic<bool> double_free_detected_{false};
+
+  // Required to access the constructor in Get().
+  friend base::NoDestructor<GuardedPageAllocator>;
+
+  DISALLOW_COPY_AND_ASSIGN(GuardedPageAllocator);
+
+  friend class GuardedPageAllocatorTest;
+  FRIEND_TEST_ALL_PREFIXES(GuardedPageAllocatorTest,
+                           GetNearestValidPageEdgeCases);
+  FRIEND_TEST_ALL_PREFIXES(GuardedPageAllocatorTest, GetErrorTypeEdgeCases);
+};
+
+}  // namespace internal
+}  // namespace gwp_asan
+
+#endif  // COMPONENTS_GWP_ASAN_COMMON_GUARDED_PAGE_ALLOCATOR_H_
diff --git a/components/gwp_asan/common/guarded_page_allocator_unittest.cc b/components/gwp_asan/common/guarded_page_allocator_unittest.cc
new file mode 100644
index 0000000..cba8da4
--- /dev/null
+++ b/components/gwp_asan/common/guarded_page_allocator_unittest.cc
@@ -0,0 +1,248 @@
+// 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/gwp_asan/common/guarded_page_allocator.h"
+
+#include <array>
+#include <set>
+
+#include "base/bits.h"
+#include "base/process/process_metrics.h"
+#include "base/test/gtest_util.h"
+#include "base/threading/simple_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gwp_asan {
+namespace internal {
+
+static constexpr size_t kGpaMaxPages = GuardedPageAllocator::kGpaMaxPages;
+
+class GuardedPageAllocatorTest : public testing::Test {
+ protected:
+  explicit GuardedPageAllocatorTest(size_t num_pages = kGpaMaxPages)
+      : gpa_(num_pages) {}
+
+  // Get a left- or right- aligned allocation (or nullptr on error.)
+  char* GetAlignedAllocation(bool left_aligned, size_t sz) {
+    for (size_t i = 0; i < 100; i++) {
+      void* alloc = gpa_.Allocate(sz);
+      if (!alloc)
+        return nullptr;
+
+      uintptr_t addr = reinterpret_cast<uintptr_t>(alloc);
+      bool is_left_aligned =
+          (base::bits::Align(addr, base::GetPageSize()) == addr);
+      if (is_left_aligned == left_aligned)
+        return reinterpret_cast<char*>(addr);
+
+      gpa_.Deallocate(alloc);
+    }
+
+    return nullptr;
+  }
+
+  GuardedPageAllocator gpa_;
+};
+
+TEST_F(GuardedPageAllocatorTest, SingleAllocDealloc) {
+  char* buf = reinterpret_cast<char*>(gpa_.Allocate(base::GetPageSize()));
+  EXPECT_NE(buf, nullptr);
+  EXPECT_TRUE(gpa_.PointerIsMine(buf));
+  memset(buf, 'A', base::GetPageSize());
+  EXPECT_DEATH(buf[base::GetPageSize()] = 'A', "");
+  gpa_.Deallocate(buf);
+  EXPECT_DEATH(buf[0] = 'B', "");
+  EXPECT_DEATH(gpa_.Deallocate(buf), "");
+}
+
+TEST_F(GuardedPageAllocatorTest, PointerIsMine) {
+  void* buf = gpa_.Allocate(1);
+  auto malloc_ptr = std::make_unique<char>();
+  EXPECT_TRUE(gpa_.PointerIsMine(buf));
+  gpa_.Deallocate(buf);
+  EXPECT_TRUE(gpa_.PointerIsMine(buf));
+  int stack_var;
+  EXPECT_FALSE(gpa_.PointerIsMine(&stack_var));
+  EXPECT_FALSE(gpa_.PointerIsMine(malloc_ptr.get()));
+}
+
+TEST_F(GuardedPageAllocatorTest, LeftAlignedAllocation) {
+  char* buf = GetAlignedAllocation(true, 16);
+  ASSERT_NE(buf, nullptr);
+  EXPECT_DEATH(buf[-1] = 'A', "");
+  buf[0] = 'A';
+  buf[base::GetPageSize() - 1] = 'A';
+  gpa_.Deallocate(buf);
+}
+
+TEST_F(GuardedPageAllocatorTest, RightAlignedAllocation) {
+  char* buf =
+      GetAlignedAllocation(false, GuardedPageAllocator::kGpaAllocAlignment);
+  ASSERT_NE(buf, nullptr);
+  buf[-1] = 'A';
+  buf[0] = 'A';
+  EXPECT_DEATH(buf[GuardedPageAllocator::kGpaAllocAlignment] = 'A', "");
+  gpa_.Deallocate(buf);
+}
+
+TEST_F(GuardedPageAllocatorTest, GetNearestValidPageEdgeCases) {
+  EXPECT_EQ(gpa_.GetPageAddr(gpa_.GetNearestValidPage(gpa_.pages_base_addr_)),
+            gpa_.first_page_addr_);
+  EXPECT_EQ(
+      gpa_.GetPageAddr(gpa_.GetNearestValidPage(gpa_.pages_end_addr_ - 1)),
+      gpa_.pages_end_addr_ - (2 * gpa_.page_size_));
+}
+
+TEST_F(GuardedPageAllocatorTest, GetErrorTypeEdgeCases) {
+  EXPECT_EQ(gpa_.GetErrorType(gpa_.pages_base_addr_, true, false),
+            GuardedPageAllocator::ErrorType::kBufferUnderflow);
+  EXPECT_EQ(gpa_.GetErrorType(gpa_.pages_end_addr_ - 1, true, false),
+            GuardedPageAllocator::ErrorType::kBufferOverflow);
+}
+
+class GuardedPageAllocatorParamTest
+    : public GuardedPageAllocatorTest,
+      public testing::WithParamInterface<size_t> {
+ protected:
+  GuardedPageAllocatorParamTest() : GuardedPageAllocatorTest(GetParam()) {}
+};
+
+TEST_P(GuardedPageAllocatorParamTest, AllocDeallocAllPages) {
+  size_t num_pages = GetParam();
+  char* bufs[kGpaMaxPages];
+  for (size_t i = 0; i < num_pages; i++) {
+    bufs[i] = reinterpret_cast<char*>(gpa_.Allocate(1));
+    EXPECT_NE(bufs[i], nullptr);
+    EXPECT_TRUE(gpa_.PointerIsMine(bufs[i]));
+  }
+  EXPECT_EQ(gpa_.Allocate(1), nullptr);
+  gpa_.Deallocate(bufs[0]);
+  bufs[0] = reinterpret_cast<char*>(gpa_.Allocate(1));
+  EXPECT_NE(bufs[0], nullptr);
+  EXPECT_TRUE(gpa_.PointerIsMine(bufs[0]));
+
+  // Ensure that no allocation is returned twice.
+  std::set<char*> ptr_set;
+  for (size_t i = 0; i < num_pages; i++)
+    ptr_set.insert(bufs[i]);
+  EXPECT_EQ(ptr_set.size(), num_pages);
+
+  for (size_t i = 0; i < num_pages; i++) {
+    SCOPED_TRACE(i);
+    // Ensure all allocations are valid and writable.
+    bufs[i][0] = 'A';
+    gpa_.Deallocate(bufs[i]);
+    // Performing death tests post-allocation times out on Windows.
+  }
+}
+INSTANTIATE_TEST_CASE_P(VaryNumPages,
+                        GuardedPageAllocatorParamTest,
+                        testing::Values(1, kGpaMaxPages / 2, kGpaMaxPages));
+
+class ThreadedAllocCountDelegate : public base::DelegateSimpleThread::Delegate {
+ public:
+  explicit ThreadedAllocCountDelegate(
+      GuardedPageAllocator* gpa,
+      std::array<void*, kGpaMaxPages>* allocations)
+      : gpa_(gpa), allocations_(allocations) {}
+
+  void Run() override {
+    for (size_t i = 0; i < kGpaMaxPages; i++) {
+      (*allocations_)[i] = gpa_->Allocate(1);
+    }
+  }
+
+ private:
+  GuardedPageAllocator* gpa_;
+  std::array<void*, kGpaMaxPages>* allocations_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadedAllocCountDelegate);
+};
+
+// Test that no pages are double-allocated or left unallocated, and that no
+// extra pages are allocated when there's concurrent calls to Allocate().
+TEST_F(GuardedPageAllocatorTest, ThreadedAllocCount) {
+  constexpr size_t num_threads = 2;
+  std::array<void*, kGpaMaxPages> allocations[num_threads];
+  {
+    base::DelegateSimpleThreadPool threads("alloc_threads", num_threads);
+    threads.Start();
+
+    std::vector<std::unique_ptr<ThreadedAllocCountDelegate>> delegates;
+    for (size_t i = 0; i < num_threads; i++) {
+      auto delegate =
+          std::make_unique<ThreadedAllocCountDelegate>(&gpa_, &allocations[i]);
+      threads.AddWork(delegate.get());
+      delegates.push_back(std::move(delegate));
+    }
+
+    threads.JoinAll();
+  }
+  std::set<void*> allocations_set;
+  for (size_t i = 0; i < num_threads; i++) {
+    for (size_t j = 0; j < kGpaMaxPages; j++) {
+      allocations_set.insert(allocations[i][j]);
+    }
+  }
+  allocations_set.erase(nullptr);
+  EXPECT_EQ(allocations_set.size(), kGpaMaxPages);
+}
+
+class ThreadedHighContentionDelegate
+    : public base::DelegateSimpleThread::Delegate {
+ public:
+  explicit ThreadedHighContentionDelegate(GuardedPageAllocator* gpa)
+      : gpa_(gpa) {}
+
+  void Run() override {
+    char* buf;
+    while ((buf = reinterpret_cast<char*>(gpa_->Allocate(1))) == nullptr) {
+      base::PlatformThread::Sleep(base::TimeDelta::FromNanoseconds(5000));
+    }
+
+    // Verify that no other thread has access to this page.
+    EXPECT_EQ(buf[0], 0);
+
+    // Mark this page and allow some time for another thread to potentially
+    // gain access to this page.
+    buf[0] = 'A';
+    base::PlatformThread::Sleep(base::TimeDelta::FromNanoseconds(10000));
+    EXPECT_EQ(buf[0], 'A');
+
+    // Unmark this page and deallocate.
+    buf[0] = 0;
+    gpa_->Deallocate(buf);
+  }
+
+ private:
+  GuardedPageAllocator* gpa_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadedHighContentionDelegate);
+};
+
+// Test that allocator remains in consistent state under high contention and
+// doesn't double-allocate pages or fail to deallocate pages.
+TEST_F(GuardedPageAllocatorTest, ThreadedHighContention) {
+  constexpr size_t num_threads = 1000;
+  {
+    base::DelegateSimpleThreadPool threads("page_writers", num_threads);
+    threads.Start();
+
+    std::vector<std::unique_ptr<ThreadedHighContentionDelegate>> delegates;
+    for (size_t i = 0; i < num_threads; i++) {
+      auto delegate = std::make_unique<ThreadedHighContentionDelegate>(&gpa_);
+      threads.AddWork(delegate.get());
+      delegates.push_back(std::move(delegate));
+    }
+
+    threads.JoinAll();
+  }
+
+  // Verify all pages have been deallocated now that all threads are done.
+  for (size_t i = 0; i < kGpaMaxPages; i++)
+    EXPECT_NE(gpa_.Allocate(1), nullptr);
+}
+
+}  // namespace internal
+}  // namespace gwp_asan
diff --git a/components/gwp_asan/common/guarded_page_allocator_win.cc b/components/gwp_asan/common/guarded_page_allocator_win.cc
new file mode 100644
index 0000000..c504d86
--- /dev/null
+++ b/components/gwp_asan/common/guarded_page_allocator_win.cc
@@ -0,0 +1,86 @@
+// 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 <windows.h>
+
+#include "components/gwp_asan/common/guarded_page_allocator.h"
+
+#include "base/bits.h"
+#include "base/logging.h"
+#include "build/build_config.h"
+
+namespace gwp_asan {
+namespace internal {
+
+unsigned CountTrailingZeroBits64(uint64_t x) {
+#if defined(ARCH_CPU_64_BITS)
+  return base::bits::CountTrailingZeroBits(x);
+#else
+  // Windows 32-bit builds do not support CountTrailingZeroBits on a uint64_t.
+  // TODO(vtsyrklevich): Fix this in base::bits instead.
+  uint32_t right = static_cast<uint32_t>(x);
+  unsigned right_trailing = base::bits::CountTrailingZeroBits(right);
+  if (right_trailing < 32)
+    return right_trailing;
+
+  uint32_t left = static_cast<uint32_t>(x >> 32);
+  unsigned left_trailing = base::bits::CountTrailingZeroBits(left);
+  return left_trailing + right_trailing;
+#endif
+}
+
+// TODO(vtsyrklevich): See if the platform-specific memory allocation and
+// protection routines can be broken out in base/ and merged with those used for
+// PartionAlloc/ProtectedMemory.
+bool GuardedPageAllocator::MapPages() {
+  size_t len = (2 * num_pages_ + 1) * page_size_;
+  void* base_ptr = VirtualAlloc(nullptr, len, MEM_RESERVE, PAGE_NOACCESS);
+  if (!base_ptr) {
+    DPLOG(ERROR) << "Failed to reserve guarded allocator region";
+    return false;
+  }
+
+  uintptr_t base_addr = reinterpret_cast<uintptr_t>(base_ptr);
+
+  // Commit the pages used for allocations.
+  for (size_t i = 0; i < num_pages_; i++) {
+    uintptr_t address = base_addr + page_size_ * ((2 * i) + 1);
+    LPVOID ret = VirtualAlloc(reinterpret_cast<LPVOID>(address), page_size_,
+                              MEM_COMMIT, PAGE_NOACCESS);
+    if (!ret) {
+      PLOG(ERROR) << "Failed to commit allocation page";
+      UnmapPages();
+      return false;
+    }
+  }
+
+  pages_base_addr_ = base_addr;
+  first_page_addr_ = pages_base_addr_ + page_size_;
+  pages_end_addr_ = pages_base_addr_ + len;
+
+  return true;
+}
+
+void GuardedPageAllocator::UnmapPages() {
+  DCHECK(pages_base_addr_);
+  BOOL err =
+      VirtualFree(reinterpret_cast<void*>(pages_base_addr_), 0, MEM_RELEASE);
+  DCHECK(err);
+  (void)err;
+}
+
+void GuardedPageAllocator::MarkPageReadWrite(void* ptr) {
+  DWORD old_prot;
+  BOOL err = VirtualProtect(ptr, page_size_, PAGE_READWRITE, &old_prot);
+  PCHECK(err != 0) << "VirtualProtect";
+}
+
+void GuardedPageAllocator::MarkPageInaccessible(void* ptr) {
+  DWORD old_prot;
+  BOOL err = VirtualProtect(ptr, page_size_, PAGE_NOACCESS, &old_prot);
+  PCHECK(err != 0) << "VirtualProtect";
+}
+
+}  // namespace internal
+}  // namespace gwp_asan
diff --git a/components/offline_pages/core/prefetch/prefetch_item.h b/components/offline_pages/core/prefetch/prefetch_item.h
index e45066e..27e244b 100644
--- a/components/offline_pages/core/prefetch/prefetch_item.h
+++ b/components/offline_pages/core/prefetch/prefetch_item.h
@@ -61,6 +61,18 @@
   // left empty if they are the same.
   GURL final_archived_url;
 
+  // The URL to the thumbnail image representing the article.
+  GURL thumbnail_url;
+
+  // The URL to the favicon image of the article's hosting web site.
+  GURL favicon_url;
+
+  // A snippet of the article's contents.
+  std::string snippet;
+
+  // The publisher name/web site the article is attributed to.
+  std::string attribution;
+
   // Number of attempts to request OPS to generate an archive for this item.
   int generate_bundle_attempts = 0;
 
diff --git a/components/offline_pages/core/prefetch/prefetch_item_unittest.cc b/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
index 7a9e6ca..8e01d2d 100644
--- a/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
+++ b/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
@@ -97,6 +97,18 @@
   item1.final_archived_url = GURL("http://test.com/final");
   CheckFieldAndResetItem(item1, "final_archived_url");
 
+  item1.thumbnail_url = GURL("http://thumbnail");
+  CheckFieldAndResetItem(item1, "thumbnail_url");
+
+  item1.favicon_url = GURL("http://favicon");
+  CheckFieldAndResetItem(item1, "favicon_url");
+
+  item1.snippet = "snippet";
+  CheckFieldAndResetItem(item1, "snippet");
+
+  item1.attribution = "attribution";
+  CheckFieldAndResetItem(item1, "attribution");
+
   item1.generate_bundle_attempts = 10;
   CheckFieldAndResetItem(item1, "generate_bundle_attempts");
 
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_schema.cc b/components/offline_pages/core/prefetch/store/prefetch_store_schema.cc
index d05e891c..8e047984 100644
--- a/components/offline_pages/core/prefetch/store/prefetch_store_schema.cc
+++ b/components/offline_pages/core/prefetch/store/prefetch_store_schema.cc
@@ -15,6 +15,7 @@
 //   tables.
 // * 2: Changes prefetch_items.file_size to have a default value of -1 (instead
 //   of 0).
+// * 3: Add thumbnail_url, favicon_url, snippet, and attribution.
 
 // static
 constexpr int PrefetchStoreSchema::kCurrentVersion;
@@ -58,13 +59,12 @@
 // IMPORTANT #1: when making changes to these columns please also reflect them
 // into:
 // - PrefetchItem: update existing fields and all method implementations
-//   (operator=, operator<<, ToString, etc).
+//   (operator==, ToString, etc).
 // - PrefetchItemTest, PrefetchStoreTestUtil: update test related code to cover
 //   the changed set of columns and PrefetchItem members.
 // - MockPrefetchItemGenerator: so that its generated items consider all fields.
-// IMPORTANT #2: the ordering of column types is important in SQLite 3 tables to
-// simplify data retrieval. Columns with fixed length types must come first and
-// variable length types must come later.
+// IMPORTANT #2: Commonly used columns should appear first, as SQLite can stop
+//  reading the row early if later columns are not being read.
 static const char kItemsTableCreationSql[] =
     // Fixed length columns come first.
     R"sql(
@@ -87,7 +87,11 @@
 operation_name VARCHAR NOT NULL DEFAULT '',
 archive_body_name VARCHAR NOT NULL DEFAULT '',
 title VARCHAR NOT NULL DEFAULT '',
-file_path VARCHAR NOT NULL DEFAULT ''
+file_path VARCHAR NOT NULL DEFAULT '',
+thumbnail_url VARCHAR NOT NULL DEFAULT '',
+favicon_url VARCHAR NOT NULL DEFAULT '',
+snippet VARCHAR NOT NULL DEFAULT '',
+attribution VARCHAR NOT NULL DEFAULT ''
 )
 )sql";
 
@@ -121,6 +125,9 @@
 }
 
 int MigrateFromVersion1To2(sql::Database* db, sql::MetaTable* meta_table) {
+  // Version 2 simply changes the default value of file_size from 0 to -1.
+  // Because SQLite doesn't support removing or modifying columns, we create
+  // a new table and insert data from the old table.
   const int target_version = 2;
   const int target_compatible_version = 1;
   // 1. Rename the existing items table.
@@ -181,39 +188,71 @@
   return kVersionError;
 }
 
+int MigrateFromVersion2To3(sql::Database* db, sql::MetaTable* meta_table) {
+  const int target_version = 3;
+  const int target_compatible_version = 1;
+  static const char k2To3Sql[] = R"sql(
+ALTER TABLE prefetch_items ADD COLUMN thumbnail_url VARCHAR NOT NULL DEFAULT '';
+ALTER TABLE prefetch_items ADD COLUMN favicon_url VARCHAR NOT NULL DEFAULT '';
+ALTER TABLE prefetch_items ADD COLUMN snippet VARCHAR NOT NULL DEFAULT '';
+ALTER TABLE prefetch_items ADD COLUMN attribution VARCHAR NOT NULL DEFAULT '';
+)sql";
+
+  sql::Transaction transaction(db);
+  if (transaction.Begin() && db->Execute(k2To3Sql) &&
+      SetVersionNumber(meta_table, target_version) &&
+      SetCompatibleVersionNumber(meta_table, target_compatible_version) &&
+      transaction.Commit())
+    return target_version;
+
+  return kVersionError;
+}
+
+// Returns true if the database has previously been initialized to a compatible
+// version.
+bool DatabaseIsValid(sql::Database* db,
+                     sql::MetaTable* meta_table,
+                     int* current_version,
+                     int* compatible_version) {
+  if (!sql::MetaTable::DoesTableExist(db) ||
+      !meta_table->Init(db, PrefetchStoreSchema::kCurrentVersion,
+                        PrefetchStoreSchema::kCompatibleVersion))
+    return false;
+  *compatible_version = GetCompatibleVersionNumber(meta_table);
+  *current_version = GetVersionNumber(meta_table);
+  return  // Sanity checks.
+      *current_version != kVersionError &&
+      *compatible_version != kVersionError && *current_version >= 1 &&
+      *compatible_version >= 1 &&
+      // This can be false when Chrome is downgraded after a db change that's
+      // not backwards-compatible.
+      *compatible_version <= PrefetchStoreSchema::kCurrentVersion;
+}
+
 }  // namespace
 
 // static
 bool PrefetchStoreSchema::CreateOrUpgradeIfNeeded(sql::Database* db) {
-  DCHECK_GE(kCurrentVersion, kCompatibleVersion);
+  // TODO(harringtond): Add UMA to track errors and important actions here.
   DCHECK(db);
-  if (!db)
-    return false;
-
   sql::MetaTable meta_table;
-  if (!meta_table.Init(db, kCurrentVersion, kCompatibleVersion))
-    return false;
-
-  const int compatible_version = GetCompatibleVersionNumber(&meta_table);
-  int current_version = GetVersionNumber(&meta_table);
-  if (current_version == kVersionError || compatible_version == kVersionError)
-    return false;
-  DCHECK_GE(current_version, compatible_version);
-
-  // Stored database version is newer and incompatible with the current running
-  // code (Chrome was downgraded). The DB will never work until Chrome is
-  // re-upgraded.
-  if (compatible_version > kCurrentVersion)
-    return false;
-
-  // Database is already at the latest version or has just been created. Create
-  // any missing tables and return.
-  if (current_version == kCurrentVersion)
-    return CreateLatestSchema(db);
-
-  // Versions 0 and below are unexpected.
-  if (current_version <= 0)
-    return false;
+  int current_version, compatible_version;
+  if (!DatabaseIsValid(db, &meta_table, &current_version,
+                       &compatible_version)) {
+    // Raze the database to get back to a working state. Note that this is
+    // considered dangerous, and may lose data that could be recovered later.
+    // The benefit of this is that we won't be stuck in a bad state. For
+    // prefetch, loss of the data in the database is not terrible: prefetching
+    // is best effort, and the user will get more prefetch suggestions later.
+    if (!db->Raze())
+      return false;
+    sql::Transaction transaction(db);
+    sql::MetaTable new_meta;
+    return transaction.Begin() &&
+           new_meta.Init(db, PrefetchStoreSchema::kCurrentVersion,
+                         PrefetchStoreSchema::kCompatibleVersion) &&
+           CreateLatestSchema(db) && transaction.Commit();
+  }
 
   // Schema upgrade code starts here.
   //
@@ -224,9 +263,11 @@
   // should not. For instance, one should never refer to kCurrentVersion or
   // kCompatibleVersion when setting values for the current and compatible
   // versions as these are definitely going to change with each schema change.
-  if (current_version == 1) {
+  if (current_version == 1)
     current_version = MigrateFromVersion1To2(db, &meta_table);
-  }
+
+  if (current_version == 2)
+    current_version = MigrateFromVersion2To3(db, &meta_table);
 
   return current_version == kCurrentVersion;
 }
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_schema.h b/components/offline_pages/core/prefetch/store/prefetch_store_schema.h
index 49adb72..7334c58b 100644
--- a/components/offline_pages/core/prefetch/store/prefetch_store_schema.h
+++ b/components/offline_pages/core/prefetch/store/prefetch_store_schema.h
@@ -17,8 +17,11 @@
 // from any and all previous database versions to the latest.
 class PrefetchStoreSchema {
  public:
-  static constexpr int kCurrentVersion = 2;
+  // See version_schemas for a history of schema versions.
+  static constexpr int kCurrentVersion = 3;
   static constexpr int kCompatibleVersion = 1;
+  static_assert(kCurrentVersion >= kCompatibleVersion,
+                "compatible version shouldn't be greater than the current one");
 
   // Creates or upgrade the database schema as needed from information stored in
   // a metadata table. Returns |true| if the database is ready to be used,
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_schema_unittest.cc b/components/offline_pages/core/prefetch/store/prefetch_store_schema_unittest.cc
index deea8d8..3d40391 100644
--- a/components/offline_pages/core/prefetch/store/prefetch_store_schema_unittest.cc
+++ b/components/offline_pages/core/prefetch/store/prefetch_store_schema_unittest.cc
@@ -247,6 +247,18 @@
   EXPECT_TRUE(db.DoesColumnExist("some_table", "value"));
 }
 
+TEST(PrefetchStoreSchemaTest, TestInvalidMetaTable) {
+  // Verify CreateOrUpgradeIfNeeded will raze the db if it can't be used.
+  sql::Database db;
+  ASSERT_TRUE(db.OpenInMemory());
+  sql::MetaTable meta;
+  meta.Init(&db, 100, 99);  // Some future version.
+  ASSERT_TRUE(db.Execute("CREATE TABLE prefetch_items (x INTEGER DEFAULT 1);"));
+  ASSERT_TRUE(PrefetchStoreSchema::CreateOrUpgradeIfNeeded(&db));
+
+  ExpectDbIsCurrent(&db);
+}
+
 // Verify the latest v#.sql accurately represents the current schema.
 //
 // Note: We keep the creation code for the current schema version duplicated in
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
index b878738..1f72096 100644
--- a/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
+++ b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
@@ -45,12 +45,17 @@
     "archive_body_name, "
     "title, "
     "file_path, "
-    "file_size";
+    "file_size, "
+    "thumbnail_url, "
+    "favicon_url, "
+    "snippet, "
+    "attribution";
 
 bool InsertPrefetchItemSync(const PrefetchItem& item, sql::Database* db) {
   static const std::string kSql = base::StringPrintf(
       "INSERT INTO prefetch_items (%s)"
-      " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+      " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
+      " ?, ?, ?)",
       kSqlAllColumnNames);
   sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql.c_str()));
   statement.BindInt64(0, item.offline_id);
@@ -72,6 +77,10 @@
   statement.BindString16(16, item.title);
   statement.BindString(17, store_utils::ToDatabaseFilePath(item.file_path));
   statement.BindInt64(18, item.file_size);
+  statement.BindString(19, item.thumbnail_url.spec());
+  statement.BindString(20, item.favicon_url.spec());
+  statement.BindString(21, item.snippet);
+  statement.BindString(22, item.attribution);
 
   return statement.Run();
 }
@@ -89,7 +98,7 @@
 // Populates the PrefetchItem with the data from the current row of the passed
 // in statement following the natural column ordering.
 void PopulatePrefetchItem(const sql::Statement& statement, PrefetchItem* item) {
-  DCHECK_EQ(19, statement.ColumnCount());
+  DCHECK_EQ(23, statement.ColumnCount());
   DCHECK(item);
 
   // Fields are assigned to the item in the order they are stored in the SQL
@@ -115,6 +124,10 @@
   item->file_path =
       store_utils::FromDatabaseFilePath(statement.ColumnString(17));
   item->file_size = statement.ColumnInt64(18);
+  item->thumbnail_url = GURL(statement.ColumnString(19));
+  item->favicon_url = GURL(statement.ColumnString(20));
+  item->snippet = statement.ColumnString(21);
+  item->attribution = statement.ColumnString(22);
 }
 
 std::unique_ptr<PrefetchItem> GetPrefetchItemSync(int64_t offline_id,
diff --git a/components/offline_pages/core/prefetch/test_util.cc b/components/offline_pages/core/prefetch/test_util.cc
index 35b0055e..7e70e57 100644
--- a/components/offline_pages/core/prefetch/test_util.cc
+++ b/components/offline_pages/core/prefetch/test_util.cc
@@ -16,6 +16,9 @@
     << client_id << ", state=" << state
     << ", url=" << url.possibly_invalid_spec()
     << ", final_url=" << final_archived_url.possibly_invalid_spec()
+    << ", thumbnail_url=" << thumbnail_url.possibly_invalid_spec()
+    << ", favicon_url=" << favicon_url.possibly_invalid_spec()
+    << ", snippet=" << snippet << ", attribution=" << attribution
     << ", gb_attempts=" << generate_bundle_attempts
     << ", get_attempts=" << get_operation_attempts
     << ", dl_attempts=" << download_initiation_attempts
@@ -43,6 +46,9 @@
   return offline_id == other.offline_id && guid == other.guid &&
          client_id == other.client_id && state == other.state &&
          url == other.url && final_archived_url == other.final_archived_url &&
+         thumbnail_url == other.thumbnail_url &&
+         favicon_url == other.favicon_url && snippet == other.snippet &&
+         attribution == other.attribution &&
          generate_bundle_attempts == other.generate_bundle_attempts &&
          get_operation_attempts == other.get_operation_attempts &&
          download_initiation_attempts == other.download_initiation_attempts &&
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index 9bc5861b..41b56804 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/buildflag_header.gni")
 import("//build/config/jumbo.gni")
+import("//build/config/ui.gni")
 import("//device/vr/buildflags/buildflags.gni")
 import("//third_party/protobuf/proto_library.gni")
 import("//components/vector_icons/vector_icons.gni")
@@ -27,6 +28,7 @@
     "answer_finance.icon",
     "answer_sunrise.icon",
     "answer_when_is.icon",
+    "blank.icon",
     "bookmark.icon",
     "clear.icon",
     "drive_docs.icon",
@@ -34,17 +36,36 @@
     "drive_logo.icon",
     "drive_sheets.icon",
     "drive_slides.icon",
-    "blank.icon",
     "calculator.icon",
     "extension_app.icon",
+    "find_in_page.icon",
+    "http.icon",
+    "https_invalid.icon",
+    "https_valid.icon",
+    "https_valid_in_chip.icon",
     "keyword_search.icon",
+    "offline_pin.icon",
+    "open_in_new.icon",
     "page.icon",
     "pedal.icon",
+    "product.icon",
+    "star_active.icon",
+    "star.icon",
     "switch.icon",
     "tab.icon",
   ]
 }
 
+static_library("vector_icons") {
+  sources = get_target_outputs(":omnibox_vector_icons")
+  deps = [
+    ":omnibox_vector_icons",
+    "//components/vector_icons",
+    "//skia",
+    "//ui/gfx",
+  ]
+}
+
 jumbo_static_library("browser") {
   sources = [
     "answers_cache.cc",
@@ -152,6 +173,13 @@
     "tailored_word_break_iterator.h",
     "titled_url_match_utils.cc",
     "titled_url_match_utils.h",
+    "toolbar_field_trial.cc",
+    "toolbar_field_trial.h",
+    "toolbar_model.h",
+    "toolbar_model_delegate.cc",
+    "toolbar_model_delegate.h",
+    "toolbar_model_impl.cc",
+    "toolbar_model_impl.h",
     "url_index_private_data.cc",
     "url_index_private_data.h",
     "url_prefix.cc",
@@ -165,14 +193,16 @@
   defines = [ "OMNIBOX_BROWSER_IMPLEMENTATION" ]
 
   public_deps = [
+    "//base",
     "//components/history/core/browser",
     "//components/omnibox/common",
+    "//components/security_state/core",
     "//third_party/metrics_proto",
+    "//url",
   ]
   deps = [
     ":buildflags",
     ":in_memory_url_index_cache_proto",
-    "//base",
     "//base:i18n",
     "//components/bookmarks/browser",
     "//components/data_use_measurement/core",
@@ -191,7 +221,6 @@
     "//components/sessions",
     "//components/strings",
     "//components/sync",
-    "//components/toolbar",
     "//components/url_formatter",
     "//components/variations",
     "//components/variations/net",
@@ -203,15 +232,10 @@
     "//third_party/protobuf:protobuf_lite",
     "//ui/base",
     "//ui/gfx",
-    "//url",
   ]
 
   if ((!is_android || enable_vr) && !is_ios) {
-    sources += get_target_outputs(":omnibox_vector_icons")
-    deps += [
-      ":omnibox_vector_icons",
-      "//components/vector_icons",
-    ]
+    deps += [ ":vector_icons" ]
   }
 }
 
@@ -260,26 +284,37 @@
     "test_omnibox_view.h",
     "test_scheme_classifier.cc",
     "test_scheme_classifier.h",
+    "test_toolbar_model.cc",
+    "test_toolbar_model.h",
+  ]
+
+  public_deps = [
+    ":browser",
+    "//base",
   ]
 
   deps = [
-    ":browser",
-    "//base",
     "//base/test:test_support",
     "//components/bookmarks/browser",
     "//components/bookmarks/test",
     "//components/history/core/browser",
     "//components/history/core/test",
+    "//components/resources",
     "//components/search_engines",
     "//components/sessions",
-    "//components/toolbar:test_support",
     "//net",
     "//services/network:test_support",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/metrics_proto",
     "//ui/base",
+    "//ui/gfx",
   ]
+
+  if (toolkit_views) {
+    # Needed to get the TOOLKIT_VIEWS define.
+    deps += [ "//ui/views" ]
+  }
 }
 
 bundle_data("unit_tests_bundle_data") {
@@ -334,6 +369,7 @@
     "suggestion_answer_unittest.cc",
     "tailored_word_break_iterator_unittest.cc",
     "titled_url_match_utils_unittest.cc",
+    "toolbar_model_impl_unittest.cc",
     "url_prefix_unittest.cc",
     "zero_suggest_provider_unittest.cc",
   ]
@@ -354,7 +390,6 @@
     "//components/search_engines",
     "//components/sessions",
     "//components/strings",
-    "//components/toolbar:test_support",
     "//components/url_formatter",
     "//components/variations",
     "//services/network:test_support",
diff --git a/components/omnibox/browser/DEPS b/components/omnibox/browser/DEPS
index 1f16aa21..c4374110 100644
--- a/components/omnibox/browser/DEPS
+++ b/components/omnibox/browser/DEPS
@@ -4,6 +4,7 @@
   "+components/data_use_measurement/core",
   "+components/favicon_base",
   "+components/favicon/core",
+  "+copmonents/grit",
   "+components/history/core/browser",
   "+components/history/core/test",
   "+components/keyed_service/core",
@@ -19,7 +20,6 @@
   "+components/sessions",
   "+components/sync",
   "+components/strings/grit/components_strings.h",
-  "+components/toolbar",
   "+components/url_formatter",
   "+components/variations",
   "+components/vector_icons",
diff --git a/components/omnibox/browser/in_memory_url_index_types.cc b/components/omnibox/browser/in_memory_url_index_types.cc
index 904c86df..46377ea4 100644
--- a/components/omnibox/browser/in_memory_url_index_types.cc
+++ b/components/omnibox/browser/in_memory_url_index_types.cc
@@ -10,12 +10,10 @@
 #include <numeric>
 #include <set>
 
-#include "base/feature_list.h"
 #include "base/i18n/break_iterator.h"
 #include "base/i18n/case_conversion.h"
 #include "base/strings/string_util.h"
 #include "base/trace_event/memory_usage_estimator.h"
-#include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/tailored_word_break_iterator.h"
 #include "net/base/escape.h"
 
@@ -136,29 +134,18 @@
     WordStarts* word_starts) {
   if (word_starts)
     word_starts->clear();
-  static const bool experiment_enabled =
-      base::FeatureList::IsEnabled(omnibox::kBreakWordsAtUnderscores);
-  return String16VectorFromString16(cleaned_uni_string, break_on_space,
-                                    experiment_enabled, word_starts);
-}
-
-String16Vector String16VectorFromString16(
-    const base::string16& cleaned_uni_string,
-    bool break_on_space,
-    bool break_on_underscore,
-    WordStarts* word_starts) {
   base::i18n::BreakIterator::BreakType break_mode =
       break_on_space ? base::i18n::BreakIterator::BREAK_SPACE
                      : base::i18n::BreakIterator::BREAK_WORD;
   String16Vector words;
-  if (break_on_underscore && !break_on_space) {
+  if (!break_on_space) {
     TailoredWordBreakIterator iter(cleaned_uni_string, break_mode);
     if (!iter.Init())
       return words;
     while (iter.Advance()) {
-      if (break_on_space || iter.IsWord()) {
-        String16VectorFromString16Internal(iter.GetString(), iter.prev(),
-                                           break_on_space, &words, word_starts);
+      if (iter.IsWord()) {
+        String16VectorFromString16Internal(iter.GetString(), iter.prev(), false,
+                                           &words, word_starts);
       }
     }
   } else {
@@ -166,10 +153,8 @@
     if (!iter.Init())
       return words;
     while (iter.Advance()) {
-      if (break_on_space || iter.IsWord()) {
-        String16VectorFromString16Internal(iter.GetString(), iter.prev(),
-                                           break_on_space, &words, word_starts);
-      }
+      String16VectorFromString16Internal(iter.GetString(), iter.prev(), true,
+                                         &words, word_starts);
     }
   }
   return words;
diff --git a/components/omnibox/browser/in_memory_url_index_types.h b/components/omnibox/browser/in_memory_url_index_types.h
index d682c1f..c8e933547 100644
--- a/components/omnibox/browser/in_memory_url_index_types.h
+++ b/components/omnibox/browser/in_memory_url_index_types.h
@@ -88,36 +88,30 @@
 String16Set String16SetFromString16(const base::string16& cleaned_uni_string,
                                     WordStarts* word_starts);
 
-// Breaks the |cleaned_uni_string| string down into individual words
-// and return a vector with the individual words in their original
-// order.  Use CleanUpUrlForMatching() or CleanUpUrlTitleMatching()
-// before passing |cleaned_uni_string| to this function.  If
-// |break_on_space| is false then the resulting list will contain only
-// words containing alpha-numeric characters. If |break_on_space| is
-// true then the resulting list will contain strings broken at
-// whitespace. (|break_on_space| indicates that the
-// BreakIterator::BREAK_SPACE (equivalent to BREAK_LINE) approach is
-// to be used. For a complete description of this algorithm refer to
-// the comments in base/i18n/break_iterator.h.) If |word_starts| is
-// not NULL then clears and pushes the word starts onto |word_starts|.
+// Breaks the |cleaned_uni_string| string down into individual words and
+// return a vector with the individual words in their original order. Use
+// CleanUpUrlForMatching() or CleanUpUrlTitleMatching() before passing
+// |cleaned_uni_string| to this function. If |break_on_space| is false then
+// the string is broken using BreakIterator's BREAK_WORD detection logic,
+// augmented so that it additionally breaks words at underscores. The resulting
+// list will contain only words containing alpha-numeric characters. If
+// |break_on_space| is true then the string is broken only at whitespace (no
+// word-boundary logic, no breaking at underscores). (|break_on_space| tells
+// BreakIterator to use BREAK_SPACE logic.) For more details, refer to the
+// comments in base/i18n/break_iterator.h.) If |word_starts| is not NULL
+// then clears and pushes the word starts onto |word_starts|.
 //
 // Example:
-//   Given: |cleaned_uni_string|: "http://www.google.com/ harry the rabbit."
+//   Given: |cleaned_uni_string|: "http://www.google.com/ harry the_rabbit."
 //   With |break_on_space| false the returned list will contain:
 //    "http", "www", "google", "com", "harry", "the", "rabbit"
 //   With |break_on_space| true the returned list will contain:
-//    "http://", "www.google.com/", "harry", "the", "rabbit."
+//    "http://", "www.google.com/", "harry", "the_rabbit."
 String16Vector String16VectorFromString16(
     const base::string16& cleaned_uni_string,
     bool break_on_space,
     WordStarts* word_starts);
 
-String16Vector String16VectorFromString16(
-    const base::string16& cleaned_uni_string,
-    bool break_on_space,
-    bool break_on_underscore,
-    WordStarts* word_starts);
-
 // Breaks the |uni_word| string down into its individual characters.
 // Note that this is temporarily intended to work on a single word, but
 // _will_ work on a string of words, perhaps with unexpected results.
diff --git a/components/omnibox/browser/in_memory_url_index_types_unittest.cc b/components/omnibox/browser/in_memory_url_index_types_unittest.cc
index 8cf6a2d..c8788ffb 100644
--- a/components/omnibox/browser/in_memory_url_index_types_unittest.cc
+++ b/components/omnibox/browser/in_memory_url_index_types_unittest.cc
@@ -78,8 +78,7 @@
   base::string16 string_d(
       base::UTF8ToUTF16("http://www.google.com/frammy_the_brammy"));
   WordStarts actual_starts_d;
-  string_vec =
-      String16VectorFromString16(string_d, false, true, &actual_starts_d);
+  string_vec = String16VectorFromString16(string_d, false, &actual_starts_d);
   ASSERT_EQ(7U, string_vec.size());
   EXPECT_EQ(UTF8ToUTF16("http"), string_vec[0]);
   EXPECT_EQ(UTF8ToUTF16("www"), string_vec[1]);
diff --git a/components/omnibox/browser/in_memory_url_index_unittest.cc b/components/omnibox/browser/in_memory_url_index_unittest.cc
index 62caf90..70d81c2 100644
--- a/components/omnibox/browser/in_memory_url_index_unittest.cc
+++ b/components/omnibox/browser/in_memory_url_index_unittest.cc
@@ -1393,7 +1393,7 @@
                   &lower_string, &lower_terms);
     WordStarts lower_terms_to_word_starts_offsets;
     URLIndexPrivateData::CalculateWordStartsOffsets(
-        lower_terms, true, &lower_terms_to_word_starts_offsets);
+        lower_terms, &lower_terms_to_word_starts_offsets);
 
     // Verify against expectations.
     EXPECT_EQ(test_cases[i].expected_word_starts_offsets_size,
diff --git a/components/omnibox/browser/omnibox_edit_controller.cc b/components/omnibox/browser/omnibox_edit_controller.cc
index 1ddfd0e..b374aa2 100644
--- a/components/omnibox/browser/omnibox_edit_controller.cc
+++ b/components/omnibox/browser/omnibox_edit_controller.cc
@@ -4,7 +4,7 @@
 
 #include "components/omnibox/browser/omnibox_edit_controller.h"
 
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 
 void OmniboxEditController::OnAutocompleteAccept(
     const GURL& destination_url,
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index a279c630..b93ef26e 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -38,10 +38,10 @@
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/omnibox/browser/query_in_omnibox.h"
 #include "components/omnibox/browser/search_provider.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_prepopulate_data.h"
 #include "components/search_engines/template_url_service.h"
-#include "components/toolbar/toolbar_model.h"
 #include "components/url_formatter/url_fixer.h"
 #include "third_party/metrics_proto/omnibox_event.pb.h"
 #include "ui/gfx/image/image.h"
@@ -283,7 +283,16 @@
   has_temporary_text_ = false;
 }
 
-void OmniboxEditModel::SetUserTextToURLForEditing() {
+void OmniboxEditModel::Unelide(bool exit_query_in_omnibox) {
+  // Unelision should not occur if the user has already inputted text.
+  if (user_input_in_progress())
+    return;
+
+  // Early exit if we don't want to exit Query in Omnibox mode, and the omnibox
+  // is displaying a query.
+  if (!exit_query_in_omnibox && GetQueryInOmniboxSearchTerms(nullptr))
+    return;
+
   SetUserText(url_for_editing_);
   view_->SetWindowTextAndCaretPos(url_for_editing_, 0, false, false);
 
diff --git a/components/omnibox/browser/omnibox_edit_model.h b/components/omnibox/browser/omnibox_edit_model.h
index 3748f40..2891bbb 100644
--- a/components/omnibox/browser/omnibox_edit_model.h
+++ b/components/omnibox/browser/omnibox_edit_model.h
@@ -176,10 +176,11 @@
   // Sets the user_text_ to |text|.
   void SetUserText(const base::string16& text);
 
-  // Sets the user text to be url_for_editing_. This also selects all and
-  // enters user-input-in-progress mode. This method is used to exit both
-  // Steady State Elisions and Query in Omnibox mode.
-  void SetUserTextToURLForEditing();
+  // Unapplies any Steady State Elisions by setting the user text to be
+  // url_for_editing_. This also selects all and enters user-input-in-progress
+  // mode. If |exit_query_in_omnibox| is set to true, this will alse exit
+  // Query in Omnibox mode if the omnibox is showing a query.
+  void Unelide(bool exit_query_in_omnibox);
 
   // Invoked any time the text may have changed in the edit. Notifies the
   // controller.
diff --git a/components/omnibox/browser/omnibox_edit_model_unittest.cc b/components/omnibox/browser/omnibox_edit_model_unittest.cc
index fd0dcfc2..68851c7 100644
--- a/components/omnibox/browser/omnibox_edit_model_unittest.cc
+++ b/components/omnibox/browser/omnibox_edit_model_unittest.cc
@@ -20,7 +20,7 @@
 #include "components/omnibox/browser/test_omnibox_edit_controller.h"
 #include "components/omnibox/browser/test_omnibox_edit_model.h"
 #include "components/omnibox/browser/test_omnibox_view.h"
-#include "components/toolbar/test_toolbar_model.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class OmniboxEditModelTest : public testing::Test {
@@ -158,8 +158,7 @@
 // Tests that AdjustTextForCopy behaves properly with Query in Omnibox enabled.
 // For more general tests of copy adjustment, see the AdjustTextForCopy test.
 TEST_F(OmniboxEditModelTest, AdjustTextForCopyQueryInOmnibox) {
-  toolbar_model()->set_formatted_full_url(
-      base::ASCIIToUTF16("https://www.example.com/"));
+  toolbar_model()->set_url(GURL("https://www.example.com/"));
   toolbar_model()->set_url_for_display(base::ASCIIToUTF16("example.com"));
 
   TestOmniboxClient* client =
@@ -255,8 +254,7 @@
 }
 
 TEST_F(OmniboxEditModelTest, CurrentMatch) {
-  toolbar_model()->set_formatted_full_url(
-      base::ASCIIToUTF16("http://localhost/"));
+  toolbar_model()->set_url(GURL("http://localhost/"));
   toolbar_model()->set_url_for_display(base::ASCIIToUTF16("localhost"));
   model()->ResetDisplayTexts();
 
@@ -283,29 +281,38 @@
 }
 
 TEST_F(OmniboxEditModelTest, DisplayText) {
-  toolbar_model()->set_formatted_full_url(
-      base::ASCIIToUTF16("https://www.example.com/"));
+  toolbar_model()->set_url(GURL("https://www.example.com/"));
   toolbar_model()->set_url_for_display(base::ASCIIToUTF16("example.com"));
 
   // Verify we show the display text when there is no Query in Omnibox match.
-  {
-    model()->ResetDisplayTexts();
+  model()->ResetDisplayTexts();
 #if defined(OS_IOS)
-    // iOS OmniboxEditModel always provides the full URL as the OmniboxView
-    // permanent display text.
-    EXPECT_EQ(base::ASCIIToUTF16("https://www.example.com/"),
-              model()->GetPermanentDisplayText());
+  // iOS OmniboxEditModel always provides the full URL as the OmniboxView
+  // permanent display text.
+  EXPECT_EQ(base::ASCIIToUTF16("https://www.example.com/"),
+            model()->GetPermanentDisplayText());
 #else
-    EXPECT_EQ(base::ASCIIToUTF16("example.com"),
-              model()->GetPermanentDisplayText());
+  EXPECT_EQ(base::ASCIIToUTF16("example.com"),
+            model()->GetPermanentDisplayText());
 #endif
 
-    base::string16 search_terms;
-    EXPECT_FALSE(model()->GetQueryInOmniboxSearchTerms(&search_terms));
-    EXPECT_TRUE(search_terms.empty());
+  base::string16 search_terms;
+  EXPECT_FALSE(model()->GetQueryInOmniboxSearchTerms(&search_terms));
+  EXPECT_TRUE(search_terms.empty());
 
-    EXPECT_TRUE(model()->CurrentTextIsURL());
-  }
+  EXPECT_TRUE(model()->CurrentTextIsURL());
+
+  // Verify we can unelide and show the full URL properly.
+  model()->Unelide(false /* exit_query_in_omnibox */);
+  EXPECT_EQ(base::ASCIIToUTF16("https://www.example.com/"), view()->GetText());
+  EXPECT_TRUE(model()->user_input_in_progress());
+  EXPECT_TRUE(view()->IsSelectAll());
+  EXPECT_TRUE(model()->CurrentTextIsURL());
+}
+
+TEST_F(OmniboxEditModelTest, DisplayAndExitQueryInOmnibox) {
+  toolbar_model()->set_url(GURL("https://www.example.com/"));
+  toolbar_model()->set_url_for_display(base::ASCIIToUTF16("example.com"));
 
   // Verify the displayed text when there is a Query in Omnibox match.
   TestOmniboxClient* client =
@@ -321,10 +328,11 @@
   EXPECT_FALSE(model()->CurrentTextIsURL());
 
   // Verify we can exit Query in Omnibox mode properly.
-  model()->SetUserTextToURLForEditing();
+  model()->Unelide(true /* exit_query_in_omnibox */);
   EXPECT_EQ(base::ASCIIToUTF16("https://www.example.com/"), view()->GetText());
   EXPECT_TRUE(model()->user_input_in_progress());
   EXPECT_TRUE(view()->IsSelectAll());
+  EXPECT_TRUE(model()->CurrentTextIsURL());
 }
 
 TEST_F(OmniboxEditModelTest, DisablePasteAndGoForLongTexts) {
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index 097fc148..156ae1e 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -178,11 +178,6 @@
       base::FEATURE_ENABLED_BY_DEFAULT
 };
 
-// Feature used to allow breaking words at underscores in building
-// URLIndexPrivateData.
-const base::Feature kBreakWordsAtUnderscores{"OmniboxBreakWordsAtUnderscores",
-                                             base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Feature used to fetch document suggestions.
 const base::Feature kDocumentProvider{"OmniboxDocumentProvider",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index 57c20014..4e5fa75 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -45,7 +45,6 @@
 extern const base::Feature kUIExperimentSwapTitleAndUrl;
 extern const base::Feature kUIExperimentVerticalMargin;
 extern const base::Feature kSpeculativeServiceWorkerStartOnQueryInput;
-extern const base::Feature kBreakWordsAtUnderscores;
 extern const base::Feature kDocumentProvider;
 extern const base::Feature kOmniboxPopupShortcutIconsInZeroState;
 
diff --git a/components/omnibox/browser/omnibox_view.cc b/components/omnibox/browser/omnibox_view.cc
index 7f6990e..10714b9 100644
--- a/components/omnibox/browser/omnibox_view.cc
+++ b/components/omnibox/browser/omnibox_view.cc
@@ -20,7 +20,7 @@
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/query_in_omnibox.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "extensions/common/constants.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/components/omnibox/browser/omnibox_view.h b/components/omnibox/browser/omnibox_view.h
index 65641ca..7b419c1d 100644
--- a/components/omnibox/browser/omnibox_view.h
+++ b/components/omnibox/browser/omnibox_view.h
@@ -143,7 +143,7 @@
   // defines a method with that name.
   virtual void CloseOmniboxPopup();
 
-  // Sets the focus to the autocomplete view.
+  // Sets the focus to the omnibox.
   virtual void SetFocus() = 0;
 
   // Shows or hides the caret based on whether the model's is_caret_visible() is
diff --git a/components/omnibox/browser/test_omnibox_edit_controller.h b/components/omnibox/browser/test_omnibox_edit_controller.h
index 2d61b440..60c7340 100644
--- a/components/omnibox/browser/test_omnibox_edit_controller.h
+++ b/components/omnibox/browser/test_omnibox_edit_controller.h
@@ -6,7 +6,7 @@
 #define COMPONENTS_OMNIBOX_BROWSER_TEST_OMNIBOX_EDIT_CONTROLLER_H_
 
 #include "components/omnibox/browser/omnibox_edit_controller.h"
-#include "components/toolbar/test_toolbar_model.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
 
 class TestOmniboxEditController : public OmniboxEditController {
  public:
diff --git a/components/toolbar/test_toolbar_model.cc b/components/omnibox/browser/test_toolbar_model.cc
similarity index 76%
rename from components/toolbar/test_toolbar_model.cc
rename to components/omnibox/browser/test_toolbar_model.cc
index 61f7c35..daa8642 100644
--- a/components/toolbar/test_toolbar_model.cc
+++ b/components/omnibox/browser/test_toolbar_model.cc
@@ -2,16 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/toolbar/test_toolbar_model.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
+
+#include "base/strings/utf_string_conversions.h"
 
 #if defined(TOOLKIT_VIEWS)
-#include "components/toolbar/vector_icons.h"  // nogncheck
+#include "components/omnibox/browser/vector_icons.h"  // nogncheck
 #endif
 
 TestToolbarModel::TestToolbarModel()
     : security_level_(security_state::NONE),
 #if defined(TOOLKIT_VIEWS)
-      icon_(&toolbar::kHttpIcon),
+      icon_(&omnibox::kHttpIcon),
 #endif
       should_display_url_(true) {
 }
@@ -19,11 +21,17 @@
 TestToolbarModel::~TestToolbarModel() {}
 
 base::string16 TestToolbarModel::GetFormattedFullURL() const {
-  return formatted_full_url_;
+  if (!formatted_full_url_)
+    return base::UTF8ToUTF16(url_.spec());
+
+  return *formatted_full_url_;
 }
 
 base::string16 TestToolbarModel::GetURLForDisplay() const {
-  return url_for_display_;
+  if (!url_for_display_)
+    return base::UTF8ToUTF16(url_.spec());
+
+  return *url_for_display_;
 }
 
 GURL TestToolbarModel::GetURL() const {
diff --git a/components/toolbar/test_toolbar_model.h b/components/omnibox/browser/test_toolbar_model.h
similarity index 76%
rename from components/toolbar/test_toolbar_model.h
rename to components/omnibox/browser/test_toolbar_model.h
index 780820f..599b943 100644
--- a/components/toolbar/test_toolbar_model.h
+++ b/components/omnibox/browser/test_toolbar_model.h
@@ -2,15 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_TOOLBAR_TEST_TOOLBAR_MODEL_H_
-#define COMPONENTS_TOOLBAR_TEST_TOOLBAR_MODEL_H_
+#ifndef COMPONENTS_OMNIBOX_BROWSER_TEST_TOOLBAR_MODEL_H_
+#define COMPONENTS_OMNIBOX_BROWSER_TEST_TOOLBAR_MODEL_H_
 
 #include <stddef.h>
+#include <memory>
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 
 namespace gfx {
 struct VectorIcon;
@@ -36,10 +37,10 @@
   bool IsOfflinePage() const override;
 
   void set_formatted_full_url(const base::string16& url) {
-    formatted_full_url_ = url;
+    formatted_full_url_ = std::make_unique<base::string16>(url);
   }
   void set_url_for_display(const base::string16& url) {
-    url_for_display_ = url;
+    url_for_display_ = std::make_unique<base::string16>(url);
   }
   void set_url(const GURL& url) { url_ = url; }
   void set_security_level(security_state::SecurityLevel security_level) {
@@ -55,8 +56,11 @@
   void set_offline_page(bool offline_page) { offline_page_ = offline_page; }
 
  private:
-  base::string16 formatted_full_url_;
-  base::string16 url_for_display_;
+  // If either of these is not explicitly set, the test class will return
+  // |url_.spec()| for the URL for display or fully formatted URL.
+  std::unique_ptr<base::string16> formatted_full_url_;
+  std::unique_ptr<base::string16> url_for_display_;
+
   GURL url_;
   security_state::SecurityLevel security_level_ = security_state::NONE;
   const gfx::VectorIcon* icon_ = nullptr;
@@ -67,4 +71,4 @@
   DISALLOW_COPY_AND_ASSIGN(TestToolbarModel);
 };
 
-#endif  // COMPONENTS_TOOLBAR_TEST_TOOLBAR_MODEL_H_
+#endif  // COMPONENTS_OMNIBOX_BROWSER_TEST_TOOLBAR_MODEL_H_
diff --git a/components/toolbar/toolbar_field_trial.cc b/components/omnibox/browser/toolbar_field_trial.cc
similarity index 96%
rename from components/toolbar/toolbar_field_trial.cc
rename to components/omnibox/browser/toolbar_field_trial.cc
index a76e283d7..ad87abc 100644
--- a/components/toolbar/toolbar_field_trial.cc
+++ b/components/omnibox/browser/toolbar_field_trial.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 "components/toolbar/toolbar_field_trial.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
 
 #include "base/feature_list.h"
 #include "build/build_config.h"
diff --git a/components/toolbar/toolbar_field_trial.h b/components/omnibox/browser/toolbar_field_trial.h
similarity index 92%
rename from components/toolbar/toolbar_field_trial.h
rename to components/omnibox/browser/toolbar_field_trial.h
index 9ab9e345..a67d04c6 100644
--- a/components/toolbar/toolbar_field_trial.h
+++ b/components/omnibox/browser/toolbar_field_trial.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 COMPONENTS_TOOLBAR_TOOLBAR_FIELD_TRIAL_H_
-#define COMPONENTS_TOOLBAR_TOOLBAR_FIELD_TRIAL_H_
+#ifndef COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_FIELD_TRIAL_H_
+#define COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_FIELD_TRIAL_H_
 
 #include "base/feature_list.h"
 
@@ -56,4 +56,4 @@
 }  // namespace features
 }  // namespace toolbar
 
-#endif  // COMPONENTS_TOOLBAR_TOOLBAR_FIELD_TRIAL_H_
+#endif  // COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_FIELD_TRIAL_H_
diff --git a/components/toolbar/toolbar_model.h b/components/omnibox/browser/toolbar_model.h
similarity index 95%
rename from components/toolbar/toolbar_model.h
rename to components/omnibox/browser/toolbar_model.h
index cecb40a..53997e1 100644
--- a/components/toolbar/toolbar_model.h
+++ b/components/omnibox/browser/toolbar_model.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 COMPONENTS_TOOLBAR_TOOLBAR_MODEL_H_
-#define COMPONENTS_TOOLBAR_TOOLBAR_MODEL_H_
+#ifndef COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_H_
+#define COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_H_
 
 #include <stddef.h>
 
@@ -88,4 +88,4 @@
   DISALLOW_COPY_AND_ASSIGN(ToolbarModel);
 };
 
-#endif  // COMPONENTS_TOOLBAR_TOOLBAR_MODEL_H_
+#endif  // COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_H_
diff --git a/components/toolbar/toolbar_model_delegate.cc b/components/omnibox/browser/toolbar_model_delegate.cc
similarity index 92%
rename from components/toolbar/toolbar_model_delegate.cc
rename to components/omnibox/browser/toolbar_model_delegate.cc
index e11ee30..6509f5c 100644
--- a/components/toolbar/toolbar_model_delegate.cc
+++ b/components/omnibox/browser/toolbar_model_delegate.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/toolbar/toolbar_model_delegate.h"
+#include "components/omnibox/browser/toolbar_model_delegate.h"
 
 bool ToolbarModelDelegate::ShouldDisplayURL() const {
   return true;
diff --git a/components/toolbar/toolbar_model_delegate.h b/components/omnibox/browser/toolbar_model_delegate.h
similarity index 92%
rename from components/toolbar/toolbar_model_delegate.h
rename to components/omnibox/browser/toolbar_model_delegate.h
index 0beaa28..05e51dfb 100644
--- a/components/toolbar/toolbar_model_delegate.h
+++ b/components/omnibox/browser/toolbar_model_delegate.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_TOOLBAR_TOOLBAR_MODEL_DELEGATE_H_
-#define COMPONENTS_TOOLBAR_TOOLBAR_MODEL_DELEGATE_H_
+#ifndef COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_DELEGATE_H_
+#define COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_DELEGATE_H_
 
 #include <string>
 
@@ -67,4 +67,4 @@
   virtual ~ToolbarModelDelegate() {}
 };
 
-#endif  // COMPONENTS_TOOLBAR_TOOLBAR_MODEL_DELEGATE_H_
+#endif  // COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_DELEGATE_H_
diff --git a/components/toolbar/toolbar_model_impl.cc b/components/omnibox/browser/toolbar_model_impl.cc
similarity index 91%
rename from components/toolbar/toolbar_model_impl.cc
rename to components/omnibox/browser/toolbar_model_impl.cc
index b3bc7b6db..4feb18f6 100644
--- a/components/toolbar/toolbar_model_impl.cc
+++ b/components/omnibox/browser/toolbar_model_impl.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 "components/toolbar/toolbar_model_impl.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 
 #include "base/feature_list.h"
 #include "base/logging.h"
@@ -10,12 +10,12 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "components/omnibox/browser/buildflags.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
+#include "components/omnibox/browser/toolbar_model_delegate.h"
 #include "components/prefs/pref_service.h"
 #include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/buildflags.h"
-#include "components/toolbar/toolbar_field_trial.h"
-#include "components/toolbar/toolbar_model_delegate.h"
 #include "net/cert/cert_status_flags.h"
 #include "net/cert/x509_certificate.h"
 #include "net/ssl/ssl_connection_status_flags.h"
@@ -24,8 +24,8 @@
 #include "ui/gfx/vector_icon_types.h"
 
 #if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS)
-#include "components/toolbar/vector_icons.h"  // nogncheck
-#include "components/vector_icons/vector_icons.h"  // nogncheck
+#include "components/omnibox/browser/vector_icons.h"  // nogncheck
+#include "components/vector_icons/vector_icons.h"     // nogncheck
 #endif
 
 ToolbarModelImpl::ToolbarModelImpl(ToolbarModelDelegate* delegate,
@@ -34,8 +34,7 @@
   DCHECK(delegate_);
 }
 
-ToolbarModelImpl::~ToolbarModelImpl() {
-}
+ToolbarModelImpl::~ToolbarModelImpl() {}
 
 // ToolbarModelImpl Implementation.
 base::string16 ToolbarModelImpl::GetFormattedFullURL() const {
@@ -108,25 +107,25 @@
     return *icon_override;
 
   if (IsOfflinePage())
-    return toolbar::kOfflinePinIcon;
+    return omnibox::kOfflinePinIcon;
 
   switch (GetSecurityLevel(false)) {
     case security_state::NONE:
     case security_state::HTTP_SHOW_WARNING:
-      return toolbar::kHttpIcon;
+      return omnibox::kHttpIcon;
     case security_state::EV_SECURE:
     case security_state::SECURE:
-      return toolbar::kHttpsValidIcon;
+      return omnibox::kHttpsValidIcon;
     case security_state::SECURE_WITH_POLICY_INSTALLED_CERT:
       return vector_icons::kBusinessIcon;
     case security_state::DANGEROUS:
-      return toolbar::kHttpsInvalidIcon;
+      return omnibox::kHttpsInvalidIcon;
     case security_state::SECURITY_LEVEL_COUNT:
       NOTREACHED();
-      return toolbar::kHttpIcon;
+      return omnibox::kHttpIcon;
   }
   NOTREACHED();
-  return toolbar::kHttpIcon;
+  return omnibox::kHttpIcon;
 #else
   NOTREACHED();
   static const gfx::VectorIcon dummy = {};
diff --git a/components/toolbar/toolbar_model_impl.h b/components/omnibox/browser/toolbar_model_impl.h
similarity index 88%
rename from components/toolbar/toolbar_model_impl.h
rename to components/omnibox/browser/toolbar_model_impl.h
index 4ecdb17..b1a0a21 100644
--- a/components/toolbar/toolbar_model_impl.h
+++ b/components/omnibox/browser/toolbar_model_impl.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 COMPONENTS_TOOLBAR_TOOLBAR_MODEL_IMPL_H_
-#define COMPONENTS_TOOLBAR_TOOLBAR_MODEL_IMPL_H_
+#ifndef COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_IMPL_H_
+#define COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_IMPL_H_
 
 #include <stddef.h>
 
@@ -12,7 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/url_formatter/url_formatter.h"
 #include "url/gurl.h"
 
@@ -52,4 +52,4 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(ToolbarModelImpl);
 };
 
-#endif  // COMPONENTS_TOOLBAR_TOOLBAR_MODEL_IMPL_H_
+#endif  // COMPONENTS_OMNIBOX_BROWSER_TOOLBAR_MODEL_IMPL_H_
diff --git a/components/toolbar/toolbar_model_impl_unittest.cc b/components/omnibox/browser/toolbar_model_impl_unittest.cc
similarity index 89%
rename from components/toolbar/toolbar_model_impl_unittest.cc
rename to components/omnibox/browser/toolbar_model_impl_unittest.cc
index 443fb464..8e182637 100644
--- a/components/toolbar/toolbar_model_impl_unittest.cc
+++ b/components/omnibox/browser/toolbar_model_impl_unittest.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/toolbar/toolbar_model_impl.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
-#include "components/toolbar/toolbar_field_trial.h"
-#include "components/toolbar/toolbar_model_delegate.h"
+#include "components/omnibox/browser/toolbar_field_trial.h"
+#include "components/omnibox/browser/toolbar_model_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
diff --git a/components/omnibox/browser/url_index_private_data.cc b/components/omnibox/browser/url_index_private_data.cc
index 47192a77..5ca70977 100644
--- a/components/omnibox/browser/url_index_private_data.cc
+++ b/components/omnibox/browser/url_index_private_data.cc
@@ -15,7 +15,6 @@
 #include <utility>
 
 #include "base/containers/stack.h"
-#include "base/feature_list.h"
 #include "base/files/file_util.h"
 #include "base/i18n/break_iterator.h"
 #include "base/i18n/case_conversion.h"
@@ -756,51 +755,23 @@
 void URLIndexPrivateData::CalculateWordStartsOffsets(
     const String16Vector& lower_terms,
     WordStarts* lower_terms_to_word_starts_offsets) {
-  static const bool experiment_enabled =
-      base::FeatureList::IsEnabled(omnibox::kBreakWordsAtUnderscores);
-  CalculateWordStartsOffsets(lower_terms, experiment_enabled,
-                             lower_terms_to_word_starts_offsets);
-}
-
-// static
-void URLIndexPrivateData::CalculateWordStartsOffsets(
-    const String16Vector& lower_terms,
-    bool force_break_on_underscore,
-    WordStarts* lower_terms_to_word_starts_offsets) {
   // Calculate offsets for each term.  For instance, the offset for
   // ".net" should be 1, indicating that the actual word-part of the term
   // starts at offset 1.
   lower_terms_to_word_starts_offsets->resize(lower_terms.size(), 0u);
-  if (force_break_on_underscore) {
-    for (size_t i = 0; i < lower_terms.size(); ++i) {
-      TailoredWordBreakIterator iter(lower_terms[i],
-                                base::i18n::BreakIterator::BREAK_WORD);
-      // If the iterator doesn't work, assume an offset of 0.
-      if (!iter.Init())
-        continue;
-      // Find the first word start. If the iterator didn't find a word break,
-      // set an offset of term size. For example, the offset for "://" should be
-      // 3, indicating that the word-part is missing.
-      while (iter.Advance() && !iter.IsWord()) {
-      }
-
-      (*lower_terms_to_word_starts_offsets)[i] = iter.prev();
+  for (size_t i = 0; i < lower_terms.size(); ++i) {
+    TailoredWordBreakIterator iter(lower_terms[i],
+                                   base::i18n::BreakIterator::BREAK_WORD);
+    // If the iterator doesn't work, assume an offset of 0.
+    if (!iter.Init())
+      continue;
+    // Find the first word start. If the iterator didn't find a word break,
+    // set an offset of term size. For example, the offset for "://" should be
+    // 3, indicating that the word-part is missing.
+    while (iter.Advance() && !iter.IsWord()) {
     }
-  } else {
-    for (size_t i = 0; i < lower_terms.size(); ++i) {
-      base::i18n::BreakIterator iter(lower_terms[i],
-                                     base::i18n::BreakIterator::BREAK_WORD);
-      // If the iterator doesn't work, assume an offset of 0.
-      if (!iter.Init())
-        continue;
-      // Find the first word start. If the iterator didn't find a word break,
-      // set an offset of term size. For example, the offset for "://" should be
-      // 3, indicating that the word-part is missing.
-      while (iter.Advance() && !iter.IsWord()) {
-      }
 
-      (*lower_terms_to_word_starts_offsets)[i] = iter.prev();
-    }
+    (*lower_terms_to_word_starts_offsets)[i] = iter.prev();
   }
 }
 
diff --git a/components/omnibox/browser/url_index_private_data.h b/components/omnibox/browser/url_index_private_data.h
index 6381af1..c61b2c22 100644
--- a/components/omnibox/browser/url_index_private_data.h
+++ b/components/omnibox/browser/url_index_private_data.h
@@ -250,11 +250,6 @@
       const String16Vector& terms,
       WordStarts* terms_to_word_starts_offsets);
 
-  static void CalculateWordStartsOffsets(
-      const String16Vector& terms,
-      bool force_break_on_underscore,
-      WordStarts* terms_to_word_starts_offsets);
-
   // Indexes one URL history item as described by |row|. Returns true if the
   // row was actually indexed. |scheme_whitelist| is used to filter
   // non-qualifying schemes.  If |history_db| is not NULL then this function
diff --git a/components/toolbar/vector_icons/find_in_page.icon b/components/omnibox/browser/vector_icons/find_in_page.icon
similarity index 100%
rename from components/toolbar/vector_icons/find_in_page.icon
rename to components/omnibox/browser/vector_icons/find_in_page.icon
diff --git a/components/toolbar/vector_icons/http.icon b/components/omnibox/browser/vector_icons/http.icon
similarity index 100%
rename from components/toolbar/vector_icons/http.icon
rename to components/omnibox/browser/vector_icons/http.icon
diff --git a/components/toolbar/vector_icons/https_invalid.icon b/components/omnibox/browser/vector_icons/https_invalid.icon
similarity index 100%
rename from components/toolbar/vector_icons/https_invalid.icon
rename to components/omnibox/browser/vector_icons/https_invalid.icon
diff --git a/components/toolbar/vector_icons/https_valid.icon b/components/omnibox/browser/vector_icons/https_valid.icon
similarity index 100%
rename from components/toolbar/vector_icons/https_valid.icon
rename to components/omnibox/browser/vector_icons/https_valid.icon
diff --git a/components/toolbar/vector_icons/https_valid_in_chip.icon b/components/omnibox/browser/vector_icons/https_valid_in_chip.icon
similarity index 100%
rename from components/toolbar/vector_icons/https_valid_in_chip.icon
rename to components/omnibox/browser/vector_icons/https_valid_in_chip.icon
diff --git a/components/toolbar/vector_icons/offline_pin.icon b/components/omnibox/browser/vector_icons/offline_pin.icon
similarity index 100%
rename from components/toolbar/vector_icons/offline_pin.icon
rename to components/omnibox/browser/vector_icons/offline_pin.icon
diff --git a/components/toolbar/vector_icons/open_in_new.icon b/components/omnibox/browser/vector_icons/open_in_new.icon
similarity index 100%
rename from components/toolbar/vector_icons/open_in_new.icon
rename to components/omnibox/browser/vector_icons/open_in_new.icon
diff --git a/components/toolbar/vector_icons/product.icon b/components/omnibox/browser/vector_icons/product.icon
similarity index 100%
rename from components/toolbar/vector_icons/product.icon
rename to components/omnibox/browser/vector_icons/product.icon
diff --git a/components/toolbar/vector_icons/star.icon b/components/omnibox/browser/vector_icons/star.icon
similarity index 100%
rename from components/toolbar/vector_icons/star.icon
rename to components/omnibox/browser/vector_icons/star.icon
diff --git a/components/toolbar/vector_icons/star_active.icon b/components/omnibox/browser/vector_icons/star_active.icon
similarity index 100%
rename from components/toolbar/vector_icons/star_active.icon
rename to components/omnibox/browser/vector_icons/star_active.icon
diff --git a/components/test/data/offline_pages/prefetch/version_schemas/v1.data b/components/test/data/offline_pages/prefetch/version_schemas/v1.data
index 27402a6..6cabab9 100644
--- a/components/test/data/offline_pages/prefetch/version_schemas/v1.data
+++ b/components/test/data/offline_pages/prefetch/version_schemas/v1.data
@@ -24,3 +24,7 @@
 archive_body_name: "archive_body_name"
 title: "title"
 file_path: "file_path"
+thumbnail_url: ""
+favicon_url: ""
+snippet: ""
+attribution: ""
diff --git a/components/test/data/offline_pages/prefetch/version_schemas/v2.data b/components/test/data/offline_pages/prefetch/version_schemas/v2.data
index 27402a6..6cabab9 100644
--- a/components/test/data/offline_pages/prefetch/version_schemas/v2.data
+++ b/components/test/data/offline_pages/prefetch/version_schemas/v2.data
@@ -24,3 +24,7 @@
 archive_body_name: "archive_body_name"
 title: "title"
 file_path: "file_path"
+thumbnail_url: ""
+favicon_url: ""
+snippet: ""
+attribution: ""
diff --git a/components/test/data/offline_pages/prefetch/version_schemas/v3.data b/components/test/data/offline_pages/prefetch/version_schemas/v3.data
new file mode 100644
index 0000000..fe302a67
--- /dev/null
+++ b/components/test/data/offline_pages/prefetch/version_schemas/v3.data
@@ -0,0 +1,30 @@
+-- TABLE prefetch_downloader_quota --
+--- ROW 0 ---
+quota_id: "1"
+update_time: "2"
+available_quota: "3"
+-- TABLE prefetch_items --
+--- ROW 0 ---
+offline_id: "1"
+state: "2"
+generate_bundle_attempts: "3"
+get_operation_attempts: "4"
+download_initiation_attempts: "5"
+archive_body_length: "6"
+creation_time: "7"
+freshness_time: "8"
+error_code: "9"
+file_size: "10"
+guid: "guid"
+client_namespace: "client_namespace"
+client_id: "client_id"
+requested_url: "requested_url"
+final_archived_url: "final_archived_url"
+operation_name: "operation_name"
+archive_body_name: "archive_body_name"
+title: "title"
+file_path: "file_path"
+thumbnail_url: "thumbnail_url"
+favicon_url: "favicon_url"
+snippet: "snippet"
+attribution: "attribution"
diff --git a/components/test/data/offline_pages/prefetch/version_schemas/v3.sql b/components/test/data/offline_pages/prefetch/version_schemas/v3.sql
new file mode 100644
index 0000000..8b2b7c7
--- /dev/null
+++ b/components/test/data/offline_pages/prefetch/version_schemas/v3.sql
@@ -0,0 +1,103 @@
+INSERT OR REPLACE INTO meta (key, value)
+VALUES ("version", 3), ("last_compatible_version", 1);
+
+CREATE TABLE IF NOT EXISTS prefetch_items
+(
+offline_id INTEGER PRIMARY KEY NOT NULL,
+state INTEGER NOT NULL DEFAULT 0,
+generate_bundle_attempts INTEGER NOT NULL DEFAULT 0,
+get_operation_attempts INTEGER NOT NULL DEFAULT 0,
+download_initiation_attempts INTEGER NOT NULL DEFAULT 0,
+archive_body_length INTEGER_NOT_NULL DEFAULT -1,
+creation_time INTEGER NOT NULL,
+freshness_time INTEGER NOT NULL,
+error_code INTEGER NOT NULL DEFAULT 0,
+file_size INTEGER NOT NULL DEFAULT -1,
+guid VARCHAR NOT NULL DEFAULT '',
+client_namespace VARCHAR NOT NULL DEFAULT '',
+client_id VARCHAR NOT NULL DEFAULT '',
+requested_url VARCHAR NOT NULL DEFAULT '',
+final_archived_url VARCHAR NOT NULL DEFAULT '',
+operation_name VARCHAR NOT NULL DEFAULT '',
+archive_body_name VARCHAR NOT NULL DEFAULT '',
+title VARCHAR NOT NULL DEFAULT '',
+file_path VARCHAR NOT NULL DEFAULT '',
+thumbnail_url VARCHAR NOT NULL DEFAULT '',
+favicon_url VARCHAR NOT NULL DEFAULT '',
+snippet VARCHAR NOT NULL DEFAULT '',
+attribution VARCHAR NOT NULL DEFAULT ''
+);
+
+CREATE TABLE IF NOT EXISTS prefetch_downloader_quota
+(
+quota_id INTEGER PRIMARY KEY NOT NULL DEFAULT 1,
+update_time INTEGER NOT NULL,
+available_quota INTEGER NOT NULL DEFAULT 0
+);
+
+
+INSERT INTO prefetch_items
+(
+offline_id,
+state,
+generate_bundle_attempts,
+get_operation_attempts,
+download_initiation_attempts,
+archive_body_length,
+creation_time,
+freshness_time,
+error_code,
+file_size,
+guid,
+client_namespace,
+client_id,
+requested_url,
+final_archived_url,
+operation_name,
+archive_body_name,
+title,
+file_path,
+thumbnail_url,
+favicon_url,
+snippet,
+attribution
+)
+VALUES
+(
+1,  -- offline_id
+2,  -- state
+3,  -- generate_bundle_attempts
+4,  -- get_operation_attempts
+5,  -- download_initiation_attempts
+6,  -- archive_body_length
+7,  -- creation_time
+8,  -- freshness_time
+9,  -- error_code
+10,  -- file_size
+'guid',  -- guid
+'client_namespace',  -- client_namespace
+'client_id',  -- client_id
+'requested_url',  -- requested_url
+'final_archived_url',  -- final_archived_url
+'operation_name',  -- operation_name
+'archive_body_name',  -- archive_body_name
+'title',  -- title
+'file_path',  -- file_path
+'thumbnail_url',  -- thumbnail_url
+'favicon_url',  -- favicon_url
+'snippet',  -- snippet
+'attribution'  -- attribution
+);
+
+INSERT INTO prefetch_downloader_quota
+(
+quota_id,
+update_time,
+available_quota
+)
+VALUES
+(
+1,
+2,
+3
+);
diff --git a/components/toolbar/BUILD.gn b/components/toolbar/BUILD.gn
deleted file mode 100644
index 2492cc25..0000000
--- a/components/toolbar/BUILD.gn
+++ /dev/null
@@ -1,113 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/buildflag_header.gni")
-import("//build/config/ui.gni")
-import("//device/vr/buildflags/buildflags.gni")
-import("//components/vector_icons/vector_icons.gni")
-
-buildflag_header("buildflags") {
-  header = "buildflags.h"
-  flags = [ "ENABLE_VR=$enable_vr" ]
-}
-
-aggregate_vector_icons("toolbar_vector_icons") {
-  icon_directory = "vector_icons"
-
-  icons = [
-    "find_in_page.icon",
-    "http.icon",
-    "https_invalid.icon",
-    "https_valid.icon",
-    "https_valid_in_chip.icon",
-    "offline_pin.icon",
-    "open_in_new.icon",
-    "product.icon",
-    "star_active.icon",
-    "star.icon",
-  ]
-}
-
-static_library("vector_icons") {
-  sources = get_target_outputs(":toolbar_vector_icons")
-  deps = [
-    ":toolbar_vector_icons",
-    "//components/vector_icons",
-    "//skia",
-    "//ui/gfx",
-  ]
-}
-
-static_library("toolbar") {
-  sources = [
-    "toolbar_field_trial.cc",
-    "toolbar_field_trial.h",
-    "toolbar_model.h",
-    "toolbar_model_delegate.cc",
-    "toolbar_model_delegate.h",
-    "toolbar_model_impl.cc",
-    "toolbar_model_impl.h",
-  ]
-
-  public_deps = [
-    "//base",
-    "//components/security_state/core",
-    "//url",
-  ]
-
-  deps = [
-    ":buildflags",
-    "//components/google/core/browser",
-    "//components/prefs",
-    "//components/resources",
-    "//components/strings",
-    "//components/url_formatter",
-    "//net",
-    "//ui/base",
-    "//ui/gfx",
-  ]
-
-  if ((!is_android || enable_vr) && !is_ios) {
-    deps += [ ":vector_icons" ]
-  }
-}
-
-static_library("test_support") {
-  testonly = true
-
-  sources = [
-    "test_toolbar_model.cc",
-    "test_toolbar_model.h",
-  ]
-
-  public_deps = [
-    ":toolbar",
-    "//base",
-  ]
-
-  deps = [
-    "//components/resources",
-    "//ui/gfx",
-  ]
-
-  if (toolkit_views) {
-    # Needed to get the TOOLKIT_VIEWS define.
-    deps += [ "//ui/views" ]
-  }
-}
-
-source_set("unit_tests") {
-  testonly = true
-  sources = [
-    "toolbar_model_impl_unittest.cc",
-  ]
-
-  deps = [
-    ":toolbar",
-    "//base",
-    "//base/test:test_support",
-    "//testing/gtest",
-    "//url",
-  ]
-}
diff --git a/components/toolbar/DEPS b/components/toolbar/DEPS
deleted file mode 100644
index e844d5b2..0000000
--- a/components/toolbar/DEPS
+++ /dev/null
@@ -1,12 +0,0 @@
-include_rules = [
-  "+components/google/core/browser",
-  "+components/grit",
-  "+components/prefs",
-  "+components/security_state",
-  "+components/strings/grit",
-  "+components/url_formatter",
-  "+net",
-  "+ui/base",
-  "+ui/gfx",
-  "+components/vector_icons",
-]
diff --git a/components/toolbar/OWNERS b/components/toolbar/OWNERS
deleted file mode 100644
index 7f8f3b4..0000000
--- a/components/toolbar/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-estade@chromium.org
-pkasting@chromium.org
-
-# COMPONENT: UI>Browser>Toolbar
diff --git a/components/toolbar/vector_icons/OWNERS b/components/toolbar/vector_icons/OWNERS
deleted file mode 100644
index d7ec991..0000000
--- a/components/toolbar/vector_icons/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/vector_icons/OWNERS
diff --git a/components/toolbar/vector_icons/vector_icons.cc.template b/components/toolbar/vector_icons/vector_icons.cc.template
deleted file mode 100644
index dc4a46f0..0000000
--- a/components/toolbar/vector_icons/vector_icons.cc.template
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// vector_icons.cc.template is used to generate vector_icons.cc. Edit the former
-// rather than the latter.
-
-#include "components/toolbar/vector_icons.h"
-
-#include "base/logging.h"
-#include "ui/gfx/vector_icon_types.h"
-
-#include "components/vector_icons/cc_macros.h"
-
-namespace toolbar {
-
-using namespace gfx;
-
-TEMPLATE_PLACEHOLDER
-
-}
diff --git a/components/toolbar/vector_icons/vector_icons.h.template b/components/toolbar/vector_icons/vector_icons.h.template
deleted file mode 100644
index 024a309..0000000
--- a/components/toolbar/vector_icons/vector_icons.h.template
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// vector_icons.h.template is used to generate vector_icons.h. Edit the former
-// rather than the latter.
-
-#ifndef COMPONENTS_TOOLBAR_VECTOR_ICONS_H_
-#define COMPONENTS_TOOLBAR_VECTOR_ICONS_H_
-
-namespace gfx {
-struct VectorIcon;
-}
-
-#define VECTOR_ICON_TEMPLATE_H(icon_name) \
-extern const gfx::VectorIcon icon_name;
-
-namespace toolbar {
-
-TEMPLATE_PLACEHOLDER
-
-}
-
-#undef VECTOR_ICON_TEMPLATE_H
-
-#endif  // COMPONENTS_TOOLBAR_VECTOR_ICONS_H_
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc
index f6ab459..fa89d73b 100644
--- a/components/url_pattern_index/url_pattern_index.cc
+++ b/components/url_pattern_index/url_pattern_index.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <limits>
 #include <string>
+#include <utility>
 
 #include "base/containers/flat_map.h"
 #include "base/logging.h"
@@ -169,25 +170,10 @@
         else
           domains_included.push_back(offset);
       }
-
-      // The comparator ensuring the domains order necessary for fast matching.
-      auto precedes = [&builder](FlatStringOffset lhs, FlatStringOffset rhs) {
-        return CompareDomains(ToStringPiece(flatbuffers::GetTemporaryPointer(
-                                  *builder, lhs)),
-                              ToStringPiece(flatbuffers::GetTemporaryPointer(
-                                  *builder, rhs))) < 0;
-      };
-
       // The domains are stored in sorted order to support fast matching.
-      if (!domains_included.empty()) {
-        // TODO(pkalinnikov): Don't sort if it is already sorted offline.
-        std::sort(domains_included.begin(), domains_included.end(), precedes);
-        domains_included_offset = builder->CreateVector(domains_included);
-      }
-      if (!domains_excluded.empty()) {
-        std::sort(domains_excluded.begin(), domains_excluded.end(), precedes);
-        domains_excluded_offset = builder->CreateVector(domains_excluded);
-      }
+      domains_included_offset = SerializeDomainList(std::move(domains_included), builder);
+      domains_excluded_offset =
+          SerializeDomainList(std::move(domains_excluded), builder);
     }
 
     // Non-ascii characters in patterns are unsupported.
@@ -205,6 +191,22 @@
   }
 
  private:
+  FlatDomainsOffset SerializeDomainList(
+      std::vector<FlatStringOffset> domains,
+      flatbuffers::FlatBufferBuilder* builder) const {
+    // The comparator ensuring the domains order necessary for fast matching.
+    auto precedes = [&builder](FlatStringOffset lhs, FlatStringOffset rhs) {
+      return CompareDomains(
+                 ToStringPiece(flatbuffers::GetTemporaryPointer(*builder, lhs)),
+                 ToStringPiece(
+                     flatbuffers::GetTemporaryPointer(*builder, rhs))) < 0;
+    };
+    if (domains.empty())
+      return FlatDomainsOffset();
+    std::sort(domains.begin(), domains.end(), precedes);
+    return builder->CreateVector(domains);
+  }
+
   static bool ConvertAnchorType(proto::AnchorType anchor_type,
                                 flat::AnchorType* result) {
     switch (anchor_type) {
diff --git a/components/viz/common/quads/render_pass.cc b/components/viz/common/quads/render_pass.cc
index 985ada9..1720831d 100644
--- a/components/viz/common/quads/render_pass.cc
+++ b/components/viz/common/quads/render_pass.cc
@@ -110,7 +110,7 @@
   std::unique_ptr<RenderPass> copy_pass(
       Create(shared_quad_state_list.size(), quad_list.size()));
   copy_pass->SetAll(new_id, output_rect, damage_rect, transform_to_root_target,
-                    filters, background_filters, color_space,
+                    filters, backdrop_filters, color_space,
                     has_transparent_background, cache_render_pass,
                     has_damage_from_contributing_content, generate_mipmap);
   return copy_pass;
@@ -124,7 +124,7 @@
   std::unique_ptr<RenderPass> copy_pass(
       Create(shared_quad_state_list.size(), quad_list.size()));
   copy_pass->SetAll(id, output_rect, damage_rect, transform_to_root_target,
-                    filters, background_filters, color_space,
+                    filters, backdrop_filters, color_space,
                     has_transparent_background, cache_render_pass,
                     has_damage_from_contributing_content, generate_mipmap);
 
@@ -188,7 +188,7 @@
                         const gfx::Rect& damage_rect,
                         const gfx::Transform& transform_to_root_target,
                         const cc::FilterOperations& filters,
-                        const cc::FilterOperations& background_filters,
+                        const cc::FilterOperations& backdrop_filters,
                         const gfx::ColorSpace& color_space,
                         bool has_transparent_background,
                         bool cache_render_pass,
@@ -201,7 +201,7 @@
   this->damage_rect = damage_rect;
   this->transform_to_root_target = transform_to_root_target;
   this->filters = filters;
-  this->background_filters = background_filters;
+  this->backdrop_filters = backdrop_filters;
   this->color_space = color_space;
   this->has_transparent_background = has_transparent_background;
   this->cache_render_pass = cache_render_pass;
@@ -230,8 +230,8 @@
   filters.AsValueInto(value);
   value->EndArray();
 
-  value->BeginArray("background_filters");
-  background_filters.AsValueInto(value);
+  value->BeginArray("backdrop_filters");
+  backdrop_filters.AsValueInto(value);
   value->EndArray();
 
   value->BeginArray("shared_quad_state_list");
diff --git a/components/viz/common/quads/render_pass.h b/components/viz/common/quads/render_pass.h
index f988133..904b0cfd 100644
--- a/components/viz/common/quads/render_pass.h
+++ b/components/viz/common/quads/render_pass.h
@@ -90,7 +90,7 @@
               const gfx::Rect& damage_rect,
               const gfx::Transform& transform_to_root_target,
               const cc::FilterOperations& filters,
-              const cc::FilterOperations& background_filters,
+              const cc::FilterOperations& backdrop_filters,
               const gfx::ColorSpace& color_space,
               bool has_transparent_background,
               bool cache_render_pass,
@@ -126,8 +126,8 @@
   cc::FilterOperations filters;
 
   // Post-processing filters, applied to the pixels showing through the
-  // background of the render pass, from behind it.
-  cc::FilterOperations background_filters;
+  // backdrop of the render pass, from behind it.
+  cc::FilterOperations backdrop_filters;
 
   // The color space into which content will be rendered for this render pass.
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
diff --git a/components/viz/common/quads/render_pass_unittest.cc b/components/viz/common/quads/render_pass_unittest.cc
index 0f91993..a501452 100644
--- a/components/viz/common/quads/render_pass_unittest.cc
+++ b/components/viz/common/quads/render_pass_unittest.cc
@@ -27,7 +27,7 @@
   gfx::Rect damage_rect;
   gfx::Transform transform_to_root_target;
   cc::FilterOperations filters;
-  cc::FilterOperations background_filters;
+  cc::FilterOperations backdrop_filters;
   gfx::ColorSpace color_space;
   bool has_transparent_background;
   bool generate_mipmap;
@@ -49,7 +49,7 @@
               actual->transform_to_root_target);
     EXPECT_EQ(expected->damage_rect, actual->damage_rect);
     EXPECT_EQ(expected->filters, actual->filters);
-    EXPECT_EQ(expected->background_filters, expected->background_filters);
+    EXPECT_EQ(expected->backdrop_filters, expected->backdrop_filters);
     EXPECT_EQ(expected->has_transparent_background,
               actual->has_transparent_background);
     EXPECT_EQ(expected->generate_mipmap, actual->generate_mipmap);
@@ -76,8 +76,8 @@
   gfx::Rect damage_rect(56, 123, 19, 43);
   cc::FilterOperations filters;
   filters.Append(cc::FilterOperation::CreateOpacityFilter(0.5));
-  cc::FilterOperations background_filters;
-  background_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
+  cc::FilterOperations backdrop_filters;
+  backdrop_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
   bool has_transparent_background = true;
   bool cache_render_pass = false;
@@ -86,7 +86,7 @@
 
   std::unique_ptr<RenderPass> pass = RenderPass::Create();
   pass->SetAll(render_pass_id, output_rect, damage_rect, transform_to_root,
-               filters, background_filters, color_space,
+               filters, backdrop_filters, color_space,
                has_transparent_background, cache_render_pass,
                has_damage_from_contributing_content, generate_mipmap);
   pass->copy_requests.push_back(CopyOutputRequest::CreateStubForTesting());
@@ -108,7 +108,7 @@
   EXPECT_EQ(pass->transform_to_root_target, copy->transform_to_root_target);
   EXPECT_EQ(pass->damage_rect, copy->damage_rect);
   EXPECT_EQ(pass->filters, copy->filters);
-  EXPECT_EQ(pass->background_filters, copy->background_filters);
+  EXPECT_EQ(pass->backdrop_filters, copy->backdrop_filters);
   EXPECT_EQ(pass->has_transparent_background, copy->has_transparent_background);
   EXPECT_EQ(pass->generate_mipmap, copy->generate_mipmap);
   EXPECT_EQ(0u, copy->quad_list.size());
@@ -130,8 +130,8 @@
   gfx::Rect damage_rect(56, 123, 19, 43);
   cc::FilterOperations filters;
   filters.Append(cc::FilterOperation::CreateOpacityFilter(0.5));
-  cc::FilterOperations background_filters;
-  background_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
+  cc::FilterOperations backdrop_filters;
+  backdrop_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateXYZD50();
   bool has_transparent_background = true;
   bool cache_render_pass = false;
@@ -140,7 +140,7 @@
 
   std::unique_ptr<RenderPass> pass = RenderPass::Create();
   pass->SetAll(id, output_rect, damage_rect, transform_to_root, filters,
-               background_filters, color_space, has_transparent_background,
+               backdrop_filters, color_space, has_transparent_background,
                cache_render_pass, has_damage_from_contributing_content,
                generate_mipmap);
 
@@ -182,9 +182,8 @@
   gfx::Rect contrib_damage_rect(11, 16, 10, 15);
   cc::FilterOperations contrib_filters;
   contrib_filters.Append(cc::FilterOperation::CreateSepiaFilter(0.5));
-  cc::FilterOperations contrib_background_filters;
-  contrib_background_filters.Append(
-      cc::FilterOperation::CreateSaturateFilter(1));
+  cc::FilterOperations contrib_backdrop_filters;
+  contrib_backdrop_filters.Append(cc::FilterOperation::CreateSaturateFilter(1));
   gfx::ColorSpace contrib_color_space = gfx::ColorSpace::CreateSCRGBLinear();
   bool contrib_has_transparent_background = true;
   bool contrib_cache_render_pass = false;
@@ -194,7 +193,7 @@
   std::unique_ptr<RenderPass> contrib = RenderPass::Create();
   contrib->SetAll(contrib_id, contrib_output_rect, contrib_damage_rect,
                   contrib_transform_to_root, contrib_filters,
-                  contrib_background_filters, contrib_color_space,
+                  contrib_backdrop_filters, contrib_color_space,
                   contrib_has_transparent_background, contrib_cache_render_pass,
                   contrib_has_damage_from_contributing_content,
                   contrib_generate_mipmap);
@@ -237,8 +236,8 @@
   gfx::Rect damage_rect(56, 123, 19, 43);
   cc::FilterOperations filters;
   filters.Append(cc::FilterOperation::CreateOpacityFilter(0.5));
-  cc::FilterOperations background_filters;
-  background_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
+  cc::FilterOperations backdrop_filters;
+  backdrop_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateSCRGBLinear();
   bool has_transparent_background = true;
   bool cache_render_pass = false;
@@ -247,7 +246,7 @@
 
   std::unique_ptr<RenderPass> pass = RenderPass::Create();
   pass->SetAll(id, output_rect, damage_rect, transform_to_root, filters,
-               background_filters, color_space, has_transparent_background,
+               backdrop_filters, color_space, has_transparent_background,
                cache_render_pass, has_damage_from_contributing_content,
                generate_mipmap);
 
diff --git a/components/viz/service/display/ca_layer_overlay.cc b/components/viz/service/display/ca_layer_overlay.cc
index 284ccf3..d1c440b 100644
--- a/components/viz/service/display/ca_layer_overlay.cc
+++ b/components/viz/service/display/ca_layer_overlay.cc
@@ -48,7 +48,7 @@
   CA_LAYER_FAILED_DIFFERENT_CLIP_SETTINGS,
   CA_LAYER_FAILED_DIFFERENT_VERTEX_OPACITIES,
   CA_LAYER_FAILED_RENDER_PASS_FILTER_SCALE,
-  CA_LAYER_FAILED_RENDER_PASS_BACKGROUND_FILTERS,
+  CA_LAYER_FAILED_RENDER_PASS_BACKDROP_FILTERS,
   CA_LAYER_FAILED_RENDER_PASS_MASK,
   CA_LAYER_FAILED_RENDER_PASS_FILTER_OPERATION,
   CA_LAYER_FAILED_RENDER_PASS_SORTING_CONTEXT_ID,
@@ -80,10 +80,10 @@
     const base::flat_map<RenderPassId, cc::FilterOperations*>&
         render_pass_filters,
     const base::flat_map<RenderPassId, cc::FilterOperations*>&
-        render_pass_background_filters,
+        render_pass_backdrop_filters,
     CALayerOverlay* ca_layer_overlay) {
-  if (render_pass_background_filters.count(quad->render_pass_id)) {
-    return CA_LAYER_FAILED_RENDER_PASS_BACKGROUND_FILTERS;
+  if (render_pass_backdrop_filters.count(quad->render_pass_id)) {
+    return CA_LAYER_FAILED_RENDER_PASS_BACKDROP_FILTERS;
   }
 
   if (quad->shared_quad_state->sorting_context_id != 0)
@@ -182,7 +182,7 @@
       const base::flat_map<RenderPassId, cc::FilterOperations*>&
           render_pass_filters,
       const base::flat_map<RenderPassId, cc::FilterOperations*>&
-          render_pass_background_filters,
+          render_pass_backdrop_filters,
       CALayerOverlay* ca_layer_overlay,
       bool* skip,
       bool* render_pass_draw_quad) {
@@ -249,7 +249,7 @@
       case DrawQuad::RENDER_PASS:
         return FromRenderPassQuad(
             resource_provider, RenderPassDrawQuad::MaterialCast(quad),
-            render_pass_filters, render_pass_background_filters,
+            render_pass_filters, render_pass_backdrop_filters,
             ca_layer_overlay);
       case DrawQuad::SURFACE_CONTENT:
         return CA_LAYER_FAILED_SURFACE_CONTENT;
@@ -282,7 +282,7 @@
     const base::flat_map<RenderPassId, cc::FilterOperations*>&
         render_pass_filters,
     const base::flat_map<RenderPassId, cc::FilterOperations*>&
-        render_pass_background_filters,
+        render_pass_backdrop_filters,
     CALayerOverlayList* ca_layer_overlays) {
   CALayerResult result = CA_LAYER_SUCCESS;
   ca_layer_overlays->reserve(quad_list.size());
@@ -295,10 +295,9 @@
     CALayerOverlay ca_layer;
     bool skip = false;
     bool render_pass_draw_quad = false;
-    result = processor.FromDrawQuad(resource_provider, display_rect, quad,
-                                    render_pass_filters,
-                                    render_pass_background_filters, &ca_layer,
-                                    &skip, &render_pass_draw_quad);
+    result = processor.FromDrawQuad(
+        resource_provider, display_rect, quad, render_pass_filters,
+        render_pass_backdrop_filters, &ca_layer, &skip, &render_pass_draw_quad);
     if (result != CA_LAYER_SUCCESS)
       break;
 
diff --git a/components/viz/service/display/ca_layer_overlay.h b/components/viz/service/display/ca_layer_overlay.h
index ac52d0e..cabc6bae 100644
--- a/components/viz/service/display/ca_layer_overlay.h
+++ b/components/viz/service/display/ca_layer_overlay.h
@@ -80,7 +80,7 @@
     const base::flat_map<RenderPassId, cc::FilterOperations*>&
         render_pass_filters,
     const base::flat_map<RenderPassId, cc::FilterOperations*>&
-        render_pass_background_filters,
+        render_pass_backdrop_filters,
     CALayerOverlayList* ca_layer_overlays);
 
 }  // namespace viz
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
index 8a69964..0b491d5 100644
--- a/components/viz/service/display/direct_renderer.cc
+++ b/components/viz/service/display/direct_renderer.cc
@@ -323,8 +323,8 @@
   for (const auto& pass : *render_passes_in_draw_order) {
     if (!pass->filters.IsEmpty())
       render_pass_filters_[pass->id] = &pass->filters;
-    if (!pass->background_filters.IsEmpty())
-      render_pass_background_filters_[pass->id] = &pass->background_filters;
+    if (!pass->backdrop_filters.IsEmpty())
+      render_pass_backdrop_filters_[pass->id] = &pass->backdrop_filters;
   }
 
   // Create the overlay candidate for the output surface, and mark it as
@@ -346,7 +346,7 @@
   overlay_processor_->ProcessForOverlays(
       resource_provider_, render_passes_in_draw_order,
       output_surface_->color_matrix(), render_pass_filters_,
-      render_pass_background_filters_, &current_frame()->overlay_list,
+      render_pass_backdrop_filters_, &current_frame()->overlay_list,
       &current_frame()->ca_layer_overlay_list,
       &current_frame()->dc_layer_overlay_list,
       &current_frame()->root_damage_rect,
@@ -405,7 +405,7 @@
   FinishDrawingFrame();
   render_passes_in_draw_order->clear();
   render_pass_filters_.clear();
-  render_pass_background_filters_.clear();
+  render_pass_backdrop_filters_.clear();
 
   current_frame_valid_ = false;
 }
@@ -495,8 +495,8 @@
 
 const cc::FilterOperations* DirectRenderer::BackgroundFiltersForPass(
     RenderPassId render_pass_id) const {
-  auto it = render_pass_background_filters_.find(render_pass_id);
-  return it == render_pass_background_filters_.end() ? nullptr : it->second;
+  auto it = render_pass_backdrop_filters_.find(render_pass_id);
+  return it == render_pass_backdrop_filters_.end() ? nullptr : it->second;
 }
 
 void DirectRenderer::FlushPolygons(
diff --git a/components/viz/service/display/direct_renderer.h b/components/viz/service/display/direct_renderer.h
index 5780b2f..5e05236 100644
--- a/components/viz/service/display/direct_renderer.h
+++ b/components/viz/service/display/direct_renderer.h
@@ -233,7 +233,7 @@
   // A map from RenderPass id to the filters used when drawing the RenderPass.
   base::flat_map<RenderPassId, cc::FilterOperations*> render_pass_filters_;
   base::flat_map<RenderPassId, cc::FilterOperations*>
-      render_pass_background_filters_;
+      render_pass_backdrop_filters_;
 
   bool visible_ = false;
   bool disable_color_checks_for_testing_ = false;
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 775d568..4778c227 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -660,7 +660,7 @@
   for (const auto& pass : frame->render_pass_list) {
     // TODO(yiyix): Add filter effects to draw occlusion calculation and perform
     // draw occlusion on render pass.
-    if (!pass->filters.IsEmpty() || !pass->background_filters.IsEmpty()) {
+    if (!pass->filters.IsEmpty() || !pass->backdrop_filters.IsEmpty()) {
       for (auto* const quad : pass->quad_list) {
         total_quad_area_shown_wo_occlusion_px +=
             quad->visible_rect.size().GetCheckedArea();
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 6b16ec2..5720d33 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -209,7 +209,7 @@
   gfx::Transform projection_matrix;
   gfx::Transform quad_to_target_transform;
   const cc::FilterOperations* filters = nullptr;
-  const cc::FilterOperations* background_filters = nullptr;
+  const cc::FilterOperations* backdrop_filters = nullptr;
 
   // Whether the texture to be sampled from needs to be flipped.
   bool source_needs_flip = false;
@@ -658,10 +658,10 @@
 
 bool GLRenderer::ShouldApplyBackgroundFilters(
     const RenderPassDrawQuad* quad,
-    const cc::FilterOperations* background_filters) {
-  if (!background_filters)
+    const cc::FilterOperations* backdrop_filters) {
+  if (!backdrop_filters)
     return false;
-  DCHECK(!background_filters->IsEmpty());
+  DCHECK(!backdrop_filters->IsEmpty());
 
   // TODO(hendrikw): Look into allowing background filters to see pixels from
   // other render targets.  See crbug.com/314867.
@@ -710,7 +710,7 @@
     const RenderPassDrawQuad* quad,
     const gfx::Transform& contents_device_transform,
     const cc::FilterOperations* filters,
-    const cc::FilterOperations* background_filters,
+    const cc::FilterOperations* backdrop_filters,
     const gfx::QuadF* clip_region,
     bool use_aa,
     gfx::Rect* unclipped_rect) {
@@ -722,7 +722,7 @@
   gfx::Rect backdrop_rect = gfx::ToEnclosingRect(cc::MathUtil::MapClippedRect(
       contents_device_transform, scaled_region.BoundingBox()));
 
-  if (ShouldApplyBackgroundFilters(quad, background_filters)) {
+  if (ShouldApplyBackgroundFilters(quad, backdrop_filters)) {
     SkMatrix matrix;
     matrix.setScale(quad->filters_scale.x(), quad->filters_scale.y());
     if (FlippedFramebuffer()) {
@@ -731,7 +731,7 @@
       // current_frame()->window_matrix and contents_device_transform?
       matrix.postScale(1, -1);
     }
-    backdrop_rect = background_filters->MapRectReverse(backdrop_rect, matrix);
+    backdrop_rect = backdrop_filters->MapRectReverse(backdrop_rect, matrix);
   }
 
   if (!backdrop_rect.IsEmpty() && use_aa) {
@@ -802,18 +802,18 @@
 
 sk_sp<SkImage> GLRenderer::ApplyBackgroundFilters(
     const RenderPassDrawQuad* quad,
-    const cc::FilterOperations& background_filters,
+    const cc::FilterOperations& backdrop_filters,
     uint32_t background_texture,
     const gfx::Rect& rect,
     const gfx::Rect& unclipped_rect) {
-  DCHECK(ShouldApplyBackgroundFilters(quad, &background_filters));
+  DCHECK(ShouldApplyBackgroundFilters(quad, &backdrop_filters));
   auto use_gr_context = ScopedUseGrContext::Create(this);
 
   gfx::Vector2d clipping_offset =
       (rect.top_right() - unclipped_rect.top_right()) +
       (rect.bottom_left() - unclipped_rect.bottom_left());
   auto paint_filter = cc::RenderSurfaceFilters::BuildImageFilter(
-      background_filters, gfx::SizeF(rect.size()),
+      backdrop_filters, gfx::SizeF(rect.size()),
       gfx::Vector2dF(clipping_offset));
 
   // TODO(senorblanco): background filters should be moved to the
@@ -942,7 +942,7 @@
   local_matrix.setTranslate(quad->filters_origin.x(), quad->filters_origin.y());
   local_matrix.postScale(quad->filters_scale.x(), quad->filters_scale.y());
   params->filters = FiltersForPass(quad->render_pass_id);
-  params->background_filters = BackgroundFiltersForPass(quad->render_pass_id);
+  params->backdrop_filters = BackgroundFiltersForPass(quad->render_pass_id);
   gfx::Rect dst_rect = params->filters
                            ? params->filters->MapRect(quad->rect, local_matrix)
                            : quad->rect;
@@ -1005,7 +1005,7 @@
   SkBlendMode blend_mode = quad->shared_quad_state->blend_mode;
   params->use_shaders_for_blending =
       !CanApplyBlendModeUsingBlendFunc(blend_mode) ||
-      ShouldApplyBackgroundFilters(quad, params->background_filters) ||
+      ShouldApplyBackgroundFilters(quad, params->backdrop_filters) ||
       settings_->force_blending_with_shaders;
 
   if (params->use_shaders_for_blending) {
@@ -1014,7 +1014,7 @@
     gfx::Rect unclipped_rect;
     params->background_rect = GetBackdropBoundingBoxForRenderPassQuad(
         quad, params->contents_device_transform, params->filters,
-        params->background_filters, params->clip_region, params->use_aa,
+        params->backdrop_filters, params->clip_region, params->use_aa,
         &unclipped_rect);
 
     if (!params->background_rect.IsEmpty()) {
@@ -1029,11 +1029,11 @@
       // LayerTreeHost::CalculateMemoryForRenderSurfaces.
       params->background_texture = GetBackdropTexture(params->background_rect);
 
-      if (ShouldApplyBackgroundFilters(quad, params->background_filters)) {
+      if (ShouldApplyBackgroundFilters(quad, params->backdrop_filters)) {
         // Apply the background filters to R, so that it is applied in the
         // pixels' coordinate space.
         params->background_image = ApplyBackgroundFilters(
-            quad, *params->background_filters, params->background_texture,
+            quad, *params->backdrop_filters, params->background_texture,
             params->background_rect, unclipped_rect);
         if (params->background_image) {
           params->background_image_id =
@@ -1050,7 +1050,7 @@
         params->background_texture = 0;
       }
     } else if (CanApplyBlendModeUsingBlendFunc(blend_mode) &&
-               ShouldApplyBackgroundFilters(quad, params->background_filters)) {
+               ShouldApplyBackgroundFilters(quad, params->backdrop_filters)) {
       // Something went wrong with applying background filters to the backdrop.
       params->use_shaders_for_blending = false;
       gl_->DeleteTextures(1, &params->background_texture);
diff --git a/components/viz/service/display/gl_renderer.h b/components/viz/service/display/gl_renderer.h
index 11d1664..cd43cab 100644
--- a/components/viz/service/display/gl_renderer.h
+++ b/components/viz/service/display/gl_renderer.h
@@ -195,7 +195,7 @@
       const RenderPassDrawQuad* quad,
       const gfx::Transform& contents_device_transform,
       const cc::FilterOperations* filters,
-      const cc::FilterOperations* background_filters,
+      const cc::FilterOperations* backdrop_filters,
       const gfx::QuadF* clip_region,
       bool use_aa,
       gfx::Rect* unclipped_rect);
@@ -205,10 +205,10 @@
 
   static bool ShouldApplyBackgroundFilters(
       const RenderPassDrawQuad* quad,
-      const cc::FilterOperations* background_filters);
+      const cc::FilterOperations* backdrop_filters);
   sk_sp<SkImage> ApplyBackgroundFilters(
       const RenderPassDrawQuad* quad,
-      const cc::FilterOperations& background_filters,
+      const cc::FilterOperations& backdrop_filters,
       uint32_t background_texture,
       const gfx::Rect& rect,
       const gfx::Rect& unclipped_rect);
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc
index e9209f4..0f5cd02 100644
--- a/components/viz/service/display/gl_renderer_unittest.cc
+++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -2151,7 +2151,7 @@
     MOCK_METHOD6(Attempt,
                  bool(const SkMatrix44& output_color_matrix,
                       const OverlayProcessor::FilterOperationsMap&
-                          render_pass_background_filters,
+                          render_pass_backdrop_filters,
                       DisplayResourceProvider* resource_provider,
                       RenderPass* render_pass,
                       OverlayCandidateList* candidates,
@@ -2955,7 +2955,7 @@
 
     bool Attempt(const SkMatrix44& output_color_matrix,
                  const OverlayProcessor::FilterOperationsMap&
-                     render_pass_background_filters,
+                     render_pass_backdrop_filters,
                  DisplayResourceProvider* resource_provider,
                  RenderPass* render_pass,
                  OverlayCandidateList* candidates,
diff --git a/components/viz/service/display/overlay_candidate.cc b/components/viz/service/display/overlay_candidate.cc
index 8db823bb..e346a4d 100644
--- a/components/viz/service/display/overlay_candidate.cc
+++ b/components/viz/service/display/overlay_candidate.cc
@@ -271,7 +271,7 @@
     QuadList::ConstIterator quad_list_begin,
     QuadList::ConstIterator quad_list_end,
     const base::flat_map<RenderPassId, cc::FilterOperations*>&
-        render_pass_background_filters) {
+        render_pass_backdrop_filters) {
   for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end;
        ++overlap_iter) {
     if (overlap_iter->material == DrawQuad::RENDER_PASS) {
@@ -281,7 +281,7 @@
       const RenderPassDrawQuad* render_pass_draw_quad =
           RenderPassDrawQuad::MaterialCast(*overlap_iter);
       if (candidate.display_rect.Intersects(overlap_rect) &&
-          render_pass_background_filters.count(
+          render_pass_backdrop_filters.count(
               render_pass_draw_quad->render_pass_id)) {
         return true;
       }
diff --git a/components/viz/service/display/overlay_candidate.h b/components/viz/service/display/overlay_candidate.h
index 57ae63a..02e68d16 100644
--- a/components/viz/service/display/overlay_candidate.h
+++ b/components/viz/service/display/overlay_candidate.h
@@ -55,7 +55,7 @@
       QuadList::ConstIterator quad_list_begin,
       QuadList::ConstIterator quad_list_end,
       const base::flat_map<RenderPassId, cc::FilterOperations*>&
-          render_pass_background_filters);
+          render_pass_backdrop_filters);
 
   OverlayCandidate();
   OverlayCandidate(const OverlayCandidate& other);
diff --git a/components/viz/service/display/overlay_processor.cc b/components/viz/service/display/overlay_processor.cc
index ba80d44..0ba857d2 100644
--- a/components/viz/service/display/overlay_processor.cc
+++ b/components/viz/service/display/overlay_processor.cc
@@ -72,7 +72,7 @@
     DisplayResourceProvider* resource_provider,
     RenderPass* render_pass,
     const OverlayProcessor::FilterOperationsMap& render_pass_filters,
-    const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
+    const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
     OverlayCandidateList* overlay_candidates,
     CALayerOverlayList* ca_layer_overlays,
     gfx::Rect* damage_rect) {
@@ -84,7 +84,7 @@
   if (!ProcessForCALayerOverlays(
           resource_provider, gfx::RectF(render_pass->output_rect),
           render_pass->quad_list, render_pass_filters,
-          render_pass_background_filters, ca_layer_overlays))
+          render_pass_backdrop_filters, ca_layer_overlays))
     return false;
 
   // CALayer overlays are all-or-nothing. If all quads were replaced with
@@ -100,7 +100,7 @@
     DisplayResourceProvider* resource_provider,
     RenderPassList* render_passes,
     const OverlayProcessor::FilterOperationsMap& render_pass_filters,
-    const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
+    const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
     OverlayCandidateList* overlay_candidates,
     DCLayerOverlayList* dc_layer_overlays,
     gfx::Rect* damage_rect) {
@@ -122,7 +122,7 @@
     RenderPassList* render_passes,
     const SkMatrix44& output_color_matrix,
     const OverlayProcessor::FilterOperationsMap& render_pass_filters,
-    const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
+    const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
     OverlayCandidateList* candidates,
     CALayerOverlayList* ca_layer_overlays,
     DCLayerOverlayList* dc_layer_overlays,
@@ -156,13 +156,13 @@
 
   // First attempt to process for CALayers.
   if (ProcessForCALayers(resource_provider, render_passes->back().get(),
-                         render_pass_filters, render_pass_background_filters,
+                         render_pass_filters, render_pass_backdrop_filters,
                          candidates, ca_layer_overlays, damage_rect)) {
     return;
   }
 
   if (ProcessForDCLayers(resource_provider, render_passes, render_pass_filters,
-                         render_pass_background_filters, candidates,
+                         render_pass_backdrop_filters, candidates,
                          dc_layer_overlays, damage_rect)) {
     return;
   }
@@ -170,7 +170,7 @@
   // Only if that fails, attempt hardware overlay strategies.
   Strategy* successful_strategy = nullptr;
   for (const auto& strategy : strategies_) {
-    if (!strategy->Attempt(output_color_matrix, render_pass_background_filters,
+    if (!strategy->Attempt(output_color_matrix, render_pass_backdrop_filters,
                            resource_provider, render_passes->back().get(),
                            candidates, content_bounds)) {
       continue;
diff --git a/components/viz/service/display/overlay_processor.h b/components/viz/service/display/overlay_processor.h
index 478fff5..14797b4 100644
--- a/components/viz/service/display/overlay_processor.h
+++ b/components/viz/service/display/overlay_processor.h
@@ -48,7 +48,7 @@
     // |render_passes|.
     virtual bool Attempt(
         const SkMatrix44& output_color_matrix,
-        const FilterOperationsMap& render_pass_background_filters,
+        const FilterOperationsMap& render_pass_backdrop_filters,
         DisplayResourceProvider* resource_provider,
         RenderPass* render_pass,
         OverlayCandidateList* candidates,
@@ -72,7 +72,7 @@
       RenderPassList* render_passes,
       const SkMatrix44& output_color_matrix,
       const FilterOperationsMap& render_pass_filters,
-      const FilterOperationsMap& render_pass_background_filters,
+      const FilterOperationsMap& render_pass_backdrop_filters,
       OverlayCandidateList* overlay_candidates,
       CALayerOverlayList* ca_layer_overlays,
       DCLayerOverlayList* dc_layer_overlays,
@@ -82,10 +82,11 @@
   // Determine if we can eliminate (all remaining quads are black or
   // transparent) or crop (non-black content is a small sub-rectangle) the
   // primary framebuffer.
-  static void EliminateOrCropPrimary(const QuadList& quad_list,
-                                     const QuadList::Iterator& candidate_iterator,
-                                     OverlayCandidate* primary,
-                                     OverlayCandidateList* candidate_list);
+  static void EliminateOrCropPrimary(
+      const QuadList& quad_list,
+      const QuadList::Iterator& candidate_iterator,
+      OverlayCandidate* primary,
+      OverlayCandidateList* candidate_list);
 
  protected:
   StrategyList strategies_;
@@ -99,7 +100,7 @@
       DisplayResourceProvider* resource_provider,
       RenderPass* render_pass,
       const FilterOperationsMap& render_pass_filters,
-      const FilterOperationsMap& render_pass_background_filters,
+      const FilterOperationsMap& render_pass_backdrop_filters,
       OverlayCandidateList* overlay_candidates,
       CALayerOverlayList* ca_layer_overlays,
       gfx::Rect* damage_rect);
@@ -107,7 +108,7 @@
       DisplayResourceProvider* resource_provider,
       RenderPassList* render_passes,
       const FilterOperationsMap& render_pass_filters,
-      const FilterOperationsMap& render_pass_background_filters,
+      const FilterOperationsMap& render_pass_backdrop_filters,
       OverlayCandidateList* overlay_candidates,
       DCLayerOverlayList* dc_layer_overlays,
       gfx::Rect* damage_rect);
diff --git a/components/viz/service/display/overlay_strategy_fullscreen.cc b/components/viz/service/display/overlay_strategy_fullscreen.cc
index 55670fb..5aa46b5 100644
--- a/components/viz/service/display/overlay_strategy_fullscreen.cc
+++ b/components/viz/service/display/overlay_strategy_fullscreen.cc
@@ -22,7 +22,7 @@
 
 bool OverlayStrategyFullscreen::Attempt(
     const SkMatrix44& output_color_matrix,
-    const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
+    const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
     DisplayResourceProvider* resource_provider,
     RenderPass* render_pass,
     OverlayCandidateList* candidate_list,
diff --git a/components/viz/service/display/overlay_strategy_fullscreen.h b/components/viz/service/display/overlay_strategy_fullscreen.h
index fec6320..67e0c9b 100644
--- a/components/viz/service/display/overlay_strategy_fullscreen.h
+++ b/components/viz/service/display/overlay_strategy_fullscreen.h
@@ -22,13 +22,13 @@
       OverlayCandidateValidator* capability_checker);
   ~OverlayStrategyFullscreen() override;
 
-  bool Attempt(const SkMatrix44& output_color_matrix,
-               const OverlayProcessor::FilterOperationsMap&
-                   render_pass_background_filters,
-               DisplayResourceProvider* resource_provider,
-               RenderPass* render_pass,
-               OverlayCandidateList* candidate_list,
-               std::vector<gfx::Rect>* content_bounds) override;
+  bool Attempt(
+      const SkMatrix44& output_color_matrix,
+      const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
+      DisplayResourceProvider* resource_provider,
+      RenderPass* render_pass,
+      OverlayCandidateList* candidate_list,
+      std::vector<gfx::Rect>* content_bounds) override;
 
   OverlayProcessor::StrategyType GetUMAEnum() const override;
 
diff --git a/components/viz/service/display/overlay_strategy_single_on_top.cc b/components/viz/service/display/overlay_strategy_single_on_top.cc
index f3e8537..7c1497d 100644
--- a/components/viz/service/display/overlay_strategy_single_on_top.cc
+++ b/components/viz/service/display/overlay_strategy_single_on_top.cc
@@ -20,7 +20,7 @@
 
 bool OverlayStrategySingleOnTop::Attempt(
     const SkMatrix44& output_color_matrix,
-    const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
+    const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
     DisplayResourceProvider* resource_provider,
     RenderPass* render_pass,
     OverlayCandidateList* candidate_list,
diff --git a/components/viz/service/display/overlay_strategy_single_on_top.h b/components/viz/service/display/overlay_strategy_single_on_top.h
index 0fc45b6d..9b6a9c01 100644
--- a/components/viz/service/display/overlay_strategy_single_on_top.h
+++ b/components/viz/service/display/overlay_strategy_single_on_top.h
@@ -20,13 +20,13 @@
       OverlayCandidateValidator* capability_checker);
   ~OverlayStrategySingleOnTop() override;
 
-  bool Attempt(const SkMatrix44& output_color_matrix,
-               const OverlayProcessor::FilterOperationsMap&
-                   render_pass_background_filters,
-               DisplayResourceProvider* resource_provider,
-               RenderPass* render_pass,
-               OverlayCandidateList* candidate_list,
-               std::vector<gfx::Rect>* content_bounds) override;
+  bool Attempt(
+      const SkMatrix44& output_color_matrix,
+      const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
+      DisplayResourceProvider* resource_provider,
+      RenderPass* render_pass,
+      OverlayCandidateList* candidate_list,
+      std::vector<gfx::Rect>* content_bounds) override;
 
   OverlayProcessor::StrategyType GetUMAEnum() const override;
 
diff --git a/components/viz/service/display/overlay_strategy_underlay.cc b/components/viz/service/display/overlay_strategy_underlay.cc
index acd716f5..e3ce532 100644
--- a/components/viz/service/display/overlay_strategy_underlay.cc
+++ b/components/viz/service/display/overlay_strategy_underlay.cc
@@ -22,7 +22,7 @@
 
 bool OverlayStrategyUnderlay::Attempt(
     const SkMatrix44& output_color_matrix,
-    const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
+    const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
     DisplayResourceProvider* resource_provider,
     RenderPass* render_pass,
     OverlayCandidateList* candidate_list,
@@ -41,7 +41,7 @@
     // be filtered.  This is a problem when there are hardware planes because
     // the planes are not composited until they are on the display controller.
     if (OverlayCandidate::IsOccludedByFilteredQuad(
-            candidate, quad_list.begin(), it, render_pass_background_filters)) {
+            candidate, quad_list.begin(), it, render_pass_backdrop_filters)) {
       continue;
     }
 
diff --git a/components/viz/service/display/overlay_strategy_underlay.h b/components/viz/service/display/overlay_strategy_underlay.h
index a51261a..7fcddcb 100644
--- a/components/viz/service/display/overlay_strategy_underlay.h
+++ b/components/viz/service/display/overlay_strategy_underlay.h
@@ -36,13 +36,13 @@
       OpaqueMode opaque_mode = OpaqueMode::RequireOpaqueCandidates);
   ~OverlayStrategyUnderlay() override;
 
-  bool Attempt(const SkMatrix44& output_color_matrix,
-               const OverlayProcessor::FilterOperationsMap&
-                   render_pass_background_filters,
-               DisplayResourceProvider* resource_provider,
-               RenderPass* render_pass,
-               OverlayCandidateList* candidate_list,
-               std::vector<gfx::Rect>* content_bounds) override;
+  bool Attempt(
+      const SkMatrix44& output_color_matrix,
+      const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
+      DisplayResourceProvider* resource_provider,
+      RenderPass* render_pass,
+      OverlayCandidateList* candidate_list,
+      std::vector<gfx::Rect>* content_bounds) override;
 
   OverlayProcessor::StrategyType GetUMAEnum() const override;
 
diff --git a/components/viz/service/display/overlay_strategy_underlay_cast.cc b/components/viz/service/display/overlay_strategy_underlay_cast.cc
index 2cea01d..24fdc25 100644
--- a/components/viz/service/display/overlay_strategy_underlay_cast.cc
+++ b/components/viz/service/display/overlay_strategy_underlay_cast.cc
@@ -26,7 +26,7 @@
 
 bool OverlayStrategyUnderlayCast::Attempt(
     const SkMatrix44& output_color_matrix,
-    const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
+    const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
     DisplayResourceProvider* resource_provider,
     RenderPass* render_pass,
     OverlayCandidateList* candidate_list,
diff --git a/components/viz/service/display/overlay_strategy_underlay_cast.h b/components/viz/service/display/overlay_strategy_underlay_cast.h
index 41b001e..60595ce 100644
--- a/components/viz/service/display/overlay_strategy_underlay_cast.h
+++ b/components/viz/service/display/overlay_strategy_underlay_cast.h
@@ -23,13 +23,13 @@
       OverlayCandidateValidator* capability_checker);
   ~OverlayStrategyUnderlayCast() override;
 
-  bool Attempt(const SkMatrix44& output_color_matrix,
-               const OverlayProcessor::FilterOperationsMap&
-                   render_pass_background_filters,
-               DisplayResourceProvider* resource_provider,
-               RenderPass* render_pass,
-               OverlayCandidateList* candidate_list,
-               std::vector<gfx::Rect>* content_bounds) override;
+  bool Attempt(
+      const SkMatrix44& output_color_matrix,
+      const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
+      DisplayResourceProvider* resource_provider,
+      RenderPass* render_pass,
+      OverlayCandidateList* candidate_list,
+      std::vector<gfx::Rect>* content_bounds) override;
 
   // Callback that's made whenever an overlay quad is processed in the
   // compositor. Used to allow hardware video plane to be positioned to match
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index 688349bc..90cf582a5b4 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -630,14 +630,14 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
 
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 
@@ -665,7 +665,7 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
@@ -674,7 +674,7 @@
   // overlays since color matrices are not supported yet.
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetNonIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(0U, candidate_list.size());
 
@@ -692,14 +692,14 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
 
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   // Check that all the quads are gone.
@@ -718,14 +718,14 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
 
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 
@@ -748,14 +748,14 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
 
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(0U, candidate_list.size());
 
@@ -775,13 +775,13 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(0U, candidate_list.size());
 
@@ -807,13 +807,13 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 
@@ -839,13 +839,13 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 
@@ -890,13 +890,13 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 
@@ -932,12 +932,12 @@
   candidate_list.push_back(output_surface_plane);
 
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_TRUE(damage_rect_.IsEmpty());
 }
@@ -957,10 +957,10 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
   // There should be nothing new here.
@@ -986,10 +986,10 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
   // There should be nothing new here.
@@ -1012,12 +1012,12 @@
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1031,13 +1031,13 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   damage_rect_ = quad->rect;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
   EXPECT_FALSE(damage_rect_.IsEmpty());
@@ -1055,12 +1055,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1074,12 +1074,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1093,12 +1093,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1113,12 +1113,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1133,12 +1133,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1155,12 +1155,12 @@
                                                                       -1.0f);
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL,
@@ -1180,12 +1180,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL,
@@ -1203,12 +1203,12 @@
                                                                       1.0f);
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1225,12 +1225,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 }
@@ -1247,12 +1247,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_90, candidate_list.back().transform);
@@ -1270,12 +1270,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_180, candidate_list.back().transform);
@@ -1293,12 +1293,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_270, candidate_list.back().transform);
@@ -1314,12 +1314,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 }
@@ -1333,12 +1333,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(0U, candidate_list.size());
 }
@@ -1364,15 +1364,15 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
 
-  render_pass_background_filters[render_pass_id] = &filters;
+  render_pass_backdrop_filters[render_pass_id] = &filters;
 
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(0U, candidate_list.size());
 }
@@ -1387,12 +1387,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 }
@@ -1406,12 +1406,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 }
@@ -1431,12 +1431,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1458,12 +1458,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1483,12 +1483,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1507,12 +1507,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1529,12 +1529,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1567,12 +1567,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, candidate_list.size());
 }
@@ -1613,12 +1613,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1632,12 +1632,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1651,12 +1651,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1670,12 +1670,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(1U, candidate_list.size());
 }
@@ -1694,13 +1694,13 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(-1, candidate_list[0].plane_z_order);
@@ -1724,13 +1724,13 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   RenderPass* main_pass = pass.get();
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
   EXPECT_EQ(-1, candidate_list[0].plane_z_order);
@@ -1753,12 +1753,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   EXPECT_EQ(kOverlayRect, damage_rect_);
@@ -1781,12 +1781,12 @@
 
     OverlayCandidateList candidate_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &candidate_list,
+        render_pass_filters, render_pass_backdrop_filters, &candidate_list,
         nullptr, nullptr, &damage_rect_, &content_bounds_);
   }
 
@@ -1814,12 +1814,12 @@
 
     OverlayCandidateList candidate_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &candidate_list,
+        render_pass_filters, render_pass_backdrop_filters, &candidate_list,
         nullptr, nullptr, &damage_rect_, &content_bounds_);
 
     EXPECT_EQ(overlay_rects[i], damage_rect_);
@@ -1849,12 +1849,12 @@
 
     OverlayCandidateList candidate_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &candidate_list,
+        render_pass_filters, render_pass_backdrop_filters, &candidate_list,
         nullptr, nullptr, &damage_rect_, &content_bounds_);
   }
 
@@ -1880,12 +1880,12 @@
 
     OverlayCandidateList candidate_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &candidate_list,
+        render_pass_filters, render_pass_backdrop_filters, &candidate_list,
         nullptr, nullptr, &damage_rect_, &content_bounds_);
 
     // The damage rect should not be subtracted if the underlay is occluded
@@ -1912,12 +1912,12 @@
 
     OverlayCandidateList candidate_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &candidate_list,
+        render_pass_filters, render_pass_backdrop_filters, &candidate_list,
         nullptr, nullptr, &damage_rect_, &content_bounds_);
   }
 
@@ -1943,12 +1943,12 @@
 
     OverlayCandidateList candidate_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &candidate_list,
+        render_pass_filters, render_pass_backdrop_filters, &candidate_list,
         nullptr, nullptr, &damage_rect_, &content_bounds_);
   }
 
@@ -1975,12 +1975,12 @@
   candidate_list.push_back(candidate);
 
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   EXPECT_EQ(2U, candidate_list.size());
@@ -2008,12 +2008,12 @@
 
     OverlayCandidateList candidate_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &candidate_list,
+        render_pass_filters, render_pass_backdrop_filters, &candidate_list,
         nullptr, nullptr, &damage_rect_, &content_bounds_);
   }
 
@@ -2072,12 +2072,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, content_bounds_.size());
 }
@@ -2091,12 +2091,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   EXPECT_EQ(1U, content_bounds_.size());
@@ -2124,12 +2124,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   EXPECT_EQ(1U, content_bounds_.size());
@@ -2148,12 +2148,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   EXPECT_EQ(1U, content_bounds_.size());
@@ -2175,12 +2175,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   EXPECT_EQ(1U, content_bounds_.size());
@@ -2208,12 +2208,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   EXPECT_EQ(1U, content_bounds_.size());
@@ -2242,12 +2242,12 @@
 
   OverlayCandidateList candidate_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   EXPECT_EQ(1U, content_bounds_.size());
@@ -2274,12 +2274,12 @@
   candidate_list.push_back(candidate);
 
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &candidate_list,
+      render_pass_filters, render_pass_backdrop_filters, &candidate_list,
       nullptr, nullptr, &damage_rect_, &content_bounds_);
 
   ASSERT_EQ(false, candidate_list[0].is_opaque);
@@ -2299,12 +2299,12 @@
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &overlay_list,
+      render_pass_filters, render_pass_backdrop_filters, &overlay_list,
       &ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(gfx::Rect(), damage_rect);
   EXPECT_EQ(0U, overlay_list.size());
@@ -2323,12 +2323,12 @@
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &overlay_list,
+      render_pass_filters, render_pass_backdrop_filters, &overlay_list,
       &ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(0U, overlay_list.size());
   EXPECT_EQ(1U, ca_layer_list.size());
@@ -2351,12 +2351,12 @@
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &overlay_list,
+      render_pass_filters, render_pass_backdrop_filters, &overlay_list,
       &ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(gfx::Rect(), damage_rect);
   EXPECT_EQ(0U, overlay_list.size());
@@ -2376,12 +2376,12 @@
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &overlay_list,
+      render_pass_filters, render_pass_backdrop_filters, &overlay_list,
       &ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(gfx::Rect(), damage_rect);
   EXPECT_EQ(0U, overlay_list.size());
@@ -2403,12 +2403,12 @@
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &overlay_list,
+      render_pass_filters, render_pass_backdrop_filters, &overlay_list,
       &ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
   EXPECT_EQ(gfx::Rect(), damage_rect);
   EXPECT_EQ(0U, overlay_list.size());
@@ -2433,14 +2433,14 @@
   DCLayerOverlayList dc_layer_list;
   OverlayCandidateList overlay_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   damage_rect_ = gfx::Rect(1, 1, 10, 10);
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &overlay_list,
-      nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+      render_pass_filters, render_pass_backdrop_filters, &overlay_list, nullptr,
+      &dc_layer_list, &damage_rect_, &content_bounds_);
   EXPECT_EQ(gfx::Rect(), damage_rect);
   EXPECT_EQ(0U, overlay_list.size());
   EXPECT_EQ(1U, dc_layer_list.size());
@@ -2465,14 +2465,14 @@
   DCLayerOverlayList dc_layer_list;
   OverlayCandidateList overlay_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   damage_rect_ = gfx::Rect(1, 1, 10, 10);
   RenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &overlay_list,
-      nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+      render_pass_filters, render_pass_backdrop_filters, &overlay_list, nullptr,
+      &dc_layer_list, &damage_rect_, &content_bounds_);
   EXPECT_EQ(gfx::Rect(), damage_rect);
   EXPECT_EQ(0U, overlay_list.size());
   ASSERT_EQ(1U, dc_layer_list.size());
@@ -2503,13 +2503,13 @@
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &overlay_list,
+        render_pass_filters, render_pass_backdrop_filters, &overlay_list,
         nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
     EXPECT_EQ(0U, overlay_list.size());
     EXPECT_EQ(2U, dc_layer_list.size());
@@ -2537,13 +2537,13 @@
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &overlay_list,
+        render_pass_filters, render_pass_backdrop_filters, &overlay_list,
         nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
     EXPECT_EQ(0U, overlay_list.size());
     EXPECT_EQ(2U, dc_layer_list.size());
@@ -2567,13 +2567,13 @@
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &overlay_list,
+        render_pass_filters, render_pass_backdrop_filters, &overlay_list,
         nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
     EXPECT_EQ(gfx::Rect(), damage_rect);
     EXPECT_EQ(0U, overlay_list.size());
@@ -2662,15 +2662,15 @@
   DCLayerOverlayList dc_layer_list;
   OverlayCandidateList overlay_list;
   OverlayProcessor::FilterOperationsMap render_pass_filters;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
   RenderPassList pass_list;
   pass_list.push_back(std::move(child_pass1));
   pass_list.push_back(std::move(child_pass2));
   pass_list.push_back(std::move(root_pass));
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_background_filters, &overlay_list,
-      nullptr, &dc_layer_list, &root_damage_rect, &content_bounds_);
+      render_pass_filters, render_pass_backdrop_filters, &overlay_list, nullptr,
+      &dc_layer_list, &root_damage_rect, &content_bounds_);
   EXPECT_EQ(0U, overlay_list.size());
   EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
 
@@ -2756,13 +2756,13 @@
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &overlay_list,
+        render_pass_filters, render_pass_backdrop_filters, &overlay_list,
         nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
     EXPECT_EQ(0U, overlay_list.size());
     EXPECT_EQ(1U, dc_layer_list.size());
@@ -2793,13 +2793,13 @@
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
     OverlayProcessor::FilterOperationsMap render_pass_filters;
-    OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+    OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     RenderPassList pass_list;
     pass_list.push_back(std::move(pass));
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-        render_pass_filters, render_pass_background_filters, &overlay_list,
+        render_pass_filters, render_pass_backdrop_filters, &overlay_list,
         nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
     EXPECT_EQ(0U, overlay_list.size());
     EXPECT_EQ(1U, dc_layer_list.size());
@@ -3406,7 +3406,7 @@
     overlay_list_ = BackbufferOverlayList(pass_);
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), &pass_list_, GetIdentityColorMatrix(),
-        render_pass_filters_, render_pass_background_filters_, &overlay_list_,
+        render_pass_filters_, render_pass_backdrop_filters_, &overlay_list_,
         &ca_layer_list_, nullptr, &damage_rect_, &content_bounds_);
   }
   RenderPassList pass_list_;
@@ -3414,9 +3414,9 @@
   RenderPassDrawQuad* quad_;
   int render_pass_id_;
   cc::FilterOperations filters_;
-  cc::FilterOperations background_filters_;
+  cc::FilterOperations backdrop_filters_;
   OverlayProcessor::FilterOperationsMap render_pass_filters_;
-  OverlayProcessor::FilterOperationsMap render_pass_background_filters_;
+  OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters_;
   CALayerOverlayList ca_layer_list_;
   OverlayCandidateList overlay_list_;
 };
@@ -3483,8 +3483,8 @@
 }
 
 TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadBackgroundFilter) {
-  background_filters_.Append(cc::FilterOperation::CreateGrayscaleFilter(0.1f));
-  render_pass_background_filters_[render_pass_id_] = &background_filters_;
+  backdrop_filters_.Append(cc::FilterOperation::CreateGrayscaleFilter(0.1f));
+  render_pass_backdrop_filters_[render_pass_id_] = &backdrop_filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
                 gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index 96c7d8a..22ff9e6e 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -2489,7 +2489,7 @@
     gfx::Transform transform_to_root;
     std::unique_ptr<RenderPass> filter_pass = CreateTestRenderPass(
         filter_pass_id, filter_pass_layer_rect_, transform_to_root);
-    filter_pass->background_filters = this->background_filters_;
+    filter_pass->backdrop_filters = this->backdrop_filters_;
 
     // A non-visible quad in the filtering render pass.
     {
@@ -2568,7 +2568,7 @@
   }
 
   RenderPassList pass_list_;
-  cc::FilterOperations background_filters_;
+  cc::FilterOperations backdrop_filters_;
   gfx::Transform filter_pass_to_target_transform_;
   gfx::Rect filter_pass_layer_rect_;
 };
@@ -2581,8 +2581,7 @@
                 BackgroundFilterRendererTypes);
 
 TYPED_TEST(RendererPixelTestWithBackgroundFilter, InvertFilter) {
-  this->background_filters_.Append(
-      cc::FilterOperation::CreateInvertFilter(1.f));
+  this->backdrop_filters_.Append(cc::FilterOperation::CreateInvertFilter(1.f));
 
   this->filter_pass_layer_rect_ = gfx::Rect(this->device_viewport_size_);
   this->filter_pass_layer_rect_.Inset(12, 14, 16, 18);
@@ -2590,7 +2589,7 @@
   this->SetUpRenderPassList();
   EXPECT_TRUE(this->RunPixelTest(
       &this->pass_list_,
-      base::FilePath(FILE_PATH_LITERAL("background_filter.png")),
+      base::FilePath(FILE_PATH_LITERAL("backdrop_filter.png")),
       cc::ExactPixelComparator(true)));
 }
 
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index b86ae9e..207fd53 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -997,10 +997,10 @@
     DCHECK(mask_filter);
   }
 
-  const cc::FilterOperations* background_filters =
+  const cc::FilterOperations* backdrop_filters =
       BackgroundFiltersForPass(quad->render_pass_id);
   // Without backdrop effect.
-  if (!ShouldApplyBackgroundFilters(quad, background_filters)) {
+  if (!ShouldApplyBackgroundFilters(quad, backdrop_filters)) {
     if (!mask_filter) {
       // Not mask, so we just draw the context_image directly.
       current_canvas_->drawImageRect(content_image, content_rect,
@@ -1025,7 +1025,7 @@
 
   // Draw render pass with backdrop effects.
   auto background_paint_filter = cc::RenderSurfaceFilters::BuildImageFilter(
-      *background_filters,
+      *backdrop_filters,
       gfx::SizeF(content_image->width(), content_image->height()));
   auto background_image_filter =
       background_paint_filter ? background_paint_filter->cached_sk_filter_
@@ -1194,10 +1194,10 @@
 
 bool SkiaRenderer::ShouldApplyBackgroundFilters(
     const RenderPassDrawQuad* quad,
-    const cc::FilterOperations* background_filters) const {
-  if (!background_filters)
+    const cc::FilterOperations* backdrop_filters) const {
+  if (!backdrop_filters)
     return false;
-  DCHECK(!background_filters->IsEmpty());
+  DCHECK(!backdrop_filters->IsEmpty());
 
   // TODO(hendrikw): Look into allowing background filters to see pixels from
   // other render targets.  See crbug.com/314867.
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h
index cd54755..d5da31a 100644
--- a/components/viz/service/display/skia_renderer.h
+++ b/components/viz/service/display/skia_renderer.h
@@ -116,7 +116,7 @@
                            DrawRenderPassDrawQuadParams* params);
   bool ShouldApplyBackgroundFilters(
       const RenderPassDrawQuad* quad,
-      const cc::FilterOperations* background_filters) const;
+      const cc::FilterOperations* backdrop_filters) const;
   bool IsUsingVulkan() const;
   const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;
 
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc
index 5c41958..1b2c335 100644
--- a/components/viz/service/display/software_renderer.cc
+++ b/components/viz/service/display/software_renderer.cc
@@ -639,10 +639,10 @@
 
 bool SoftwareRenderer::ShouldApplyBackgroundFilters(
     const RenderPassDrawQuad* quad,
-    const cc::FilterOperations* background_filters) const {
-  if (!background_filters)
+    const cc::FilterOperations* backdrop_filters) const {
+  if (!backdrop_filters)
     return false;
-  DCHECK(!background_filters->IsEmpty());
+  DCHECK(!backdrop_filters->IsEmpty());
 
   // TODO(hendrikw): Look into allowing background filters to see pixels from
   // other render targets.  See crbug.com/314867.
@@ -707,15 +707,15 @@
 gfx::Rect SoftwareRenderer::GetBackdropBoundingBoxForRenderPassQuad(
     const RenderPassDrawQuad* quad,
     const gfx::Transform& contents_device_transform,
-    const cc::FilterOperations* background_filters,
+    const cc::FilterOperations* backdrop_filters,
     gfx::Rect* unclipped_rect) const {
-  DCHECK(ShouldApplyBackgroundFilters(quad, background_filters));
+  DCHECK(ShouldApplyBackgroundFilters(quad, backdrop_filters));
   gfx::Rect backdrop_rect = gfx::ToEnclosingRect(cc::MathUtil::MapClippedRect(
       contents_device_transform, QuadVertexRect()));
 
   SkMatrix matrix;
   matrix.setScale(quad->filters_scale.x(), quad->filters_scale.y());
-  backdrop_rect = background_filters->MapRectReverse(backdrop_rect, matrix);
+  backdrop_rect = backdrop_filters->MapRectReverse(backdrop_rect, matrix);
 
   *unclipped_rect = backdrop_rect;
   backdrop_rect.Intersect(MoveFromDrawToWindowSpace(
@@ -727,9 +727,9 @@
 sk_sp<SkShader> SoftwareRenderer::GetBackgroundFilterShader(
     const RenderPassDrawQuad* quad,
     SkShader::TileMode content_tile_mode) const {
-  const cc::FilterOperations* background_filters =
+  const cc::FilterOperations* backdrop_filters =
       BackgroundFiltersForPass(quad->render_pass_id);
-  if (!ShouldApplyBackgroundFilters(quad, background_filters))
+  if (!ShouldApplyBackgroundFilters(quad, backdrop_filters))
     return nullptr;
 
   gfx::Transform quad_rect_matrix;
@@ -743,7 +743,7 @@
 
   gfx::Rect unclipped_rect;
   gfx::Rect backdrop_rect = GetBackdropBoundingBoxForRenderPassQuad(
-      quad, contents_device_transform, background_filters, &unclipped_rect);
+      quad, contents_device_transform, backdrop_filters, &unclipped_rect);
 
   // Figure out the transformations to move it back to pixel space.
   gfx::Transform contents_device_transform_inverse;
@@ -762,7 +762,7 @@
       (backdrop_rect.bottom_left() - unclipped_rect.bottom_left());
   sk_sp<SkImageFilter> filter =
       cc::RenderSurfaceFilters::BuildImageFilter(
-          *background_filters,
+          *backdrop_filters,
           gfx::SizeF(backdrop_bitmap.width(), backdrop_bitmap.height()),
           clipping_offset)
           ->cached_sk_filter_;
diff --git a/components/viz/service/display/software_renderer.h b/components/viz/service/display/software_renderer.h
index 0b901e7..6f30f1b 100644
--- a/components/viz/service/display/software_renderer.h
+++ b/components/viz/service/display/software_renderer.h
@@ -80,7 +80,7 @@
   void DrawUnsupportedQuad(const DrawQuad* quad);
   bool ShouldApplyBackgroundFilters(
       const RenderPassDrawQuad* quad,
-      const cc::FilterOperations* background_filters) const;
+      const cc::FilterOperations* backdrop_filters) const;
   sk_sp<SkImage> ApplyImageFilter(SkImageFilter* filter,
                                   const RenderPassDrawQuad* quad,
                                   const SkBitmap& to_filter,
@@ -88,7 +88,7 @@
   gfx::Rect GetBackdropBoundingBoxForRenderPassQuad(
       const RenderPassDrawQuad* quad,
       const gfx::Transform& contents_device_transform,
-      const cc::FilterOperations* background_filters,
+      const cc::FilterOperations* backdrop_filters,
       gfx::Rect* unclipped_rect) const;
   SkBitmap GetBackdropBitmap(const gfx::Rect& bounding_rect) const;
   sk_sp<SkShader> GetBackgroundFilterShader(
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 6fde371..4b770ef 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -328,7 +328,7 @@
     copy_pass->SetAll(
         remapped_pass_id, source.output_rect, source.output_rect,
         source.transform_to_root_target, source.filters,
-        source.background_filters, blending_color_space_,
+        source.backdrop_filters, blending_color_space_,
         source.has_transparent_background, source.cache_render_pass,
         source.has_damage_from_contributing_content, source.generate_mipmap);
 
@@ -730,7 +730,7 @@
     copy_pass->SetAll(
         remapped_pass_id, source.output_rect, source.output_rect,
         source.transform_to_root_target, source.filters,
-        source.background_filters, blending_color_space_,
+        source.backdrop_filters, blending_color_space_,
         source.has_transparent_background, source.cache_render_pass,
         source.has_damage_from_contributing_content, source.generate_mipmap);
 
@@ -838,16 +838,16 @@
   };
   std::vector<SurfaceInfo> child_surfaces;
 
-  gfx::Rect pixel_moving_background_filters_rect;
+  gfx::Rect pixel_moving_backdrop_filters_rect;
   // This data is created once and typically small or empty. Collect all items
   // and pass to a flat_vector to sort once.
   std::vector<RenderPassId> pixel_moving_background_filter_passes_data;
   for (const auto& render_pass : frame.render_pass_list) {
-    if (render_pass->background_filters.HasFilterThatMovesPixels()) {
+    if (render_pass->backdrop_filters.HasFilterThatMovesPixels()) {
       pixel_moving_background_filter_passes_data.push_back(
           RemapPassId(render_pass->id, surface->surface_id()));
 
-      pixel_moving_background_filters_rect.Union(
+      pixel_moving_backdrop_filters_rect.Union(
           cc::MathUtil::MapEnclosingClippedRect(
               render_pass->transform_to_root_target, render_pass->output_rect));
     }
@@ -1020,8 +1020,8 @@
   if (!damage_rect.IsEmpty() && frame.metadata.may_contain_video)
     result->may_contain_video = true;
 
-  if (damage_rect.Intersects(pixel_moving_background_filters_rect))
-    damage_rect.Union(pixel_moving_background_filters_rect);
+  if (damage_rect.Intersects(pixel_moving_backdrop_filters_rect))
+    damage_rect.Union(pixel_moving_backdrop_filters_rect);
 
   return damage_rect;
 }
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index 9e612f5c..5b53cff 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -3022,7 +3022,7 @@
     auto* root_pass = root_pass_list[1].get();
     root_pass->shared_quad_state_list.ElementAt(1)
         ->quad_to_target_transform.Translate(10, 10);
-    pass->background_filters.Append(
+    pass->backdrop_filters.Append(
         cc::FilterOperation::CreateOpacityFilter(0.5f));
     root_pass->damage_rect = gfx::Rect(10, 10, 2, 2);
     SubmitPassListAsFrame(support_.get(), root_local_surface_id_,
@@ -3074,7 +3074,7 @@
     auto* root_pass = root_pass_list[1].get();
     root_pass->shared_quad_state_list.ElementAt(1)
         ->quad_to_target_transform.Translate(5, 5);
-    pass_with_filter->background_filters.Append(
+    pass_with_filter->backdrop_filters.Append(
         cc::FilterOperation::CreateBlurFilter(2));
     // Damage rect intersects with render passes of |pass_with_filter| and
     // |root_pass|.
@@ -3130,7 +3130,7 @@
     auto* root_pass = root_pass_list[1].get();
     root_pass->shared_quad_state_list.ElementAt(1)
         ->quad_to_target_transform.Translate(5, 5);
-    pass_with_filter->background_filters.Append(
+    pass_with_filter->backdrop_filters.Append(
         cc::FilterOperation::CreateBlurFilter(2));
     // Damage rect does not intersect with render pass.
     root_pass->damage_rect = gfx::Rect(6, 6, 3, 3);
diff --git a/components/viz/test/data/background_filter.png b/components/viz/test/data/backdrop_filter.png
similarity index 100%
rename from components/viz/test/data/background_filter.png
rename to components/viz/test/data/backdrop_filter.png
Binary files differ
diff --git a/components/viz/test/data/background_filter_blur.png b/components/viz/test/data/backdrop_filter_blur.png
similarity index 100%
rename from components/viz/test/data/background_filter_blur.png
rename to components/viz/test/data/backdrop_filter_blur.png
Binary files differ
diff --git a/components/viz/test/data/background_filter_blur_off_axis.png b/components/viz/test/data/backdrop_filter_blur_off_axis.png
similarity index 100%
rename from components/viz/test/data/background_filter_blur_off_axis.png
rename to components/viz/test/data/backdrop_filter_blur_off_axis.png
Binary files differ
diff --git a/components/viz/test/data/background_filter_blur_outsets.png b/components/viz/test/data/backdrop_filter_blur_outsets.png
similarity index 100%
rename from components/viz/test/data/background_filter_blur_outsets.png
rename to components/viz/test/data/backdrop_filter_blur_outsets.png
Binary files differ
diff --git a/components/viz/test/data/background_filter_on_scaled_layer_gl.png b/components/viz/test/data/backdrop_filter_on_scaled_layer_gl.png
similarity index 100%
rename from components/viz/test/data/background_filter_on_scaled_layer_gl.png
rename to components/viz/test/data/backdrop_filter_on_scaled_layer_gl.png
Binary files differ
diff --git a/components/viz/test/data/background_filter_on_scaled_layer_sw.png b/components/viz/test/data/backdrop_filter_on_scaled_layer_sw.png
similarity index 100%
rename from components/viz/test/data/background_filter_on_scaled_layer_sw.png
rename to components/viz/test/data/backdrop_filter_on_scaled_layer_sw.png
Binary files differ
diff --git a/components/viz/test/data/background_filter_rotated_gl.png b/components/viz/test/data/backdrop_filter_rotated_gl.png
similarity index 100%
rename from components/viz/test/data/background_filter_rotated_gl.png
rename to components/viz/test/data/backdrop_filter_rotated_gl.png
Binary files differ
diff --git a/components/viz/test/data/background_filter_rotated_sw.png b/components/viz/test/data/backdrop_filter_rotated_sw.png
similarity index 100%
rename from components/viz/test/data/background_filter_rotated_sw.png
rename to components/viz/test/data/backdrop_filter_rotated_sw.png
Binary files differ
diff --git a/components/viz/test/data/mask_of_background_filter.png b/components/viz/test/data/mask_of_backdrop_filter.png
similarity index 100%
rename from components/viz/test/data/mask_of_background_filter.png
rename to components/viz/test/data/mask_of_backdrop_filter.png
Binary files differ
diff --git a/components/viz/test/data/mask_of_background_filter_and_blend.png b/components/viz/test/data/mask_of_backdrop_filter_and_blend.png
similarity index 100%
rename from components/viz/test/data/mask_of_background_filter_and_blend.png
rename to components/viz/test/data/mask_of_backdrop_filter_and_blend.png
Binary files differ
diff --git a/components/viz/test/data/mask_of_background_filter_gpu.png b/components/viz/test/data/mask_of_backdrop_filter_gpu.png
similarity index 100%
rename from components/viz/test/data/mask_of_background_filter_gpu.png
rename to components/viz/test/data/mask_of_backdrop_filter_gpu.png
Binary files differ
diff --git a/components/viz/test/data/offset_background_filter_1x.png b/components/viz/test/data/offset_backdrop_filter_1x.png
similarity index 100%
rename from components/viz/test/data/offset_background_filter_1x.png
rename to components/viz/test/data/offset_backdrop_filter_1x.png
Binary files differ
diff --git a/components/viz/test/data/offset_background_filter_2x.png b/components/viz/test/data/offset_backdrop_filter_2x.png
similarity index 100%
rename from components/viz/test/data/offset_background_filter_2x.png
rename to components/viz/test/data/offset_backdrop_filter_2x.png
Binary files differ
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 44d5ba9..38da8bd 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -623,6 +623,8 @@
     "devtools/devtools_frame_trace_recorder.h",
     "devtools/devtools_http_handler.cc",
     "devtools/devtools_http_handler.h",
+    "devtools/devtools_instrumentation.cc",
+    "devtools/devtools_instrumentation.h",
     "devtools/devtools_interceptor_controller.cc",
     "devtools/devtools_interceptor_controller.h",
     "devtools/devtools_io_context.cc",
diff --git a/content/browser/devtools/browser_devtools_agent_host.cc b/content/browser/devtools/browser_devtools_agent_host.cc
index bf38edb..210ef3a 100644
--- a/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/content/browser/devtools/browser_devtools_agent_host.cc
@@ -8,6 +8,7 @@
 #include "base/guid.h"
 #include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
+#include "base/no_destructor.h"
 #include "base/single_thread_task_runner.h"
 #include "content/browser/devtools/devtools_session.h"
 #include "content/browser/devtools/protocol/browser_handler.h"
@@ -36,6 +37,19 @@
   return new BrowserDevToolsAgentHost(nullptr, std::move(null_callback), true);
 }
 
+namespace {
+std::set<BrowserDevToolsAgentHost*>& BrowserDevToolsAgentHostInstances() {
+  static base::NoDestructor<std::set<BrowserDevToolsAgentHost*>> instances;
+  return *instances;
+}
+}  // namespace
+
+// static
+const std::set<BrowserDevToolsAgentHost*>&
+BrowserDevToolsAgentHost::Instances() {
+  return BrowserDevToolsAgentHostInstances();
+}
+
 BrowserDevToolsAgentHost::BrowserDevToolsAgentHost(
     scoped_refptr<base::SingleThreadTaskRunner> tethering_task_runner,
     const CreateServerSocketCallback& socket_callback,
@@ -45,9 +59,11 @@
       socket_callback_(socket_callback),
       only_discovery_(only_discovery) {
   NotifyCreated();
+  BrowserDevToolsAgentHostInstances().insert(this);
 }
 
 BrowserDevToolsAgentHost::~BrowserDevToolsAgentHost() {
+  BrowserDevToolsAgentHostInstances().erase(this);
 }
 
 bool BrowserDevToolsAgentHost::AttachSession(DevToolsSession* session,
diff --git a/content/browser/devtools/browser_devtools_agent_host.h b/content/browser/devtools/browser_devtools_agent_host.h
index 0bdd0bc..655d08821 100644
--- a/content/browser/devtools/browser_devtools_agent_host.h
+++ b/content/browser/devtools/browser_devtools_agent_host.h
@@ -13,6 +13,10 @@
 class TargetRegistry;
 
 class BrowserDevToolsAgentHost : public DevToolsAgentHostImpl {
+ public:
+  // TODO(caseq,dgozman): this should probably be a singleton.
+  static const std::set<BrowserDevToolsAgentHost*>& Instances();
+
  private:
   friend class DevToolsAgentHost;
   BrowserDevToolsAgentHost(
diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc
index e549424..2c78d0f 100644
--- a/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/content/browser/devtools/devtools_agent_host_impl.cc
@@ -36,34 +36,6 @@
 
 base::LazyInstance<base::ObserverList<DevToolsAgentHostObserver>::Unchecked>::
     Leaky g_devtools_observers = LAZY_INSTANCE_INITIALIZER;
-
-// Returns a list of all active hosts on browser targets.
-DevToolsAgentHost::List GetBrowserAgentHosts() {
-  DevToolsAgentHost::List result;
-  for (const auto& id_host : g_devtools_instances.Get()) {
-    if (id_host.second->GetType() == DevToolsAgentHost::kTypeBrowser)
-      result.push_back(id_host.second);
-  }
-  return result;
-}
-
-// Notify the provided agent host of a certificate error. Returns true if one of
-// the host's handlers will handle the certificate error.
-bool NotifyCertificateError(
-    DevToolsAgentHost* host,
-    int cert_error,
-    const GURL& request_url,
-    const DevToolsAgentHostImpl::CertErrorCallback& callback) {
-  DevToolsAgentHostImpl* host_impl = static_cast<DevToolsAgentHostImpl*>(host);
-  for (auto* security_handler :
-       protocol::SecurityHandler::ForAgentHost(host_impl)) {
-    if (security_handler->NotifyCertificateError(cert_error, request_url,
-                                                 callback)) {
-      return true;
-    }
-  }
-  return false;
-}
 }  // namespace
 
 const char DevToolsAgentHost::kTypePage[] = "page";
@@ -145,31 +117,6 @@
   return new ForwardingAgentHost(id, std::move(delegate));
 }
 
-// static
-bool DevToolsAgentHostImpl::HandleCertificateError(WebContents* web_contents,
-                                                   int cert_error,
-                                                   const GURL& request_url,
-                                                   CertErrorCallback callback) {
-  scoped_refptr<DevToolsAgentHost> agent_host =
-      DevToolsAgentHost::GetOrCreateFor(web_contents).get();
-  if (NotifyCertificateError(agent_host.get(), cert_error, request_url,
-                             callback)) {
-    // Only allow a single agent host to handle the error.
-    callback.Reset();
-  }
-
-  for (scoped_refptr<DevToolsAgentHost> browser_agent_host :
-       GetBrowserAgentHosts()) {
-    if (NotifyCertificateError(browser_agent_host.get(), cert_error,
-                               request_url, callback)) {
-      // Only allow a single agent host to handle the error.
-      callback.Reset();
-    }
-  }
-
-  return !callback;
-}
-
 DevToolsSession* DevToolsAgentHostImpl::SessionByClient(
     DevToolsAgentHostClient* client) {
   auto it = session_by_client_.find(client);
diff --git a/content/browser/devtools/devtools_agent_host_impl.h b/content/browser/devtools/devtools_agent_host_impl.h
index a2a4578..46823e3a 100644
--- a/content/browser/devtools/devtools_agent_host_impl.h
+++ b/content/browser/devtools/devtools_agent_host_impl.h
@@ -29,15 +29,6 @@
 // Describes interface for managing devtools agents from the browser process.
 class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
  public:
-  // Asks any interested agents to handle the given certificate error. Returns
-  // |true| if the error was handled, |false| otherwise.
-  using CertErrorCallback =
-      base::RepeatingCallback<void(content::CertificateRequestResultType)>;
-  static bool HandleCertificateError(WebContents* web_contents,
-                                     int cert_error,
-                                     const GURL& request_url,
-                                     CertErrorCallback callback);
-
   // DevToolsAgentHost implementation.
   bool AttachClient(DevToolsAgentHostClient* client) override;
   bool DetachClient(DevToolsAgentHostClient* client) override;
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc
new file mode 100644
index 0000000..4bdaf38
--- /dev/null
+++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -0,0 +1,264 @@
+// 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 "content/browser/devtools/devtools_instrumentation.h"
+
+#include "content/browser/devtools/browser_devtools_agent_host.h"
+#include "content/browser/devtools/protocol/emulation_handler.h"
+#include "content/browser/devtools/protocol/network_handler.h"
+#include "content/browser/devtools/protocol/page_handler.h"
+#include "content/browser/devtools/protocol/security_handler.h"
+#include "content/browser/devtools/protocol/target_handler.h"
+#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/frame_host/navigation_request.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
+#include "content/common/navigation_params.mojom.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_request_headers.h"
+#include "net/ssl/ssl_info.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace content {
+namespace devtools_instrumentation {
+
+namespace {
+
+template <typename Handler, typename... MethodArgs, typename... Args>
+void DispatchToAgents(FrameTreeNode* frame_tree_node,
+                      void (Handler::*method)(MethodArgs...),
+                      Args&&... args) {
+  DevToolsAgentHostImpl* agent_host =
+      RenderFrameDevToolsAgentHost::GetFor(frame_tree_node);
+  if (!agent_host)
+    return;
+  for (auto* h : Handler::ForAgentHost(agent_host))
+    (h->*method)(std::forward<Args>(args)...);
+}
+
+template <typename Handler, typename... MethodArgs, typename... Args>
+void DispatchToAgents(int frame_tree_node_id,
+                      void (Handler::*method)(MethodArgs...),
+                      Args&&... args) {
+  FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+  if (ftn)
+    DispatchToAgents(ftn, method, std::forward<Args>(args)...);
+}
+
+}  // namespace
+
+void OnResetNavigationRequest(NavigationRequest* navigation_request) {
+  // Traverse frame chain all the way to the top and report to all
+  // page handlers that the navigation completed.
+  for (FrameTreeNode* node = navigation_request->frame_tree_node(); node;
+       node = node->parent()) {
+    DispatchToAgents(node, &protocol::PageHandler::NavigationReset,
+                     navigation_request);
+  }
+}
+
+void OnNavigationResponseReceived(const NavigationRequest& nav_request,
+                                  const network::ResourceResponse& response) {
+  FrameTreeNode* ftn = nav_request.frame_tree_node();
+  std::string id = nav_request.devtools_navigation_token().ToString();
+  std::string frame_id = ftn->devtools_frame_token().ToString();
+  GURL url = nav_request.common_params().url;
+  DispatchToAgents(ftn, &protocol::NetworkHandler::ResponseReceived, id, id,
+                   url, protocol::Network::ResourceTypeEnum::Document,
+                   response.head, frame_id);
+}
+
+void OnNavigationRequestFailed(
+    const NavigationRequest& nav_request,
+    const network::URLLoaderCompletionStatus& status) {
+  FrameTreeNode* ftn = nav_request.frame_tree_node();
+  std::string id = nav_request.devtools_navigation_token().ToString();
+  DispatchToAgents(ftn, &protocol::NetworkHandler::LoadingComplete, id,
+                   protocol::Network::ResourceTypeEnum::Document, status);
+}
+
+void OnSignedExchangeReceived(
+    FrameTreeNode* frame_tree_node,
+    base::Optional<const base::UnguessableToken> devtools_navigation_token,
+    const GURL& outer_request_url,
+    const network::ResourceResponseHead& outer_response,
+    const base::Optional<SignedExchangeEnvelope>& envelope,
+    const scoped_refptr<net::X509Certificate>& certificate,
+    const base::Optional<net::SSLInfo>& ssl_info,
+    const std::vector<SignedExchangeError>& errors) {
+  DispatchToAgents(frame_tree_node,
+                   &protocol::NetworkHandler::OnSignedExchangeReceived,
+                   devtools_navigation_token, outer_request_url, outer_response,
+                   envelope, certificate, ssl_info, errors);
+}
+
+void OnSignedExchangeCertificateRequestSent(
+    FrameTreeNode* frame_tree_node,
+    const base::UnguessableToken& request_id,
+    const base::UnguessableToken& loader_id,
+    const network::ResourceRequest& request,
+    const GURL& signed_exchange_url) {
+  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::RequestSent,
+                   request_id.ToString(), loader_id.ToString(), request,
+                   protocol::Network::Initiator::TypeEnum::SignedExchange,
+                   signed_exchange_url);
+}
+
+void OnSignedExchangeCertificateResponseReceived(
+    FrameTreeNode* frame_tree_node,
+    const base::UnguessableToken& request_id,
+    const base::UnguessableToken& loader_id,
+    const GURL& url,
+    const network::ResourceResponseHead& head) {
+  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::ResponseReceived,
+                   request_id.ToString(), loader_id.ToString(), url,
+                   protocol::Network::ResourceTypeEnum::Other, head,
+                   protocol::Maybe<std::string>());
+}
+
+void OnSignedExchangeCertificateRequestCompleted(
+    FrameTreeNode* frame_tree_node,
+    const base::UnguessableToken& request_id,
+    const network::URLLoaderCompletionStatus& status) {
+  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::LoadingComplete,
+                   request_id.ToString(),
+                   protocol::Network::ResourceTypeEnum::Other, status);
+}
+
+std::vector<std::unique_ptr<NavigationThrottle>> CreateNavigationThrottles(
+    NavigationHandleImpl* navigation_handle) {
+  std::vector<std::unique_ptr<NavigationThrottle>> result;
+  FrameTreeNode* frame_tree_node = navigation_handle->frame_tree_node();
+
+  DevToolsAgentHostImpl* agent_host =
+      RenderFrameDevToolsAgentHost::GetFor(frame_tree_node);
+  if (agent_host) {
+    // Interception might throttle navigations in inspected frames.
+    for (auto* network_handler :
+         protocol::NetworkHandler::ForAgentHost(agent_host)) {
+      std::unique_ptr<NavigationThrottle> throttle =
+          network_handler->CreateThrottleForNavigation(navigation_handle);
+      if (throttle)
+        result.push_back(std::move(throttle));
+    }
+  }
+  if (!frame_tree_node->parent())
+    return result;
+  agent_host = RenderFrameDevToolsAgentHost::GetFor(frame_tree_node->parent());
+  if (agent_host) {
+    for (auto* target_handler :
+         protocol::TargetHandler::ForAgentHost(agent_host)) {
+      std::unique_ptr<NavigationThrottle> throttle =
+          target_handler->CreateThrottleForNavigation(navigation_handle);
+      if (throttle)
+        result.push_back(std::move(throttle));
+    }
+  }
+
+  return result;
+}
+
+void ApplyNetworkRequestOverrides(FrameTreeNode* frame_tree_node,
+                                  mojom::BeginNavigationParams* begin_params,
+                                  bool* report_raw_headers) {
+  bool disable_cache = false;
+  DevToolsAgentHostImpl* agent_host =
+      RenderFrameDevToolsAgentHost::GetFor(frame_tree_node);
+  if (!agent_host)
+    return;
+  net::HttpRequestHeaders headers;
+  headers.AddHeadersFromString(begin_params->headers);
+  for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) {
+    if (!network->enabled())
+      continue;
+    *report_raw_headers = true;
+    network->ApplyOverrides(&headers, &begin_params->skip_service_worker,
+                            &disable_cache);
+  }
+
+  for (auto* emulation : protocol::EmulationHandler::ForAgentHost(agent_host))
+    emulation->ApplyOverrides(&headers);
+
+  if (disable_cache) {
+    begin_params->load_flags &=
+        ~(net::LOAD_VALIDATE_CACHE | net::LOAD_SKIP_CACHE_VALIDATION |
+          net::LOAD_ONLY_FROM_CACHE | net::LOAD_DISABLE_CACHE);
+    begin_params->load_flags |= net::LOAD_BYPASS_CACHE;
+  }
+
+  begin_params->headers = headers.ToString();
+}
+
+bool WillCreateURLLoaderFactory(
+    RenderFrameHostImpl* rfh,
+    bool is_navigation,
+    bool is_download,
+    network::mojom::URLLoaderFactoryRequest* target_factory_request) {
+  DevToolsAgentHostImpl* agent_host =
+      RenderFrameDevToolsAgentHost::GetFor(rfh->frame_tree_node());
+  if (!agent_host)
+    return false;
+  DCHECK(!is_download || is_navigation);
+  bool had_interceptors = false;
+  const auto& network_handlers =
+      protocol::NetworkHandler::ForAgentHost(agent_host);
+  for (auto it = network_handlers.rbegin(); it != network_handlers.rend();
+       ++it) {
+    had_interceptors =
+        (*it)->MaybeCreateProxyForInterception(rfh, is_navigation, is_download,
+                                               target_factory_request) ||
+        had_interceptors;
+  }
+  return had_interceptors;
+}
+
+void OnNavigationRequestWillBeSent(
+    const NavigationRequest& navigation_request) {
+  DispatchToAgents(navigation_request.frame_tree_node(),
+                   &protocol::NetworkHandler::NavigationRequestWillBeSent,
+                   navigation_request);
+}
+
+// Notify the provided agent host of a certificate error. Returns true if one of
+// the host's handlers will handle the certificate error.
+bool NotifyCertificateError(DevToolsAgentHost* host,
+                            int cert_error,
+                            const GURL& request_url,
+                            const CertErrorCallback& callback) {
+  DevToolsAgentHostImpl* host_impl = static_cast<DevToolsAgentHostImpl*>(host);
+  for (auto* security_handler :
+       protocol::SecurityHandler::ForAgentHost(host_impl)) {
+    if (security_handler->NotifyCertificateError(cert_error, request_url,
+                                                 callback)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool HandleCertificateError(WebContents* web_contents,
+                            int cert_error,
+                            const GURL& request_url,
+                            CertErrorCallback callback) {
+  scoped_refptr<DevToolsAgentHost> agent_host =
+      DevToolsAgentHost::GetOrCreateFor(web_contents).get();
+  if (NotifyCertificateError(agent_host.get(), cert_error, request_url,
+                             callback)) {
+    // Only allow a single agent host to handle the error.
+    callback.Reset();
+  }
+
+  for (auto* browser_agent_host : BrowserDevToolsAgentHost::Instances()) {
+    if (NotifyCertificateError(browser_agent_host, cert_error, request_url,
+                               callback)) {
+      // Only allow a single agent host to handle the error.
+      callback.Reset();
+    }
+  }
+  return !callback;
+}
+
+}  // namespace devtools_instrumentation
+
+}  // namespace content
\ No newline at end of file
diff --git a/content/browser/devtools/devtools_instrumentation.h b/content/browser/devtools/devtools_instrumentation.h
new file mode 100644
index 0000000..9730992
--- /dev/null
+++ b/content/browser/devtools/devtools_instrumentation.h
@@ -0,0 +1,107 @@
+// 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_INSTRUMENTATION_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_INSTRUMENTATION_H_
+
+/*
+  The functions in this file are for routing instrumentation signals
+  to the relevant set of devtools protocol handlers.
+*/
+
+#include <vector>
+
+#include "base/optional.h"
+#include "content/common/navigation_params.mojom.h"
+#include "content/public/browser/certificate_request_result_type.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+class GURL;
+
+namespace base {
+class UnguessableToken;
+}
+
+namespace net {
+class SSLInfo;
+class X509Certificate;
+}  // namespace net
+
+namespace network {
+struct ResourceResponse;
+}
+
+namespace content {
+class SignedExchangeEnvelope;
+class FrameTreeNode;
+class NavigationHandleImpl;
+class NavigationRequest;
+class NavigationThrottle;
+class RenderFrameHostImpl;
+class WebContents;
+
+struct SignedExchangeError;
+
+namespace devtools_instrumentation {
+
+void ApplyNetworkRequestOverrides(FrameTreeNode* frame_tree_node,
+                                  mojom::BeginNavigationParams* begin_params,
+                                  bool* report_raw_headers);
+
+bool WillCreateURLLoaderFactory(
+    RenderFrameHostImpl* rfh,
+    bool is_navigation,
+    bool is_download,
+    network::mojom::URLLoaderFactoryRequest* loader_factory_request);
+
+void OnResetNavigationRequest(NavigationRequest* navigation_request);
+void OnNavigationRequestWillBeSent(const NavigationRequest& navigation_request);
+void OnNavigationResponseReceived(const NavigationRequest& nav_request,
+                                  const network::ResourceResponse& response);
+void OnNavigationRequestFailed(
+    const NavigationRequest& nav_request,
+    const network::URLLoaderCompletionStatus& status);
+
+void OnSignedExchangeReceived(
+    FrameTreeNode* frame_tree_node,
+    base::Optional<const base::UnguessableToken> devtools_navigation_token,
+    const GURL& outer_request_url,
+    const network::ResourceResponseHead& outer_response,
+    const base::Optional<SignedExchangeEnvelope>& header,
+    const scoped_refptr<net::X509Certificate>& certificate,
+    const base::Optional<net::SSLInfo>& ssl_info,
+    const std::vector<SignedExchangeError>& errors);
+void OnSignedExchangeCertificateRequestSent(
+    FrameTreeNode* frame_tree_node,
+    const base::UnguessableToken& request_id,
+    const base::UnguessableToken& loader_id,
+    const network::ResourceRequest& request,
+    const GURL& signed_exchange_url);
+void OnSignedExchangeCertificateResponseReceived(
+    FrameTreeNode* frame_tree_node,
+    const base::UnguessableToken& request_id,
+    const base::UnguessableToken& loader_id,
+    const GURL& url,
+    const network::ResourceResponseHead& head);
+void OnSignedExchangeCertificateRequestCompleted(
+    FrameTreeNode* frame_tree_node,
+    const base::UnguessableToken& request_id,
+    const network::URLLoaderCompletionStatus& status);
+
+std::vector<std::unique_ptr<NavigationThrottle>> CreateNavigationThrottles(
+    NavigationHandleImpl* navigation_handle);
+
+// Asks any interested agents to handle the given certificate error. Returns
+// |true| if the error was handled, |false| otherwise.
+using CertErrorCallback =
+    base::RepeatingCallback<void(content::CertificateRequestResultType)>;
+bool HandleCertificateError(WebContents* web_contents,
+                            int cert_error,
+                            const GURL& request_url,
+                            CertErrorCallback callback);
+
+}  // namespace devtools_instrumentation
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_INSTRUMENTATION_H_
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index f22102d..96188ba2 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -54,9 +54,6 @@
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_request_headers.h"
-#include "net/ssl/ssl_info.h"
 #include "services/network/public/cpp/features.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/web/devtools_agent.mojom.h"
@@ -99,27 +96,6 @@
 
 }  // namespace
 
-template <typename Handler, typename... MethodArgs, typename... Args>
-void DispatchToAgents(FrameTreeNode* frame_tree_node,
-                      void (Handler::*method)(MethodArgs...),
-                      Args&&... args) {
-  RenderFrameDevToolsAgentHost* agent_host =
-      FindAgentHost(GetFrameTreeNodeAncestor(frame_tree_node));
-  if (!agent_host)
-    return;
-  for (auto* h : Handler::ForAgentHost(agent_host))
-    (h->*method)(std::forward<Args>(args)...);
-}
-
-template <typename Handler, typename... MethodArgs, typename... Args>
-void DispatchToAgents(int frame_tree_node_id,
-                      void (Handler::*method)(MethodArgs...),
-                      Args&&... args) {
-  FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
-  if (ftn)
-    DispatchToAgents(ftn, method, std::forward<Args>(args)...);
-}
-
 // static
 scoped_refptr<DevToolsAgentHost>
 DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) {
@@ -133,6 +109,12 @@
 }
 
 // static
+DevToolsAgentHostImpl* RenderFrameDevToolsAgentHost::GetFor(
+    FrameTreeNode* frame_tree_node) {
+  frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
+  return FindAgentHost(frame_tree_node);
+}
+
 scoped_refptr<DevToolsAgentHost> RenderFrameDevToolsAgentHost::GetOrCreateFor(
     FrameTreeNode* frame_tree_node) {
   frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
@@ -193,199 +175,6 @@
 }
 
 // static
-void RenderFrameDevToolsAgentHost::OnResetNavigationRequest(
-    NavigationRequest* navigation_request) {
-  // Traverse frame chain all the way to the top and report to all
-  // page handlers that the navigation completed.
-  for (FrameTreeNode* node = navigation_request->frame_tree_node(); node;
-       node = node->parent()) {
-    DispatchToAgents(node, &protocol::PageHandler::NavigationReset,
-                     navigation_request);
-  }
-}
-
-// static
-void RenderFrameDevToolsAgentHost::OnNavigationResponseReceived(
-    const NavigationRequest& nav_request,
-    const network::ResourceResponse& response) {
-  FrameTreeNode* ftn = nav_request.frame_tree_node();
-  std::string id = nav_request.devtools_navigation_token().ToString();
-  std::string frame_id = ftn->devtools_frame_token().ToString();
-  GURL url = nav_request.common_params().url;
-  DispatchToAgents(ftn, &protocol::NetworkHandler::ResponseReceived, id, id,
-                   url, protocol::Network::ResourceTypeEnum::Document,
-                   response.head, frame_id);
-}
-
-// static
-void RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(
-    const NavigationRequest& nav_request,
-    const network::URLLoaderCompletionStatus& status) {
-  FrameTreeNode* ftn = nav_request.frame_tree_node();
-  std::string id = nav_request.devtools_navigation_token().ToString();
-  DispatchToAgents(ftn, &protocol::NetworkHandler::LoadingComplete, id,
-                   protocol::Network::ResourceTypeEnum::Document, status);
-}
-
-// static
-void RenderFrameDevToolsAgentHost::OnSignedExchangeReceived(
-    FrameTreeNode* frame_tree_node,
-    base::Optional<const base::UnguessableToken> devtools_navigation_token,
-    const GURL& outer_request_url,
-    const network::ResourceResponseHead& outer_response,
-    const base::Optional<SignedExchangeEnvelope>& envelope,
-    const scoped_refptr<net::X509Certificate>& certificate,
-    const base::Optional<net::SSLInfo>& ssl_info,
-    const std::vector<SignedExchangeError>& errors) {
-  DispatchToAgents(frame_tree_node,
-                   &protocol::NetworkHandler::OnSignedExchangeReceived,
-                   devtools_navigation_token, outer_request_url, outer_response,
-                   envelope, certificate, ssl_info, errors);
-}
-
-// static
-void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestSent(
-    FrameTreeNode* frame_tree_node,
-    const base::UnguessableToken& request_id,
-    const base::UnguessableToken& loader_id,
-    const network::ResourceRequest& request,
-    const GURL& signed_exchange_url) {
-  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::RequestSent,
-                   request_id.ToString(), loader_id.ToString(), request,
-                   protocol::Network::Initiator::TypeEnum::SignedExchange,
-                   signed_exchange_url);
-}
-
-// static
-void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateResponseReceived(
-    FrameTreeNode* frame_tree_node,
-    const base::UnguessableToken& request_id,
-    const base::UnguessableToken& loader_id,
-    const GURL& url,
-    const network::ResourceResponseHead& head) {
-  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::ResponseReceived,
-                   request_id.ToString(), loader_id.ToString(), url,
-                   protocol::Network::ResourceTypeEnum::Other, head,
-                   protocol::Maybe<std::string>());
-}
-
-// static
-void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestCompleted(
-    FrameTreeNode* frame_tree_node,
-    const base::UnguessableToken& request_id,
-    const network::URLLoaderCompletionStatus& status) {
-  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::LoadingComplete,
-                   request_id.ToString(),
-                   protocol::Network::ResourceTypeEnum::Other, status);
-}
-
-// static
-std::vector<std::unique_ptr<NavigationThrottle>>
-RenderFrameDevToolsAgentHost::CreateNavigationThrottles(
-    NavigationHandleImpl* navigation_handle) {
-  std::vector<std::unique_ptr<NavigationThrottle>> result;
-  FrameTreeNode* frame_tree_node = navigation_handle->frame_tree_node();
-
-  // Interception might throttle navigations in inspected frames.
-  RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
-  if (agent_host) {
-    for (auto* network_handler :
-         protocol::NetworkHandler::ForAgentHost(agent_host)) {
-      std::unique_ptr<NavigationThrottle> throttle =
-          network_handler->CreateThrottleForNavigation(navigation_handle);
-      if (throttle)
-        result.push_back(std::move(throttle));
-    }
-  }
-
-  agent_host = nullptr;
-  if (frame_tree_node->parent()) {
-    // Target domain of the parent frame's DevTools may want to pause
-    // this frame to do some setup.
-    agent_host =
-        FindAgentHost(GetFrameTreeNodeAncestor(frame_tree_node->parent()));
-  }
-  if (agent_host) {
-    for (auto* target_handler :
-         protocol::TargetHandler::ForAgentHost(agent_host)) {
-      std::unique_ptr<NavigationThrottle> throttle =
-          target_handler->CreateThrottleForNavigation(navigation_handle);
-      if (throttle)
-        result.push_back(std::move(throttle));
-    }
-  }
-
-  return result;
-}
-
-// static
-void RenderFrameDevToolsAgentHost::ApplyOverrides(
-    FrameTreeNode* frame_tree_node,
-    mojom::BeginNavigationParams* begin_params,
-    bool* report_raw_headers) {
-  bool disable_cache = false;
-  frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
-  RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
-  if (!agent_host)
-    return;
-  net::HttpRequestHeaders headers;
-  headers.AddHeadersFromString(begin_params->headers);
-  for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) {
-    // TODO(caseq): consider chaining intercepting proxies from multiple agents.
-    if (!network->enabled())
-      continue;
-    *report_raw_headers = true;
-    network->ApplyOverrides(&headers, &begin_params->skip_service_worker,
-                            &disable_cache);
-  }
-
-  for (auto* emulation : protocol::EmulationHandler::ForAgentHost(agent_host))
-    emulation->ApplyOverrides(&headers);
-
-  if (disable_cache) {
-    begin_params->load_flags &=
-        ~(net::LOAD_VALIDATE_CACHE | net::LOAD_SKIP_CACHE_VALIDATION |
-          net::LOAD_ONLY_FROM_CACHE | net::LOAD_DISABLE_CACHE);
-    begin_params->load_flags |= net::LOAD_BYPASS_CACHE;
-  }
-
-  begin_params->headers = headers.ToString();
-}
-
-// static
-bool RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
-    RenderFrameHostImpl* rfh,
-    bool is_navigation,
-    bool is_download,
-    network::mojom::URLLoaderFactoryRequest* target_factory_request) {
-  FrameTreeNode* frame_tree_node = rfh->frame_tree_node();
-  frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
-  RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
-  if (!agent_host)
-    return false;
-  DCHECK(!is_download || is_navigation);
-  bool had_interceptors = false;
-  const auto& network_handlers =
-      protocol::NetworkHandler::ForAgentHost(agent_host);
-  for (auto it = network_handlers.rbegin(); it != network_handlers.rend();
-       ++it) {
-    had_interceptors =
-        (*it)->MaybeCreateProxyForInterception(rfh, is_navigation, is_download,
-                                               target_factory_request) ||
-        had_interceptors;
-  }
-  return had_interceptors;
-}
-
-// static
-void RenderFrameDevToolsAgentHost::OnNavigationRequestWillBeSent(
-    const NavigationRequest& navigation_request) {
-  DispatchToAgents(navigation_request.frame_tree_node(),
-                   &protocol::NetworkHandler::NavigationRequestWillBeSent,
-                   navigation_request);
-}
-
-// static
 void RenderFrameDevToolsAgentHost::WebContentsCreated(
     WebContents* web_contents) {
   if (ShouldForceCreation()) {
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h
index 42907088..2354c833 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -27,40 +27,28 @@
 #include "ui/android/view_android.h"
 #endif  // OS_ANDROID
 
-namespace base {
-class UnguessableToken;
-}
-
-namespace network {
-struct ResourceResponse;
-}
-
 namespace viz {
 class CompositorFrameMetadata;
 }
 
-namespace net {
-class SSLInfo;
-class X509Certificate;
-}
-
 namespace content {
 
 class BrowserContext;
 class DevToolsFrameTraceRecorder;
 class FrameTreeNode;
 class NavigationHandleImpl;
-class NavigationRequest;
-class NavigationThrottle;
 class RenderFrameHostImpl;
-class SignedExchangeEnvelope;
-struct SignedExchangeError;
 
 class CONTENT_EXPORT RenderFrameDevToolsAgentHost
     : public DevToolsAgentHostImpl,
       private WebContentsObserver {
  public:
   static void AddAllAgentHosts(DevToolsAgentHost::List* result);
+
+  // Returns appropriate agent host for given frame tree node, traversing
+  // up to local root as needed.
+  static DevToolsAgentHostImpl* GetFor(FrameTreeNode* frame_tree_node);
+  // Similar to GetFor(), but creates a host if it doesn't exist yet.
   static scoped_refptr<DevToolsAgentHost> GetOrCreateFor(
       FrameTreeNode* frame_tree_node);
 
@@ -72,60 +60,6 @@
   static scoped_refptr<DevToolsAgentHost> FindForDangling(
       FrameTreeNode* frame_tree_node);
 
-  static void OnWillSendNavigationRequest(
-      FrameTreeNode* frame_tree_node,
-      mojom::BeginNavigationParams* begin_params,
-      bool* report_raw_headers);
-
-  static void OnResetNavigationRequest(NavigationRequest* navigation_request);
-
-  static void ApplyOverrides(FrameTreeNode* frame_tree_node,
-                             mojom::BeginNavigationParams* begin_params,
-                             bool* report_raw_headers);
-  static bool WillCreateURLLoaderFactory(
-      RenderFrameHostImpl* rfh,
-      bool is_navigation,
-      bool is_download,
-      network::mojom::URLLoaderFactoryRequest* loader_factory_request);
-
-  static void OnNavigationRequestWillBeSent(
-      const NavigationRequest& navigation_request);
-  static void OnNavigationResponseReceived(
-      const NavigationRequest& nav_request,
-      const network::ResourceResponse& response);
-  static void OnNavigationRequestFailed(
-      const NavigationRequest& nav_request,
-      const network::URLLoaderCompletionStatus& status);
-
-  static void OnSignedExchangeReceived(
-      FrameTreeNode* frame_tree_node,
-      base::Optional<const base::UnguessableToken> devtools_navigation_token,
-      const GURL& outer_request_url,
-      const network::ResourceResponseHead& outer_response,
-      const base::Optional<SignedExchangeEnvelope>& header,
-      const scoped_refptr<net::X509Certificate>& certificate,
-      const base::Optional<net::SSLInfo>& ssl_info,
-      const std::vector<SignedExchangeError>& errors);
-  static void OnSignedExchangeCertificateRequestSent(
-      FrameTreeNode* frame_tree_node,
-      const base::UnguessableToken& request_id,
-      const base::UnguessableToken& loader_id,
-      const network::ResourceRequest& request,
-      const GURL& signed_exchange_url);
-  static void OnSignedExchangeCertificateResponseReceived(
-      FrameTreeNode* frame_tree_node,
-      const base::UnguessableToken& request_id,
-      const base::UnguessableToken& loader_id,
-      const GURL& url,
-      const network::ResourceResponseHead& head);
-  static void OnSignedExchangeCertificateRequestCompleted(
-      FrameTreeNode* frame_tree_node,
-      const base::UnguessableToken& request_id,
-      const network::URLLoaderCompletionStatus& status);
-
-  static std::vector<std::unique_ptr<NavigationThrottle>>
-  CreateNavigationThrottles(NavigationHandleImpl* navigation_handle);
-  static bool IsNetworkHandlerEnabled(FrameTreeNode* frame_tree_node);
   static void WebContentsCreated(WebContents* web_contents);
 
   static void SignalSynchronousSwapCompositorFrame(
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 13e7ee4..a214fd5 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -40,7 +40,7 @@
 #include "components/download/public/common/url_download_handler_factory.h"
 #include "content/browser/byte_stream.h"
 #include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/download/byte_stream_input_stream.h"
 #include "content/browser/download/download_resource_handler.h"
 #include "content/browser/download/download_utils.h"
@@ -279,7 +279,7 @@
     network::mojom::URLLoaderFactoryPtrInfo devtools_factory_ptr_info;
     network::mojom::URLLoaderFactoryRequest devtools_factory_request =
         MakeRequest(&devtools_factory_ptr_info);
-    if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
+    if (devtools_instrumentation::WillCreateURLLoaderFactory(
             static_cast<RenderFrameHostImpl*>(rfh), true, is_download,
             &devtools_factory_request)) {
       proxy_factory_ptr_info = std::move(devtools_factory_ptr_info);
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc
index 3230029..88eeb74 100644
--- a/content/browser/frame_host/frame_tree_node.cc
+++ b/content/browser/frame_host/frame_tree_node.cc
@@ -14,7 +14,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
-#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/navigation_request.h"
 #include "content/browser/frame_host/navigator.h"
@@ -354,8 +354,7 @@
 
 void FrameTreeNode::TransferNavigationRequestOwnership(
     RenderFrameHostImpl* render_frame_host) {
-  RenderFrameDevToolsAgentHost::OnResetNavigationRequest(
-      navigation_request_.get());
+  devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
   render_frame_host->SetNavigationRequest(std::move(navigation_request_));
 }
 
@@ -399,8 +398,7 @@
   if (!navigation_request_)
     return;
 
-  RenderFrameDevToolsAgentHost::OnResetNavigationRequest(
-      navigation_request_.get());
+  devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
 
   // The renderer should be informed if the caller allows to do so and the
   // navigation came from a BeginNavigation IPC.
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index 56a5851..51d0e879 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -14,7 +14,7 @@
 #include "content/browser/appcache/appcache_navigation_handle.h"
 #include "content/browser/appcache/appcache_service_impl.h"
 #include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/frame_host/ancestor_throttle.h"
 #include "content/browser/frame_host/blocked_scheme_navigation_throttle.h"
 #include "content/browser/frame_host/debug_urls.h"
@@ -1374,7 +1374,7 @@
   AddThrottle(OriginPolicyThrottle::MaybeCreateThrottleFor(this));
 
   for (auto& throttle :
-       RenderFrameDevToolsAgentHost::CreateNavigationThrottles(this)) {
+       devtools_instrumentation::CreateNavigationThrottles(this)) {
     AddThrottle(std::move(throttle));
   }
 
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 445dc876..7ae18a4 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -15,7 +15,7 @@
 #include "content/browser/appcache/appcache_navigation_handle.h"
 #include "content/browser/appcache/chrome_appcache_service.h"
 #include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/download/download_manager_impl.h"
 #include "content/browser/frame_host/debug_urls.h"
 #include "content/browser/frame_host/frame_tree.h"
@@ -509,7 +509,7 @@
 NavigationRequest::~NavigationRequest() {
   TRACE_EVENT_ASYNC_END0("navigation", "NavigationRequest", this);
   if (state_ == STARTED) {
-    RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(
+    devtools_instrumentation::OnNavigationRequestFailed(
         *this, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
   }
 }
@@ -1061,7 +1061,7 @@
     }
   }
 
-  RenderFrameDevToolsAgentHost::OnNavigationResponseReceived(*this, *response);
+  devtools_instrumentation::OnNavigationResponseReceived(*this, *response);
 
   // The response code indicates that this is an error page, but we don't
   // know how to display the content.  We follow Firefox here and show our
@@ -1127,7 +1127,7 @@
            error_page_content.has_value()));
   common_params_.previews_state = content::PREVIEWS_OFF;
 
-  RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(*this, status);
+  devtools_instrumentation::OnNavigationRequestFailed(*this, status);
 
   // TODO(https://crbug.com/757633): Check that ssl_info.has_value() if
   // net_error is a certificate error.
@@ -1370,9 +1370,9 @@
   // Give DevTools a chance to override begin params (headers, skip SW)
   // before actually loading resource.
   bool report_raw_headers = false;
-  RenderFrameDevToolsAgentHost::ApplyOverrides(
+  devtools_instrumentation::ApplyNetworkRequestOverrides(
       frame_tree_node_, begin_params_.get(), &report_raw_headers);
-  RenderFrameDevToolsAgentHost::OnNavigationRequestWillBeSent(*this);
+  devtools_instrumentation::OnNavigationRequestWillBeSent(*this);
 
   loader_ = NavigationURLLoader::Create(
       browser_context->GetResourceContext(), partition,
@@ -1429,7 +1429,7 @@
     return;
   }
 
-  RenderFrameDevToolsAgentHost::OnNavigationRequestWillBeSent(*this);
+  devtools_instrumentation::OnNavigationRequestWillBeSent(*this);
 
   base::Optional<net::HttpRequestHeaders> embedder_additional_headers;
   GetContentClient()->browser()->NavigationRequestRedirected(
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 0b9f55d..fa3e9eaa 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -36,7 +36,7 @@
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/dedicated_worker/dedicated_worker_host.h"
-#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
 #include "content/browser/download/mhtml_generation_manager.h"
 #include "content/browser/file_url_loader_factory.h"
@@ -4313,8 +4313,8 @@
           browser_context, this, false /* is_navigation */,
           GetOriginForURLLoaderFactory(common_params.url, GetSiteInstance()),
           &factory_request, nullptr /* bypass_redirect_checks */);
-      // Keep DevTools proxy lasy, i.e. closest to the network.
-      RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
+      // Keep DevTools proxy last, i.e. closest to the network.
+      devtools_instrumentation::WillCreateURLLoaderFactory(
           this, false /* is_navigation */, false /* is_download */,
           &factory_request);
       factory.second->Clone(std::move(factory_request));
@@ -5047,7 +5047,7 @@
   }
 
   // Keep DevTools proxy last, i.e. closest to the network.
-  RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
+  devtools_instrumentation::WillCreateURLLoaderFactory(
       this, false /* is_navigation */, false /* is_download */,
       &default_factory_request);
 
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 9ab9c6a..0a79585 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -22,7 +22,7 @@
 #include "content/browser/appcache/appcache_navigation_handle_core.h"
 #include "content/browser/appcache/appcache_request_handler.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/file_url_loader_factory.h"
 #include "content/browser/fileapi/file_system_url_loader_factory.h"
 #include "content/browser/frame_host/frame_tree_node.h"
@@ -1652,7 +1652,7 @@
         partition->browser_context(), frame_tree_node->current_frame_host(),
         true /* is_navigation */, navigation_request_initiator,
         &factory_request, &bypass_redirect_checks);
-    if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
+    if (devtools_instrumentation::WillCreateURLLoaderFactory(
             frame_tree_node->current_frame_host(), true, false,
             &factory_request)) {
       use_proxy = true;
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc
index 19cf17e..aacf776 100644
--- a/content/browser/media/session/media_session_impl.cc
+++ b/content/browser/media/session/media_session_impl.cc
@@ -755,6 +755,14 @@
   }
 }
 
+void MediaSessionImpl::PreviousTrack() {
+  DidReceiveAction(blink::mojom::MediaSessionAction::PREVIOUS_TRACK);
+}
+
+void MediaSessionImpl::NextTrack() {
+  DidReceiveAction(blink::mojom::MediaSessionAction::NEXT_TRACK);
+}
+
 void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
   if (audio_focus_state_ == State::INACTIVE || !normal_players_.empty() ||
       !pepper_players_.empty() || !one_shot_players_.empty()) {
diff --git a/content/browser/media/session/media_session_impl.h b/content/browser/media/session/media_session_impl.h
index 3c1e003..5df1caa7 100644
--- a/content/browser/media/session/media_session_impl.h
+++ b/content/browser/media/session/media_session_impl.h
@@ -227,6 +227,12 @@
       media_session::mojom::AudioFocusType type,
       bool result);
 
+  // Skip to the previous track.
+  CONTENT_EXPORT void PreviousTrack() override;
+
+  // Skip to the next track.
+  CONTENT_EXPORT void NextTrack() override;
+
  private:
   friend class content::WebContentsUserData<MediaSessionImpl>;
   friend class ::MediaSessionImplBrowserTest;
diff --git a/content/browser/media/session/media_session_impl_service_routing_unittest.cc b/content/browser/media/session/media_session_impl_service_routing_unittest.cc
index e546e11..3cb6d8c 100644
--- a/content/browser/media/session/media_session_impl_service_routing_unittest.cc
+++ b/content/browser/media/session/media_session_impl_service_routing_unittest.cc
@@ -413,4 +413,45 @@
       ->DidReceiveAction(blink::mojom::MediaSessionAction::PAUSE);
 }
 
+TEST_F(MediaSessionImplServiceRoutingTest,
+       TestPreviousTrackBehaviorWhenMainFrameIsRouted) {
+  base::RunLoop run_loop;
+
+  StartPlayerForFrame(main_frame_);
+  StartPlayerForFrame(sub_frame_);
+
+  CreateServiceForFrame(main_frame_);
+
+  EXPECT_CALL(
+      *GetClientForFrame(main_frame_),
+      DidReceiveAction(blink::mojom::MediaSessionAction::PREVIOUS_TRACK))
+      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+
+  services_[main_frame_]->EnableAction(
+      blink::mojom::MediaSessionAction::PREVIOUS_TRACK);
+
+  MediaSessionImpl::Get(contents())->PreviousTrack();
+  run_loop.Run();
+}
+
+TEST_F(MediaSessionImplServiceRoutingTest,
+       TestNextTrackBehaviorWhenMainFrameIsRouted) {
+  base::RunLoop run_loop;
+
+  StartPlayerForFrame(main_frame_);
+  StartPlayerForFrame(sub_frame_);
+
+  CreateServiceForFrame(main_frame_);
+
+  EXPECT_CALL(*GetClientForFrame(main_frame_),
+              DidReceiveAction(blink::mojom::MediaSessionAction::NEXT_TRACK))
+      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+
+  services_[main_frame_]->EnableAction(
+      blink::mojom::MediaSessionAction::NEXT_TRACK);
+
+  MediaSessionImpl::Get(contents())->NextTrack();
+  run_loop.Run();
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index e3d81412..581f84c 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1326,22 +1326,15 @@
         // the GFS are directly injected to RWHI rather than being generated
         // from wheel events in MouseWheelEventQueue.
         is_in_gesture_scroll_[gesture_event.SourceDevice()] = false;
-      } else {
-        // No GSE is sent before GFS, so is_in_gesture_scroll must be true.
-        // TODO(sahel): This often gets tripped on Debug builds in ChromeOS
-        // indicating some kind of gesture event ordering race.
-        // https://crbug.com/821237.
-        // DCHECK(is_in_gesture_scroll_[gesture_event.SourceDevice()]);
-
-        // The FlingController handles GFS with touchpad source and sends wheel
-        // events to progress the fling, the wheel events will get processed by
-        // the MouseWheelEventQueue and GSU events with inertial phase will be
-        // sent to the renderer. is_in_gesture_scroll must stay true till the
-        // fling progress is finished. Then the FlingController will generate
-        // and send a wheel event with phaseEnded. MouseWheelEventQueue will
-        // process the wheel event to generate and send a GSE which shows the
-        // end of a scroll sequence.
       }
+      // a GSB event is generated from the first wheel event in a sequence after
+      // the event is acked as not consumed by the renderer. Sometimes when the
+      // main thread is busy/slow (e.g ChromeOS debug builds) a GFS arrives
+      // before the first wheel is acked. In these cases no GSB will arrive
+      // before the GFS. With browser side fling the out of order GFS arrival
+      // does not need a DCHECK since the fling controller will process the GFS
+      // and start queuing wheel events which will follow the one currently
+      // awaiting ACK and the renderer receives the events in order.
 
       is_in_touchpad_gesture_fling_ = true;
     } else {
diff --git a/content/browser/ssl/ssl_manager.cc b/content/browser/ssl/ssl_manager.cc
index fe1d7902a..45f96ac 100644
--- a/content/browser/ssl/ssl_manager.cc
+++ b/content/browser/ssl/ssl_manager.cc
@@ -13,7 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/supports_user_data.h"
 #include "base/task/post_task.h"
-#include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_request_info_impl.h"
@@ -336,7 +336,7 @@
       base::Bind(&OnAllowCertificate, base::Owned(handler.release()),
                  ssl_host_state_delegate_);
 
-  if (DevToolsAgentHostImpl::HandleCertificateError(
+  if (devtools_instrumentation::HandleCertificateError(
           web_contents, cert_error, request_url,
           base::BindRepeating(&OnAllowCertificateWithRecordDecision, false,
                               callback))) {
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc b/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
index 4540e58..1601c32 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
+++ b/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/optional.h"
 #include "base/strings/string_piece.h"
 #include "base/test/scoped_task_environment.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/public/common/resource_type.h"
 #include "content/public/common/url_loader_throttle.h"
diff --git a/content/browser/web_package/signed_exchange_certificate_chain.cc b/content/browser/web_package/signed_exchange_certificate_chain.cc
index d2e3bc38..c195011 100644
--- a/content/browser/web_package/signed_exchange_certificate_chain.cc
+++ b/content/browser/web_package/signed_exchange_certificate_chain.cc
@@ -8,7 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
-#include "components/cbor/cbor_reader.h"
+#include "components/cbor/reader.h"
 #include "content/browser/web_package/signed_exchange_consts.h"
 #include "content/browser/web_package/signed_exchange_utils.h"
 #include "net/cert/x509_certificate.h"
diff --git a/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc b/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
index 94cf0ff7..2e712fe 100644
--- a/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
+++ b/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
@@ -9,8 +9,8 @@
 #include "base/optional.h"
 #include "base/path_service.h"
 #include "base/strings/string_piece.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "content/public/common/content_paths.h"
 #include "net/cert/x509_util.h"
 #include "net/test/cert_test_util.h"
diff --git a/content/browser/web_package/signed_exchange_devtools_proxy.cc b/content/browser/web_package/signed_exchange_devtools_proxy.cc
index 918b99c9..a0afafa6 100644
--- a/content/browser/web_package/signed_exchange_devtools_proxy.cc
+++ b/content/browser/web_package/signed_exchange_devtools_proxy.cc
@@ -6,7 +6,7 @@
 
 #include "base/task/post_task.h"
 #include "base/trace_event/trace_event.h"
-#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/web_package/signed_exchange_envelope.h"
 #include "content/browser/web_package/signed_exchange_error.h"
@@ -41,7 +41,7 @@
       FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
   if (!frame_tree_node)
     return;
-  RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestSent(
+  devtools_instrumentation::OnSignedExchangeCertificateRequestSent(
       frame_tree_node, request_id, loader_id, request, signed_exchange_url);
 }
 
@@ -55,7 +55,7 @@
       FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
   if (!frame_tree_node)
     return;
-  RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateResponseReceived(
+  devtools_instrumentation::OnSignedExchangeCertificateResponseReceived(
       frame_tree_node, request_id, loader_id, url, response->head);
 }
 
@@ -67,7 +67,7 @@
       FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
   if (!frame_tree_node)
     return;
-  RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestCompleted(
+  devtools_instrumentation::OnSignedExchangeCertificateRequestCompleted(
       frame_tree_node, request_id, status);
 }
 
@@ -84,7 +84,7 @@
       FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
   if (!frame_tree_node)
     return;
-  RenderFrameDevToolsAgentHost::OnSignedExchangeReceived(
+  devtools_instrumentation::OnSignedExchangeReceived(
       frame_tree_node, devtools_navigation_token, outer_request_url,
       outer_response->head, envelope, certificate, ssl_info, errors);
 }
diff --git a/content/browser/web_package/signed_exchange_envelope.cc b/content/browser/web_package/signed_exchange_envelope.cc
index 039a8d6..a2eb89b 100644
--- a/content/browser/web_package/signed_exchange_envelope.cc
+++ b/content/browser/web_package/signed_exchange_envelope.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
-#include "components/cbor/cbor_reader.h"
+#include "components/cbor/reader.h"
 #include "content/browser/web_package/signed_exchange_consts.h"
 #include "content/browser/web_package/signed_exchange_utils.h"
 #include "net/http/http_response_headers.h"
diff --git a/content/browser/web_package/signed_exchange_envelope_unittest.cc b/content/browser/web_package/signed_exchange_envelope_unittest.cc
index d9259ca..ee854883 100644
--- a/content/browser/web_package/signed_exchange_envelope_unittest.cc
+++ b/content/browser/web_package/signed_exchange_envelope_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "content/browser/web_package/signed_exchange_consts.h"
 #include "content/browser/web_package/signed_exchange_prologue.h"
 #include "content/public/common/content_paths.h"
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 4ebddda..e62dba6 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -19,8 +19,8 @@
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/values.h"
 #include "content/public/browser/authenticator_request_client_delegate.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/common/content_features.h"
diff --git a/content/public/browser/media_session.h b/content/public/browser/media_session.h
index b915ccf..da3e90d 100644
--- a/content/public/browser/media_session.h
+++ b/content/public/browser/media_session.h
@@ -85,6 +85,14 @@
   void AddObserver(
       media_session::mojom::MediaSessionObserverPtr observer) override = 0;
 
+  // Skip to the previous track. If there is no previous track then this will be
+  // a no-op.
+  void PreviousTrack() override = 0;
+
+  // Skip to the next track. If there is no next track then this will be a
+  // no-op.
+  void NextTrack() override = 0;
+
  protected:
   MediaSession() = default;
 
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc
index fd3b834..bd2b2cb9 100644
--- a/content/renderer/media/media_factory.cc
+++ b/content/renderer/media/media_factory.cc
@@ -109,7 +109,10 @@
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
     scoped_refptr<viz::ContextProvider> unwanted_context_provider,
     blink::WebSubmitterConfigurationCallback set_context_provider_callback) {
-  main_task_runner->PostTask(
+  // |unwanted_context_provider| needs to be destroyed on the current thread.
+  // Therefore, post a reply-callback that retains a reference to it, so that it
+  // doesn't get destroyed on the main thread.
+  main_task_runner->PostTaskAndReply(
       FROM_HERE,
       base::BindOnce(
           [](scoped_refptr<viz::ContextProvider> unwanted_context_provider,
@@ -120,8 +123,11 @@
             std::move(cb).Run(!rti->IsGpuCompositingDisabled(),
                               std::move(context_provider));
           },
-          std::move(unwanted_context_provider),
-          media::BindToCurrentLoop(std::move(set_context_provider_callback))));
+          unwanted_context_provider,
+          media::BindToCurrentLoop(std::move(set_context_provider_callback))),
+      base::BindOnce(
+          [](scoped_refptr<viz::ContextProvider> unwanted_context_provider) {},
+          unwanted_context_provider));
 }
 
 }  // namespace
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc
index 6ef81ae9..634c70eb 100644
--- a/content/renderer/media/stream/webmediaplayer_ms.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -1115,7 +1115,11 @@
   OnRotationChanged(video_rotation);
   OnOpacityChanged(is_opaque);
 
-  if (surface_layer_mode_ == blink::WebMediaPlayer::SurfaceLayerMode::kAlways) {
+  if (surface_layer_mode_ == blink::WebMediaPlayer::SurfaceLayerMode::kAlways ||
+      (surface_layer_mode_ ==
+           blink::WebMediaPlayer::SurfaceLayerMode::kOnDemand &&
+       client_->DisplayType() ==
+           WebMediaPlayer::DisplayType::kPictureInPicture)) {
     ActivateSurfaceLayerForVideo();
   }
 
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index a0955e0..dde4120a 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1739,6 +1739,12 @@
     BrowserControlsState constraints,
     BrowserControlsState current,
     bool animate) {
+  TRACE_EVENT2("renderer", "RenderViewImpl::UpdateBrowserControlsState",
+               "Constraint", static_cast<int>(constraints), "Current",
+               static_cast<int>(current));
+  TRACE_EVENT_INSTANT1("renderer", "is_animated", TRACE_EVENT_SCOPE_THREAD,
+                       "animated", animate);
+
   if (GetWidget() && GetWidget()->layer_tree_view()) {
     GetWidget()->layer_tree_view()->UpdateBrowserControlsState(
         ContentToCc(constraints), ContentToCc(current), animate);
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index aef69d4..1de6e2c 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -1124,6 +1124,9 @@
     #     ['linux', 'amd'], bug=483282)
     self.Fail('conformance2/textures/misc/copy-texture-image-luma-format.html',
         ['linux', 'amd'], bug=483282)
+    self.Fail('conformance2/vertex_arrays/' +
+        'vertex-array-object-and-disabled-attributes.html',
+        ['linux', 'amd'], bug=899754)
 
     self.Fail('deqp/functional/gles3/texturespecification/' +
         'teximage2d_pbo_cube_00.html',
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index dfb9934..d5165b0 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -564,6 +564,9 @@
         ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2918) # ANGLE bug ID
     self.Fail('conformance/context/premultiplyalpha-test.html',
         ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2922) # ANGLE bug ID
+    self.Flaky('conformance/rendering/gl-scissor-fbo-test.html',
+        ['win', 'passthrough', 'vulkan', 'nvidia', 'debug'],
+        bug=2939) # ANGLE bug ID
     self.Fail('conformance/textures/misc/texture-size.html',
         ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2915) # ANGLE bug ID
     self.Fail('conformance/textures/misc/texture-size-cube-maps.html',
@@ -572,6 +575,9 @@
         ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2915) # ANGLE bug ID
     self.Fail('deqp/data/gles2/shaders/conversions.html',
         ['win', 'passthrough', 'vulkan', 'nvidia'], bug=2926) # ANGLE bug ID
+    self.Flaky('deqp/data/gles2/shaders/swizzles.html',
+        ['win', 'passthrough', 'vulkan', 'nvidia', 'debug'],
+        bug=2940) # ANGLE bug ID
 
     # Vulkan / Win / Intel / Passthough command decoder
     self.Fail('conformance/rendering/clipping-wide-points.html',
@@ -753,6 +759,8 @@
         ['android', 'qualcomm', 'no_passthrough'], bug=499555)
 
     # Nexus 5
+    self.Fail('conformance/attribs/gl-disabled-vertex-attrib-update.html',
+        ['android', ('qualcomm', 'Adreno (TM) 330')], bug=899754)
     self.Fail('conformance/extensions/angle-instanced-arrays.html',
         ['android', ('qualcomm', 'Adreno (TM) 330')], bug=611943)
     self.Fail('conformance/extensions/ext-texture-filter-anisotropic.html',
@@ -869,6 +877,13 @@
     self.Skip('conformance/more/functions/bindBufferBadArgs.html',
         ['android', 'android-webview-instrumentation',
          ('qualcomm', 'Adreno (TM) 420')], bug=499874)
+    self.Fail('conformance/reading/' +
+        'fbo-remains-unchanged-after-read-pixels.html',
+        ['android', ('qualcomm', 'Adreno (TM) 420')], bug=899754)
+    self.Fail('conformance/reading/read-pixels-pack-alignment.html',
+        ['android', ('qualcomm', 'Adreno (TM) 420')], bug=899754)
+    self.Fail('conformance/reading/read-pixels-test.html',
+        ['android', ('qualcomm', 'Adreno (TM) 420')], bug=899754)
     self.Fail('conformance/rendering/clear-after-copyTexImage2D.html',
         ['android', ('qualcomm', 'Adreno (TM) 420')], bug=737002)
     self.Fail('conformance/rendering/gl-scissor-test.html',
diff --git a/device/fido/attestation_object.cc b/device/fido/attestation_object.cc
index 2369573..8bec23e 100644
--- a/device/fido/attestation_object.cc
+++ b/device/fido/attestation_object.cc
@@ -6,8 +6,8 @@
 
 #include <utility>
 
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "device/fido/attestation_statement.h"
 #include "device/fido/fido_constants.h"
 
diff --git a/device/fido/attestation_statement.h b/device/fido/attestation_statement.h
index 59d26891..2119f430 100644
--- a/device/fido/attestation_statement.h
+++ b/device/fido/attestation_statement.h
@@ -11,7 +11,7 @@
 #include "base/containers/span.h"
 #include "base/macros.h"
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 
 namespace device {
 
diff --git a/device/fido/attestation_statement_formats.h b/device/fido/attestation_statement_formats.h
index 5c1ac23..3bb9137 100644
--- a/device/fido/attestation_statement_formats.h
+++ b/device/fido/attestation_statement_formats.h
@@ -12,7 +12,7 @@
 #include "base/component_export.h"
 #include "base/containers/span.h"
 #include "base/macros.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 #include "device/fido/attestation_statement.h"
 #include "device/fido/fido_constants.h"
 
diff --git a/device/fido/attestation_statement_formats_unittest.cc b/device/fido/attestation_statement_formats_unittest.cc
index bcd69e2a..8db60906 100644
--- a/device/fido/attestation_statement_formats_unittest.cc
+++ b/device/fido/attestation_statement_formats_unittest.cc
@@ -4,8 +4,8 @@
 
 #include <vector>
 
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/writer.h"
 #include "device/fido/attestation_statement_formats.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_parsing_utils.h"
diff --git a/device/fido/attested_credential_data.cc b/device/fido/attested_credential_data.cc
index ab05a59..7f59a16b 100644
--- a/device/fido/attested_credential_data.cc
+++ b/device/fido/attested_credential_data.cc
@@ -8,7 +8,7 @@
 #include <utility>
 
 #include "base/numerics/safe_math.h"
-#include "components/cbor/cbor_reader.h"
+#include "components/cbor/reader.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_parsing_utils.h"
 #include "device/fido/opaque_public_key.h"
diff --git a/device/fido/authenticator_data.cc b/device/fido/authenticator_data.cc
index 207d0732..104967a4 100644
--- a/device/fido/authenticator_data.cc
+++ b/device/fido/authenticator_data.cc
@@ -6,8 +6,8 @@
 
 #include <utility>
 
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/writer.h"
 #include "device/fido/attested_credential_data.h"
 #include "device/fido/fido_parsing_utils.h"
 
diff --git a/device/fido/authenticator_data.h b/device/fido/authenticator_data.h
index 5bec5ab..3f4f440 100644
--- a/device/fido/authenticator_data.h
+++ b/device/fido/authenticator_data.h
@@ -16,7 +16,7 @@
 #include "base/macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 #include "device/fido/attested_credential_data.h"
 #include "device/fido/fido_constants.h"
 
diff --git a/device/fido/authenticator_get_assertion_response.cc b/device/fido/authenticator_get_assertion_response.cc
index 3ef8a04..dc635d4 100644
--- a/device/fido/authenticator_get_assertion_response.cc
+++ b/device/fido/authenticator_get_assertion_response.cc
@@ -7,8 +7,8 @@
 #include <utility>
 
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "device/fido/authenticator_data.h"
 #include "device/fido/fido_parsing_utils.h"
 
diff --git a/device/fido/authenticator_get_info_response.cc b/device/fido/authenticator_get_info_response.cc
index b0f66c7..d5f63d4 100644
--- a/device/fido/authenticator_get_info_response.cc
+++ b/device/fido/authenticator_get_info_response.cc
@@ -6,8 +6,8 @@
 
 #include <utility>
 
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "device/fido/fido_parsing_utils.h"
 
 namespace device {
diff --git a/device/fido/authenticator_supported_options.h b/device/fido/authenticator_supported_options.h
index 2aaeb7c..4672c153 100644
--- a/device/fido/authenticator_supported_options.h
+++ b/device/fido/authenticator_supported_options.h
@@ -8,7 +8,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 
 namespace device {
 
diff --git a/device/fido/cable/fido_cable_handshake_handler.cc b/device/fido/cable/fido_cable_handshake_handler.cc
index b7d40dbc..8c6e6fc 100644
--- a/device/fido/cable/fido_cable_handshake_handler.cc
+++ b/device/fido/cable/fido_cable_handshake_handler.cc
@@ -9,9 +9,9 @@
 
 #include "base/containers/span.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "crypto/hkdf.h"
 #include "crypto/hmac.h"
 #include "crypto/random.h"
diff --git a/device/fido/cable/fido_cable_handshake_handler_unittest.cc b/device/fido/cable/fido_cable_handshake_handler_unittest.cc
index 175b0cce..7c2117a4 100644
--- a/device/fido/cable/fido_cable_handshake_handler_unittest.cc
+++ b/device/fido/cable/fido_cable_handshake_handler_unittest.cc
@@ -13,9 +13,9 @@
 #include "base/optional.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "crypto/hkdf.h"
 #include "crypto/hmac.h"
 #include "device/bluetooth/test/bluetooth_test.h"
diff --git a/device/fido/ctap_get_assertion_request.cc b/device/fido/ctap_get_assertion_request.cc
index 6b09b056..42b4f5f 100644
--- a/device/fido/ctap_get_assertion_request.cc
+++ b/device/fido/ctap_get_assertion_request.cc
@@ -9,8 +9,8 @@
 #include <utility>
 
 #include "base/numerics/safe_conversions.h"
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/writer.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_parsing_utils.h"
 
diff --git a/device/fido/ctap_make_credential_request.cc b/device/fido/ctap_make_credential_request.cc
index 9991f8e2..9d4d8ca 100644
--- a/device/fido/ctap_make_credential_request.cc
+++ b/device/fido/ctap_make_credential_request.cc
@@ -9,8 +9,8 @@
 #include <utility>
 
 #include "base/numerics/safe_conversions.h"
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/writer.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_parsing_utils.h"
 
diff --git a/device/fido/ctap_response_unittest.cc b/device/fido/ctap_response_unittest.cc
index cc8cc8f..be87a09 100644
--- a/device/fido/ctap_response_unittest.cc
+++ b/device/fido/ctap_response_unittest.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "device/fido/attestation_statement_formats.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/authenticator_make_credential_response.h"
diff --git a/device/fido/device_response_converter.cc b/device/fido/device_response_converter.cc
index 7060524..a31f7669 100644
--- a/device/fido/device_response_converter.cc
+++ b/device/fido/device_response_converter.cc
@@ -12,8 +12,8 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/writer.h"
 #include "device/fido/authenticator_data.h"
 #include "device/fido/authenticator_supported_options.h"
 #include "device/fido/fido_constants.h"
diff --git a/device/fido/ec_public_key.cc b/device/fido/ec_public_key.cc
index 61ad96d..207ae33 100644
--- a/device/fido/ec_public_key.cc
+++ b/device/fido/ec_public_key.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/writer.h"
 #include "device/fido/fido_parsing_utils.h"
 
 namespace device {
diff --git a/device/fido/mac/credential_metadata.cc b/device/fido/mac/credential_metadata.cc
index ee292fa..54c69ed 100644
--- a/device/fido/mac/credential_metadata.cc
+++ b/device/fido/mac/credential_metadata.cc
@@ -7,9 +7,9 @@
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "components/cbor/cbor_reader.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "device/fido/public_key_credential_user_entity.h"
 #include "third_party/boringssl/src/include/openssl/digest.h"
 #include "third_party/boringssl/src/include/openssl/hkdf.h"
diff --git a/device/fido/mac/util.mm b/device/fido/mac/util.mm
index 3bda144..999a7487 100644
--- a/device/fido/mac/util.mm
+++ b/device/fido/mac/util.mm
@@ -16,7 +16,7 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/strings/string_number_conversions.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/writer.h"
 #include "device/fido/ec_public_key.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_parsing_utils.h"
diff --git a/device/fido/opaque_attestation_statement.cc b/device/fido/opaque_attestation_statement.cc
index 7bf7793..8edb742 100644
--- a/device/fido/opaque_attestation_statement.cc
+++ b/device/fido/opaque_attestation_statement.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 
 using cbor::Value;
 
diff --git a/device/fido/opaque_attestation_statement.h b/device/fido/opaque_attestation_statement.h
index 4606931d..7f6cef0 100644
--- a/device/fido/opaque_attestation_statement.h
+++ b/device/fido/opaque_attestation_statement.h
@@ -9,7 +9,7 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 #include "device/fido/attestation_statement.h"
 
 namespace device {
diff --git a/device/fido/public_key_credential_descriptor.h b/device/fido/public_key_credential_descriptor.h
index bf23a52..1dde94a 100644
--- a/device/fido/public_key_credential_descriptor.h
+++ b/device/fido/public_key_credential_descriptor.h
@@ -12,7 +12,7 @@
 #include "base/component_export.h"
 #include "base/containers/flat_set.h"
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_transport_protocol.h"
 
diff --git a/device/fido/public_key_credential_params.h b/device/fido/public_key_credential_params.h
index f7f3c0d..cfb6f14 100644
--- a/device/fido/public_key_credential_params.h
+++ b/device/fido/public_key_credential_params.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 #include "device/fido/fido_constants.h"
 
 namespace device {
diff --git a/device/fido/public_key_credential_rp_entity.h b/device/fido/public_key_credential_rp_entity.h
index 03ac8ea..d7a7d23 100644
--- a/device/fido/public_key_credential_rp_entity.h
+++ b/device/fido/public_key_credential_rp_entity.h
@@ -11,7 +11,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 #include "url/gurl.h"
 
 namespace device {
diff --git a/device/fido/public_key_credential_user_entity.h b/device/fido/public_key_credential_user_entity.h
index 810dc4b..fcd77eb9 100644
--- a/device/fido/public_key_credential_user_entity.h
+++ b/device/fido/public_key_credential_user_entity.h
@@ -11,7 +11,7 @@
 
 #include "base/component_export.h"
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 #include "url/gurl.h"
 
 namespace device {
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index e69ffec6..d5d1779a 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -12,7 +12,7 @@
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/cbor/cbor_writer.h"
+#include "components/cbor/writer.h"
 #include "crypto/ec_private_key.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/authenticator_make_credential_response.h"
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h
index 4c5f96ed..0ffe2cf 100644
--- a/device/fido/virtual_ctap2_device.h
+++ b/device/fido/virtual_ctap2_device.h
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/optional.h"
-#include "components/cbor/cbor_values.h"
+#include "components/cbor/values.h"
 #include "device/fido/attested_credential_data.h"
 #include "device/fido/authenticator_data.h"
 #include "device/fido/authenticator_supported_options.h"
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index a8577f9..03921dc 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -63,8 +63,6 @@
         "android/gvr/gvr_gamepad_data_fetcher.cc",
         "android/gvr/gvr_gamepad_data_fetcher.h",
         "android/gvr/gvr_gamepad_data_provider.h",
-        "android/gvr/vr_module_delegate.cc",
-        "android/gvr/vr_module_delegate.h",
       ]
 
       if (enable_arcore) {
diff --git a/device/vr/android/gvr/gvr_device.cc b/device/vr/android/gvr/gvr_device.cc
index 3e7d855..a8a3118d 100644
--- a/device/vr/android/gvr/gvr_device.cc
+++ b/device/vr/android/gvr/gvr_device.cc
@@ -16,7 +16,6 @@
 #include "device/vr/android/gvr/gvr_delegate_provider.h"
 #include "device/vr/android/gvr/gvr_delegate_provider_factory.h"
 #include "device/vr/android/gvr/gvr_device_provider.h"
-#include "device/vr/android/gvr/vr_module_delegate.h"
 #include "device/vr/vr_display_impl.h"
 #include "jni/NonPresentingGvrContext_jni.h"
 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h"
@@ -162,12 +161,33 @@
     mojom::XRRuntimeSessionOptionsPtr options,
     mojom::XRRuntime::RequestSessionCallback callback) {
   if (!gvr_api_) {
-    Init(base::BindOnce(&GvrDevice::OnInitRequestSessionFinished,
-                        base::Unretained(this), std::move(options),
-                        std::move(callback)));
+    EnsureGvrReady();
+    if (!gvr_api_) {
+      std::move(callback).Run(nullptr, nullptr);
+      return;
+    }
+  }
+
+  if (!options->immersive) {
+    // TODO(https://crbug.com/695937): This should be NOTREACHED() once we no
+    // longer need the hacked GRV non-immersive mode.  This should now only be
+    // hit if orientation devices are disabled by flag.
+    ReturnNonImmersiveSession(std::move(callback));
     return;
   }
-  OnInitRequestSessionFinished(std::move(options), std::move(callback), true);
+
+  GvrDelegateProvider* delegate_provider = GetGvrDelegateProvider();
+  if (!delegate_provider) {
+    std::move(callback).Run(nullptr, nullptr);
+    return;
+  }
+
+  // StartWebXRPresentation is async as we may trigger a DON (Device ON) flow
+  // that pauses Chrome.
+  delegate_provider->StartWebXRPresentation(
+      GetVRDisplayInfo(), std::move(options),
+      base::BindOnce(&GvrDevice::OnStartPresentResult,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void GvrDevice::OnStartPresentResult(
@@ -213,6 +233,30 @@
   exclusive_controller_binding_.Close();
 }
 
+void GvrDevice::EnsureGvrReady() {
+  if (!non_presenting_context_.obj() || !gvr_api_) {
+    GvrDelegateProvider* delegate_provider = GetGvrDelegateProvider();
+    if (!delegate_provider || delegate_provider->ShouldDisableGvrDevice())
+      return;
+    JNIEnv* env = base::android::AttachCurrentThread();
+    non_presenting_context_.Reset(Java_NonPresentingGvrContext_create(
+        env, reinterpret_cast<jlong>(this)));
+    if (!non_presenting_context_.obj())
+      return;
+    jlong context = Java_NonPresentingGvrContext_getNativeGvrContext(
+        env, non_presenting_context_);
+    gvr_api_ =
+        gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(context));
+    SetVRDisplayInfo(CreateVRDisplayInfo(gvr_api_.get(), GetId()));
+
+    if (paused_) {
+      PauseTracking();
+    } else {
+      ResumeTracking();
+    }
+  }
+}
+
 void GvrDevice::OnMagicWindowFrameDataRequest(
     mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   if (!gvr_api_) {
@@ -251,9 +295,8 @@
 }
 
 void GvrDevice::EnsureInitialized(EnsureInitializedCallback callback) {
-  Init(base::BindOnce([](EnsureInitializedCallback callback,
-                         bool success) { std::move(callback).Run(); },
-                      std::move(callback)));
+  EnsureGvrReady();
+  std::move(callback).Run();
 }
 
 GvrDelegateProvider* GvrDevice::GetGvrDelegateProvider() {
@@ -276,85 +319,4 @@
   OnActivate(reason, std::move(on_handled));
 }
 
-void GvrDevice::Init(base::OnceCallback<void(bool)> on_finished) {
-  VrModuleDelegate* module_delegate = VrModuleDelegate::Get();
-  if (!module_delegate) {
-    std::move(on_finished).Run(false);
-    return;
-  }
-  if (!module_delegate->ModuleInstalled()) {
-    module_delegate->InstallModule(
-        base::BindOnce(&GvrDevice::OnVrModuleInstalled, base::Unretained(this),
-                       std::move(on_finished)));
-    return;
-  }
-  OnVrModuleInstalled(std::move(on_finished), true);
-}
-
-void GvrDevice::OnVrModuleInstalled(base::OnceCallback<void(bool)> on_finished,
-                                    bool success) {
-  if (!success) {
-    std::move(on_finished).Run(false);
-    return;
-  }
-  GvrDelegateProvider* delegate_provider = GetGvrDelegateProvider();
-  if (!delegate_provider || delegate_provider->ShouldDisableGvrDevice()) {
-    std::move(on_finished).Run(false);
-    return;
-  }
-  CreateNonPresentingContext();
-  std::move(on_finished).Run(non_presenting_context_.obj() != nullptr);
-}
-
-void GvrDevice::CreateNonPresentingContext() {
-  if (non_presenting_context_.obj())
-    return;
-  JNIEnv* env = base::android::AttachCurrentThread();
-  non_presenting_context_.Reset(
-      Java_NonPresentingGvrContext_create(env, reinterpret_cast<jlong>(this)));
-  if (!non_presenting_context_.obj())
-    return;
-  jlong context = Java_NonPresentingGvrContext_getNativeGvrContext(
-      env, non_presenting_context_);
-  gvr_api_ = gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(context));
-  SetVRDisplayInfo(CreateVRDisplayInfo(gvr_api_.get(), GetId()));
-
-  if (paused_) {
-    PauseTracking();
-  } else {
-    ResumeTracking();
-  }
-}
-
-void GvrDevice::OnInitRequestSessionFinished(
-    mojom::XRRuntimeSessionOptionsPtr options,
-    mojom::XRRuntime::RequestSessionCallback callback,
-    bool success) {
-  if (!success) {
-    std::move(callback).Run(nullptr, nullptr);
-    return;
-  }
-
-  if (!options->immersive) {
-    // TODO(https://crbug.com/695937): This should be NOTREACHED() once we no
-    // longer need the hacked GRV non-immersive mode.  This should now only be
-    // hit if orientation devices are disabled by flag.
-    ReturnNonImmersiveSession(std::move(callback));
-    return;
-  }
-
-  GvrDelegateProvider* delegate_provider = GetGvrDelegateProvider();
-  if (!delegate_provider) {
-    std::move(callback).Run(nullptr, nullptr);
-    return;
-  }
-
-  // StartWebXRPresentation is async as we may trigger a DON (Device ON) flow
-  // that pauses Chrome.
-  delegate_provider->StartWebXRPresentation(
-      GetVRDisplayInfo(), std::move(options),
-      base::BindOnce(&GvrDevice::OnStartPresentResult,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-}
-
 }  // namespace device
diff --git a/device/vr/android/gvr/gvr_device.h b/device/vr/android/gvr/gvr_device.h
index 342f1be..93388c05 100644
--- a/device/vr/android/gvr/gvr_device.h
+++ b/device/vr/android/gvr/gvr_device.h
@@ -53,17 +53,9 @@
 
   void OnPresentingControllerMojoConnectionError();
   void StopPresenting();
+  void EnsureGvrReady();
   GvrDelegateProvider* GetGvrDelegateProvider();
 
-  void Init(base::OnceCallback<void(bool)> on_finished);
-  void OnVrModuleInstalled(base::OnceCallback<void(bool)> on_finished,
-                           bool success);
-  void CreateNonPresentingContext();
-  void OnInitRequestSessionFinished(
-      mojom::XRRuntimeSessionOptionsPtr options,
-      mojom::XRRuntime::RequestSessionCallback callback,
-      bool success);
-
   base::android::ScopedJavaGlobalRef<jobject> non_presenting_context_;
   std::unique_ptr<gvr::GvrApi> gvr_api_;
 
diff --git a/device/vr/android/gvr/vr_module_delegate.cc b/device/vr/android/gvr/vr_module_delegate.cc
deleted file mode 100644
index d2043470..0000000
--- a/device/vr/android/gvr/vr_module_delegate.cc
+++ /dev/null
@@ -1,28 +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 "device/vr/android/gvr/vr_module_delegate.h"
-
-namespace device {
-
-namespace {
-// Storing the global delegate in a raw pointer - as opposed to e.g. an
-// std::unique_ptr - to avoid adding a static initializer.
-VrModuleDelegate* g_vr_module_delegate = nullptr;
-}  // namespace
-
-// static
-VrModuleDelegate* VrModuleDelegate::Get() {
-  return g_vr_module_delegate;
-}
-
-// static
-void VrModuleDelegate::Set(std::unique_ptr<VrModuleDelegate> delegate) {
-  if (g_vr_module_delegate) {
-    delete g_vr_module_delegate;
-  }
-  g_vr_module_delegate = delegate.release();
-}
-
-}  // namespace device
diff --git a/device/vr/android/gvr/vr_module_delegate.h b/device/vr/android/gvr/vr_module_delegate.h
deleted file mode 100644
index 9e6c204..0000000
--- a/device/vr/android/gvr/vr_module_delegate.h
+++ /dev/null
@@ -1,38 +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 DEVICE_VR_ANDROID_GVR_VR_MODULE_DELEGATE_H_
-#define DEVICE_VR_ANDROID_GVR_VR_MODULE_DELEGATE_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "device/vr/vr_export.h"
-
-namespace device {
-
-// Delegates installation of the VR module.
-class DEVICE_VR_EXPORT VrModuleDelegate {
- public:
-  // Returns the global module delegate.
-  static VrModuleDelegate* Get();
-  // Sets the global module delegate.
-  static void Set(std::unique_ptr<VrModuleDelegate> delegate);
-
-  VrModuleDelegate() = default;
-  virtual ~VrModuleDelegate() = default;
-  // Returns true if the VR module is installed.
-  virtual bool ModuleInstalled() = 0;
-  // Asynchronously requests to install the VR module. |on_finished| is called
-  // after the module install is completed. If |success| is false the module
-  // install failed.
-  virtual void InstallModule(
-      base::OnceCallback<void(bool success)> on_finished) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(VrModuleDelegate);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_VR_ANDROID_GVR_VR_MODULE_DELEGATE_H_
diff --git a/infra/config/branch/cq.cfg b/infra/config/branch/cq.cfg
index 5a6e413..83357e37 100644
--- a/infra/config/branch/cq.cfg
+++ b/infra/config/branch/cq.cfg
@@ -173,7 +173,8 @@
         path_regexp: "ui/gl/.+"
       }
       builders { name: "win-libfuzzer-asan-rel" }
-      builders { name: "win10_chromium_x64_rel_ng" }
+      # TODO(martiniss): Re-add to CQ once outage is over. See crbug.com/899908
+      # builders { name: "win10_chromium_x64_rel_ng" }
       builders {
         name: "win7_chromium_rel_loc_exp"
         experiment_percentage: 20
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index bc2ad90f..823fb1c 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -1022,22 +1022,18 @@
   manifest_name: "REVISION"
   builders {
     name: "buildbot/chromium.chrome/Google Chrome Win"
-    name: "buildbucket/luci.chromium.ci/Google Chrome Win"
     short_name: "win"
   }
   builders {
     name: "buildbot/chromium.chrome/Google Chrome Linux x64"
-    name: "buildbucket/luci.chromium.ci/Google Chrome Linux x64"
     short_name: "lnx"
   }
   builders {
     name: "buildbot/chromium.chrome/Google Chrome Mac"
-    name: "buildbucket/luci.chromium.ci/Google Chrome Mac"
     short_name: "mac"
   }
   builders {
     name: "buildbot/chromium.chrome/Google Chrome ChromeOS"
-    name: "buildbucket/luci.chromium.ci/Google Chrome ChromeOS"
     short_name: "cro"
   }
 }
@@ -4553,9 +4549,6 @@
     name: "buildbot/tryserver.chromium.win/win_upload_clang"
   }
   builders {
-    name: "buildbot/tryserver.chromium.win/win_chrome_official"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/win_x64_archive"
   }
   builders {
@@ -5049,9 +5042,6 @@
     name: "buildbucket/luci.chromium.try/win_archive"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/win_chrome_official"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/win_chromium_compile_dbg_ng"
   }
   builders {
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 09054ba..d7af2777 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -75,7 +75,6 @@
   "+components/sync_sessions",
   "+components/sync_preferences",
   "+components/task_scheduler_util",
-  "+components/toolbar",
   "+components/translate/core",
   "+components/translate/ios",
   "+components/ui_metrics",
diff --git a/ios/chrome/browser/search_engines/resources/search_engine.js b/ios/chrome/browser/search_engines/resources/search_engine.js
index 901382d..65456a23 100644
--- a/ios/chrome/browser/search_engines/resources/search_engine.js
+++ b/ios/chrome/browser/search_engines/resources/search_engine.js
@@ -217,16 +217,17 @@
     if (isSubmitElement_(element)) {
       // Only append the active submit element's name-value pair.
       if (element === activeSubmitElement) {
+        var value = element.value;
         // <input type="submit"> will have "Submit" as default "value" when
         // submitted with empty "value" and non-empty "name". This probably
         // comes from the default label text of <input type="submit">:
         //   https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/submit
-        if (element.tagName == 'INPUT' && !element.value) {
-          element.value = 'Submit';
+        if (element.tagName == 'INPUT' && !value) {
+          value = 'Submit';
         }
         queryArgs.push(
             encodeFormData_(element.name) + '=' +
-            encodeFormData_(element.value));
+            encodeFormData_(value));
       }
       continue;
     }
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index 0a105c8..933da7e4 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -86,11 +86,11 @@
     "//base/test:test_support",
     "//components/bookmarks/browser",
     "//components/bookmarks/test",
+    "//components/omnibox/browser:test_support",
     "//components/payments/core",
     "//components/prefs:test_support",
     "//components/search_engines",
     "//components/sessions",
-    "//components/toolbar:test_support",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
     "//ios/chrome/browser/bookmarks",
@@ -265,6 +265,7 @@
     "//components/feature_engagement",
     "//components/image_fetcher/ios",
     "//components/language/ios/browser",
+    "//components/omnibox/browser",
     "//components/payments/core",
     "//components/prefs",
     "//components/reading_list/core",
@@ -274,7 +275,6 @@
     "//components/signin/ios/browser",
     "//components/signin/ios/browser:active_state_manager",
     "//components/strings",
-    "//components/toolbar",
     "//components/url_formatter",
     "//ios/chrome/app:tests_hook",
     "//ios/chrome/app/strings",
@@ -488,7 +488,7 @@
   deps = [
     "//base",
     "//base/test:test_support",
-    "//components/toolbar:test_support",
+    "//components/omnibox/browser:test_support",
     "//ios/chrome/browser/autocomplete",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/search_engines",
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 66bc184..5e38623 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -38,6 +38,7 @@
 #include "components/feature_engagement/public/tracker.h"
 #include "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h"
 #import "components/language/ios/browser/ios_language_detection_tab_helper.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 #include "components/prefs/pref_service.h"
 #include "components/reading_list/core/reading_list_model.h"
 #include "components/search_engines/search_engines_pref_names.h"
@@ -49,7 +50,6 @@
 #import "components/signin/ios/browser/account_consistency_service.h"
 #include "components/signin/ios/browser/active_state_manager.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/toolbar/toolbar_model_impl.h"
 #include "ios/chrome/app/tests_hook.h"
 #import "ios/chrome/browser/app_launcher/app_launcher_abuse_detector.h"
 #import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
diff --git a/ios/chrome/browser/ui/browser_view_controller_helper_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_helper_unittest.mm
index 1976e30..042cd8d 100644
--- a/ios/chrome/browser/ui/browser_view_controller_helper_unittest.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_helper_unittest.mm
@@ -11,7 +11,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
-#include "components/toolbar/test_toolbar_model.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/ui/toolbar/test/toolbar_test_navigation_manager.h"
diff --git a/ios/chrome/browser/ui/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
index d4f25725..19951798 100644
--- a/ios/chrome/browser/ui/browser_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
@@ -12,10 +12,10 @@
 #include "base/path_service.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/sessions/core/tab_restore_service.h"
-#include "components/toolbar/test_toolbar_model.h"
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_paths.h"
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn
index 9c4239f..7bd02c34 100644
--- a/ios/chrome/browser/ui/location_bar/BUILD.gn
+++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -29,11 +29,9 @@
     "resources:location_bar_voice",
     "//base",
     "//components/google/core/browser",
-    "//components/google/core/browser",
     "//components/omnibox/browser",
     "//components/search_engines",
     "//components/strings",
-    "//components/toolbar",
     "//components/variations/net",
     "//ios/chrome/app/strings",
     "//ios/chrome/app/theme",
@@ -94,7 +92,6 @@
     "//base",
     "//components/omnibox/browser",
     "//components/prefs",
-    "//components/toolbar",
     "//ios/chrome/browser",
     "//ios/chrome/browser/autocomplete",
     "//ios/chrome/browser/browser_state",
@@ -127,7 +124,7 @@
     ":location_bar",
     "//base",
     "//base/test:test_support",
-    "//components/toolbar:test_support",
+    "//components/omnibox/browser:test_support",
     "//components/variations",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator_unittest.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator_unittest.mm
index 423f5c3..c838761 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator_unittest.mm
@@ -8,7 +8,7 @@
 #include <string>
 #include <vector>
 
-#include "components/toolbar/test_toolbar_model.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
 #include "components/variations/variations_http_header_provider.h"
 #include "ios/chrome/browser/autocomplete/autocomplete_classifier_factory.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
index c42af32..287b099 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
@@ -6,8 +6,8 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/security_state/core/security_state_ui.h"
-#include "components/toolbar/toolbar_model.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/ssl/ios_security_state_tab_helper.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_consumer.h"
diff --git a/ios/chrome/browser/ui/location_bar/toolbar_model_delegate_ios.h b/ios/chrome/browser/ui/location_bar/toolbar_model_delegate_ios.h
index e90ae6ea..4c22130 100644
--- a/ios/chrome/browser/ui/location_bar/toolbar_model_delegate_ios.h
+++ b/ios/chrome/browser/ui/location_bar/toolbar_model_delegate_ios.h
@@ -6,7 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_LOCATION_BAR_TOOLBAR_MODEL_DELEGATE_IOS_H_
 
 #include "base/macros.h"
-#include "components/toolbar/toolbar_model_delegate.h"
+#include "components/omnibox/browser/toolbar_model_delegate.h"
 
 class WebStateList;
 
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn
index 0480acb..eea46df 100644
--- a/ios/chrome/browser/ui/omnibox/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -138,7 +138,6 @@
   ]
   public_deps = [
     "//components/omnibox/browser",
-    "//components/toolbar",
   ]
   libs = [
     "CoreText.framework",
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
index 41e5da0..c793228 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
@@ -9,7 +9,7 @@
 
 #include <memory>
 #include "components/omnibox/browser/omnibox_view.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_left_image_consumer.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
 #include "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_provider.h"
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
index 8640c3223..91298ca 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -19,7 +19,7 @@
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h"
diff --git a/ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.mm b/ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.mm
index bc15f46..5e16e46 100644
--- a/ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.mm
+++ b/ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.mm
@@ -4,7 +4,7 @@
 
 #include "ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.h"
 
-#include "components/toolbar/toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_url_loader.h"
 #import "ios/chrome/browser/ui/omnibox/location_bar_delegate.h"
 #include "url/gurl.h"
diff --git a/ios/chrome/browser/ui/omnibox_perftest.mm b/ios/chrome/browser/ui/omnibox_perftest.mm
index 8cd84903..ce658f86 100644
--- a/ios/chrome/browser/ui/omnibox_perftest.mm
+++ b/ios/chrome/browser/ui/omnibox_perftest.mm
@@ -8,8 +8,8 @@
 
 #import "base/test/ios/wait_util.h"
 #include "base/time/time.h"
-#include "components/toolbar/test_toolbar_model.h"
-#include "components/toolbar/toolbar_model_impl.h"
+#include "components/omnibox/browser/test_toolbar_model.h"
+#include "components/omnibox/browser/toolbar_model_impl.h"
 #include "ios/chrome/browser/autocomplete/autocomplete_classifier_factory.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/search_engines/template_url_service_factory.h"
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn
index f107c168..cab28d2 100644
--- a/ios/chrome/browser/ui/payments/BUILD.gn
+++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -65,11 +65,11 @@
     "//base",
     "//components/autofill/core/browser",
     "//components/autofill/ios/browser",
+    "//components/omnibox/browser",
     "//components/payments/core",
     "//components/payments/mojom",
     "//components/signin/core/browser",
     "//components/strings",
-    "//components/toolbar",
     "//components/url_formatter",
     "//ios/chrome/app/strings",
     "//ios/chrome/app/theme",
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm
index 758c971..960982f 100644
--- a/ios/chrome/browser/ui/payments/payment_request_manager.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm
@@ -24,6 +24,7 @@
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/ios/browser/autofill_driver_ios.h"
+#include "components/omnibox/browser/toolbar_model.h"
 #include "components/payments/core/can_make_payment_query.h"
 #include "components/payments/core/features.h"
 #include "components/payments/core/journey_logger.h"
@@ -39,7 +40,6 @@
 #include "components/payments/core/web_payment_request.h"
 #include "components/payments/mojom/payment_request_data.mojom.h"
 #include "components/prefs/pref_service.h"
-#include "components/toolbar/toolbar_model.h"
 #include "components/url_formatter/elide_url.h"
 #include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
 #include "ios/chrome/browser/autofill/validation_rules_storage_factory.h"
diff --git a/ios/chrome/browser/ui/toolbar/fullscreen/BUILD.gn b/ios/chrome/browser/ui/toolbar/fullscreen/BUILD.gn
index c81cf30..92410e0 100644
--- a/ios/chrome/browser/ui/toolbar/fullscreen/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/fullscreen/BUILD.gn
@@ -44,7 +44,7 @@
     "//base",
     "//components/bookmarks/browser",
     "//components/bookmarks/test",
-    "//components/toolbar:test_support",
+    "//components/omnibox/browser:test_support",
     "//ios/chrome/browser",
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state:test_support",
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc
index f0dd1c7..e360c0a 100644
--- a/media/renderers/paint_canvas_video_renderer.cc
+++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -336,8 +336,9 @@
     return true;
   }
 
-  bool QueryYUV8(SkYUVSizeInfo* sizeInfo,
-                 SkYUVColorSpace* color_space) const override {
+  bool QueryYUVA8(SkYUVASizeInfo* sizeInfo,
+                  SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+                  SkYUVColorSpace* color_space) const override {
     if (!media::IsYuvPlanar(frame_->format()) ||
         // TODO(rileya): Skia currently doesn't support YUVA conversion. Remove
         // this case once it does. As-is we will fall back on the pure-software
@@ -363,19 +364,41 @@
       sizeInfo->fSizes[plane].set(size.width(), size.height());
       sizeInfo->fWidthBytes[plane] = size.width();
     }
+    sizeInfo->fSizes[VideoFrame::kAPlane] = SkISize::MakeEmpty();
+    sizeInfo->fWidthBytes[VideoFrame::kAPlane] = 0;
+
+    indices[SkYUVAIndex::kY_Index] = {VideoFrame::kYPlane, SkColorChannel::kR};
+    indices[SkYUVAIndex::kU_Index] = {VideoFrame::kUPlane, SkColorChannel::kR};
+    indices[SkYUVAIndex::kV_Index] = {VideoFrame::kVPlane, SkColorChannel::kR};
+    indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kR};
 
     return true;
   }
 
-  bool GetYUV8Planes(const SkYUVSizeInfo& sizeInfo,
-                     void* planes[3],
-                     size_t frame_index,
-                     uint32_t lazy_pixel_ref) override {
+  bool GetYUVA8Planes(const SkYUVASizeInfo& sizeInfo,
+                      const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+                      void* planes[4],
+                      size_t frame_index,
+                      uint32_t lazy_pixel_ref) override {
     DCHECK_EQ(frame_index, 0u);
 
     media::VideoPixelFormat format = frame_->format();
     DCHECK(media::IsYuvPlanar(format) && format != PIXEL_FORMAT_I420A);
 
+    for (int i = 0; i <= VideoFrame::kVPlane; ++i) {
+      if (sizeInfo.fSizes[i].isEmpty() || !sizeInfo.fWidthBytes[i]) {
+        return false;
+      }
+    }
+    if (!sizeInfo.fSizes[VideoFrame::kAPlane].isEmpty() ||
+        sizeInfo.fWidthBytes[VideoFrame::kAPlane]) {
+      return false;
+    }
+    int numPlanes;
+    if (!SkYUVAIndex::AreValidIndices(indices, &numPlanes) || numPlanes != 3) {
+      return false;
+    }
+
     for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane;
          ++plane) {
       const gfx::Size size =
diff --git a/mojo/public/cpp/bindings/sync_call_restrictions.h b/mojo/public/cpp/bindings/sync_call_restrictions.h
index b260b9f0..9ba9efa 100644
--- a/mojo/public/cpp/bindings/sync_call_restrictions.h
+++ b/mojo/public/cpp/bindings/sync_call_restrictions.h
@@ -15,8 +15,6 @@
 #define ENABLE_SYNC_CALL_RESTRICTIONS 0
 #endif
 
-class ChromeSelectFileDialogFactory;
-
 namespace sync_preferences {
 class PrefServiceSyncable;
 }
@@ -85,8 +83,6 @@
   // Incognito pref service instances are created synchronously.
   friend class sync_preferences::PrefServiceSyncable;
   friend class mojo::ScopedAllowSyncCallForTesting;
-  // For file open and save dialogs created synchronously.
-  friend class ::ChromeSelectFileDialogFactory;
   // For synchronous system clipboard access.
   friend class ui::ClipboardClient;
   // For destroying the GL context/surface that draw to a platform window before
diff --git a/services/media_session/media_controller.cc b/services/media_session/media_controller.cc
index 1ab33d7..fdddf74 100644
--- a/services/media_session/media_controller.cc
+++ b/services/media_session/media_controller.cc
@@ -63,6 +63,20 @@
   session_info_ = std::move(info);
 }
 
+void MediaController::PreviousTrack() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (session_)
+    session_->PreviousTrack();
+}
+
+void MediaController::NextTrack() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (session_)
+    session_->NextTrack();
+}
+
 void MediaController::SetMediaSession(mojom::MediaSession* session) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   session_ = session;
diff --git a/services/media_session/media_controller.h b/services/media_session/media_controller.h
index fa53149..36deb02e 100644
--- a/services/media_session/media_controller.h
+++ b/services/media_session/media_controller.h
@@ -31,6 +31,8 @@
   void Resume() override;
   void ToggleSuspendResume() override;
   void AddObserver(mojom::MediaSessionObserverPtr) override;
+  void PreviousTrack() override;
+  void NextTrack() override;
 
   // mojom::MediaSessionObserver overrides.
   void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr) override;
diff --git a/services/media_session/media_controller_unittest.cc b/services/media_session/media_controller_unittest.cc
index dc3d1f1..f29b19b 100644
--- a/services/media_session/media_controller_unittest.cc
+++ b/services/media_session/media_controller_unittest.cc
@@ -276,4 +276,38 @@
   }
 }
 
+TEST_F(MediaControllerTest, ActiveController_PreviousTrack) {
+  test::MockMediaSession media_session;
+  EXPECT_EQ(0, media_session.prev_track_count());
+
+  {
+    test::MockMediaSessionMojoObserver observer(media_session);
+    RequestAudioFocus(media_session);
+    observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
+    EXPECT_EQ(0, media_session.prev_track_count());
+  }
+
+  controller()->PreviousTrack();
+  controller().FlushForTesting();
+
+  EXPECT_EQ(1, media_session.prev_track_count());
+}
+
+TEST_F(MediaControllerTest, ActiveController_NextTrack) {
+  test::MockMediaSession media_session;
+  EXPECT_EQ(0, media_session.next_track_count());
+
+  {
+    test::MockMediaSessionMojoObserver observer(media_session);
+    RequestAudioFocus(media_session);
+    observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
+    EXPECT_EQ(0, media_session.next_track_count());
+  }
+
+  controller()->NextTrack();
+  controller().FlushForTesting();
+
+  EXPECT_EQ(1, media_session.next_track_count());
+}
+
 }  // namespace media_session
diff --git a/services/media_session/mock_media_session.cc b/services/media_session/mock_media_session.cc
index 5ffed7c..783f152e 100644
--- a/services/media_session/mock_media_session.cc
+++ b/services/media_session/mock_media_session.cc
@@ -102,6 +102,14 @@
   std::move(callback).Run(std::move(debug_info));
 }
 
+void MockMediaSession::PreviousTrack() {
+  prev_track_count_++;
+}
+
+void MockMediaSession::NextTrack() {
+  next_track_count_++;
+}
+
 void MockMediaSession::Stop() {
   SetState(mojom::MediaSessionInfo::SessionState::kInactive);
 }
diff --git a/services/media_session/mock_media_session.h b/services/media_session/mock_media_session.h
index 6210526..90e622e 100644
--- a/services/media_session/mock_media_session.h
+++ b/services/media_session/mock_media_session.h
@@ -63,6 +63,8 @@
   void GetMediaSessionInfo(GetMediaSessionInfoCallback) override;
   void AddObserver(mojom::MediaSessionObserverPtr) override;
   void GetDebugInfo(GetDebugInfoCallback) override;
+  void PreviousTrack() override;
+  void NextTrack() override;
 
   void Stop();
 
@@ -80,6 +82,9 @@
   }
   void FlushForTesting();
 
+  int prev_track_count() const { return prev_track_count_; }
+  int next_track_count() const { return next_track_count_; }
+
  private:
   void SetState(mojom::MediaSessionInfo::SessionState);
   void NotifyObservers();
@@ -90,6 +95,9 @@
   const bool force_duck_ = false;
   bool is_ducking_ = false;
 
+  int prev_track_count_ = 0;
+  int next_track_count_ = 0;
+
   mojom::MediaSessionInfo::SessionState state_ =
       mojom::MediaSessionInfo::SessionState::kInactive;
 
diff --git a/services/media_session/public/cpp/test/test_media_controller.cc b/services/media_session/public/cpp/test/test_media_controller.cc
index f00ead8..300cff2 100644
--- a/services/media_session/public/cpp/test/test_media_controller.cc
+++ b/services/media_session/public/cpp/test/test_media_controller.cc
@@ -21,5 +21,13 @@
   ++toggle_suspend_resume_count_;
 }
 
+void TestMediaController::PreviousTrack() {
+  ++previous_track_count_;
+}
+
+void TestMediaController::NextTrack() {
+  ++next_track_count_;
+}
+
 }  // namespace test
 }  // namespace media_session
diff --git a/services/media_session/public/cpp/test/test_media_controller.h b/services/media_session/public/cpp/test/test_media_controller.h
index 86f5b22..917ab78 100644
--- a/services/media_session/public/cpp/test/test_media_controller.h
+++ b/services/media_session/public/cpp/test/test_media_controller.h
@@ -26,13 +26,20 @@
   void Resume() override {}
   void ToggleSuspendResume() override;
   void AddObserver(mojom::MediaSessionObserverPtr) override {}
+  void PreviousTrack() override;
+  void NextTrack() override;
 
   int toggle_suspend_resume_count() const {
     return toggle_suspend_resume_count_;
   }
 
+  int previous_track_count() const { return previous_track_count_; }
+  int next_track_count() const { return next_track_count_; }
+
  private:
   int toggle_suspend_resume_count_ = 0;
+  int previous_track_count_ = 0;
+  int next_track_count_ = 0;
 
   mojo::Binding<mojom::MediaController> binding_{this};
 
diff --git a/services/media_session/public/mojom/media_controller.mojom b/services/media_session/public/mojom/media_controller.mojom
index 70ffdd4..13c9df3 100644
--- a/services/media_session/public/mojom/media_controller.mojom
+++ b/services/media_session/public/mojom/media_controller.mojom
@@ -24,4 +24,10 @@
   // If the active session changes then observers do not need to be readded.
   // Adding the observer will update the observer with the latest state.
   AddObserver(MediaSessionObserver observer);
+
+  // Skip to the previous track.
+  PreviousTrack();
+
+  // Skip to the next track.
+  NextTrack();
 };
diff --git a/services/media_session/public/mojom/media_session.mojom b/services/media_session/public/mojom/media_session.mojom
index 4c60a20e..e82b617 100644
--- a/services/media_session/public/mojom/media_session.mojom
+++ b/services/media_session/public/mojom/media_session.mojom
@@ -65,7 +65,7 @@
 // WebContents or ARC app.
 // TODO(https://crbug.com/875004): migrate media session from content/public
 // to mojo.
-// Next Method ID: 6
+// Next Method ID: 9
 interface MediaSession {
   [Extensible]
   enum SuspendType {
@@ -100,4 +100,10 @@
   Resume@5(SuspendType suspend_type);
 
   AddObserver@6(MediaSessionObserver observer);
+
+  // Skip to the previous track.
+  PreviousTrack@7();
+
+  // Skip to the next track.
+  NextTrack@8();
 };
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
index 0eb900a..f7bec193 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -178,7 +178,7 @@
 
     int name_index = 0;
     int category_name_index = 0;
-    int arg_name_indices[base::trace_event::TraceArguments::kMaxSize] = {0};
+    int arg_name_indices[base::trace_event::kTraceMaxNumArgs] = {0};
 
     // Populate any new string table parts first; has to be done before
     // the add_trace_events() call (as the string table is part of the outer
@@ -192,7 +192,8 @@
       category_name_index = GetStringTableIndexForString(
           TraceLog::GetCategoryGroupName(trace_event.category_group_enabled()));
 
-      for (size_t i = 0; i < trace_event.arg_size() && trace_event.arg_name(i);
+      for (int i = 0;
+           i < base::trace_event::kTraceMaxNumArgs && trace_event.arg_name(i);
            ++i) {
         arg_name_indices[i] =
             GetStringTableIndexForString(trace_event.arg_name(i));
@@ -237,7 +238,8 @@
     char phase = trace_event.phase();
     new_trace_event->set_phase(phase);
 
-    for (size_t i = 0; i < trace_event.arg_size() && trace_event.arg_name(i);
+    for (int i = 0;
+         i < base::trace_event::kTraceMaxNumArgs && trace_event.arg_name(i);
          ++i) {
       auto type = trace_event.arg_type(i);
       auto* new_arg = new_trace_event->add_args();
diff --git a/services/viz/public/cpp/compositing/render_pass_struct_traits.cc b/services/viz/public/cpp/compositing/render_pass_struct_traits.cc
index 5fe24d1b..f7c3d29 100644
--- a/services/viz/public/cpp/compositing/render_pass_struct_traits.cc
+++ b/services/viz/public/cpp/compositing/render_pass_struct_traits.cc
@@ -21,7 +21,7 @@
       !data.ReadDamageRect(&(*out)->damage_rect) ||
       !data.ReadTransformToRootTarget(&(*out)->transform_to_root_target) ||
       !data.ReadFilters(&(*out)->filters) ||
-      !data.ReadBackgroundFilters(&(*out)->background_filters) ||
+      !data.ReadBackdropFilters(&(*out)->backdrop_filters) ||
       !data.ReadColorSpace(&(*out)->color_space) ||
       !data.ReadCopyRequests(&(*out)->copy_requests)) {
     return false;
diff --git a/services/viz/public/cpp/compositing/render_pass_struct_traits.h b/services/viz/public/cpp/compositing/render_pass_struct_traits.h
index a7e871d..47996a7 100644
--- a/services/viz/public/cpp/compositing/render_pass_struct_traits.h
+++ b/services/viz/public/cpp/compositing/render_pass_struct_traits.h
@@ -45,9 +45,9 @@
     return input->filters;
   }
 
-  static const cc::FilterOperations& background_filters(
+  static const cc::FilterOperations& backdrop_filters(
       const std::unique_ptr<viz::RenderPass>& input) {
-    return input->background_filters;
+    return input->backdrop_filters;
   }
 
   static const gfx::ColorSpace& color_space(
diff --git a/services/viz/public/cpp/compositing/struct_traits_unittest.cc b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
index e33415f..fdc693e 100644
--- a/services/viz/public/cpp/compositing/struct_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
@@ -719,10 +719,10 @@
   cc::FilterOperations filters;
   filters.Append(cc::FilterOperation::CreateBlurFilter(0.f));
   filters.Append(cc::FilterOperation::CreateZoomFilter(2.0f, 1));
-  cc::FilterOperations background_filters;
-  background_filters.Append(cc::FilterOperation::CreateSaturateFilter(4.f));
-  background_filters.Append(cc::FilterOperation::CreateZoomFilter(2.0f, 1));
-  background_filters.Append(cc::FilterOperation::CreateSaturateFilter(2.f));
+  cc::FilterOperations backdrop_filters;
+  backdrop_filters.Append(cc::FilterOperation::CreateSaturateFilter(4.f));
+  backdrop_filters.Append(cc::FilterOperation::CreateZoomFilter(2.0f, 1));
+  backdrop_filters.Append(cc::FilterOperation::CreateSaturateFilter(2.f));
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateXYZD50();
   const bool has_transparent_background = true;
   const bool cache_render_pass = true;
@@ -730,7 +730,7 @@
   const bool generate_mipmap = true;
   std::unique_ptr<RenderPass> input = RenderPass::Create();
   input->SetAll(render_pass_id, output_rect, damage_rect, transform_to_root,
-                filters, background_filters, color_space,
+                filters, backdrop_filters, color_space,
                 has_transparent_background, cache_render_pass,
                 has_damage_from_contributing_content, generate_mipmap);
   input->copy_requests.push_back(CopyOutputRequest::CreateStubForTesting());
@@ -791,7 +791,7 @@
   EXPECT_EQ(color_space, output->color_space);
   EXPECT_EQ(has_transparent_background, output->has_transparent_background);
   EXPECT_EQ(filters, output->filters);
-  EXPECT_EQ(background_filters, output->background_filters);
+  EXPECT_EQ(backdrop_filters, output->backdrop_filters);
   EXPECT_EQ(cache_render_pass, output->cache_render_pass);
   EXPECT_EQ(has_damage_from_contributing_content,
             output->has_damage_from_contributing_content);
diff --git a/services/viz/public/interfaces/compositing/render_pass.mojom b/services/viz/public/interfaces/compositing/render_pass.mojom
index af2b98c..283b0e1 100644
--- a/services/viz/public/interfaces/compositing/render_pass.mojom
+++ b/services/viz/public/interfaces/compositing/render_pass.mojom
@@ -18,7 +18,7 @@
   gfx.mojom.Rect damage_rect;
   gfx.mojom.Transform transform_to_root_target;
   FilterOperations filters;
-  FilterOperations background_filters;
+  FilterOperations backdrop_filters;
   gfx.mojom.ColorSpace color_space;
   bool has_transparent_background;
   bool cache_render_pass = false;
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index b8c2e5b..75316aa 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -160,6 +160,8 @@
 #define SK_SUPPORT_LEGACY_AAA_CHOICE
 #endif
 
+#define SK_LEGACY_SRGB_STAGE_CHOICE
+
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
 
 /* In some places Skia can use static initializers for global initialization,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index cb80b3c..25c6815 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -391,7 +391,6 @@
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
-        "experiment_percentage": 100,
         "isolate_name": "telemetry_unittests",
         "name": "telemetry_unittests",
         "swarming": {
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter b/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter
index afbb30a8..aab12681 100644
--- a/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter
+++ b/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter
@@ -138,9 +138,6 @@
 # Failing on ASAN bot. crbug.com/882631
 -ExtensionWebRequestApiTest.WebRequestTypes
 
-# Crashing flakily. https://crbug.com/883371
--ExtensionDisabledGlobalErrorTest.UninstallWhilePromptBeingShown
-
 # Flaky on ASAN bot. crbug.com/884216
 -KeyboardOverlayUIBrowserTest.*
 
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.interactive_ui_tests.filter b/testing/buildbot/filters/chromeos.single_process_mash.interactive_ui_tests.filter
index 0be7bd78..95dc5da 100644
--- a/testing/buildbot/filters/chromeos.single_process_mash.interactive_ui_tests.filter
+++ b/testing/buildbot/filters/chromeos.single_process_mash.interactive_ui_tests.filter
@@ -8,9 +8,6 @@
 # ChromeOS.
 -BrowserKeyEventsTest.AccessKeys
 
-# misc.
--DevToolsManagerDelegateTest.ShowMinimizedWindow
-
 # Broken tests related to accessibility. crbug.com/888750 and crbug.com/889093
 -GuestSpokenFeedbackTest.FocusToolbar
 -SelectToSpeakTest.ActivatesWithTapOnSelectToSpeakTray
@@ -41,7 +38,6 @@
 -TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/1
 
 # TabDragging: crbug.com/890071
--DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest.CancelDragTabToWindowIn1stDisplay
 -TabDragging/DetachToBrowserInSeparateDisplayTabDragControllerTest.DragBrowserWindowWhenMajorityOfBoundsInSecondDisplay/0
 -TabDragging/DetachToBrowserTabDragControllerTest.DeferredTargetTabStripTest/1
 -TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/1
diff --git a/testing/buildbot/generate_buildbot_json_coveragetest.py b/testing/buildbot/generate_buildbot_json_coveragetest.py
index dc542ccb..077ac1b 100755
--- a/testing/buildbot/generate_buildbot_json_coveragetest.py
+++ b/testing/buildbot/generate_buildbot_json_coveragetest.py
@@ -19,8 +19,8 @@
   cov = coverage.coverage(include='*generate_buildbot_json.py')
   cov.start()
   import generate_buildbot_json_unittest
-  suite = unittest.TestLoader().loadTestsFromTestCase(
-    generate_buildbot_json_unittest.UnitTest)
+  suite = unittest.TestLoader().loadTestsFromModule(
+    generate_buildbot_json_unittest)
   unittest.TextTestRunner(stream=FakeStream()).run(suite)
   cov.stop()
   outf = cStringIO.StringIO()
diff --git a/testing/buildbot/generate_buildbot_json_unittest.py b/testing/buildbot/generate_buildbot_json_unittest.py
index 09da7b92..d50b045 100755
--- a/testing/buildbot/generate_buildbot_json_unittest.py
+++ b/testing/buildbot/generate_buildbot_json_unittest.py
@@ -124,165 +124,6 @@
 ]
 """
 
-FOO_GTESTS_WATERFALL_MIXIN_WATERFALL = """\
-[
-  {
-    'mixins': ['waterfall_mixin'],
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'swarming': {},
-        'test_suites': {
-          'gtest_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
-
-FOO_GTESTS_BUILDER_MIXIN_WATERFALL = """\
-[
-  {
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'mixins': ['builder_mixin'],
-        'swarming': {},
-        'test_suites': {
-          'gtest_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
-
-FOO_GTESTS_BUILDER_MIXIN_NON_SWARMING_WATERFALL = """\
-[
-  {
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'mixins': ['random_mixin'],
-        'swarming': {},
-        'test_suites': {
-          'gtest_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
-
-FOO_GTESTS_DIMENSIONS_MIXIN_WATERFALL = """\
-[
-  {
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'mixins': ['dimension_mixin'],
-        'swarming': {},
-        'test_suites': {
-          'gtest_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
-
-FOO_GPU_TELEMETRY_TEST_DIMENSIONS_WATERFALL = """\
-[
-  {
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'mixins': ['dimension_mixin'],
-        'os_type': 'win',
-        'browser_config': 'release',
-        'test_suites': {
-          'gpu_telemetry_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
-
-# Swarming mixins must be a list, a single string is not allowed.
-FOO_GTESTS_INVALID_LIST_MIXIN_WATERFALL = """\
-[
-  {
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'mixins': 'dimension_mixin',
-        'swarming': {},
-        'test_suites': {
-          'gtest_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
-FOO_GTESTS_INVALID_NOTFOUND_MIXIN_WATERFALL = """\
-[
-  {
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'mixins': ['nonexistant'],
-        'swarming': {},
-        'test_suites': {
-          'gtest_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
-
-FOO_GTESTS_TEST_MIXIN_WATERFALL = """\
-[
-  {
-    'mixins': ['waterfall_mixin'],
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'swarming': {},
-        'test_suites': {
-          'gtest_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
-
-FOO_GTESTS_SORTING_MIXINS_WATERFALL = """\
-[
-  {
-    'mixins': ['a_mixin', 'b_mixin', 'c_mixin'],
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'kvm': '1',
-            },
-          ],
-        },
-        'test_suites': {
-          'gtest_tests': 'foo_tests',
-        },
-      },
-    },
-  },
-]
-"""
 
 FOO_LINUX_GTESTS_WATERFALL = """\
 [
@@ -393,22 +234,6 @@
 ]
 """
 
-FOO_CTS_WATERFALL_MIXINS = """\
-[
-  {
-    'name': 'chromium.test',
-    'machines': {
-      'Fake Tester': {
-        'mixins': ['test_mixin'],
-        'test_suites': {
-          'cts_tests': 'foo_cts_tests',
-        },
-      },
-    },
-  },
-]
-"""
-
 FOO_INSTRUMENTATION_TEST_WATERFALL = """\
 [
   {
@@ -619,25 +444,6 @@
 }
 """
 
-FOO_TEST_SUITE_WITH_MIXIN = """\
-{
-  'basic_suites': {
-    'foo_tests': {
-      'foo_test': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'integrity': 'high',
-            }
-          ],
-          'expiration': 120,
-        },
-        'mixins': ['test_mixin'],
-      },
-    },
-  },
-}
-"""
 
 FOO_SCRIPT_SUITE = """\
 {
@@ -1393,152 +1199,6 @@
 }
 """
 
-WATERFALL_MIXIN_WATERFALL_OUTPUT = """\
-{
-  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
-  "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "Fake Tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ],
-          "expiration": 120,
-          "value": "waterfall"
-        },
-        "test": "foo_test"
-      }
-    ]
-  }
-}
-"""
-
-WATERFALL_MIXIN_WATERFALL_EXCEPTION_OUTPUT = """\
-{
-  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
-  "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "Fake Tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ],
-          "expiration": 120,
-          "value": "exception"
-        },
-        "test": "foo_test"
-      }
-    ]
-  }
-}
-"""
-
-BUILDER_MIXIN_WATERFALL_OUTPUT = """\
-{
-  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
-  "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "Fake Tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ],
-          "expiration": 120,
-          "value": "builder"
-        },
-        "test": "foo_test"
-      }
-    ]
-  }
-}
-"""
-
-BUILDER_MIXIN_NON_SWARMING_WATERFALL_OUTPUT = """\
-{
-  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
-  "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "Fake Tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ],
-          "expiration": 120
-        },
-        "test": "foo_test",
-        "value": "random"
-      }
-    ]
-  }
-}
-"""
-
-TEST_MIXIN_WATERFALL_OUTPUT = """\
-{
-  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
-  "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "Fake Tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high",
-              "kvm": "1"
-            }
-          ],
-          "expiration": 120,
-          "value": "test"
-        },
-        "test": "foo_test"
-      }
-    ]
-  }
-}
-"""
-
-DIMENSIONS_MIXIN_WATERFALL_OUTPUT = """\
-{
-  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
-  "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "Fake Tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "iama": "mixin",
-              "integrity": "high"
-            }
-          ],
-          "expiration": 120,
-          "value": "test"
-        },
-        "test": "foo_test"
-      }
-    ]
-  }
-}
-"""
-
 GPU_DIMENSIONS_WATERFALL_OUTPUT = """\
 {
   "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
@@ -1591,77 +1251,6 @@
 }
 """
 
-# These mixins are invalid; if passed to check_input_file_consistency, they will
-# fail. These are used for output file consistency checks.
-SWARMING_MIXINS = """\
-{
-  'builder_mixin': {
-    'swarming': {
-      'value': 'builder',
-    },
-  },
-  'dimension_mixin': {
-    'swarming': {
-      'dimensions': {
-        'iama': 'mixin',
-      },
-    },
-  },
-  'random_mixin': {
-    'value': 'random',
-  },
-  'test_mixin': {
-    'swarming': {
-      'value': 'test',
-    },
-  },
-  'waterfall_mixin': {
-    'swarming': {
-      'value': 'waterfall',
-    },
-  },
-}
-"""
-
-SWARMING_MIXINS_DUPLICATED = """\
-{
-  'builder_mixin': {
-    'value': 'builder',
-  },
-  'builder_mixin': {
-    'value': 'builder',
-  },
-}
-"""
-
-SWARMING_MIXINS_UNSORTED = """\
-{
-  'b_mixin': {
-    'b': 'b',
-  },
-  'a_mixin': {
-    'a': 'a',
-  },
-  'c_mixin': {
-    'c': 'c',
-  },
-}
-"""
-
-SWARMING_MIXINS_SORTED = """\
-{
-  'a_mixin': {
-    'a': 'a',
-  },
-  'b_mixin': {
-    'b': 'b',
-  },
-  'c_mixin': {
-    'c': 'c',
-  },
-}
-"""
-
 TEST_SUITE_SORTING_WATERFALL = """
 [
   {
@@ -2247,145 +1836,6 @@
       fbb.check_input_file_consistency(verbose=True)
     self.assertFalse(fbb.printed_lines)
 
-  def test_mixins_waterfall(self):
-    fbb = FakeBBGen(FOO_GTESTS_WATERFALL_MIXIN_WATERFALL,
-                    FOO_TEST_SUITE,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = WATERFALL_MIXIN_WATERFALL_OUTPUT
-    fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_waterfall_exception_overrides(self):
-    fbb = FakeBBGen(FOO_GTESTS_WATERFALL_MIXIN_WATERFALL,
-                    FOO_TEST_SUITE,
-                    SCRIPT_WITH_ARGS_SWARMING_EXCEPTIONS,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = WATERFALL_MIXIN_WATERFALL_EXCEPTION_OUTPUT
-    fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_builder(self):
-    fbb = FakeBBGen(FOO_GTESTS_BUILDER_MIXIN_WATERFALL,
-                    FOO_TEST_SUITE,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = BUILDER_MIXIN_WATERFALL_OUTPUT
-    fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_builder_non_swarming(self):
-    fbb = FakeBBGen(FOO_GTESTS_BUILDER_MIXIN_NON_SWARMING_WATERFALL,
-                    FOO_TEST_SUITE,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = (
-        BUILDER_MIXIN_NON_SWARMING_WATERFALL_OUTPUT)
-    fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_test(self):
-    fbb = FakeBBGen(FOO_GTESTS_WATERFALL,
-                    FOO_TEST_SUITE_WITH_MIXIN,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = TEST_MIXIN_WATERFALL_OUTPUT
-    fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_dimension(self):
-    fbb = FakeBBGen(FOO_GTESTS_DIMENSIONS_MIXIN_WATERFALL,
-                    FOO_TEST_SUITE_WITH_MIXIN,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = DIMENSIONS_MIXIN_WATERFALL_OUTPUT
-    fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_dimension_gpu(self):
-    fbb = FakeBBGen(FOO_GPU_TELEMETRY_TEST_DIMENSIONS_WATERFALL,
-                    FOO_TEST_SUITE_WITH_MIXIN,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = GPU_DIMENSIONS_WATERFALL_OUTPUT
-    fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_unreferenced(self):
-    fbb = FakeBBGen(FOO_GTESTS_WATERFALL,
-                    FOO_TEST_SUITE_WITH_MIXIN,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    with self.assertRaisesRegexp(generate_buildbot_json.BBGenErr,
-                                 '.*mixins are unreferenced.*'):
-      fbb.check_input_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_cts(self):
-    fbb = FakeBBGen(FOO_CTS_WATERFALL_MIXINS,
-                    FOO_CTS_SUITE ,
-                    EMPTY_PYL_FILE,
-                    EMPTY_PYL_FILE,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = CTS_OUTPUT
-    fbb.check_input_file_consistency(verbose=True)
-    fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_unused(self):
-    fbb = FakeBBGen(FOO_GTESTS_INVALID_NOTFOUND_MIXIN_WATERFALL,
-                    FOO_TEST_SUITE_WITH_MIXIN,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = DIMENSIONS_MIXIN_WATERFALL_OUTPUT
-    with self.assertRaises(generate_buildbot_json.BBGenErr):
-      fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_list(self):
-    fbb = FakeBBGen(FOO_GTESTS_INVALID_LIST_MIXIN_WATERFALL,
-                    FOO_TEST_SUITE_WITH_MIXIN,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS,
-                    LUCI_MILO_CFG)
-    fbb.files['chromium.test.json'] = DIMENSIONS_MIXIN_WATERFALL_OUTPUT
-    with self.assertRaises(generate_buildbot_json.BBGenErr):
-      fbb.check_output_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-  def test_mixins_must_be_sorted(self):
-    fbb = FakeBBGen(FOO_GTESTS_SORTING_MIXINS_WATERFALL,
-                    FOO_TEST_SUITE,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS_SORTED,
-                    LUCI_MILO_CFG)
-    fbb.check_input_file_consistency(verbose=True)
-    self.assertFalse(fbb.printed_lines)
-
-    fbb = FakeBBGen(FOO_GTESTS_SORTING_MIXINS_WATERFALL,
-                    FOO_TEST_SUITE,
-                    EMPTY_PYL_FILE,
-                    SWARMING_MIXINS_UNSORTED,
-                    LUCI_MILO_CFG)
-    with self.assertRaises(generate_buildbot_json.BBGenErr):
-      fbb.check_input_file_consistency(verbose=True)
-    joined_lines = ' '.join(fbb.printed_lines)
-    self.assertRegexpMatches(
-        joined_lines, '.*\+._mixin.*')
-    self.assertRegexpMatches(
-        joined_lines, '.*\-._mixin.*')
-    fbb.printed_lines = []
-    self.assertFalse(fbb.printed_lines)
-
   def test_waterfalls_must_be_sorted(self):
     fbb = FakeBBGen(TEST_SUITE_SORTED_WATERFALL,
                     TEST_SUITE_SORTED,
@@ -2482,7 +1932,563 @@
       fbb.printed_lines = []
       self.assertFalse(fbb.printed_lines)
 
-  def test_mixins_no_duplicate_keys(self):
+
+FOO_GTESTS_WATERFALL_MIXIN_WATERFALL = """\
+[
+  {
+    'mixins': ['waterfall_mixin'],
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'swarming': {},
+        'test_suites': {
+          'gtest_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+FOO_GTESTS_BUILDER_MIXIN_WATERFALL = """\
+[
+  {
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'mixins': ['builder_mixin'],
+        'swarming': {},
+        'test_suites': {
+          'gtest_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+FOO_GTESTS_BUILDER_MIXIN_NON_SWARMING_WATERFALL = """\
+[
+  {
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'mixins': ['random_mixin'],
+        'swarming': {},
+        'test_suites': {
+          'gtest_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+FOO_GTESTS_DIMENSIONS_MIXIN_WATERFALL = """\
+[
+  {
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'mixins': ['dimension_mixin'],
+        'swarming': {},
+        'test_suites': {
+          'gtest_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+FOO_GPU_TELEMETRY_TEST_DIMENSIONS_WATERFALL = """\
+[
+  {
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'mixins': ['dimension_mixin'],
+        'os_type': 'win',
+        'browser_config': 'release',
+        'test_suites': {
+          'gpu_telemetry_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+# Swarming mixins must be a list, a single string is not allowed.
+FOO_GTESTS_INVALID_LIST_MIXIN_WATERFALL = """\
+[
+  {
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'mixins': 'dimension_mixin',
+        'swarming': {},
+        'test_suites': {
+          'gtest_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+FOO_GTESTS_INVALID_NOTFOUND_MIXIN_WATERFALL = """\
+[
+  {
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'mixins': ['nonexistant'],
+        'swarming': {},
+        'test_suites': {
+          'gtest_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+FOO_GTESTS_TEST_MIXIN_WATERFALL = """\
+[
+  {
+    'mixins': ['waterfall_mixin'],
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'swarming': {},
+        'test_suites': {
+          'gtest_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+FOO_GTESTS_SORTING_MIXINS_WATERFALL = """\
+[
+  {
+    'mixins': ['a_mixin', 'b_mixin', 'c_mixin'],
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'swarming': {
+          'dimension_sets': [
+            {
+              'kvm': '1',
+            },
+          ],
+        },
+        'test_suites': {
+          'gtest_tests': 'foo_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+FOO_TEST_SUITE_WITH_MIXIN = """\
+{
+  'basic_suites': {
+    'foo_tests': {
+      'foo_test': {
+        'swarming': {
+          'dimension_sets': [
+            {
+              'integrity': 'high',
+            }
+          ],
+          'expiration': 120,
+        },
+        'mixins': ['test_mixin'],
+      },
+    },
+  },
+}
+"""
+
+# These mixins are invalid; if passed to check_input_file_consistency, they will
+# fail. These are used for output file consistency checks.
+SWARMING_MIXINS = """\
+{
+  'builder_mixin': {
+    'swarming': {
+      'value': 'builder',
+    },
+  },
+  'dimension_mixin': {
+    'swarming': {
+      'dimensions': {
+        'iama': 'mixin',
+      },
+    },
+  },
+  'random_mixin': {
+    'value': 'random',
+  },
+  'test_mixin': {
+    'swarming': {
+      'value': 'test',
+    },
+  },
+  'waterfall_mixin': {
+    'swarming': {
+      'value': 'waterfall',
+    },
+  },
+}
+"""
+
+SWARMING_MIXINS_DUPLICATED = """\
+{
+  'builder_mixin': {
+    'value': 'builder',
+  },
+  'builder_mixin': {
+    'value': 'builder',
+  },
+}
+"""
+
+SWARMING_MIXINS_UNSORTED = """\
+{
+  'b_mixin': {
+    'b': 'b',
+  },
+  'a_mixin': {
+    'a': 'a',
+  },
+  'c_mixin': {
+    'c': 'c',
+  },
+}
+"""
+
+SWARMING_MIXINS_SORTED = """\
+{
+  'a_mixin': {
+    'a': 'a',
+  },
+  'b_mixin': {
+    'b': 'b',
+  },
+  'c_mixin': {
+    'c': 'c',
+  },
+}
+"""
+
+FOO_CTS_WATERFALL_MIXINS = """\
+[
+  {
+    'name': 'chromium.test',
+    'machines': {
+      'Fake Tester': {
+        'mixins': ['test_mixin'],
+        'test_suites': {
+          'cts_tests': 'foo_cts_tests',
+        },
+      },
+    },
+  },
+]
+"""
+
+WATERFALL_MIXIN_WATERFALL_OUTPUT = """\
+{
+  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
+  "AAAAA2 See generate_buildbot_json.py to make changes": {},
+  "Fake Tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "integrity": "high"
+            }
+          ],
+          "expiration": 120,
+          "value": "waterfall"
+        },
+        "test": "foo_test"
+      }
+    ]
+  }
+}
+"""
+
+WATERFALL_MIXIN_WATERFALL_EXCEPTION_OUTPUT = """\
+{
+  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
+  "AAAAA2 See generate_buildbot_json.py to make changes": {},
+  "Fake Tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "integrity": "high"
+            }
+          ],
+          "expiration": 120,
+          "value": "exception"
+        },
+        "test": "foo_test"
+      }
+    ]
+  }
+}
+"""
+
+BUILDER_MIXIN_WATERFALL_OUTPUT = """\
+{
+  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
+  "AAAAA2 See generate_buildbot_json.py to make changes": {},
+  "Fake Tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "integrity": "high"
+            }
+          ],
+          "expiration": 120,
+          "value": "builder"
+        },
+        "test": "foo_test"
+      }
+    ]
+  }
+}
+"""
+
+BUILDER_MIXIN_NON_SWARMING_WATERFALL_OUTPUT = """\
+{
+  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
+  "AAAAA2 See generate_buildbot_json.py to make changes": {},
+  "Fake Tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "integrity": "high"
+            }
+          ],
+          "expiration": 120
+        },
+        "test": "foo_test",
+        "value": "random"
+      }
+    ]
+  }
+}
+"""
+
+TEST_MIXIN_WATERFALL_OUTPUT = """\
+{
+  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
+  "AAAAA2 See generate_buildbot_json.py to make changes": {},
+  "Fake Tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "integrity": "high",
+              "kvm": "1"
+            }
+          ],
+          "expiration": 120,
+          "value": "test"
+        },
+        "test": "foo_test"
+      }
+    ]
+  }
+}
+"""
+
+DIMENSIONS_MIXIN_WATERFALL_OUTPUT = """\
+{
+  "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
+  "AAAAA2 See generate_buildbot_json.py to make changes": {},
+  "Fake Tester": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "iama": "mixin",
+              "integrity": "high"
+            }
+          ],
+          "expiration": 120,
+          "value": "test"
+        },
+        "test": "foo_test"
+      }
+    ]
+  }
+}
+"""
+
+class MixinTests(unittest.TestCase):
+  """Tests for the mixins feature."""
+  def test_mixins_must_be_sorted(self):
+    fbb = FakeBBGen(FOO_GTESTS_SORTING_MIXINS_WATERFALL,
+                    FOO_TEST_SUITE,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS_SORTED,
+                    LUCI_MILO_CFG)
+    fbb.check_input_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+    fbb = FakeBBGen(FOO_GTESTS_SORTING_MIXINS_WATERFALL,
+                    FOO_TEST_SUITE,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS_UNSORTED,
+                    LUCI_MILO_CFG)
+    with self.assertRaises(generate_buildbot_json.BBGenErr):
+      fbb.check_input_file_consistency(verbose=True)
+    joined_lines = ' '.join(fbb.printed_lines)
+    self.assertRegexpMatches(
+        joined_lines, '.*\+._mixin.*')
+    self.assertRegexpMatches(
+        joined_lines, '.*\-._mixin.*')
+    fbb.printed_lines = []
+    self.assertFalse(fbb.printed_lines)
+
+  def test_waterfall(self):
+    fbb = FakeBBGen(FOO_GTESTS_WATERFALL_MIXIN_WATERFALL,
+                    FOO_TEST_SUITE,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = WATERFALL_MIXIN_WATERFALL_OUTPUT
+    fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_waterfall_exception_overrides(self):
+    fbb = FakeBBGen(FOO_GTESTS_WATERFALL_MIXIN_WATERFALL,
+                    FOO_TEST_SUITE,
+                    SCRIPT_WITH_ARGS_SWARMING_EXCEPTIONS,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = WATERFALL_MIXIN_WATERFALL_EXCEPTION_OUTPUT
+    fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_builder(self):
+    fbb = FakeBBGen(FOO_GTESTS_BUILDER_MIXIN_WATERFALL,
+                    FOO_TEST_SUITE,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = BUILDER_MIXIN_WATERFALL_OUTPUT
+    fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_builder_non_swarming(self):
+    fbb = FakeBBGen(FOO_GTESTS_BUILDER_MIXIN_NON_SWARMING_WATERFALL,
+                    FOO_TEST_SUITE,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = (
+        BUILDER_MIXIN_NON_SWARMING_WATERFALL_OUTPUT)
+    fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_test_suite(self):
+    fbb = FakeBBGen(FOO_GTESTS_WATERFALL,
+                    FOO_TEST_SUITE_WITH_MIXIN,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = TEST_MIXIN_WATERFALL_OUTPUT
+    fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_dimension(self):
+    fbb = FakeBBGen(FOO_GTESTS_DIMENSIONS_MIXIN_WATERFALL,
+                    FOO_TEST_SUITE_WITH_MIXIN,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = DIMENSIONS_MIXIN_WATERFALL_OUTPUT
+    fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_dimension_gpu(self):
+    fbb = FakeBBGen(FOO_GPU_TELEMETRY_TEST_DIMENSIONS_WATERFALL,
+                    FOO_TEST_SUITE_WITH_MIXIN,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = GPU_DIMENSIONS_WATERFALL_OUTPUT
+    fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_unreferenced(self):
+    fbb = FakeBBGen(FOO_GTESTS_WATERFALL,
+                    FOO_TEST_SUITE_WITH_MIXIN,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    with self.assertRaisesRegexp(generate_buildbot_json.BBGenErr,
+                                 '.*mixins are unreferenced.*'):
+      fbb.check_input_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_cts(self):
+    fbb = FakeBBGen(FOO_CTS_WATERFALL_MIXINS,
+                    FOO_CTS_SUITE ,
+                    EMPTY_PYL_FILE,
+                    EMPTY_PYL_FILE,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = CTS_OUTPUT
+    fbb.check_input_file_consistency(verbose=True)
+    fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_unused(self):
+    fbb = FakeBBGen(FOO_GTESTS_INVALID_NOTFOUND_MIXIN_WATERFALL,
+                    FOO_TEST_SUITE_WITH_MIXIN,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = DIMENSIONS_MIXIN_WATERFALL_OUTPUT
+    with self.assertRaises(generate_buildbot_json.BBGenErr):
+      fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+  def test_list(self):
+    fbb = FakeBBGen(FOO_GTESTS_INVALID_LIST_MIXIN_WATERFALL,
+                    FOO_TEST_SUITE_WITH_MIXIN,
+                    EMPTY_PYL_FILE,
+                    SWARMING_MIXINS,
+                    LUCI_MILO_CFG)
+    fbb.files['chromium.test.json'] = DIMENSIONS_MIXIN_WATERFALL_OUTPUT
+    with self.assertRaises(generate_buildbot_json.BBGenErr):
+      fbb.check_output_file_consistency(verbose=True)
+    self.assertFalse(fbb.printed_lines)
+
+
+  def test_no_duplicate_keys(self):
     fbb = FakeBBGen(FOO_GTESTS_BUILDER_MIXIN_WATERFALL,
                     FOO_TEST_SUITE,
                     EMPTY_PYL_FILE,
@@ -2525,6 +2531,5 @@
         ])
 
 
-
 if __name__ == '__main__':
   unittest.main()
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 1a682e1..6ee9c22 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -24,11 +24,11 @@
 # needs to be; valid values are:
 #
 #  "windowed_test_launcher"
-#  : the test is a gtest-based test that uses the "brave-new-test-launcher"
+#  : the test is a gtest-based test that uses the parallelizing TestLauncher
 #    from //base/test:test_support and needs to run under Xvfb if run on
 #    some platforms (eg. Linux Desktop and Ozone CrOS).
 #  "console_test_launcher"
-#  : the test is a gtest-based test that uses the "brave-new-test-launcher"
+#  : the test is a gtest-based test that uses the parallelizing TestLauncher
 #    from //base/test:test_support but does not need Xvfb.
 #  "additional_compile_target"
 #  : this isn't actually a test, but we still need a mapping from the
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 3a017468..72ac806 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -479,8 +479,6 @@
           '--remote=127.0.0.1',
           '--remote-ssh-port=9222',
         ],
-        # TODO(crbug.com/876494): Move this out of experimental.
-        'experiment_percentage': 100,
         'swarming': {
           'hard_timeout': 1200,
           'idempotent': False,  # https://crbug.com/549140
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index 0a4e89f..1e81b89 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -426,19 +426,17 @@
   libfuzzer_options = [ "only_ascii=1" ]
 }
 
-if (!is_win) {
-  fuzzer_test("skia_image_filter_proto_fuzzer") {
-    sources = [
-      "skia_image_filter_proto_fuzzer.cc",
-    ]
+fuzzer_test("skia_image_filter_proto_fuzzer") {
+  sources = [
+    "skia_image_filter_proto_fuzzer.cc",
+  ]
 
-    deps = [
-      "//base",
-      "//base/test:test_support",
-      "//skia",
-      "//testing/libfuzzer/proto:skia_image_filter_converter",
-      "//testing/libfuzzer/proto:skia_image_filter_proto",
-      "//third_party/libprotobuf-mutator",
-    ]
-  }
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//skia",
+    "//testing/libfuzzer/proto:skia_image_filter_converter",
+    "//testing/libfuzzer/proto:skia_image_filter_proto",
+    "//third_party/libprotobuf-mutator",
+  ]
 }
diff --git a/testing/libfuzzer/proto/BUILD.gn b/testing/libfuzzer/proto/BUILD.gn
index 861e8e65..5e62020 100644
--- a/testing/libfuzzer/proto/BUILD.gn
+++ b/testing/libfuzzer/proto/BUILD.gn
@@ -36,34 +36,29 @@
   ]
 }
 
-if (!is_win) {
-  static_library("skia_image_filter_converter") {
-    sources = [
-      "skia_image_filter_proto_converter.cc",
-      "skia_image_filter_proto_converter.h",
-    ]
-    deps = [
-      ":skia_image_filter_proto",
-      "//base",
-      "//skia",
-      "//third_party/libprotobuf-mutator",
-    ]
-    defines = [ "AVOID_MISBEHAVIOR=1" ]
+static_library("skia_image_filter_converter") {
+  sources = [
+    "skia_image_filter_proto_converter.cc",
+    "skia_image_filter_proto_converter.h",
+  ]
+  deps = [
+    ":skia_image_filter_proto",
+    "//base",
+    "//skia",
+    "//third_party/libprotobuf-mutator",
+  ]
+  defines = [ "AVOID_MISBEHAVIOR=1" ]
+  testonly = true
 
-    testonly = true
-
-    #  Can't disable instrumentation because of container-overflow false
-    # positives.
-
-    # Assertion failures and integer oveflows in skia are uninteresting.
-    if (is_debug || is_ubsan) {
-      all_dependent_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
-    }
+  #  Can't disable instrumentation because of container-overflow false
+  # positives.
+  # Assertion failures and integer oveflows in skia are uninteresting.
+  if (is_debug || is_ubsan) {
+    all_dependent_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
   }
-
-  proto_library("skia_image_filter_proto") {
-    sources = [
-      "skia_image_filter.proto",
-    ]
-  }
+}
+proto_library("skia_image_filter_proto") {
+  sources = [
+    "skia_image_filter.proto",
+  ]
 }
diff --git a/testing/libfuzzer/proto/skia_image_filter_proto_converter.cc b/testing/libfuzzer/proto/skia_image_filter_proto_converter.cc
index 94cb29d0..6cb9c61 100644
--- a/testing/libfuzzer/proto/skia_image_filter_proto_converter.cc
+++ b/testing/libfuzzer/proto/skia_image_filter_proto_converter.cc
@@ -1027,7 +1027,7 @@
   flags |= (gradient_descriptor.tile_mode() << kTileModeShift_GSF);
   uint32_t grad_flags =
       (gradient_descriptor.grad_flags() % (kGradFlagsMask_GSF + 1));
-  CHECK_LE(grad_flags, kGradFlagsMask_GSF);
+  CHECK_LE(grad_flags, static_cast<uint32_t>(kGradFlagsMask_GSF));
   WriteNum(flags);
 
   const uint32_t count = gradient_descriptor.colors_size();
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index 15cc802..9bef153 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -103,8 +103,6 @@
 crbug.com/472330 fast/borders/border-image-outset-split-inline-vertical-lr.html [ Pass ]
 crbug.com/817175 compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Pass ]
 crbug.com/736052 compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ]
-# Link highlights are no longer affected by ancestor effects.
-crbug.com/857501 compositing/gestures/gesture-tapHighlight-with-filter.html [ Pass ]
 
 Bug(none) paint/invalidation/clip/clip-flex-text.html [ Pass Failure ]
 Bug(none) virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering.html [ Failure ]
@@ -766,18 +764,9 @@
 Bug(none) compositing/overflow/border-radius-composited-subframe.html [ Failure ]
 
 # Subpixel differences
-Bug(none) compositing/composited-scaled-child-with-border-radius-parent-clip.html [ Failure ]
-Bug(none) compositing/composited-translated-child-with-border-radius-parent-clip.html [ Failure ]
-Bug(none) compositing/overflow/border-radius-on-grandparent-composited-grandchild.html [ Failure ]
-Bug(none) compositing/overflow/border-radius-on-two-ancestors-composited-grandchild.html [ Failure ]
 Bug(none) compositing/overflow/border-radius-on-squashed-layers.html [ Failure ]
 Bug(none) compositing/overflow/border-radius-styles-with-composited-child.html [ Failure ]
-Bug(none) compositing/overflow/grandchild-composited-with-border-radius-ancestor.html [ Failure ]
-Bug(none) compositing/overflow/grandchild-with-border-radius-ancestor.html [ Failure ]
 Bug(none) compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline.html [ Failure ]
-Bug(none) compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped.html [ Failure ]
-Bug(none) compositing/overflow/siblings-composited-with-border-radius-ancestor.html [ Failure ]
-Bug(none) compositing/overflow/siblings-with-border-radius-ancestor.html [ Failure ]
 Bug(none) fast/canvas/canvas-composite-video-shadow.html [ Failure ]
 Bug(none) fast/scrolling/fractional-scroll-offset-fixed-position-non-composited.html [ Failure ]
 Bug(none) images/color-profile-mask-image-svg.html [ Failure ]
@@ -867,7 +856,6 @@
 crbug.com/654554 fast/forms/calendar-picker/calendar-picker-appearance-ru.html [ Failure ]
 crbug.com/654554 fast/forms/calendar-picker/calendar-picker-appearance-step.html [ Failure ]
 crbug.com/654554 fast/forms/calendar-picker/calendar-picker-appearance-zoom125.html [ Failure ]
-crbug.com/654554 fast/forms/calendar-picker/calendar-picker-appearance-zoom200.html [ Failure ]
 crbug.com/654554 fast/forms/calendar-picker/calendar-picker-appearance.html [ Failure ]
 crbug.com/654554 fast/forms/calendar-picker/month-picker-appearance-step.html [ Failure ]
 crbug.com/654554 fast/forms/calendar-picker/month-picker-appearance.html [ Failure ]
@@ -939,7 +927,6 @@
 crbug.com/589265 compositing/masks/masked-ancestor.html [ Failure ]
 crbug.com/589265 compositing/masks/multiple-masks.html [ Failure ]
 crbug.com/589265 compositing/masks/simple-composited-mask.html [ Failure ]
-crbug.com/589265 compositing/overflow/border-radius-on-parent-composited-grandchild.html [ Failure ]
 crbug.com/589265 compositing/overflow/nested-border-radius-clipping.html [ Failure ]
 crbug.com/589265 fast/borders/border-radius-with-composited-child.html [ Failure ]
 crbug.com/589265 fast/clip/overflow-border-radius-composited-parent.html [ Failure ]
@@ -990,7 +977,7 @@
 Bug(none) virtual/threaded/compositing/visibility/visibility-image-layers-dynamic.html [ Crash Failure ]
 Bug(none) virtual/threaded/compositing/visibility/visibility-image-layers.html [ Failure ]
 Bug(none) virtual/threaded/compositing/visibility/visibility-simple-video-layer.html [ Failure ]
-Bug(none) virtual/threaded/compositing/webgl/webgl-reflection.html [ Failure Crash ]
+Bug(none) virtual/threaded/compositing/webgl/webgl-reflection.html [ Failure Pass Crash ]
 Bug(none) virtual/threaded/compositing/webgl/webgl-with-accelerated-background-color.html [ Failure Pass ]
 Bug(none) virtual/threaded/printing/ [ Skip ]
 Bug(none) virtual/threaded/synthetic_gestures/ [ Failure Crash ]
@@ -1192,7 +1179,6 @@
 Bug(none) svg/transforms/text-with-pattern-with-svg-transform.svg [ Failure ]
 
 Bug(none) compositing/rendering-contexts.html [ Failure ]
-Bug(none) compositing/overflow-trumps-transform-style.html [ Failure ]
 
 Bug(none) fast/multicol/composited-layer-will-change.html [ Failure ]
 Bug(none) fast/pagination/multicol.html [ Crash ]
@@ -1305,3 +1291,4 @@
 Bug(none) compositing/overflow/overlap-testing-ancestor-scroller-high-dpi.html [ Failure ]
 Bug(none) virtual/outofblink-cors-ns/http/tests/navigation/same-document-scroll-position-restore.html [ Timeout ]
 Bug(none) virtual/threaded/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end-manual.html [ Timeout ]
+Bug(none) synthetic_gestures/animated-wheel-tiny-delta.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f96b6b9..51b4291 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -5736,3 +5736,4 @@
 # Sheriff 2018-10-29
 crbug.com/899710 [ Linux ] virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Failure Pass ]
 crbug.com/899715 [ Linux ] virtual/threaded/fast/scroll-behavior/wheel-and-touch-scroll-use-count.html [ Failure Pass ]
+crbug.com/898987 [ Android ] synthetic_gestures/smooth-scroll-tiny-delta.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/fast/harness/results.html b/third_party/WebKit/LayoutTests/fast/harness/results.html
index bdf4b1a2..3be8330 100644
--- a/third_party/WebKit/LayoutTests/fast/harness/results.html
+++ b/third_party/WebKit/LayoutTests/fast/harness/results.html
@@ -340,6 +340,7 @@
     <label id="HARNESS"><input type="checkbox">Harness failure <span></span></label>
     <label id="IMAGE"><input type="checkbox">Image failure <span></span></label>
     <label id="IMAGE_TEXT"><input type="checkbox">Image+text failure <span></span></label>
+    <label id="AUDIO"><input type="checkbox">Audio failure <span></span></label>
     <label id="SKIP"><input type="checkbox">Skipped <span></span></label>
     <label id="PASS"><input type="checkbox">Pass <span></span></label>
     <label id="WONTFIX"><input type="checkbox">WontFix <span></span></label>
@@ -385,12 +386,13 @@
   "TEXT":       { index: 3, text: "Failure", isFailure: true, isSuccess: false },
   "IMAGE":      { index: 4, text: "Failure", isFailure: true, isSuccess: false },
   "IMAGE+TEXT": { index: 5, text: "Failure", isFailure: true, isSuccess: false },
-  "TIMEOUT":    { index: 6, text: "Timeout", isFailure: true, isSuccess: false },
-  "LEAK":       { index: 7, text: "LEAK", isFailure: true, isSuccess: false },
-  "SLOW":       { index: 8, text: "Slow", isFailure: false, isSuccess: true },
-  "SKIP":       { index: 9, text: "Skip", isFailure: false, isSuccess: false },
-  "MISSING":    { index: 10, text: "Missing", isFailure: false, isSuccess: false },
-  "WONTFIX":    { index: 11, text: "WontFix", isFailure: false, isSuccess: false },
+  "AUDIO":      { index: 6, text: "Failure", isFailure: true, isSuccess: false },
+  "TIMEOUT":    { index: 7, text: "Timeout", isFailure: true, isSuccess: false },
+  "LEAK":       { index: 8, text: "LEAK", isFailure: true, isSuccess: false },
+  "SLOW":       { index: 9, text: "Slow", isFailure: false, isSuccess: true },
+  "SKIP":       { index: 10, text: "Skip", isFailure: false, isSuccess: false },
+  "MISSING":    { index: 11, text: "Missing", isFailure: false, isSuccess: false },
+  "WONTFIX":    { index: 12, text: "WontFix", isFailure: false, isSuccess: false },
   "PASS":       { index: 13, text: "Pass", isFailure: false, isSuccess: true },
   "NOTRUN":     { index: 14, text: "NOTRUN", isFailure: false, isSuccess: true }
 };
@@ -776,6 +778,9 @@
           toolbars.push(new ImageResultsToolbar().createDom(test));
           toolbars.push(new TextResultsToolbar().createDom(test));
           break;
+        case "AUDIO":
+          toolbars.push(new AudioResultsToolbar().createDom(test));
+          break;
         case "MISSING":
           toolbars.push(new PlainHtmlToolbar().createDom("Expectations are missing."));
           toolbars.push(new TextResultsToolbar().createDom(test));
@@ -988,6 +993,7 @@
       case "TEXT":
       case "IMAGE":
       case "IMAGE+TEXT":
+      case "AUDIO":
         if (expectedMap.has("FAIL"))
           return false;
         break;
@@ -1033,6 +1039,7 @@
       case "TEXT":
       case "IMAGE":
       case "IMAGE+TEXT":
+      case "AUDIO":
         if (baseMap && baseMap.has("FAIL"))
           return false;
         break;
@@ -2342,6 +2349,56 @@
   }
 } // class SimpleLinkToolbar
 
+// Audio results.
+class AudioResultsToolbar extends TXToolbar {
+
+  createDom(test) {
+    this.importStyle();
+    this.test = test;
+    let pathParser = new PathParser(test.expectPath);
+    this.toolbar = document.createElement("li");
+    this.toolbar.showDefault = (_ => {
+      this.selectAnchor(this.toolbar.querySelector("a"));
+    }).bind(this);
+    this.toolbar.classList.add("tx-toolbar");
+    this.toolbar.innerHTML = `<a href="#audioresults">audio results</a>\n`;
+    this.toolbar.addEventListener("click", ev => {
+      if (ev.target.tagName == "A") {
+        this.selectAnchor(ev.target);
+        ev.preventDefault();
+      }
+    });
+    return this.toolbar;
+  }
+
+  updateViewer() {
+    let viewer = this.getViewer();
+    if (!viewer) {
+      viewer = (new AudioResultsViewer()).createDom(this.test);
+      GUI.setResultViewer(this.toolbar, viewer);
+    }
+  }
+}
+
+class AudioResultsViewer {
+  createDom(test) {
+    this.viewer = document.createElement("div");
+    this.viewer.classList.add("audio-results-viewer");
+    let pathParser = new PathParser(test.expectPath);
+    this.viewer.innerHTML = `
+      <p>Actual:
+        <audio controls src="${pathParser.resultLink('-actual.wav')}"></audio>
+        <a download="actual.wav" href="${pathParser.resultLink('-actual.wav')}">download</a>
+      </p>
+      <p>Expected:
+        <audio controls src="${pathParser.resultLink('-expected.wav')}"></audio>
+        <a download="expected.wav" href="${pathParser.resultLink('-expected.wav')}">download</a>
+      </p>
+    `;
+    return this.viewer;
+  }
+} // class AudioResultsViewer
+
 </script>
 <script>
 // jsonp callback
diff --git a/third_party/android_crazy_linker/BUILD.gn b/third_party/android_crazy_linker/BUILD.gn
index a38f6573..c635138 100644
--- a/third_party/android_crazy_linker/BUILD.gn
+++ b/third_party/android_crazy_linker/BUILD.gn
@@ -34,6 +34,7 @@
       ":crazy_linker_test_load_library_callbacks",
       ":crazy_linker_test_load_library_depends",
       ":crazy_linker_test_load_library_with_gnu_hash_table",
+      ":crazy_linker_test_load_library_with_relr_relocations",
       ":crazy_linker_test_relocated_shared_relro",
       ":crazy_linker_test_search_path_list",
       ":crazy_linker_test_shared_relro",
@@ -91,6 +92,8 @@
         "src/src/crazy_linker_proc_maps.h",
         "src/src/crazy_linker_rdebug.cpp",
         "src/src/crazy_linker_rdebug.h",
+        "src/src/crazy_linker_relr_relocations.cpp",
+        "src/src/crazy_linker_relr_relocations.h",
         "src/src/crazy_linker_search_path_list.cpp",
         "src/src/crazy_linker_search_path_list.h",
         "src/src/crazy_linker_shared_library.cpp",
@@ -159,6 +162,7 @@
       "src/src/crazy_linker_line_reader_unittest.cpp",
       "src/src/crazy_linker_pointer_set_unittest.cpp",
       "src/src/crazy_linker_proc_maps_unittest.cpp",
+      "src/src/crazy_linker_relr_relocations_unittest.cpp",
       "src/src/crazy_linker_search_path_list_unittest.cpp",
       "src/src/crazy_linker_system_unittest.cpp",
       "src/src/crazy_linker_thread_unittest.cpp",
@@ -238,6 +242,13 @@
     ]
   }
 
+  crazy_linker_test_library("crazy_linker_tests_libfoo_with_relro_and_relr") {
+    sources = [
+      "src/tests/foo_with_relro.cpp",
+    ]
+    ldflags = [ "-Wl,--pack-dyn-relocs=relr,--use-android-relr-tags" ]
+  }
+
   crazy_linker_test_library(
       "crazy_linker_tests_libfoo_with_static_constructor") {
     sources = [
@@ -345,6 +356,20 @@
     ]
   }
 
+  executable("crazy_linker_test_load_library_with_relr_relocations") {
+    sources = [
+      "src/tests/test_load_library.cpp",
+    ]
+    data_deps = [
+      ":crazy_linker_tests_libfoo_with_relro_and_relr",
+    ]
+    defines =
+        [ "LIB_NAME=\"libcrazy_linker_tests_libfoo_with_relro_and_relr.so\"" ]
+    deps = [
+      ":android_crazy_linker",
+    ]
+  }
+
   executable("crazy_linker_test_load_library_depends") {
     sources = [
       "src/tests/test_load_library_depends.cpp",
diff --git a/third_party/android_crazy_linker/src/run_tests.sh b/third_party/android_crazy_linker/src/run_tests.sh
index 3515ade..3e94967 100755
--- a/third_party/android_crazy_linker/src/run_tests.sh
+++ b/third_party/android_crazy_linker/src/run_tests.sh
@@ -142,6 +142,7 @@
 libcrazy_linker_tests_libbar_with_two_dlopens.so \
 libcrazy_linker_tests_libfoo.so \
 libcrazy_linker_tests_libfoo_with_relro.so \
+libcrazy_linker_tests_libfoo_with_relro_and_relr.so \
 libcrazy_linker_tests_libfoo_with_static_constructor.so \
 libcrazy_linker_tests_libfoo_with_gnu_hash_table.so \
 libcrazy_linker_tests_libfoo2.so \
@@ -163,6 +164,7 @@
 crazy_linker_test_load_library \
 crazy_linker_test_load_library_depends \
 crazy_linker_test_load_library_with_gnu_hash_table \
+crazy_linker_test_load_library_with_relr_relocations \
 crazy_linker_test_relocated_shared_relro \
 crazy_linker_test_search_path_list \
 crazy_linker_test_shared_relro \
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp
index a3b0c86..ba5d798 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp
@@ -52,6 +52,34 @@
 #define DT_ANDROID_RELASZ (DT_LOOS + 5)
 #endif
 
+// Careful: the Android <elf.h> defines these with value corresponding to
+// DT_ANDROID_RELRxx below, so we undefine them, just in case. The DT_RELRxx
+// values corresponds to what lld generates by default with
+// '--pack-dyn-relocs=relr'.
+//
+// For more details, see https://reviews.llvm.org/D48247
+#undef DT_RELR
+#define DT_RELR 0x24
+#undef DT_RELRSZ
+#define DT_RELRSZ 0x23
+#undef DT_RELRENT
+#define DT_RELRENT 0x25
+
+// NOTE: The Android system linker only supports the DT_ANDROID_RELRxx entries
+// but their content is exactly equivalent to the DT_RELRxx ones. One can tell
+// lld to use the Android values with '--use-android-relr-tags'.
+//
+// The crazy linker supports both format, because it's essentially free :)
+#ifndef DT_ANDROID_RELR
+#define DT_ANDROID_RELR 0x6fffe000
+#endif
+#ifndef DT_ANDROID_RELRSZ
+#define DT_ANDROID_RELRSZ 0x6fffe001
+#endif
+#ifndef DT_ANDROID_RELRENT
+#define DT_ANDROID_RELRENT 0x6fffe003
+#endif
+
 // Processor-specific relocation types supported by the linker.
 #ifdef __arm__
 
@@ -183,6 +211,8 @@
 
 }  // namespace
 
+ElfRelocations::ElfRelocations() = default;
+
 bool ElfRelocations::Init(const ElfView* view, Error* error) {
   // Save these for later.
   phdr_ = view->phdr();
@@ -280,6 +310,26 @@
              dyn_value);
         android_relocations_size_ = dyn_value;
         break;
+      case DT_RELR:
+      case DT_ANDROID_RELR:
+        RLOG("  DT_RELR\n");
+        relr_.SetAddress(dyn_addr);
+        break;
+      case DT_ANDROID_RELRSZ:
+      case DT_RELRSZ:
+        relr_.SetSize(dyn_value);
+        RLOG("  DT_RELSZ size=%d\n", dyn_value);
+        break;
+      case DT_RELRENT:
+      case DT_ANDROID_RELRENT:
+        if (dyn_value != sizeof(ELF::Relr)) {
+          RLOG("Invalid RELR entry size (%d, expected %d)",
+               static_cast<int>(dyn_value),
+               static_cast<int>(sizeof(ELF::Relr)));
+          *error = "Invalid DT_RELRENT value";
+          return false;
+        }
+        break;
       case DT_PLTGOT:
         // Only used on MIPS currently. Could also be used on other platforms
         // when lazy binding (i.e. RTLD_LAZY) is implemented.
@@ -342,6 +392,8 @@
   if (!ApplyAndroidRelocations(symbols, resolver, error))
     return false;
 
+  relr_.Apply(load_bias_);
+
   if (!ApplyRelocs(reinterpret_cast<rel_t*>(relocations_),
                    relocations_size_ / sizeof(rel_t), symbols, resolver, error))
     return false;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h
index 8e71551..5ffcc11 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h
@@ -11,6 +11,7 @@
 #include <link.h>
 
 #include "crazy_linker_defines.h"
+#include "crazy_linker_relr_relocations.h"
 #include "elf_traits.h"
 
 namespace crazy {
@@ -28,7 +29,7 @@
   typedef ELF::Rel rel_t;
 #endif
  public:
-  ElfRelocations() { ::memset(this, 0, sizeof(*this)); }
+  ElfRelocations();
   ~ElfRelocations() {}
 
   bool Init(const ElfView* view, Error* error);
@@ -137,29 +138,31 @@
                        Error* error);
 #endif
 
-  const ELF::Phdr* phdr_;
-  size_t phdr_count_;
-  size_t load_bias_;
+  const ELF::Phdr* phdr_ = nullptr;
+  size_t phdr_count_ = 0;
+  size_t load_bias_ = 0;
 
-  ELF::Addr plt_relocations_;
-  size_t plt_relocations_size_;
-  ELF::Addr* plt_got_;
+  ELF::Addr plt_relocations_ = 0;
+  size_t plt_relocations_size_ = 0;
+  ELF::Addr* plt_got_ = nullptr;
 
-  ELF::Addr relocations_;
-  size_t relocations_size_;
+  ELF::Addr relocations_ = 0;
+  size_t relocations_size_ = 0;
+
+  RelrRelocations relr_;
 
 #if defined(__mips__)
   // MIPS-specific relocation fields.
-  ELF::Word mips_symtab_count_;
-  ELF::Word mips_local_got_count_;
-  ELF::Word mips_gotsym_;
+  ELF::Word mips_symtab_count_ = 0;
+  ELF::Word mips_local_got_count_ = 0;
+  ELF::Word mips_gotsym_ = 0;
 #endif
 
-  uint8_t* android_relocations_;
-  size_t android_relocations_size_;
+  uint8_t* android_relocations_ = nullptr;
+  size_t android_relocations_size_ = 0;
 
-  bool has_text_relocations_;
-  bool has_symbolic_;
+  bool has_text_relocations_ = false;
+  bool has_symbolic_ = false;
 };
 
 }  // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations.cpp
new file mode 100644
index 0000000..10a47d1
--- /dev/null
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations.cpp
@@ -0,0 +1,50 @@
+// 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 "crazy_linker_relr_relocations.h"
+
+namespace crazy {
+
+// Apply a single RELR relocation at virtual |offset| address, using
+// the |load_bias| value.
+static void ApplyRelrRelocation(ELF::Addr offset, size_t load_bias) {
+  offset += load_bias;
+  *reinterpret_cast<ELF::Addr*>(offset) += load_bias;
+}
+
+void RelrRelocations::Apply(size_t load_bias) {
+  // Simple sanity checks.
+  if (!relocations_ || !relocations_size_)
+    return;
+
+  const ELF::Relr* begin = relocations_;
+  const ELF::Relr* end = begin + (relocations_size_ / sizeof(ELF::Relr));
+  const size_t word_size = sizeof(ELF::Addr);
+
+  ELF::Addr base = 0;  // current relocation address
+  while (begin < end) {
+    ELF::Relr entry = *begin++;
+
+    if ((entry & 1) == 0) {
+      // An even value corresponds to the address of the next relocation.
+      ELF::Addr offset = static_cast<ELF::Addr>(entry);
+      ApplyRelrRelocation(offset, load_bias);
+      base = offset + word_size;
+    } else {
+      // An odd value corresponds to a bitmap of 31 or 63 words, based
+      // on the CPU bitness / word_size.
+      ELF::Addr offset = base;
+      while (entry != 0) {
+        entry >>= 1;
+        if ((entry & 1) != 0)
+          ApplyRelrRelocation(offset, load_bias);
+        offset += word_size;
+      }
+      // Increment |base| by 31 or 63 words.
+      base += (8 * word_size - 1) * word_size;
+    }
+  }
+}
+
+}  // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations.h b/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations.h
new file mode 100644
index 0000000..0efacee
--- /dev/null
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations.h
@@ -0,0 +1,64 @@
+// 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 CRAZY_LINKER_RELR_RELOCATIONS_H_
+#define CRAZY_LINKER_RELR_RELOCATIONS_H_
+
+#include "elf_traits.h"
+
+namespace crazy {
+
+// Convenience struct to model a set of RELR relocations and apply them.
+// For more information about their format, see:
+//    https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
+//
+// In a nutshell, this looks like the following:
+//
+//  - The relr table is just an array of ELF:Addr values (i.e. 32 or 64 bit
+//    words, depending on CPU bitness).
+//
+//  - Each relr relocation corresponds to simply applying the load bias
+//    to a given memory location. I.e. applying one relocation at VIRTUAL
+//    ADDRESS |vaddr| looks like:
+//
+//      *(reinterpret_cast<ELF::Addr*>(vaddr + load_bias)) += load_bias
+//
+//  - Even entries in the table corresponds to target virtual addresses,
+//    where a RELR relocation should happen. Note that odd addresses are
+//    not supported at all.
+//
+//  - Odd entries corresponds to bitmaps of 31 or 63 addresses following
+//    the previous one (either from an even entry, or a previous odd one).
+//    Each bit, after the lsb, that is set, means that the corresponding
+//    address should be RELR-relocated.
+//
+class RelrRelocations {
+ public:
+  // Default constructor.
+  RelrRelocations() = default;
+
+  // Set the RELR address, |dt_relr| must be the DT_RELR entry from the
+  // dynamic table.
+  void SetAddress(uintptr_t dt_relr) {
+    relocations_ =
+        const_cast<const ELF::Relr*>(reinterpret_cast<ELF::Relr*>(dt_relr));
+  }
+
+  // Set the RELR size. |dt_relrsz| must be the DT_RELRSZ entry from the
+  // dynamic table.
+  void SetSize(ELF::Addr dt_relrsz) { relocations_size_ = dt_relrsz; }
+
+  // Apply all relocations at once, where |load_bias| is the load load bias
+  // used to load the ELF file. This operation cannot fail, and doesn't do
+  // anything if there are no Relr relocations.
+  void Apply(size_t load_bias);
+
+ private:
+  const ELF::Relr* relocations_ = nullptr;
+  ELF::Addr relocations_size_ = 0;
+};
+
+}  // namespace crazy
+
+#endif  // CRAZY_LINKER_RELR_RELOCATIONS_H_
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations_unittest.cpp
new file mode 100644
index 0000000..8d3162b
--- /dev/null
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_relr_relocations_unittest.cpp
@@ -0,0 +1,101 @@
+// 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 "crazy_linker_relr_relocations.h"
+
+#include "elf_traits.h"
+
+#include <gtest/gtest.h>
+
+namespace crazy {
+
+TEST(RelrRelocations, DefaultConstruction) {
+  RelrRelocations relr;
+  relr.Apply(0);
+}
+
+TEST(RelrRelocations, ApplyWithSimpleAddressList) {
+  // Build a simple array of addresses initialized to pretty liberal values.
+  const size_t kDataSize = 128;
+  ELF::Addr data[kDataSize];
+  for (size_t n = 0; n < kDataSize; ++n)
+    data[n] = ELF::Addr(0) + n;
+
+  // Build an RELR table that lists every *even* item in data[] as a RELR
+  // relocation target. Offsets are relative to |data|, which thus must be
+  // the load bias when calling RelrRelocations::Apply() below.
+  const size_t kWordSize = sizeof(ELF::Addr);
+  const size_t kRelrSize = 8;
+  ELF::Relr relr_table[kRelrSize];
+  for (size_t n = 0; n < kRelrSize; ++n) {
+    relr_table[n] = kWordSize * n * 2;
+  }
+  RelrRelocations relr;
+  relr.SetAddress(reinterpret_cast<uintptr_t>(relr_table));
+  relr.SetSize(static_cast<ELF::Addr>(sizeof(relr_table)));
+
+  // Build the expected data table here, it's easier to understand the
+  // comparison.
+  auto load_bias = reinterpret_cast<uintptr_t>(data);
+  ELF::Addr expected[kDataSize];
+  for (size_t n = 0; n < kDataSize; ++n) {
+    if ((n < 2 * kRelrSize) && (n & 1) == 0) {
+      expected[n] = data[n] + load_bias;
+    } else {
+      expected[n] = data[n];
+    }
+  }
+
+  // Apply RELR relocations.
+  relr.Apply(load_bias);
+
+  // Compare results.
+  for (size_t n = 0; n < kDataSize; ++n) {
+    EXPECT_EQ(expected[n], data[n]) << "# " << n;
+  }
+}
+
+TEST(RelrRelocations, ApplyWithSimpleBitmaps) {
+  // Build a simple array of addresses initialized to pretty liberal values.
+  const size_t kDataSize = 128;
+  ELF::Addr data[kDataSize];
+  for (size_t n = 0; n < kDataSize; ++n)
+    data[n] = ELF::Addr(0) + n;
+
+  // Build an RELR table that lists every 3rd item in data[] as a RELR
+  // relocation target. Using only bitmaps. Base address is 0.
+  const size_t kWordSize = sizeof(ELF::Addr);
+  const size_t kBitsPerWord = (kWordSize * 8 - 1);
+  const size_t kRelrSize = (kDataSize + kBitsPerWord - 1) / kBitsPerWord;
+  ELF::Relr relr_table[kRelrSize] = {};
+  for (size_t n = 0; n < kDataSize; ++n) {
+    if ((n % 3) == 0)
+      relr_table[n / kBitsPerWord] |= (1 | (2 << (n % kBitsPerWord)));
+  }
+  RelrRelocations relr;
+  relr.SetAddress(reinterpret_cast<uintptr_t>(relr_table));
+  relr.SetSize(static_cast<ELF::Addr>(sizeof(relr_table)));
+
+  // Build the expected data table here, it's easier to understand the
+  // comparison.
+  auto load_bias = reinterpret_cast<uintptr_t>(data);
+  ELF::Addr expected[kDataSize];
+  for (size_t n = 0; n < kDataSize; ++n) {
+    if ((n % 3) == 0) {
+      expected[n] = data[n] + load_bias;
+    } else {
+      expected[n] = data[n];
+    }
+  }
+
+  // Apply RELR relocations.
+  relr.Apply(load_bias);
+
+  // Compare results.
+  for (size_t n = 0; n < kDataSize; ++n) {
+    EXPECT_EQ(expected[n], data[n]) << "# " << n;
+  }
+}
+
+}  // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/elf_traits.h b/third_party/android_crazy_linker/src/src/elf_traits.h
index 6c6e552..461edd96 100644
--- a/third_party/android_crazy_linker/src/src/elf_traits.h
+++ b/third_party/android_crazy_linker/src/src/elf_traits.h
@@ -24,6 +24,7 @@
   typedef Elf32_Sym Sym;
   typedef Elf32_Rel Rel;
   typedef Elf32_Rela Rela;
+  typedef Elf32_Word Relr;
   typedef Elf32_auxv_t auxv_t;
 
   enum { kElfClass = ELFCLASS32 };
@@ -53,6 +54,7 @@
   typedef Elf64_Sym Sym;
   typedef Elf64_Rel Rel;
   typedef Elf64_Rela Rela;
+  typedef Elf64_Xword Relr;
   typedef Elf64_auxv_t auxv_t;
 
   enum { kElfClass = ELFCLASS64 };
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index ad8bdbe..9933886 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -595,10 +595,15 @@
   StringKeyframe* keyframe = CreateReplaceOpKeyframe("--foo", "10");
   EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe));
 
+  // Length-valued properties are not compositable.
   StringKeyframe* non_animatable_keyframe =
       CreateReplaceOpKeyframe("--bar", "10px");
   EXPECT_FALSE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(
       non_animatable_keyframe));
+
+  // Cannot composite due to side effect.
+  SetCustomProperty("opacity", "var(--foo)");
+  EXPECT_FALSE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe));
 }
 
 TEST_F(AnimationCompositorAnimationsTest,
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect_model.cc b/third_party/blink/renderer/core/animation/keyframe_effect_model.cc
index f590afa..3a5c62de 100644
--- a/third_party/blink/renderer/core/animation/keyframe_effect_model.cc
+++ b/third_party/blink/renderer/core/animation/keyframe_effect_model.cc
@@ -173,11 +173,25 @@
         parent_style, should_snapshot_property_callback,
         should_snapshot_keyframe_callback);
   }
+
   // Custom properties need to be handled separately, since not all values
   // can be animated.  Need to resolve the value of each custom property to
   // ensure that it can be animated.
+  const PropertyRegistry* property_registry =
+      element.GetDocument().GetPropertyRegistry();
+  if (!property_registry) {
+    // TODO(kevers): Change to DCHECK once CSSVariables2Enabled flag is removed.
+    return updated;
+  }
+
   if (auto* inherited_variables = computed_style.InheritedVariables()) {
     for (const auto& name : inherited_variables->GetCustomPropertyNames()) {
+      if (property_registry->WasReferenced(name)) {
+        // This variable has been referenced as a property value at least once
+        // during style resolution in the document. Animating this property on
+        // the compositor could introduce misalignment in frame synchronization.
+        continue;
+      }
       updated |= SnapshotCompositorKeyFrames(
           PropertyHandle(name), element, computed_style, parent_style,
           should_snapshot_property_callback, should_snapshot_keyframe_callback);
@@ -185,6 +199,12 @@
   }
   if (auto* non_inherited_variables = computed_style.NonInheritedVariables()) {
     for (const auto& name : non_inherited_variables->GetCustomPropertyNames()) {
+      // TODO(kevers): Check if referenced in computed style. References
+      // elsewhere in the document should not prevent compositing.
+      if (property_registry->WasReferenced(name)) {
+        // Avoid potential side-effect of animating on compositor.
+        continue;
+      }
       updated |= SnapshotCompositorKeyFrames(
           PropertyHandle(name), element, computed_style, parent_style,
           should_snapshot_property_callback, should_snapshot_keyframe_callback);
diff --git a/third_party/blink/renderer/core/css/property_registration.cc b/third_party/blink/renderer/core/css/property_registration.cc
index d5d49d7a..23382173 100644
--- a/third_party/blink/renderer/core/css/property_registration.cc
+++ b/third_party/blink/renderer/core/css/property_registration.cc
@@ -46,7 +46,8 @@
           CSSInterpolationTypesMap::CreateInterpolationTypesForCSSSyntax(
               name,
               syntax,
-              *this)) {
+              *this)),
+      referenced_(false) {
   DCHECK(RuntimeEnabledFeatures::CSSVariables2Enabled());
 }
 
diff --git a/third_party/blink/renderer/core/css/property_registration.h b/third_party/blink/renderer/core/css/property_registration.h
index 68639ad4..7270a01e 100644
--- a/third_party/blink/renderer/core/css/property_registration.h
+++ b/third_party/blink/renderer/core/css/property_registration.h
@@ -45,6 +45,8 @@
   void Trace(blink::Visitor* visitor) { visitor->Trace(initial_); }
 
  private:
+  friend class ::blink::PropertyRegistry;
+
   PropertyRegistration(const AtomicString& name,
                        const CSSSyntaxDescriptor&,
                        bool inherits,
@@ -56,6 +58,7 @@
   const Member<const CSSValue> initial_;
   const scoped_refptr<CSSVariableData> initial_variable_data_;
   const InterpolationTypes interpolation_types_;
+  mutable bool referenced_;
 
   FRIEND_TEST_ALL_PREFIXES(CSSVariableResolverTest,
                            NeedsResolutionClearedByResolver);
diff --git a/third_party/blink/renderer/core/css/property_registry.cc b/third_party/blink/renderer/core/css/property_registry.cc
index 28ff581..8bc06920 100644
--- a/third_party/blink/renderer/core/css/property_registry.cc
+++ b/third_party/blink/renderer/core/css/property_registry.cc
@@ -57,4 +57,19 @@
   return parsed_value ? parsed_value : value;
 }
 
+void PropertyRegistry::MarkReferenced(const AtomicString& property_name) const {
+  const PropertyRegistration* registration = Registration(property_name);
+  if (registration) {
+    registration->referenced_ = true;
+  }
+}
+
+bool PropertyRegistry::WasReferenced(const AtomicString& property_name) const {
+  const PropertyRegistration* registration = Registration(property_name);
+  if (!registration) {
+    return false;
+  }
+  return registration->referenced_;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/property_registry.h b/third_party/blink/renderer/core/css/property_registry.h
index b9dc7a1..cbb806a 100644
--- a/third_party/blink/renderer/core/css/property_registry.h
+++ b/third_party/blink/renderer/core/css/property_registry.h
@@ -36,6 +36,9 @@
                                            const AtomicString& property_name,
                                            const CSSValue*);
 
+  void MarkReferenced(const AtomicString&) const;
+  bool WasReferenced(const AtomicString&) const;
+
  private:
   RegistrationMap registrations_;
 };
diff --git a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
index 57172354..53327a5 100644
--- a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
@@ -337,6 +337,10 @@
     non_inherited_variables_ = state_.Style()->NonInheritedVariables();
   }
 
+  if (registry_ && !is_env_variable) {
+    registry_->MarkReferenced(variable_name);
+  }
+
   scoped_refptr<CSSVariableData> variable_data =
       is_env_variable ? ValueForEnvironmentVariable(variable_name)
                       : ValueForCustomProperty(variable_name, options);
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index bf37efe..4176407 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -134,8 +134,8 @@
       externally_allocated_memory_(0),
       gpu_readback_invoked_in_current_frame_(false),
       gpu_readback_successive_frames_(0) {
-  CanvasRenderingContextHost::RecordCanvasSizeToUMA(size_.Width(),
-                                                    size_.Height(), false);
+  CanvasRenderingContextHost::RecordCanvasSizeToUMA(
+      size_.Width(), size_.Height(), false /* Canvas */);
   UseCounter::Count(document, WebFeature::kHTMLCanvasElement);
 
   GetDocument().IncrementNumberOfCanvases();
@@ -572,7 +572,7 @@
   IntSize new_size(w, h);
 
   if (old_size != new_size)
-    CanvasRenderingContextHost::RecordCanvasSizeToUMA(w, h, false);
+    CanvasRenderingContextHost::RecordCanvasSizeToUMA(w, h, false /* Canvas */);
 
   // If the size of an existing buffer matches, we can just clear it instead of
   // reallocating.  This optimization is only done for 2D canvases for now.
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index daa6c5b..19b3ffe1 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -571,6 +571,7 @@
 
   image_->SetOriginClean(
       !image->WouldTaintOrigin(document->GetSecurityOrigin()));
+  UpdateImageBitmapMemoryUsage();
 }
 
 ImageBitmap::ImageBitmap(HTMLVideoElement* video,
@@ -606,6 +607,7 @@
 
   image_->SetOriginClean(
       !video->WouldTaintOrigin(document->GetSecurityOrigin()));
+  UpdateImageBitmapMemoryUsage();
 }
 
 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas,
@@ -631,6 +633,7 @@
     return;
 
   image_->SetOriginClean(canvas->OriginClean());
+  UpdateImageBitmapMemoryUsage();
 }
 
 ImageBitmap::ImageBitmap(OffscreenCanvas* offscreen_canvas,
@@ -657,6 +660,7 @@
   if (!image_)
     return;
   image_->SetOriginClean(offscreen_canvas->OriginClean());
+  UpdateImageBitmapMemoryUsage();
 }
 
 ImageBitmap::ImageBitmap(const void* pixel_data,
@@ -678,6 +682,7 @@
   if (!image_)
     return;
   image_->SetOriginClean(is_image_bitmap_origin_clean);
+  UpdateImageBitmapMemoryUsage();
 }
 
 ImageBitmap::ImageBitmap(ImageData* data,
@@ -753,6 +758,8 @@
   // resize if up-scaling
   if (up_scaling)
     image_ = ScaleImage(std::move(image_), parsed_options);
+
+  UpdateImageBitmapMemoryUsage();
 }
 
 ImageBitmap::ImageBitmap(ImageBitmap* bitmap,
@@ -775,6 +782,7 @@
     return;
 
   image_->SetOriginClean(bitmap->OriginClean());
+  UpdateImageBitmapMemoryUsage();
 }
 
 ImageBitmap::ImageBitmap(scoped_refptr<StaticBitmapImage> image,
@@ -795,10 +803,12 @@
     return;
 
   image_->SetOriginClean(origin_clean);
+  UpdateImageBitmapMemoryUsage();
 }
 
 ImageBitmap::ImageBitmap(scoped_refptr<StaticBitmapImage> image) {
   image_ = std::move(image);
+  UpdateImageBitmapMemoryUsage();
 }
 
 scoped_refptr<StaticBitmapImage> ImageBitmap::Transfer() {
@@ -808,7 +818,25 @@
   return std::move(image_);
 }
 
-ImageBitmap::~ImageBitmap() = default;
+void ImageBitmap::UpdateImageBitmapMemoryUsage() {
+  // TODO(fserb): We should be calling GetCanvasColorParams().BytesPerPixel()
+  // but this is breaking some tests due to the repaint of the image.
+  int bytes_per_pixel = 4;
+
+  base::CheckedNumeric<int32_t> memory_usage_checked = bytes_per_pixel;
+  memory_usage_checked *= image_->width();
+  memory_usage_checked *= image_->height();
+  int32_t new_memory_usage =
+      memory_usage_checked.ValueOrDefault(std::numeric_limits<int32_t>::max());
+  v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+      new_memory_usage - memory_usage_);
+  memory_usage_ = new_memory_usage;
+}
+
+ImageBitmap::~ImageBitmap() {
+  v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+      -memory_usage_);
+}
 
 ImageBitmap* ImageBitmap::Create(ImageElementBase* image,
                                  base::Optional<IntRect> crop_rect,
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.h b/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
index 258a6a7d..e12d8fb 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
@@ -164,6 +164,7 @@
               bool is_image_bitmap_premultiplied,
               bool is_image_bitmap_origin_clean,
               const CanvasColorParams&);
+  void UpdateImageBitmapMemoryUsage();
   static void ResolvePromiseOnOriginalThread(ScriptPromiseResolver*,
                                              sk_sp<SkImage>,
                                              bool origin_clean,
@@ -175,6 +176,7 @@
                                                std::unique_ptr<ParsedOptions>);
   scoped_refptr<StaticBitmapImage> image_;
   bool is_neutered_ = false;
+  int32_t memory_usage_ = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn
index c06f170..b5a41ef 100644
--- a/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -457,7 +457,6 @@
     "ng/ng_physical_container_fragment.h",
     "ng/ng_physical_fragment.cc",
     "ng/ng_physical_fragment.h",
-    "ng/ng_positioned_float.cc",
     "ng/ng_positioned_float.h",
     "ng/ng_relative_utils.cc",
     "ng/ng_relative_utils.h",
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 40ba43b0..7d17154 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -78,7 +78,7 @@
 // Returns if the resulting fragment should be considered an "empty block".
 // There is special casing for fragments like this, e.g. margins "collapse
 // through", etc.
-bool IsEmptyBlock(bool is_new_fc, const NGLayoutResult& layout_result) {
+inline bool IsEmptyBlock(bool is_new_fc, const NGLayoutResult& layout_result) {
   // TODO(ikilpatrick): This should be a DCHECK.
   if (is_new_fc)
     return false;
@@ -101,8 +101,8 @@
 }
 
 // As above; for convenience if you have a child_space.
-bool IsEmptyBlock(const NGConstraintSpace& child_space,
-                  const NGLayoutResult& layout_result) {
+inline bool IsEmptyBlock(const NGConstraintSpace& child_space,
+                         const NGLayoutResult& layout_result) {
   return IsEmptyBlock(child_space.IsNewFormattingContext(), layout_result);
 }
 
@@ -2023,7 +2023,7 @@
 // Propagate computed baselines from children.
 // Skip children that do not produce baselines (e.g., empty blocks.)
 void NGBlockLayoutAlgorithm::PropagateBaselinesFromChildren() {
-  const Vector<NGBaselineRequest>& requests =
+  const NGConstraintSpace::NGBaselineRequestVector& requests =
       ConstraintSpace().BaselineRequests();
   if (requests.IsEmpty())
     return;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 19397aa7..90380e1 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -871,7 +871,7 @@
 void NGBlockNode::CopyBaselinesFromOldLayout(
     const NGConstraintSpace& constraint_space,
     NGBoxFragmentBuilder* builder) {
-  const Vector<NGBaselineRequest>& requests =
+  const NGConstraintSpace::NGBaselineRequestVector& requests =
       constraint_space.BaselineRequests();
   if (requests.IsEmpty())
     return;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
index d50c44a..78e6f9f1 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -66,6 +66,8 @@
     kNumberOfConstraintSpaceFlags = 11
   };
 
+  typedef Vector<NGBaselineRequest, 2> NGBaselineRequestVector;
+
   NGConstraintSpace() {}
   NGConstraintSpace(const NGConstraintSpace&) = default;
   NGConstraintSpace(NGConstraintSpace&&) = default;
@@ -280,7 +282,7 @@
   // child will be canceled out with negative clearance.
   bool ShouldForceClearance() const { return HasFlag(kForceClearance); }
 
-  const Vector<NGBaselineRequest>& BaselineRequests() const {
+  const NGBaselineRequestVector& BaselineRequests() const {
     return baseline_requests_;
   }
 
@@ -325,7 +327,7 @@
   NGExclusionSpace exclusion_space_;
   LayoutUnit clearance_offset_;
 
-  Vector<NGBaselineRequest> baseline_requests_;
+  NGBaselineRequestVector baseline_requests_;
 };
 
 inline std::ostream& operator<<(std::ostream& stream,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
index c2601fc27..6568e59 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
@@ -175,7 +175,8 @@
     return *this;
   }
 
-  void AddBaselineRequests(const Vector<NGBaselineRequest>& requests) {
+  void AddBaselineRequests(
+      const NGConstraintSpace::NGBaselineRequestVector& requests) {
     DCHECK(baseline_requests_.IsEmpty());
     baseline_requests_.AppendVector(requests);
   }
@@ -225,7 +226,7 @@
   base::Optional<LayoutUnit> floats_bfc_block_offset_;
   const NGExclusionSpace* exclusion_space_ = nullptr;
   LayoutUnit clearance_offset_;
-  Vector<NGBaselineRequest> baseline_requests_;
+  NGConstraintSpace::NGBaselineRequestVector baseline_requests_;
 
   friend class NGConstraintSpace;
 };
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
index f6b0998..05552e06 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -26,24 +26,6 @@
   return break_token->UsedBlockSize() - logical_fragment.BlockSize();
 }
 
-// Return true if the specified fragment is the first generated fragment of
-// some node.
-bool IsFirstFragment(const NGConstraintSpace& constraint_space,
-                     const NGPhysicalFragment& fragment) {
-  // TODO(mstensho): Figure out how to behave for non-box fragments here. How
-  // can we tell whether it's the first one? Looking for previously used block
-  // space certainly isn't the answer.
-  if (!fragment.IsBox())
-    return true;
-  return PreviouslyUsedBlockSpace(constraint_space, fragment) <= LayoutUnit();
-}
-
-// Return true if the specified fragment is the final fragment of some node.
-bool IsLastFragment(const NGPhysicalFragment& fragment) {
-  const auto* break_token = fragment.BreakToken();
-  return !break_token || break_token->IsFinished();
-}
-
 // At a class A break point [1], the break value with the highest precedence
 // wins. If the two values have the same precedence (e.g. "left" and "right"),
 // the value specified on a latter object wins.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
index cfb23396..6231e4e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
@@ -5,14 +5,15 @@
 #ifndef NGFragmentationUtils_h
 #define NGFragmentationUtils_h
 
+#include "third_party/blink/renderer/core/layout/ng/ng_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 
 namespace blink {
 
 class NGConstraintSpace;
-class NGPhysicalFragment;
 
 // Return the total amount of block space spent on a node by fragments
 // preceding this one (but not including this one).
@@ -21,10 +22,21 @@
 
 // Return true if the specified fragment is the first generated fragment of
 // some node.
-bool IsFirstFragment(const NGConstraintSpace&, const NGPhysicalFragment&);
+inline bool IsFirstFragment(const NGConstraintSpace& constraint_space,
+                            const NGPhysicalFragment& fragment) {
+  // TODO(mstensho): Figure out how to behave for non-box fragments here. How
+  // can we tell whether it's the first one? Looking for previously used block
+  // space certainly isn't the answer.
+  if (!fragment.IsBox())
+    return true;
+  return PreviouslyUsedBlockSpace(constraint_space, fragment) <= LayoutUnit();
+}
 
 // Return true if the specified fragment is the final fragment of some node.
-bool IsLastFragment(const NGPhysicalFragment&);
+inline bool IsLastFragment(const NGPhysicalFragment& fragment) {
+  const auto* break_token = fragment.BreakToken();
+  return !break_token || break_token->IsFinished();
+}
 
 // Join two adjacent break values specified on break-before and/or break-
 // after. avoid* values win over auto values, and forced break values win over
diff --git a/third_party/blink/renderer/core/layout/ng/ng_positioned_float.cc b/third_party/blink/renderer/core/layout/ng/ng_positioned_float.cc
deleted file mode 100644
index ef9bec9..0000000
--- a/third_party/blink/renderer/core/layout/ng/ng_positioned_float.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/layout/ng/ng_positioned_float.h"
-
-#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
-
-namespace blink {
-
-NGPositionedFloat::NGPositionedFloat(
-    scoped_refptr<NGLayoutResult> layout_result,
-    const NGBfcOffset& bfc_offset)
-    : layout_result(layout_result), bfc_offset(bfc_offset) {}
-
-// Define the destructor here, so that we can forward-declare more in the header
-// file.
-NGPositionedFloat::~NGPositionedFloat() = default;
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h b/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h
index 99d31649..d6d109be 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h
@@ -8,6 +8,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
 
 namespace blink {
 
@@ -16,8 +17,8 @@
 // Contains the information necessary for copying back data to a FloatingObject.
 struct CORE_EXPORT NGPositionedFloat {
   NGPositionedFloat(scoped_refptr<NGLayoutResult> layout_result,
-                    const NGBfcOffset& bfc_offset);
-  ~NGPositionedFloat();
+                    const NGBfcOffset& bfc_offset)
+      : layout_result(layout_result), bfc_offset(bfc_offset) {}
   NGPositionedFloat(NGPositionedFloat&&) noexcept = default;
   NGPositionedFloat(const NGPositionedFloat&) = default;
   NGPositionedFloat& operator=(NGPositionedFloat&&) = default;
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index ede5700d..f34dabb9 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -321,6 +321,10 @@
     return;
 
   HistoryItem* history_item = document_loader_->GetHistoryItem();
+  // For performance reasons, we don't save scroll anchors as often as we save
+  // scroll offsets. In order to avoid keeping around a stale anchor, we clear
+  // it when the saved scroll offset changes.
+  history_item->SetScrollAnchorData(ScrollAnchorData());
   if (ScrollableArea* layout_scrollable_area = frame_->View()->LayoutViewport())
     history_item->SetScrollOffset(layout_scrollable_area->GetScrollOffset());
   history_item->SetVisualViewportScrollOffset(ToScrollOffset(
diff --git a/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc b/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
index 5f6bf92..4b581d9 100644
--- a/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
+++ b/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
@@ -107,6 +107,34 @@
   EXPECT_EQ(400, web_view->MainFrameImpl()->GetScrollOffset().height);
 }
 
+TEST_F(ProgrammaticScrollTest, SaveScrollStateClearsAnchor) {
+  RegisterMockedHttpURLLoad("long_scroll.html");
+
+  frame_test_helpers::WebViewHelper web_view_helper;
+  WebViewImpl* web_view =
+      web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html");
+  web_view->Resize(WebSize(1000, 1000));
+  web_view->UpdateAllLifecyclePhases();
+
+  FrameLoader& loader = web_view->MainFrameImpl()->GetFrame()->Loader();
+  loader.GetDocumentLoader()->SetLoadType(WebFrameLoadType::kBackForward);
+
+  web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 500));
+  loader.GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user =
+      true;
+  loader.SaveScrollState();
+  loader.SaveScrollAnchor();
+
+  web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 0));
+  loader.SaveScrollState();
+  loader.GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user =
+      false;
+
+  loader.RestoreScrollPositionAndViewState();
+
+  EXPECT_EQ(0, web_view->MainFrameImpl()->GetScrollOffset().height);
+}
+
 class ProgrammaticScrollSimTest : public SimTest {};
 
 TEST_F(ProgrammaticScrollSimTest, NavigateToHash) {
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
index 0a495797..a1c125e 100644
--- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -35,16 +35,20 @@
 
 namespace blink {
 
-OffscreenCanvas::OffscreenCanvas(const IntSize& size) : size_(size) {}
+OffscreenCanvas::OffscreenCanvas(const IntSize& size) : size_(size) {
+  UpdateMemoryUsage();
+}
 
 OffscreenCanvas* OffscreenCanvas::Create(unsigned width, unsigned height) {
   UMA_HISTOGRAM_BOOLEAN("Blink.OffscreenCanvas.NewOffscreenCanvas", true);
-  CanvasRenderingContextHost::RecordCanvasSizeToUMA(width, height, true);
   return new OffscreenCanvas(
       IntSize(clampTo<int>(width), clampTo<int>(height)));
 }
 
-OffscreenCanvas::~OffscreenCanvas() = default;
+OffscreenCanvas::~OffscreenCanvas() {
+  v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+      -memory_usage_);
+}
 
 void OffscreenCanvas::Commit(scoped_refptr<CanvasResource> canvas_resource,
                              const SkIRect& damage_rect) {
@@ -111,8 +115,7 @@
     }
   }
   if (size != size_) {
-    CanvasRenderingContextHost::RecordCanvasSizeToUMA(size.Width(),
-                                                      size.Height(), true);
+    UpdateMemoryUsage();
   }
   size_ = size;
   if (frame_dispatcher_)
@@ -149,12 +152,14 @@
                                       "OffscreenCanvas with no context");
     return nullptr;
   }
+
   ImageBitmap* image = context_->TransferToImageBitmap(script_state);
   if (!image) {
     // Undocumented exception (not in spec)
     exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
                                       "Out of memory");
   }
+
   return image;
 }
 
@@ -417,6 +422,23 @@
   return To<WorkerGlobalScope>(GetExecutionContext())->GetFontSelector();
 }
 
+void OffscreenCanvas::UpdateMemoryUsage() {
+  CanvasRenderingContextHost::RecordCanvasSizeToUMA(
+      Size().Width(), Size().Height(), true /* OffscreenCanvas */);
+
+  int bytes_per_pixel = ColorParams().BytesPerPixel();
+
+  base::CheckedNumeric<int32_t> memory_usage_checked = bytes_per_pixel;
+  memory_usage_checked *= Size().Width();
+  memory_usage_checked *= Size().Height();
+  int32_t new_memory_usage =
+      memory_usage_checked.ValueOrDefault(std::numeric_limits<int32_t>::max());
+
+  v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+      new_memory_usage - memory_usage_);
+  memory_usage_ = new_memory_usage;
+}
+
 void OffscreenCanvas::Trace(blink::Visitor* visitor) {
   visitor->Trace(context_);
   visitor->Trace(execution_context_);
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
index f65a90a8..08b80e5 100644
--- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
+++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
@@ -115,7 +115,8 @@
   // Partial CanvasResourceHost implementation
   void NotifyGpuContextLost() override {}
   void SetNeedsCompositingUpdate() override {}
-  void UpdateMemoryUsage() override {}  // TODO(crbug.com/842693): implement
+  // TODO(fserb): Merge this with HTMLCanvasElement::UpdateMemoryUsage
+  void UpdateMemoryUsage() override;
   SkFilterQuality FilterQuality() const override {
     return kLow_SkFilterQuality;  // TODO(crbug.com/856654)
   }
@@ -169,6 +170,8 @@
   void Trace(blink::Visitor*) override;
 
  private:
+  int32_t memory_usage_ = 0;
+
   friend class OffscreenCanvasTest;
   explicit OffscreenCanvas(const IntSize&);
   using ContextFactoryVector =
diff --git a/third_party/blink/renderer/core/svg/svg_integer.cc b/third_party/blink/renderer/core/svg/svg_integer.cc
index e8f277e..a160403c 100644
--- a/third_party/blink/renderer/core/svg/svg_integer.cc
+++ b/third_party/blink/renderer/core/svg/svg_integer.cc
@@ -79,7 +79,7 @@
   animation_element->AnimateAdditiveNumber(
       percentage, repeat_count, from_integer->Value(), to_integer->Value(),
       to_at_end_of_duration_integer->Value(), animated_float);
-  value_ = static_cast<int>(roundf(animated_float));
+  value_ = clampTo<int>(roundf(animated_float));
 }
 
 float SVGInteger::CalculateDistance(SVGPropertyBase* other, SVGElement*) {
diff --git a/third_party/blink/renderer/core/workers/experimental/task.cc b/third_party/blink/renderer/core/workers/experimental/task.cc
index 6db34e8..0af9482 100644
--- a/third_party/blink/renderer/core/workers/experimental/task.cc
+++ b/third_party/blink/renderer/core/workers/experimental/task.cc
@@ -17,37 +17,38 @@
 namespace blink {
 
 ThreadPoolTask::ThreadPoolTask(ThreadPoolThreadProvider* thread_provider,
-                               v8::Isolate* isolate,
+                               ScriptState* script_state,
                                const ScriptValue& function,
                                const Vector<ScriptValue>& arguments,
                                TaskType task_type)
     : ThreadPoolTask(thread_provider,
-                     isolate,
+                     script_state,
                      function,
                      String(),
                      arguments,
                      task_type) {}
 
 ThreadPoolTask::ThreadPoolTask(ThreadPoolThreadProvider* thread_provider,
-                               v8::Isolate* isolate,
+                               ScriptState* script_state,
                                const String& function_name,
                                const Vector<ScriptValue>& arguments,
                                TaskType task_type)
     : ThreadPoolTask(thread_provider,
-                     isolate,
+                     script_state,
                      ScriptValue(),
                      function_name,
                      arguments,
                      task_type) {}
 
 ThreadPoolTask::ThreadPoolTask(ThreadPoolThreadProvider* thread_provider,
-                               v8::Isolate* isolate,
+                               ScriptState* script_state,
                                const ScriptValue& function,
                                const String& function_name,
                                const Vector<ScriptValue>& arguments,
                                TaskType task_type)
     : task_type_(task_type),
       self_keep_alive_(base::AdoptRef(this)),
+      resolver_(ScriptPromiseResolver::Create(script_state)),
       function_name_(function_name.IsolatedCopy()),
       arguments_(arguments.size()),
       weak_factory_(this) {
@@ -55,6 +56,7 @@
   DCHECK_EQ(!function.IsEmpty(), function_name.IsNull());
   DCHECK(task_type_ == TaskType::kUserInteraction ||
          task_type_ == TaskType::kIdleTask);
+  v8::Isolate* isolate = script_state->GetIsolate();
 
   // TODO(japhet): Handle serialization failures
   if (!function.IsEmpty()) {
@@ -167,7 +169,6 @@
 
 ThreadPoolTask::~ThreadPoolTask() {
   DCHECK(IsMainThread());
-  DCHECK(!resolver_);
   DCHECK(HasFinished());
   DCHECK(!function_);
   DCHECK(arguments_.IsEmpty());
@@ -340,37 +341,28 @@
     DCHECK(HasFinished());
     rejected = state_ == State::kFailed;
   }
-  if (resolver_ && resolver_->GetScriptState()->ContextIsValid()) {
-    ScriptState::Scope scope(resolver_->GetScriptState());
-    ScriptValue value = GetResult(resolver_->GetScriptState());
+
+  ScriptState* script_state = resolver_->GetScriptState();
+  if (script_state->ContextIsValid()) {
+    ScriptState::Scope scope(script_state);
+    v8::Local<v8::Value> value;
+    {
+      MutexLocker lock(mutex_);
+      value = serialized_result_->Deserialize(script_state->GetIsolate());
+    }
     if (rejected)
-      resolver_->Reject(v8::Exception::Error(value.V8Value().As<v8::String>()));
+      resolver_->Reject(v8::Exception::Error(value.As<v8::String>()));
     else
       resolver_->Resolve(value);
   }
-  resolver_ = nullptr;
   worker_thread_->DecrementTasksInProgressCount();
   self_keep_alive_.reset();
   // |this| may be deleted here.
 }
 
-ScriptValue ThreadPoolTask::GetResult(ScriptState* script_state) {
+ScriptPromise ThreadPoolTask::GetResult() {
   DCHECK(IsMainThread());
-  MutexLocker lock(mutex_);
-  if (!HasFinished()) {
-    DCHECK(!serialized_result_);
-    DCHECK(deserialized_result_.IsEmpty());
-    if (!resolver_)
-      resolver_ = ScriptPromiseResolver::Create(script_state);
-    return resolver_->Promise().GetScriptValue();
-  }
-  if (deserialized_result_.IsEmpty()) {
-    ScriptState::Scope scope(script_state);
-    deserialized_result_ = ScriptValue(
-        script_state,
-        serialized_result_->Deserialize(script_state->GetIsolate()));
-  }
-  return deserialized_result_;
+  return resolver_->Promise();
 }
 
 void ThreadPoolTask::Cancel() {
diff --git a/third_party/blink/renderer/core/workers/experimental/task.h b/third_party/blink/renderer/core/workers/experimental/task.h
index 0b64e82..0160883 100644
--- a/third_party/blink/renderer/core/workers/experimental/task.h
+++ b/third_party/blink/renderer/core/workers/experimental/task.h
@@ -26,19 +26,18 @@
  public:
   // Called on main thread
   ThreadPoolTask(ThreadPoolThreadProvider*,
-                 v8::Isolate*,
+                 ScriptState*,
                  const ScriptValue& function,
                  const Vector<ScriptValue>& arguments,
                  TaskType);
   ThreadPoolTask(ThreadPoolThreadProvider*,
-                 v8::Isolate*,
+                 ScriptState*,
                  const String& function_name,
                  const Vector<ScriptValue>& arguments,
                  TaskType);
   ~ThreadPoolTask();
-  // Returns the result of this task, or a promise that will be resolved with
-  // the result when it completes.
-  ScriptValue GetResult(ScriptState*) LOCKS_EXCLUDED(mutex_);
+  // Returns a promise that will be resolved with the result when it completes.
+  ScriptPromise GetResult();
   void Cancel() LOCKS_EXCLUDED(mutex_);
 
   base::WeakPtr<ThreadPoolTask> GetWeakPtr() {
@@ -49,7 +48,7 @@
   enum class State { kPending, kStarted, kCancelPending, kCompleted, kFailed };
 
   ThreadPoolTask(ThreadPoolThreadProvider*,
-                 v8::Isolate*,
+                 ScriptState*,
                  const ScriptValue& function,
                  const String& function_name,
                  const Vector<ScriptValue>& arguments,
@@ -85,7 +84,6 @@
 
   // Main thread only
   scoped_refptr<ThreadPoolTask> self_keep_alive_;
-  ScriptValue deserialized_result_;
   Persistent<ScriptPromiseResolver> resolver_;
 
   // Created in constructor on the main thread, consumed and cleared on
@@ -143,9 +141,7 @@
       : thread_pool_task_(thread_pool_task) {}
   ~Task() override = default;
 
-  ScriptValue result(ScriptState* script_state) {
-    return thread_pool_task_->GetResult(script_state);
-  }
+  ScriptPromise result() { return thread_pool_task_->GetResult(); }
   void cancel() { thread_pool_task_->Cancel(); }
 
   ThreadPoolTask* GetThreadPoolTask() const { return thread_pool_task_.get(); }
diff --git a/third_party/blink/renderer/core/workers/experimental/task.idl b/third_party/blink/renderer/core/workers/experimental/task.idl
index c0d2230..58a9ec4 100644
--- a/third_party/blink/renderer/core/workers/experimental/task.idl
+++ b/third_party/blink/renderer/core/workers/experimental/task.idl
@@ -6,6 +6,6 @@
     Exposed=Window,
     RuntimeEnabled=WorkerTaskQueue
 ] interface Task {
-    [CallWith=ScriptState] readonly attribute any result;
+    readonly attribute Promise<any> result;
     void cancel();
 };
diff --git a/third_party/blink/renderer/core/workers/experimental/task_worklet.cc b/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
index 7d5e145..70bb5eb 100644
--- a/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
+++ b/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
@@ -55,18 +55,16 @@
   // TODO(japhet): Here and below: it's unclear what task type should be used,
   // and whether the API should allow it to be configured. Using kIdleTask as a
   // placeholder for now.
-  ThreadPoolTask* thread_pool_task =
-      new ThreadPoolTask(this, script_state->GetIsolate(), function, arguments,
-                         TaskType::kIdleTask);
+  ThreadPoolTask* thread_pool_task = new ThreadPoolTask(
+      this, script_state, function, arguments, TaskType::kIdleTask);
   return new Task(thread_pool_task);
 }
 
 Task* TaskWorklet::postTask(ScriptState* script_state,
                             const String& function_name,
                             const Vector<ScriptValue>& arguments) {
-  ThreadPoolTask* thread_pool_task =
-      new ThreadPoolTask(this, script_state->GetIsolate(), function_name,
-                         arguments, TaskType::kIdleTask);
+  ThreadPoolTask* thread_pool_task = new ThreadPoolTask(
+      this, script_state, function_name, arguments, TaskType::kIdleTask);
   return new Task(thread_pool_task);
 }
 
diff --git a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc
index faf398b..7faaa50e 100644
--- a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc
+++ b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc
@@ -46,16 +46,12 @@
   DCHECK(task.IsFunction());
 
   ThreadPoolTask* thread_pool_task = new ThreadPoolTask(
-      ThreadPool::From(*document_), script_state->GetIsolate(), task, arguments,
-      task_type_);
+      ThreadPool::From(*document_), script_state, task, arguments, task_type_);
   if (signal) {
     signal->AddAlgorithm(
         WTF::Bind(&ThreadPoolTask::Cancel, thread_pool_task->GetWeakPtr()));
   }
-  ScriptValue value = thread_pool_task->GetResult(script_state);
-  DCHECK(value.V8Value()->IsPromise());
-
-  return ScriptPromise(script_state, value.V8Value());
+  return thread_pool_task->GetResult();
 }
 
 Task* WorkerTaskQueue::postTask(ScriptState* script_state,
@@ -64,9 +60,9 @@
   DCHECK(document_->IsContextThread());
   DCHECK(function.IsFunction());
 
-  ThreadPoolTask* thread_pool_task = new ThreadPoolTask(
-      ThreadPool::From(*document_), script_state->GetIsolate(), function,
-      arguments, task_type_);
+  ThreadPoolTask* thread_pool_task =
+      new ThreadPoolTask(ThreadPool::From(*document_), script_state, function,
+                         arguments, task_type_);
   return new Task(thread_pool_task);
 }
 
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
index 76fa9b2a..8c66de4 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
@@ -20,11 +20,23 @@
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
+using blink::IndexedDBKey;
+using blink::WebBlobInfo;
+using blink::WebData;
+using blink::WebIDBCallbacks;
+using blink::WebIDBKey;
+using blink::kWebIDBKeyTypeNumber;
+using blink::WebIDBValue;
+using blink::WebString;
+using blink::WebVector;
+using blink::mojom::blink::IDBCursor;
+using testing::StrictMock;
+
 namespace blink {
 
 namespace {
 
-class MockCursorImpl : public mojom::blink::IDBCursor {
+class MockCursorImpl : public IDBCursor {
  public:
   explicit MockCursorImpl(mojom::blink::IDBCursorAssociatedRequest request)
       : binding_(this, std::move(request)) {
@@ -79,7 +91,7 @@
   mojo::AssociatedBinding<IDBCursor> binding_;
 };
 
-class MockContinueCallbacks : public testing::StrictMock<MockWebIDBCallbacks> {
+class MockContinueCallbacks : public StrictMock<MockWebIDBCallbacks> {
  public:
   MockContinueCallbacks(IndexedDBKey* key = nullptr,
                         WebVector<WebBlobInfo>* blobs = nullptr)
diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
index 5a1720f..f088cca 100644
--- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
+++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
@@ -192,33 +192,57 @@
   return decoded;
 }
 
-bool DecodingImageGenerator::QueryYUV8(SkYUVSizeInfo* size_info,
-                                       SkYUVColorSpace* color_space) const {
+bool DecodingImageGenerator::QueryYUVA8(
+    SkYUVASizeInfo* size_info,
+    SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
+    SkYUVColorSpace* color_space) const {
   // YUV decoding does not currently support progressive decoding. See comment
   // in ImageFrameGenerator.h.
   if (!can_yuv_decode_ || !all_data_received_)
     return false;
 
-  TRACE_EVENT0("blink", "DecodingImageGenerator::queryYUV8");
+  TRACE_EVENT0("blink", "DecodingImageGenerator::queryYUVA8");
 
   if (color_space)
     *color_space = kJPEG_SkYUVColorSpace;
 
+  // Indicate that we have three separate planes
+  indices[SkYUVAIndex::kY_Index] = {0, SkColorChannel::kR};
+  indices[SkYUVAIndex::kU_Index] = {1, SkColorChannel::kR};
+  indices[SkYUVAIndex::kV_Index] = {2, SkColorChannel::kR};
+  indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kR};
+
   return frame_generator_->GetYUVComponentSizes(data_.get(), size_info);
 }
 
-bool DecodingImageGenerator::GetYUV8Planes(const SkYUVSizeInfo& size_info,
-                                           void* planes[3],
-                                           size_t frame_index,
-                                           uint32_t lazy_pixel_ref) {
+bool DecodingImageGenerator::GetYUVA8Planes(const SkYUVASizeInfo& size_info,
+                                            const SkYUVAIndex indices[4],
+                                            void* planes[3],
+                                            size_t frame_index,
+                                            uint32_t lazy_pixel_ref) {
   // YUV decoding does not currently support progressive decoding. See comment
   // in ImageFrameGenerator.h.
   DCHECK(can_yuv_decode_);
   DCHECK(all_data_received_);
 
-  TRACE_EVENT0("blink", "DecodingImageGenerator::getYUV8Planes");
+  TRACE_EVENT0("blink", "DecodingImageGenerator::getYUVA8Planes");
   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                "Decode LazyPixelRef", "LazyPixelRef", lazy_pixel_ref);
+
+  // Verify sizes and indices
+  for (int i = 0; i < 3; ++i) {
+    if (size_info.fSizes[i].isEmpty() || !size_info.fWidthBytes[i]) {
+      return false;
+    }
+  }
+  if (!size_info.fSizes[3].isEmpty() || size_info.fWidthBytes[3]) {
+    return false;
+  }
+  int numPlanes;
+  if (!SkYUVAIndex::AreValidIndices(indices, &numPlanes) || numPlanes != 3) {
+    return false;
+  }
+
   bool decoded =
       frame_generator_->DecodeToYUV(data_.get(), frame_index, size_info.fSizes,
                                     planes, size_info.fWidthBytes);
diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.h b/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
index 8e083e0..5e95cdc 100644
--- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
+++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
+#include "third_party/skia/include/core/SkYUVAIndex.h"
 
 class SkData;
 
@@ -74,11 +75,14 @@
                  size_t frame_index,
                  PaintImage::GeneratorClientId client_id,
                  uint32_t lazy_pixel_ref) override;
-  bool QueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const override;
-  bool GetYUV8Planes(const SkYUVSizeInfo&,
-                     void* planes[3],
-                     size_t frame_index,
-                     uint32_t lazy_pixel_ref) override;
+  bool QueryYUVA8(SkYUVASizeInfo*,
+                  SkYUVAIndex[SkYUVAIndex::kIndexCount],
+                  SkYUVColorSpace*) const override;
+  bool GetYUVA8Planes(const SkYUVASizeInfo&,
+                      const SkYUVAIndex[SkYUVAIndex::kIndexCount],
+                      void* planes[4],
+                      size_t frame_index,
+                      uint32_t lazy_pixel_ref) override;
   SkISize GetSupportedDecodeSize(const SkISize& requested_size) const override;
   PaintImage::ContentId GetContentIdForFrame(size_t frame_index) const override;
 
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index 9dee7c3..38b4148d 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -909,7 +909,7 @@
 }
 
 void GraphicsLayer::SetBackdropFilters(CompositorFilterOperations filters) {
-  CcLayer()->SetBackgroundFilters(filters.ReleaseCcFilterOperations());
+  CcLayer()->SetBackdropFilters(filters.ReleaseCcFilterOperations());
 }
 
 void GraphicsLayer::SetStickyPositionConstraint(
diff --git a/third_party/blink/renderer/platform/graphics/image_frame_generator.cc b/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
index 0b3c8d3..2605e4e 100644
--- a/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
+++ b/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
@@ -34,13 +34,13 @@
 #include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/skia/include/core/SkYUVSizeInfo.h"
+#include "third_party/skia/include/core/SkYUVASizeInfo.h"
 
 namespace blink {
 
 static bool UpdateYUVComponentSizes(ImageDecoder* decoder,
-                                    SkISize component_sizes[3],
-                                    size_t component_width_bytes[3]) {
+                                    SkISize component_sizes[4],
+                                    size_t component_width_bytes[4]) {
   if (!decoder->CanDecodeToYUV())
     return false;
 
@@ -49,6 +49,8 @@
     component_sizes[yuv_index].set(size.Width(), size.Height());
     component_width_bytes[yuv_index] = decoder->DecodedYUVWidthBytes(yuv_index);
   }
+  component_sizes[3] = SkISize::MakeEmpty();
+  component_width_bytes[3] = 0;
 
   return true;
 }
@@ -209,7 +211,7 @@
 }
 
 bool ImageFrameGenerator::GetYUVComponentSizes(SegmentReader* data,
-                                               SkYUVSizeInfo* size_info) {
+                                               SkYUVASizeInfo* size_info) {
   TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width",
                full_size_.width(), "height", full_size_.height());
 
diff --git a/third_party/blink/renderer/platform/graphics/image_frame_generator.h b/third_party/blink/renderer/platform/graphics/image_frame_generator.h
index 593722c..9951c2c 100644
--- a/third_party/blink/renderer/platform/graphics/image_frame_generator.h
+++ b/third_party/blink/renderer/platform/graphics/image_frame_generator.h
@@ -42,8 +42,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkSize.h"
 #include "third_party/skia/include/core/SkTypes.h"
-
-struct SkYUVSizeInfo;
+#include "third_party/skia/include/core/SkYUVASizeInfo.h"
 
 namespace blink {
 
@@ -112,7 +111,7 @@
   // Must not be called unless the SkROBuffer has all the data. YUV decoding
   // does not currently support progressive decoding. See comment above on
   // decodeToYUV().
-  bool GetYUVComponentSizes(SegmentReader*, SkYUVSizeInfo*);
+  bool GetYUVComponentSizes(SegmentReader*, SkYUVASizeInfo*);
 
  private:
   class ClientMutexLocker {
diff --git a/third_party/blink/renderer/platform/heap/heap_compact.cc b/third_party/blink/renderer/platform/heap/heap_compact.cc
index 841dde0..4b6e34c 100644
--- a/third_party/blink/renderer/platform/heap/heap_compact.cc
+++ b/third_party/blink/renderer/platform/heap/heap_compact.cc
@@ -367,10 +367,14 @@
     return force_compaction_gc_;
   }
 
+  // TODO(keishi): Should be enable after fixing the crashes.
+  if (marking_type == BlinkGC::kIncrementalMarking)
+    return false;
+
+  // TODO(harukamt): Add kIncrementalIdleGC and kIncrementalV8FollowupGC when we
+  // enable heap compaction for incremental marking.
   if (reason != BlinkGC::GCReason::kIdleGC &&
       reason != BlinkGC::GCReason::kPreciseGC &&
-      reason != BlinkGC::GCReason::kIncrementalIdleGC &&
-      reason != BlinkGC::GCReason::kIncrementalV8FollowupGC &&
       reason != BlinkGC::GCReason::kForcedGC)
     return false;
 
diff --git a/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h b/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h
index 131469f0..aa96a2b 100644
--- a/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h
+++ b/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h
@@ -11,14 +11,19 @@
 #include "third_party/blink/renderer/platform/wtf/text/cstring.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
-// Conversion from CString to TraceValue so that trace arguments can be strings.
-template <>
-struct base::trace_event::TraceValue::Helper<WTF::CString> {
-  static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING;
-  static inline void SetValue(TraceValue* v, const WTF::CString& value) {
-    v->as_string = value.data();
-  }
-};
+namespace WTF {
+
+// CString version of SetTraceValue so that trace arguments can be strings.
+static inline void SetTraceValue(const CString& arg,
+                                 unsigned char* type,
+                                 unsigned long long* value) {
+  trace_event_internal::TraceValueUnion type_value;
+  type_value.as_string = arg.data();
+  *type = TRACE_VALUE_TYPE_COPY_STRING;
+  *value = type_value.as_uint;
+}
+
+}  // namespace WTF
 
 namespace blink {
 namespace TraceEvent {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index cb9457f..a336971 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1126,6 +1126,7 @@
     // Serialize and restore scroll anchors.
     {
       name: "ScrollAnchorSerialization",
+      status: "test",
     },
     {
       name: "ScrollCustomization",
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index c76622a..6ed20d79 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -215,7 +215,10 @@
                               base::Unretained(this)),
           helper_.ControlMainThreadTaskQueue()->CreateTaskRunner(
               TaskType::kMainThreadTaskQueueControl)),
-      queueing_time_estimator_(this, kQueueingTimeWindowDuration, 20),
+      queueing_time_estimator_(this,
+                               kQueueingTimeWindowDuration,
+                               20,
+                               kLaunchingProcessIsBackgrounded),
       main_thread_only_(this,
                         compositor_task_queue_,
                         helper_.GetClock(),
@@ -995,7 +998,7 @@
   internal::ProcessState::Get()->is_process_backgrounded = backgrounded;
 
   main_thread_only().background_status_changed_at = tick_clock()->NowTicks();
-  queueing_time_estimator_.OnRendererStateChanged(
+  queueing_time_estimator_.OnRecordingStateChanged(
       backgrounded, main_thread_only().background_status_changed_at);
 
   UpdatePolicy();
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
index 18fb850..96c4844 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
@@ -4,12 +4,11 @@
 
 #include "third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h"
 
+#include <algorithm>
+
 #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
 
-#include <algorithm>
-#include <map>
-
 namespace blink {
 namespace scheduler {
 
@@ -42,8 +41,8 @@
   DCHECK_LE(task_start, task_end);
   DCHECK_LE(task_start, step_end);
   DCHECK_LT(step_start, step_end);
-  // Because we skip steps when the renderer is backgrounded, we may have gone
-  // into the future, and in that case we ignore this task completely.
+  // Because we skip steps when disabled, we may have gone into the future, and
+  // in that case we ignore this task completely.
   if (task_end < step_start)
     return base::TimeDelta();
 
@@ -67,10 +66,11 @@
 
 QueueingTimeEstimator::QueueingTimeEstimator(Client* client,
                                              base::TimeDelta window_duration,
-                                             int steps_per_window)
+                                             int steps_per_window,
+                                             bool start_disabled)
     : client_(client),
       window_step_width_(window_duration / steps_per_window),
-      renderer_backgrounded_(kLaunchingProcessIsBackgrounded),
+      disabled_(start_disabled),
       calculator_(steps_per_window) {
   DCHECK_GE(steps_per_window, 1);
 }
@@ -91,13 +91,13 @@
   busy_period_start_time_ = base::TimeTicks();
 }
 
-void QueueingTimeEstimator::OnRendererStateChanged(
-    bool backgrounded,
+void QueueingTimeEstimator::OnRecordingStateChanged(
+    bool disabled,
     base::TimeTicks transition_time) {
-  DCHECK_NE(backgrounded, renderer_backgrounded_);
+  DCHECK_NE(disabled, disabled_);
   if (!busy_)
     AdvanceTime(transition_time);
-  renderer_backgrounded_ = backgrounded;
+  disabled_ = disabled;
 }
 
 void QueueingTimeEstimator::AdvanceTime(base::TimeTicks current_time) {
@@ -110,11 +110,10 @@
   }
   base::TimeTicks reference_time =
       busy_ ? busy_period_start_time_ : step_start_time_;
-  if (renderer_backgrounded_ ||
-      current_time - reference_time > kInvalidPeriodThreshold) {
-    // Skip steps when the renderer was backgrounded, when a task took too long,
-    // or when we remained idle for too long. May cause |step_start_time_| to go
-    // slightly into the future.
+  if (disabled_ || current_time - reference_time > kInvalidPeriodThreshold) {
+    // Skip steps when we're disabled, when a task took too long, or when we
+    // remained idle for too long. May cause |step_start_time_| to go slightly
+    // into the future.
     // TODO(npm): crbug.com/776013. Base skipping long tasks/idling on a signal
     // that we've been suspended.
     step_start_time_ =
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
index f56ab52..c988dfd0 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
@@ -5,16 +5,15 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_QUEUEING_TIME_ESTIMATOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_QUEUEING_TIME_ESTIMATOR_H_
 
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "third_party/blink/public/common/page/launching_process_state.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
-
 #include <array>
 #include <vector>
 
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_status.h"
+
 namespace blink {
 namespace scheduler {
 
@@ -108,12 +107,12 @@
 
   QueueingTimeEstimator(Client* client,
                         base::TimeDelta window_duration,
-                        int steps_per_window);
+                        int steps_per_window,
+                        bool start_disabled);
 
   void OnExecutionStarted(base::TimeTicks now, MainThreadTaskQueue* queue);
   void OnExecutionStopped(base::TimeTicks now);
-  void OnRendererStateChanged(bool backgrounded,
-                              base::TimeTicks transition_time);
+  void OnRecordingStateChanged(bool disabled, base::TimeTicks transition_time);
 
  private:
   void AdvanceTime(base::TimeTicks current_time);
@@ -127,8 +126,8 @@
   bool busy_ = false;
   base::TimeTicks busy_period_start_time_;
 
-  // |renderer_backgrounded_| is the renderer's current status.
-  bool renderer_backgrounded_;
+  // |disabled_| is true iff we want to ignore start/stop events.
+  bool disabled_;
   Calculator calculator_;
 
   DISALLOW_ASSIGN(QueueingTimeEstimator);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
index 780a929..1d435fa 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
@@ -4,6 +4,10 @@
 
 #include "third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h"
 
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -14,10 +18,6 @@
 #include "third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h"
 #include "third_party/blink/renderer/platform/testing/histogram_tester.h"
 
-#include <map>
-#include <string>
-#include <vector>
-
 namespace blink {
 namespace scheduler {
 
@@ -195,8 +195,8 @@
                 fine_grained);
 }
 
-// If we idle for too long, ignore idling time, even if the renderer is on the
-// foreground. Perhaps the user's machine went to sleep while we were idling.
+// If we idle for too long, ignore idling time, even if the estimator is
+// enabled. Perhaps the user's machine went to sleep while we were idling.
 TEST_F(QueueingTimeEstimatorTest, IgnoreExtremelyLongIdlePeriods) {
   QueueingTimeEstimatorForTest estimator(
       &client, base::TimeDelta::FromSeconds(5), 1, time);
@@ -405,9 +405,9 @@
 }
 
 // There are multiple windows, but some of the EQTs are not reported due to
-// backgrounded renderer. EQT(win1) = 0. EQT(win3) = (1500+500)/2 = 1000.
+// enabling/disabling. EQT(win1) = 0. EQT(win3) = (1500+500)/2 = 1000.
 // EQT(win4) = 1/2*500/2 = 250. EQT(win7) = 1/5*200/2 = 20.
-TEST_F(QueueingTimeEstimatorTest, BackgroundedEQTsWithSingleStepPerWindow) {
+TEST_F(QueueingTimeEstimatorTest, DisabledEQTsWithSingleStepPerWindow) {
   QueueingTimeEstimatorForTest estimator(
       &client, base::TimeDelta::FromSeconds(1), 1, time);
   time += base::TimeDelta::FromMilliseconds(1000);
@@ -416,12 +416,12 @@
   time += base::TimeDelta::FromMilliseconds(1001);
 
   // Second window should not be reported.
-  estimator.OnRendererStateChanged(true, time);
+  estimator.OnRecordingStateChanged(true, time);
   estimator.OnExecutionStarted(time, nullptr);
   time += base::TimeDelta::FromMilliseconds(456);
   estimator.OnExecutionStopped(time);
   time += base::TimeDelta::FromMilliseconds(200);
-  estimator.OnRendererStateChanged(false, time);
+  estimator.OnRecordingStateChanged(false, time);
   time += base::TimeDelta::FromMilliseconds(343);
 
   // Third, fourth windows should be reported
@@ -434,9 +434,9 @@
   estimator.OnExecutionStarted(time, nullptr);
   time += base::TimeDelta::FromMilliseconds(800);
   estimator.OnExecutionStopped(time);
-  estimator.OnRendererStateChanged(true, time);
+  estimator.OnRecordingStateChanged(true, time);
   time += base::TimeDelta::FromMilliseconds(200);
-  estimator.OnRendererStateChanged(false, time);
+  estimator.OnRecordingStateChanged(false, time);
   estimator.OnExecutionStarted(time, nullptr);
   time += base::TimeDelta::FromMilliseconds(999);
 
@@ -461,9 +461,9 @@
                 fine_grained);
 }
 
-// We only ignore steps that contain some part that is backgrounded. Thus a
-// window could be made up of non-contiguous steps. The following are EQTs, with
-// time deltas with respect to the end of the first, 0-time task:
+// We only ignore steps that contain some time span that is disabled. Thus a
+// window could be made up of non-contiguous steps. The following are EQTs,
+// with time deltas with respect to the end of the first, 0-time task:
 // Win1: [0-1000]. EQT of step [0-1000]: 500/2*1/2 = 125. EQT(win1) = 125/5 =
 // 25.
 // Win2: [0-1000],[2000-3000]. EQT of [2000-3000]: (1000+200)/2*4/5 = 480.
@@ -480,7 +480,7 @@
 // EQT(win7) = (0+145+900+80+1680)/5 = 561.
 // Win8: [12000-17000]. EQT of [16000-17000]: (1700+700)/2 = 1200. EQT(win8) =
 // (145+900+80+1680+1200)/5 = 801.
-TEST_F(QueueingTimeEstimatorTest, BackgroundedEQTsWithMutipleStepsPerWindow) {
+TEST_F(QueueingTimeEstimatorTest, DisabledEQTsWithMutipleStepsPerWindow) {
   QueueingTimeEstimatorForTest estimator(
       &client, base::TimeDelta::FromSeconds(5), 5, time);
   time += base::TimeDelta::FromMilliseconds(5000);
@@ -492,12 +492,12 @@
   time += base::TimeDelta::FromMilliseconds(500);
   estimator.OnExecutionStopped(time);
 
-  estimator.OnRendererStateChanged(true, time);
+  estimator.OnRecordingStateChanged(true, time);
   // This task should be ignored.
   estimator.OnExecutionStarted(time, nullptr);
   time += base::TimeDelta::FromMilliseconds(800);
   estimator.OnExecutionStopped(time);
-  estimator.OnRendererStateChanged(false, time);
+  estimator.OnRecordingStateChanged(false, time);
 
   time += base::TimeDelta::FromMilliseconds(400);
   estimator.OnExecutionStarted(time, nullptr);
@@ -505,7 +505,7 @@
   estimator.OnExecutionStopped(time);
 
   time += base::TimeDelta::FromMilliseconds(300);
-  estimator.OnRendererStateChanged(true, time);
+  estimator.OnRecordingStateChanged(true, time);
   time += base::TimeDelta::FromMilliseconds(2000);
   // These tasks should be ignored.
   estimator.OnExecutionStarted(time, nullptr);
@@ -514,7 +514,7 @@
   estimator.OnExecutionStarted(time, nullptr);
   time += base::TimeDelta::FromMilliseconds(3400);
   estimator.OnExecutionStopped(time);
-  estimator.OnRendererStateChanged(false, time);
+  estimator.OnRecordingStateChanged(false, time);
 
   time += base::TimeDelta::FromMilliseconds(2000);
   estimator.OnExecutionStarted(time, nullptr);
@@ -527,7 +527,7 @@
   estimator.OnExecutionStopped(time);
 
   // Window with last step should not be reported.
-  estimator.OnRendererStateChanged(true, time);
+  estimator.OnRecordingStateChanged(true, time);
   time += base::TimeDelta::FromMilliseconds(1000);
   estimator.OnExecutionStarted(time, nullptr);
   estimator.OnExecutionStopped(time);
diff --git a/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.cc b/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.cc
index 3d21911e0..20bb1b5 100644
--- a/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.cc
+++ b/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.cc
@@ -7,6 +7,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_conversions.h"
+#include "third_party/blink/public/common/page/launching_process_state.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
 
 namespace blink {
@@ -140,10 +141,13 @@
     base::TimeDelta window_duration,
     int steps_per_window,
     base::TimeTicks time)
-    : QueueingTimeEstimator(client, window_duration, steps_per_window) {
-  // If initial state is not foregrounded, foreground.
+    : QueueingTimeEstimator(client,
+                            window_duration,
+                            steps_per_window,
+                            kLaunchingProcessIsBackgrounded) {
+  // If initial state is disabled, enable the estimator.
   if (kLaunchingProcessIsBackgrounded) {
-    this->OnRendererStateChanged(false, time);
+    this->OnRecordingStateChanged(false, time);
   }
 }
 
diff --git a/third_party/blink/tools/blinkpy/common/net/git_cl.py b/third_party/blink/tools/blinkpy/common/net/git_cl.py
index b425939..6b6fcbc 100644
--- a/third_party/blink/tools/blinkpy/common/net/git_cl.py
+++ b/third_party/blink/tools/blinkpy/common/net/git_cl.py
@@ -248,6 +248,8 @@
         url = result_dict['url']
         if url is None:
             return Build(builder_name, None)
+
+        # LUCI jobs
         # TODO(martiniss): Switch to using build number once `git cl
         # try-results` uses buildbucket v2 API.
         tags = result_dict.get('tags', [])
@@ -256,6 +258,13 @@
                 build_number = tag.split('/')[-1]
                 return Build(builder_name, int(build_number))
 
+        # BuildBot jobs
+        match = re.match(r'.*/builds/(\d+)/?$', url)
+        if match:
+            build_number = match.group(1)
+            return Build(builder_name, int(build_number))
+
+        # Swarming tasks
         match = re.match(r'.*/task/([0-9a-f]+)(/?|\?.*)$', url)
         assert match, '%s did not match expected format' % url
         task_id = match.group(1)
diff --git a/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py b/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py
index 755fa41b..738341c 100644
--- a/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py
+++ b/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py
@@ -478,20 +478,45 @@
     def test_filter_latest_none(self):
         self.assertIsNone(GitCL.filter_latest(None))
 
-    def test_try_job_results_with_task_id_in_url(self):
+    def test_try_job_results_url_format_fallback(self):
         git_cl = GitCL(MockHost())
         git_cl.fetch_raw_try_job_results = lambda **_: [
             {
                 'builder_name': 'builder-a',
                 'status': 'COMPLETED',
                 'result': 'FAILURE',
-                'failure_reason': 'BUILD_FAILURE',
-                'url': ('https://ci.chromium.org/swarming/task/'
-                        '36a767f405d9ee10'),
+                'tags': [
+                    'build_address:luci.chromium.try/chromium_presubmit/100',
+                ],
+                'url': 'http://ci.chromium.org/p/master/builders/builder-b/builds/10',
             },
             {
                 'builder_name': 'builder-b',
                 'status': 'COMPLETED',
+                'result': 'FAILURE',
+                'url': 'http://ci.chromium.org/p/master/builders/builder-b/builds/20',
+            },
+            {
+                'builder_name': 'builder-c',
+                'status': 'COMPLETED',
+                'result': 'FAILURE',
+                'url': 'https://ci.chromium.org/swarming/task/36a767f405d9ee10',
+            },
+        ]
+        self.assertEqual(
+            git_cl.try_job_results(),
+            {
+                Build('builder-a', 100): TryJobStatus('COMPLETED', 'FAILURE'),
+                Build('builder-b', 20): TryJobStatus('COMPLETED', 'FAILURE'),
+                Build('builder-c', '36a767f405d9ee10'): TryJobStatus('COMPLETED', 'FAILURE'),
+            })
+
+    def test_try_job_results_with_swarming_url_with_query(self):
+        git_cl = GitCL(MockHost())
+        git_cl.fetch_raw_try_job_results = lambda **_: [
+            {
+                'builder_name': 'builder-b',
+                'status': 'COMPLETED',
                 'result': 'SUCCESS',
                 'url': ('https://ci.chromium.org/swarming/task/'
                         '38740befcd9c0010?server=chromium-swarm.appspot.com'),
@@ -500,7 +525,6 @@
         self.assertEqual(
             git_cl.try_job_results(),
             {
-                Build('builder-a', '36a767f405d9ee10'): TryJobStatus('COMPLETED', 'FAILURE'),
                 Build('builder-b', '38740befcd9c0010'): TryJobStatus('COMPLETED', 'SUCCESS'),
             })
 
diff --git a/third_party/custom_tabs_client/BUILD.gn b/third_party/custom_tabs_client/BUILD.gn
index e5d6a9e..fd873ac9 100644
--- a/third_party/custom_tabs_client/BUILD.gn
+++ b/third_party/custom_tabs_client/BUILD.gn
@@ -73,6 +73,7 @@
     "src/customtabs/src/android/support/customtabs/CustomTabsServiceConnection.java",
     "src/customtabs/src/android/support/customtabs/CustomTabsSession.java",
     "src/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java",
+    "src/customtabs/src/android/support/customtabs/PostMessageBackend.java",
     "src/customtabs/src/android/support/customtabs/PostMessageService.java",
     "src/customtabs/src/android/support/customtabs/PostMessageServiceConnection.java",
     "src/customtabs/src/android/support/customtabs/TrustedWebUtils.java",
diff --git a/tools/gyp b/tools/gyp
deleted file mode 160000
index d61a939..0000000
--- a/tools/gyp
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit d61a9397e668fa9843c4aa7da9e79460fe590bfb
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index 8260745..c8f4278 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -1111,7 +1111,6 @@
       cmdline = [
         '../../testing/xvfb.py',
         './' + str(executable) + executable_suffix,
-        '--brave-new-test-launcher',
         '--test-launcher-bot-mode',
         '--asan=%d' % asan,
         '--msan=%d' % msan,
@@ -1122,7 +1121,6 @@
       cmdline = [
           '../../testing/test_env.py',
           './' + str(executable) + executable_suffix,
-          '--brave-new-test-launcher',
           '--test-launcher-bot-mode',
           '--asan=%d' % asan,
           '--msan=%d' % msan,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3d9b6398..37ea0f40 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -29198,6 +29198,7 @@
   <int value="-1536293422" label="SharedArrayBuffer:enabled"/>
   <int value="-1536242739" label="security-chip"/>
   <int value="-1535758690" label="AutoplayIgnoreWebAudio:disabled"/>
+  <int value="-1533258008" label="CalculateNativeWinOcclusion:enabled"/>
   <int value="-1532035450" label="DragTabsInTabletMode:disabled"/>
   <int value="-1532014193" label="disable-encryption-migration"/>
   <int value="-1528455406" label="OmniboxPedalSuggestions:enabled"/>
@@ -29681,10 +29682,12 @@
   <int value="-696693295" label="Canvas2DImageChromium:disabled"/>
   <int value="-684900739" label="disable-merge-key-char-events"/>
   <int value="-684223908" label="enable-android-wallpapers-app"/>
+  <int value="-683370370" label="EnableAppDataSearch:enabled"/>
   <int value="-683306022" label="OverscrollHistoryNavigation:enabled"/>
   <int value="-680787130" label="ExperimentalVRFeatures:disabled"/>
   <int value="-680589442" label="MacRTL:disabled"/>
   <int value="-674804217" label="SoleIntegration:enabled"/>
+  <int value="-673804828" label="EnablePlayStoreAppSearch:disabled"/>
   <int value="-671992446" label="TranslateRankerEnforcement:disabled"/>
   <int value="-670188266" label="enable-zip-archiver-unpacker"/>
   <int value="-667517406" label="overscroll-history-navigation"/>
@@ -30464,6 +30467,7 @@
   <int value="879992337" label="disable-pull-to-refresh-effect"/>
   <int value="880510010" label="enable-permissions-bubbles"/>
   <int value="884106779" label="supervised-user-safesites"/>
+  <int value="885971656" label="EnablePlayStoreAppSearch:enabled"/>
   <int value="886907524" label="autoplay-policy"/>
   <int value="887011602" label="enable-spelling-auto-correct"/>
   <int value="892470899" label="SendTabToSelf:enabled"/>
@@ -30492,6 +30496,7 @@
   <int value="941036016" label="ContentSuggestionsSettings:disabled"/>
   <int value="941883332" label="ProactiveTabFreezeAndDiscard:disabled"/>
   <int value="943319566" label="enable-intent-picker"/>
+  <int value="946185008" label="EnableAppDataSearch:disabled"/>
   <int value="946688335" label="OmniboxSpareRenderer:disabled"/>
   <int value="952558794" label="enable-remote-assistance"/>
   <int value="955340765" label="ChromeHomeOptOutSnackbar:enabled"/>
@@ -31088,6 +31093,7 @@
   <int value="2043321329" label="OfflinePagesPrefetchingUI:disabled"/>
   <int value="2056572020" label="EnableUsernameCorrection:disabled"/>
   <int value="2058283872" label="CCTModuleCache:disabled"/>
+  <int value="2058439723" label="CalculateNativeWinOcclusion:disabled"/>
   <int value="2059322877" label="new-avatar-menu"/>
   <int value="2063091429" label="OfflinePagesSharing:enabled"/>
   <int value="2067634730" label="LsdPermissionPrompt:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 7d55892..a28491af 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -72540,7 +72540,21 @@
   <summary>
     Measures the time from navigation timing's navigation start to the time the
     largest image is first painted after fully loaded, for main frame documents.
-    See http://bit.ly/fcp_plus_plus for details.
+    The value is recorded at the end of each page load. See
+    http://bit.ly/fcp_plus_plus for details.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Experimental.PaintTiming.NavigationToLargestTextPaint"
+    units="ms" expires_after="2019-04-23">
+  <owner>maxlg@chromium.org</owner>
+  <owner>speed-metrics-dev@chromium.org</owner>
+  <summary>
+    Measures the time from navigation timing's navigation start to the time the
+    largest text is first painted, for main frame documents. The value is
+    recorded at the end of each page load. See http://bit.ly/fcp_plus_plus for
+    details.
   </summary>
 </histogram>
 
@@ -72551,7 +72565,20 @@
   <summary>
     Measures the time from navigation timing's navigation start to the time the
     last image is first painted after fully loaded, for main frame documents.
-    See http://bit.ly/fcp_plus_plus for details.
+    The value is recorded at the end of each page load. See
+    http://bit.ly/fcp_plus_plus for details.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Experimental.PaintTiming.NavigationToLastTextPaint"
+    units="ms" expires_after="2019-04-23">
+  <owner>maxlg@chromium.org</owner>
+  <owner>speed-metrics-dev@chromium.org</owner>
+  <summary>
+    Measures the time from navigation timing's navigation start to the time the
+    last text is first painted, for main frame documents. The value is recorded
+    at the end of each page load. The value is recorded at the end of each page
+    load. See http://bit.ly/fcp_plus_plus for details.
   </summary>
 </histogram>
 
@@ -122810,6 +122837,16 @@
   </summary>
 </histogram>
 
+<histogram name="Windows.OOPSelectFileDialog.ProcessError" enum="BooleanError">
+  <owner>pmonette@chromium.org</owner>
+  <summary>
+    Indicates whether a connection error occured between the browser and the
+    shell handler process. This is usually caused by a crash in the utility
+    process. This is logged every time SelectFile() function is called and the
+    WinOOPSelectFileDialog feature is enabled.
+  </summary>
+</histogram>
+
 <histogram name="Windows.ParentProcessNameHash" enum="ProcessNameHash">
   <owner>wfh@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index b23b11a..a1c7fc9 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -3064,16 +3064,32 @@
     <summary>
       Measures the time in milliseconds from navigation timing's navigation
       start to the time when the page first paints the largest image within
-      viewport after the image finishes loading. See http://bit.ly/fcp_plus_plus
-      for more details.
+      viewport after the image finishes loading. The value is recorded at the
+      end of each page load. See http://bit.ly/fcp_plus_plus for more details.
+    </summary>
+  </metric>
+  <metric name="Experimental.PaintTiming.NavigationToLargestTextPaint">
+    <summary>
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the time when the page first paints the largest text within
+      viewport. The value is recorded at the end of each page load. See
+      http://bit.ly/fcp_plus_plus for more details.
     </summary>
   </metric>
   <metric name="Experimental.PaintTiming.NavigationToLastImagePaint">
     <summary>
       Measures the time in milliseconds from navigation timing's navigation
       start to the time when the page first paints the last image within
-      viewport after the image finishes loading. See http://bit.ly/fcp_plus_plus
-      for more details.
+      viewport after the image finishes loading. The value is recorded at the
+      end of each page load. See http://bit.ly/fcp_plus_plus for more details.
+    </summary>
+  </metric>
+  <metric name="Experimental.PaintTiming.NavigationToLastTextPaint">
+    <summary>
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the time when the page first paints the last Text within
+      viewport. The value is recorded at the end of each page load. See
+      http://bit.ly/fcp_plus_plus for more details.
     </summary>
   </metric>
   <metric name="InteractiveTiming.FirstInputDelay">
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 1cf51ae..897a255 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -32,6 +32,7 @@
  <item id="blob_reader" hash_code="5154306" type="0" deprecated="2018-06-14" content_hash_code="39702178" file_path=""/>
  <item id="bluetooth_socket" hash_code="94099818" type="0" content_hash_code="30932349" os_list="linux,windows" file_path="device/bluetooth/bluetooth_socket_net.cc"/>
  <item id="brandcode_config" hash_code="109679553" type="0" content_hash_code="128843792" os_list="linux,windows" file_path="chrome/browser/profile_resetter/brandcode_config_fetcher.cc"/>
+ <item id="browser_switcher_ieem_sitelist" hash_code="97159948" type="0" content_hash_code="9996111" os_list="windows" file_path="chrome/browser/browser_switcher/browser_switcher_service.cc"/>
  <item id="captive_portal_service" hash_code="88754904" type="0" content_hash_code="70737580" os_list="linux,windows" file_path="chrome/browser/captive_portal/captive_portal_service.cc"/>
  <item id="cast_channel_send" hash_code="103172229" type="0" deprecated="2018-08-23" content_hash_code="33946302" file_path=""/>
  <item id="cast_keep_alive_delegate" hash_code="134755844" type="0" deprecated="2018-08-23" content_hash_code="66118796" file_path=""/>
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 1b39f76..45635fc 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -138,6 +138,8 @@
     "mus/window_tree_client_delegate.cc",
     "mus/window_tree_host_mus.cc",
     "mus/window_tree_host_mus_init_params.cc",
+    "native_window_occlusion_tracker_win.cc",
+    "native_window_occlusion_tracker_win.h",
     "null_window_targeter.cc",
     "scoped_keyboard_hook.cc",
     "scoped_simple_keyboard_hook.cc",
@@ -155,6 +157,12 @@
     "window_tree_host_platform.cc",
   ]
 
+  # aura_interactive_ui_tests needs access to native_window_occlusion_tracker.h.
+  friend = [
+    ":aura_interactive_ui_tests",
+    ":aura_unittests",
+  ]
+
   defines = [ "AURA_IMPLEMENTATION" ]
 
   deps = [
@@ -394,6 +402,10 @@
     "window_unittest.cc",
   ]
 
+  if (is_win) {
+    sources += [ "native_window_occlusion_tracker_unittest.cc" ]
+  }
+
   deps = [
     ":test_support",
     "//base/test:test_support",
@@ -424,3 +436,29 @@
     "//third_party/mesa_headers",
   ]
 }
+
+# This target is added as a dependency of browser interactive_ui_tests. It must
+# be source_set, otherwise the linker will drop the tests as dead code.
+source_set("aura_interactive_ui_tests") {
+  testonly = true
+  if (is_win) {
+    sources = [
+      "native_window_occlusion_tracker_win_interactive_test.cc",
+    ]
+
+    deps = [
+      ":aura",
+      ":test_support",
+      "//base/test:test_support",
+      "//net",
+      "//testing/gtest",
+      "//ui/base/ime:ime",
+      "//ui/display:display",
+      "//ui/gfx",
+      "//ui/gfx/geometry",
+      "//ui/gl:test_support",
+      "//ui/gl/init",
+      "//ui/views:views",
+    ]
+  }
+}
diff --git a/ui/aura/DEPS b/ui/aura/DEPS
index 263ea23..b2ad0cd2 100644
--- a/ui/aura/DEPS
+++ b/ui/aura/DEPS
@@ -20,6 +20,7 @@
   "+ui/display",
   "+ui/events",
   "+ui/gfx",
+  "+ui/gl/test",
   "+ui/metro_viewer",  # TODO(beng): investigate moving remote_root_window_host
                        #             to ui/metro_viewer.
   "+ui/ozone/public",
diff --git a/ui/aura/native_window_occlusion_tracker_unittest.cc b/ui/aura/native_window_occlusion_tracker_unittest.cc
new file mode 100644
index 0000000..f34b36a
--- /dev/null
+++ b/ui/aura/native_window_occlusion_tracker_unittest.cc
@@ -0,0 +1,158 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/native_window_occlusion_tracker_win.h"
+
+#include <winuser.h>
+
+#include "base/win/scoped_gdi_object.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/test/aura_test_base.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/win/window_impl.h"
+
+namespace aura {
+
+// Test wrapper around native window HWND.
+class TestNativeWindow : public gfx::WindowImpl {
+ public:
+  TestNativeWindow() {}
+  ~TestNativeWindow() override;
+
+ private:
+  // Overridden from gfx::WindowImpl:
+  BOOL ProcessWindowMessage(HWND window,
+                            UINT message,
+                            WPARAM w_param,
+                            LPARAM l_param,
+                            LRESULT& result,
+                            DWORD msg_map_id) override {
+    return FALSE;  // Results in DefWindowProc().
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(TestNativeWindow);
+};
+
+TestNativeWindow::~TestNativeWindow() {
+  if (hwnd())
+    DestroyWindow(hwnd());
+}
+
+// This class currently tests the behavior of
+// NativeWindowOcclusionTrackerWin::IsWindowVisibleAndFullyOpaque with hwnds
+// with various attributes (e.g., minimized, transparent, etc).
+class NativeWindowOcclusionTrackerTest : public test::AuraTestBase {
+ public:
+  NativeWindowOcclusionTrackerTest() {}
+
+  TestNativeWindow* native_win() { return native_win_.get(); }
+
+  HWND CreateNativeWindow(DWORD ex_style) {
+    native_win_ = std::make_unique<TestNativeWindow>();
+    native_win_->set_window_style(WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN);
+    native_win_->set_window_ex_style(ex_style);
+    gfx::Rect bounds(0, 0, 100, 100);
+    native_win_->Init(nullptr, bounds);
+    HWND hwnd = native_win_->hwnd();
+    base::win::ScopedRegion region(CreateRectRgn(0, 0, 0, 0));
+    if (GetWindowRgn(hwnd, region.get()) == COMPLEXREGION) {
+      // On Windows 7, the newly created window has a complex region, which
+      // means it will be ignored during the occlusion calculation. So, force
+      // it to have a simple region so that we get test coverage on win 7.
+      RECT bounding_rect;
+      EXPECT_TRUE(GetWindowRect(hwnd, &bounding_rect));
+      base::win::ScopedRegion rectangular_region(
+          CreateRectRgnIndirect(&bounding_rect));
+      SetWindowRgn(hwnd, rectangular_region.get(), /*redraw=*/TRUE);
+    }
+    ShowWindow(hwnd, SW_SHOWNORMAL);
+    EXPECT_TRUE(UpdateWindow(hwnd));
+    return hwnd;
+  }
+
+  // Wrapper around IsWindowVisibleAndFullyOpaque so only the test class
+  // needs to be a friend of NativeWindowOcclusionTrackerWin.
+  bool CheckWindowVisibleAndFullyOpaque(HWND hwnd, gfx::Rect* win_rect) {
+    bool ret = NativeWindowOcclusionTrackerWin::IsWindowVisibleAndFullyOpaque(
+        hwnd, win_rect);
+    // In general, if IsWindowVisibleAndFullyOpaque returns false, the
+    // returned rect should not be altered.
+    if (!ret)
+      EXPECT_EQ(*win_rect, gfx::Rect(0, 0, 0, 0));
+    return ret;
+  }
+
+ private:
+  std::unique_ptr<TestNativeWindow> native_win_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeWindowOcclusionTrackerTest);
+};
+
+TEST_F(NativeWindowOcclusionTrackerTest, VisibleOpaqueWindow) {
+  HWND hwnd = CreateNativeWindow(/*ex_style=*/0);
+  gfx::Rect returned_rect;
+  // Normal windows should be visible.
+  EXPECT_TRUE(CheckWindowVisibleAndFullyOpaque(hwnd, &returned_rect));
+
+  // Check that the returned rect == the actual window rect of the hwnd.
+  RECT win_rect;
+  ASSERT_TRUE(GetWindowRect(hwnd, &win_rect));
+  EXPECT_EQ(returned_rect, gfx::Rect(win_rect));
+}
+
+TEST_F(NativeWindowOcclusionTrackerTest, MinimizedWindow) {
+  HWND hwnd = CreateNativeWindow(/*ex_style=*/0);
+  gfx::Rect win_rect;
+  ShowWindow(hwnd, SW_MINIMIZE);
+  // Minimized windows are not considered visible.
+  EXPECT_FALSE(CheckWindowVisibleAndFullyOpaque(hwnd, &win_rect));
+}
+
+TEST_F(NativeWindowOcclusionTrackerTest, TransparentWindow) {
+  HWND hwnd = CreateNativeWindow(WS_EX_TRANSPARENT);
+  gfx::Rect win_rect;
+  // Transparent windows are not considered visible and opaque.
+  EXPECT_FALSE(CheckWindowVisibleAndFullyOpaque(hwnd, &win_rect));
+}
+
+TEST_F(NativeWindowOcclusionTrackerTest, ToolWindow) {
+  HWND hwnd = CreateNativeWindow(WS_EX_TOOLWINDOW);
+  gfx::Rect win_rect;
+  // Tool windows are not considered visible and opaque.
+  EXPECT_FALSE(CheckWindowVisibleAndFullyOpaque(hwnd, &win_rect));
+}
+
+TEST_F(NativeWindowOcclusionTrackerTest, LayeredAlphaWindow) {
+  HWND hwnd = CreateNativeWindow(WS_EX_LAYERED);
+  gfx::Rect win_rect;
+  BYTE alpha = 1;
+  DWORD flags = LWA_ALPHA;
+  COLORREF color_ref = RGB(1, 1, 1);
+  SetLayeredWindowAttributes(hwnd, color_ref, alpha, flags);
+  // Layered windows with alpha < 255 are not considered visible and opaque.
+  EXPECT_FALSE(CheckWindowVisibleAndFullyOpaque(hwnd, &win_rect));
+}
+
+TEST_F(NativeWindowOcclusionTrackerTest, LayeredNonAlphaWindow) {
+  HWND hwnd = CreateNativeWindow(WS_EX_LAYERED);
+  gfx::Rect win_rect;
+  BYTE alpha = 1;
+  DWORD flags = 0;
+  COLORREF color_ref = RGB(1, 1, 1);
+  SetLayeredWindowAttributes(hwnd, color_ref, alpha, flags);
+  // Layered non alpha windows are considered visible and opaque.
+  EXPECT_TRUE(CheckWindowVisibleAndFullyOpaque(hwnd, &win_rect));
+}
+
+TEST_F(NativeWindowOcclusionTrackerTest, ComplexRegionWindow) {
+  HWND hwnd = CreateNativeWindow(/*ex_style=*/0);
+  gfx::Rect win_rect;
+  // Create a region with rounded corners, which should be a complex region.
+  base::win::ScopedRegion region(CreateRoundRectRgn(1, 1, 100, 100, 5, 5));
+  SetWindowRgn(hwnd, region.get(), /*redraw=*/TRUE);
+  // Windows with complex regions are not considered visible and fully opaque.
+  EXPECT_FALSE(CheckWindowVisibleAndFullyOpaque(hwnd, &win_rect));
+}
+
+}  // namespace aura
diff --git a/ui/aura/native_window_occlusion_tracker_win.cc b/ui/aura/native_window_occlusion_tracker_win.cc
new file mode 100644
index 0000000..0dddd3d
--- /dev/null
+++ b/ui/aura/native_window_occlusion_tracker_win.cc
@@ -0,0 +1,536 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/native_window_occlusion_tracker_win.h"
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/win/scoped_gdi_object.h"
+#include "ui/aura/window_tree_host.h"
+
+namespace aura {
+
+namespace {
+
+// ~16 ms = time between frames when frame rate is 60 FPS.
+const base::TimeDelta kUpdateOcclusionDelay =
+    base::TimeDelta::FromMilliseconds(16);
+
+NativeWindowOcclusionTrackerWin* g_tracker = nullptr;
+
+}  // namespace
+
+NativeWindowOcclusionTrackerWin*
+NativeWindowOcclusionTrackerWin::GetOrCreateInstance() {
+  if (!g_tracker)
+    g_tracker = new NativeWindowOcclusionTrackerWin();
+
+  return g_tracker;
+}
+
+void NativeWindowOcclusionTrackerWin::Enable(Window* window) {
+  DCHECK(window->IsRootWindow());
+  if (window->HasObserver(this)) {
+    DCHECK(FALSE) << "window shouldn't already be observing occlusion tracker";
+    return;
+  }
+  // Add this as an observer so that we can be notified
+  // when it's no longer true that all windows are minimized, and when the
+  // window is destroyed.
+  HWND root_window_hwnd = window->GetHost()->GetAcceleratedWidget();
+  window->AddObserver(this);
+  // Remember this mapping from hwnd to Window*.
+  hwnd_root_window_map_[root_window_hwnd] = window;
+  // Notify the occlusion thread of the new HWND to track.
+  update_occlusion_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &WindowOcclusionCalculator::EnableOcclusionTrackingForWindow,
+          base::Unretained(occlusion_calculator_.get()), root_window_hwnd));
+}
+
+void NativeWindowOcclusionTrackerWin::Disable(Window* window) {
+  DCHECK(window->IsRootWindow());
+  HWND root_window_hwnd = window->GetHost()->GetAcceleratedWidget();
+  // Check that the root_window_hwnd doesn't get cleared before this is called.
+  DCHECK(root_window_hwnd);
+  hwnd_root_window_map_.erase(root_window_hwnd);
+  window->RemoveObserver(this);
+  update_occlusion_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &WindowOcclusionCalculator::DisableOcclusionTrackingForWindow,
+          base::Unretained(occlusion_calculator_.get()), root_window_hwnd));
+}
+
+void NativeWindowOcclusionTrackerWin::OnWindowVisibilityChanged(Window* window,
+                                                                bool visible) {
+  if (!window->IsRootWindow())
+    return;
+  window->GetHost()->SetNativeWindowOcclusionState(
+      visible ? Window::OcclusionState::UNKNOWN
+              : Window::OcclusionState::HIDDEN);
+  update_occlusion_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&WindowOcclusionCalculator::HandleVisibilityChanged,
+                     base::Unretained(occlusion_calculator_.get()), visible));
+}
+
+void NativeWindowOcclusionTrackerWin::OnWindowDestroying(Window* window) {
+  Disable(window);
+}
+
+NativeWindowOcclusionTrackerWin::NativeWindowOcclusionTrackerWin()
+    :  // Use a COMSTATaskRunner so that registering and unregistering
+       // event hooks will happen on the same thread, as required by Windows,
+       // and the task runner will have a message loop to call
+       // EventHookCallback.
+      update_occlusion_task_runner_(base::CreateCOMSTATaskRunnerWithTraits(
+          {base::MayBlock(),
+           // This may be needed to determine that a window is no longer
+           // occluded.
+           base::TaskPriority::USER_VISIBLE,
+           // Occlusion calculation doesn't need to happen on shutdown.
+           // event hooks should also be cleaned up by Windows.
+           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {
+  occlusion_calculator_ = std::make_unique<WindowOcclusionCalculator>(
+      update_occlusion_task_runner_, base::SequencedTaskRunnerHandle::Get());
+}
+
+NativeWindowOcclusionTrackerWin::~NativeWindowOcclusionTrackerWin() {
+  // This shouldn't be reached, because if it is, |occlusion_calculator_| will
+  // be deleted on the ui thread, which is problematic if there tasks scheduled
+  // on the background thread.
+  NOTREACHED();
+}
+
+// static
+bool NativeWindowOcclusionTrackerWin::IsWindowVisibleAndFullyOpaque(
+    HWND hwnd,
+    gfx::Rect* window_rect) {
+  // Filter out windows that are not “visible”, IsWindowVisible().
+  if (!IsWindow(hwnd) || !IsWindowVisible(hwnd))
+    return false;
+
+  // Filter out minimized windows.
+  if (IsIconic(hwnd))
+    return false;
+
+  LONG ex_styles = GetWindowLong(hwnd, GWL_EXSTYLE);
+
+  // Filter out “transparent” windows, windows where the mouse clicks fall
+  // through them.
+  if (ex_styles & WS_EX_TRANSPARENT)
+    return false;
+
+  // Filter out “tool windows”, which are floating windows that do not appear on
+  // the taskbar or ALT-TAB. Floating windows can have larger window rectangles
+  // than what is visible to the user, so by filtering them out we will avoid
+  // incorrectly marking native windows as occluded.
+  if (ex_styles & WS_EX_TOOLWINDOW)
+    return false;
+
+  // Filter out layered windows that are not opaque or that set a transparency
+  // colorkey.
+  if (ex_styles & WS_EX_LAYERED) {
+    BYTE alpha;
+    DWORD flags;
+    if (GetLayeredWindowAttributes(hwnd, nullptr, &alpha, &flags)) {
+      if (flags & LWA_ALPHA && alpha < 255)
+        return false;
+      if (flags & LWA_COLORKEY)
+        return false;
+    }
+  }
+
+  // Filter out windows that do not have a simple rectangular region.
+  base::win::ScopedRegion region(CreateRectRgn(0, 0, 0, 0));
+  if (GetWindowRgn(hwnd, region.get()) == COMPLEXREGION)
+    return false;
+
+  RECT win_rect;
+  // Filter out windows that take up zero area. The call to GetWindowRect is one
+  // of the most expensive parts of this function, so it is last.
+  if (!GetWindowRect(hwnd, &win_rect))
+    return false;
+  if (IsRectEmpty(&win_rect))
+    return false;
+  *window_rect = gfx::Rect(win_rect);
+  return true;
+}
+
+void NativeWindowOcclusionTrackerWin::UpdateOcclusionState(
+    const base::flat_map<HWND, Window::OcclusionState>&
+        root_window_hwnds_occlusion_state) {
+  for (const auto& root_window_pair : root_window_hwnds_occlusion_state) {
+    auto it = hwnd_root_window_map_.find(root_window_pair.first);
+    // The window was destroyed while processing occlusion.
+    if (it == hwnd_root_window_map_.end())
+      continue;
+    Window* root_window = it->second;
+    // Check Window::IsVisible here, on the UI thread, because it can't be
+    // checked on the occlusion calculation thread.
+    it->second->GetHost()->SetNativeWindowOcclusionState(
+        !root_window->IsVisible() ? Window::OcclusionState::HIDDEN
+                                  : root_window_pair.second);
+  }
+}
+
+NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    WindowOcclusionCalculator(
+        scoped_refptr<base::SequencedTaskRunner> task_runner,
+        scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner)
+    : task_runner_(task_runner), ui_thread_task_runner_(ui_thread_task_runner) {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
+NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    ~WindowOcclusionCalculator() {
+  DCHECK(global_event_hooks_.empty());
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    EnableOcclusionTrackingForWindow(HWND hwnd) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  NativeWindowOcclusionState default_state;
+  root_window_hwnds_occlusion_state_[hwnd] = default_state;
+  if (global_event_hooks_.empty())
+    RegisterEventHooks();
+
+  // Schedule an occlusion calculation so that the newly tracked window does
+  // not have a stale occlusion status.
+  ScheduleOcclusionCalculationIfNeeded();
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    DisableOcclusionTrackingForWindow(HWND hwnd) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  root_window_hwnds_occlusion_state_.erase(hwnd);
+  if (root_window_hwnds_occlusion_state_.empty()) {
+    UnregisterEventHooks();
+    if (occlusion_update_timer_.IsRunning())
+      occlusion_update_timer_.Stop();
+  }
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    HandleVisibilityChanged(bool visible) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // May have gone from having no visible windows to having one, in
+  // which case we need to register event hooks.
+  if (visible)
+    MaybeRegisterEventHooks();
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    MaybeRegisterEventHooks() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (global_event_hooks_.empty())
+    RegisterEventHooks();
+}
+
+// static
+void CALLBACK
+NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::EventHookCallback(
+    HWINEVENTHOOK hWinEventHook,
+    DWORD event,
+    HWND hwnd,
+    LONG idObject,
+    LONG idChild,
+    DWORD dwEventThread,
+    DWORD dwmsEventTime) {
+  g_tracker->occlusion_calculator_->ProcessEventHookCallback(event, hwnd,
+                                                             idObject, idChild);
+}
+
+// static
+BOOL CALLBACK NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    ComputeNativeWindowOcclusionStatusCallback(HWND hwnd, LPARAM lParam) {
+  return g_tracker->occlusion_calculator_
+      ->ProcessComputeNativeWindowOcclusionStatusCallback(
+          hwnd, reinterpret_cast<base::flat_set<DWORD>*>(lParam));
+}
+
+// static
+BOOL CALLBACK NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    UpdateVisibleWindowProcessIdsCallback(HWND hwnd, LPARAM lParam) {
+  g_tracker->occlusion_calculator_
+      ->ProcessUpdateVisibleWindowProcessIdsCallback(hwnd);
+  return TRUE;
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    UpdateVisibleWindowProcessIds() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  pids_for_location_change_hook_.clear();
+  EnumWindows(&UpdateVisibleWindowProcessIdsCallback, 0);
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    ComputeNativeWindowOcclusionStatus() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (root_window_hwnds_occlusion_state_.empty())
+    return;
+  // Set up initial conditions for occlusion calculation.
+  bool all_minimized = true;
+  for (auto& root_window_pair : root_window_hwnds_occlusion_state_) {
+    root_window_pair.second.unoccluded_region.setEmpty();
+    HWND hwnd = root_window_pair.first;
+
+    // IsIconic() checks for a minimized window. Immediately set the state of
+    // minimized windows to HIDDEN.
+    if (IsIconic(hwnd)) {
+      root_window_pair.second.occlusion_state = Window::OcclusionState::HIDDEN;
+    } else {
+      root_window_pair.second.occlusion_state = Window::OcclusionState::UNKNOWN;
+      RECT window_rect;
+      if (GetWindowRect(hwnd, &window_rect) != 0) {
+        root_window_pair.second.unoccluded_region =
+            SkRegion(SkIRect::MakeLTRB(window_rect.left, window_rect.top,
+                                       window_rect.right, window_rect.bottom));
+      }
+      // If call to GetWindowRect fails, window will be treated as occluded,
+      // because unoccluded_region will be empty.
+      all_minimized = false;
+    }
+  }
+  // Unregister event hooks if all native windows are minimized.
+  if (all_minimized) {
+    UnregisterEventHooks();
+  } else {
+    base::flat_set<DWORD> current_pids_with_visible_windows;
+    // Calculate unoccluded region if there is a non-minimized native window.
+    // Also compute |current_pids_with_visible_windows| as we enumerate
+    // the windows.
+    EnumWindows(&ComputeNativeWindowOcclusionStatusCallback,
+                reinterpret_cast<LPARAM>(&current_pids_with_visible_windows));
+    // Check if |pids_for_location_change_hook_| has any pids of processes
+    // currently without visible windows. If so, unhook the win event,
+    // remove the pid from |pids_for_location_change_hook_| and remove
+    // the corresponding event hook from |process_event_hooks_|.
+    base::flat_set<DWORD> pids_to_remove;
+    for (auto loc_change_pid : pids_for_location_change_hook_) {
+      if (current_pids_with_visible_windows.find(loc_change_pid) ==
+          current_pids_with_visible_windows.end()) {
+        // Remove the event hook from our map, and unregister the event hook.
+        // It's possible the eventhook will no longer be valid, but if we don't
+        // unregister the event hook, a process that toggles between having
+        // visible windows and not having visible windows could cause duplicate
+        // event hooks to get registered for the process.
+        UnhookWinEvent(process_event_hooks_[loc_change_pid]);
+        process_event_hooks_.erase(loc_change_pid);
+        pids_to_remove.insert(loc_change_pid);
+      }
+    }
+    if (!pids_to_remove.empty()) {
+      // EraseIf is O(n) so erase pids not found in one fell swoop.
+      base::EraseIf(pids_for_location_change_hook_,
+                    [&pids_to_remove](DWORD pid) {
+                      return pids_to_remove.find(pid) != pids_to_remove.end();
+                    });
+    }
+  }
+  // Determine new occlusion status and post a task to the browser ui
+  // thread to update the window occlusion state on the root windows.
+  base::flat_map<HWND, Window::OcclusionState> window_occlusion_states;
+
+  for (auto& root_window_pair : root_window_hwnds_occlusion_state_) {
+    Window::OcclusionState new_state;
+    if (root_window_pair.second.occlusion_state !=
+        Window::OcclusionState::UNKNOWN) {
+      new_state = root_window_pair.second.occlusion_state;
+    } else {
+      new_state = root_window_pair.second.unoccluded_region.isEmpty()
+                      ? Window::OcclusionState::OCCLUDED
+                      : Window::OcclusionState::VISIBLE;
+    }
+    window_occlusion_states[root_window_pair.first] = new_state;
+    root_window_pair.second.occlusion_state = new_state;
+  }
+  ui_thread_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&NativeWindowOcclusionTrackerWin::UpdateOcclusionState,
+                     base::Unretained(g_tracker), window_occlusion_states));
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    ScheduleOcclusionCalculationIfNeeded() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!occlusion_update_timer_.IsRunning())
+    occlusion_update_timer_.Start(
+        FROM_HERE, kUpdateOcclusionDelay, this,
+        &WindowOcclusionCalculator::ComputeNativeWindowOcclusionStatus);
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    RegisterGlobalEventHook(UINT event_min, UINT event_max) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  HWINEVENTHOOK event_hook =
+      SetWinEventHook(event_min, event_max, nullptr, &EventHookCallback, 0, 0,
+                      WINEVENT_OUTOFCONTEXT);
+
+  global_event_hooks_.push_back(event_hook);
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    RegisterEventHookForProcess(DWORD pid) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  pids_for_location_change_hook_.insert(pid);
+  process_event_hooks_[pid] = SetWinEventHook(
+      EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, nullptr,
+      &EventHookCallback, pid, 0, WINEVENT_OUTOFCONTEXT);
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    RegisterEventHooks() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(global_event_hooks_.empty());
+
+  // Detects native window move (drag) and resizing events.
+  RegisterGlobalEventHook(EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND);
+
+  // Detects native window minimize and restore from taskbar events.
+  RegisterGlobalEventHook(EVENT_SYSTEM_MINIMIZESTART, EVENT_SYSTEM_MINIMIZEEND);
+
+  // Detects foreground window changing.
+  RegisterGlobalEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND);
+
+  // Detects object state changes, e.g., enable/disable state, native window
+  // maximize and native window restore events.
+  RegisterGlobalEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE);
+
+  // Determine which subset of processes to set EVENT_OBJECT_LOCATIONCHANGE on
+  // because otherwise event throughput is very high, as it generates events
+  // for location changes of all objects, including the mouse moving on top of a
+  // window.
+  UpdateVisibleWindowProcessIds();
+  for (DWORD pid : pids_for_location_change_hook_)
+    RegisterEventHookForProcess(pid);
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    UnregisterEventHooks() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  for (HWINEVENTHOOK event_hook : global_event_hooks_)
+    UnhookWinEvent(event_hook);
+  global_event_hooks_.clear();
+
+  for (DWORD pid : pids_for_location_change_hook_)
+    UnhookWinEvent(process_event_hooks_[pid]);
+  process_event_hooks_.clear();
+
+  pids_for_location_change_hook_.clear();
+  window_is_moving_ = false;
+}
+
+bool NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    ProcessComputeNativeWindowOcclusionStatusCallback(
+        HWND hwnd,
+        base::flat_set<DWORD>* current_pids_with_visible_windows) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  gfx::Rect window_rect;
+  // Check if |hwnd| is a root_window; if so, we're done figuring out
+  // if it's occluded because we've seen all the windows "over" it.
+  // TODO(davidbienvenu): Explore checking if occlusion state has been
+  // computed for all |root_window_hwnds_occlusion_state_|, and if so, skipping
+  // further oclcusion calculations. However, we still want to keep computing
+  // |current_pids_with_visible_windows_|, so this function always returns true.
+  for (auto& root_window_pair : root_window_hwnds_occlusion_state_) {
+    if (hwnd == root_window_pair.first) {
+      if (root_window_pair.second.occlusion_state ==
+          Window::OcclusionState::HIDDEN) {
+        break;
+      }
+
+      root_window_pair.second.occlusion_state =
+          root_window_pair.second.unoccluded_region.isEmpty()
+              ? Window::OcclusionState::OCCLUDED
+              : Window::OcclusionState::VISIBLE;
+      break;
+    }
+  }
+  if (!IsWindowVisibleAndFullyOpaque(hwnd, &window_rect))
+    return true;
+  // We are interested in this window, but are not currently hooking it with
+  // EVENT_OBJECT_LOCATION_CHANGE, so we need to hook it. We check
+  // this by seeing if its PID is in |process_event_hooks_|.
+  DWORD pid;
+  GetWindowThreadProcessId(hwnd, &pid);
+  current_pids_with_visible_windows->insert(pid);
+  if (!base::ContainsKey(process_event_hooks_, pid))
+    RegisterEventHookForProcess(pid);
+
+  SkRegion window_region(SkIRect::MakeLTRB(window_rect.x(), window_rect.y(),
+                                           window_rect.right(),
+                                           window_rect.bottom()));
+
+  for (auto& root_window_pair : root_window_hwnds_occlusion_state_) {
+    if (root_window_pair.second.occlusion_state !=
+        Window::OcclusionState::UNKNOWN)
+      continue;
+    if (!root_window_pair.second.unoccluded_region.op(
+            window_region, SkRegion::kDifference_Op)) {
+      root_window_pair.second.occlusion_state =
+          Window::OcclusionState::OCCLUDED;
+    }
+  }
+  return true;
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    ProcessEventHookCallback(DWORD event,
+                             HWND hwnd,
+                             LONG idObject,
+                             LONG idChild) {
+  // Can't do DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_) here. See
+  // comment before call to PostTask below as to why.
+
+  // No need to calculate occlusion if a zero HWND generated the event. This
+  // happens if there is no window associated with the event, e.g., mouse move
+  // events.
+  if (!hwnd)
+    return;
+  // Don't continually calculate occlusion while a window is moving, but rather
+  // once at the beginning and once at the end.
+  if (event == EVENT_SYSTEM_MOVESIZESTART) {
+    // TODO(davidbienvenu): convert to DCHECK once we've confirmed in canary
+    // that this condition isn't met.
+    CHECK(!window_is_moving_);
+    window_is_moving_ = true;
+  } else if (event == EVENT_SYSTEM_MOVESIZEEND) {
+    window_is_moving_ = false;
+  } else if (window_is_moving_) {
+    return;
+  }
+  // ProcessEventHookCallback is called from the task_runner's PeekMessage
+  // call, on the task runner's thread, but before the task_tracker thread sets
+  // up the thread sequence. In order to prevent DCHECK failures with the
+  // |occlusion_update_timer_, we need to call
+  // ScheduleOcclusionCalculationIfNeeded from a task.
+  // See SchedulerWorkerCOMDelegate::GetWorkFromWindowsMessageQueue().
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &WindowOcclusionCalculator::ScheduleOcclusionCalculationIfNeeded,
+          base::Unretained(this)));
+}
+
+void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
+    ProcessUpdateVisibleWindowProcessIdsCallback(HWND hwnd) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  gfx::Rect window_rect;
+  if (IsWindowVisibleAndFullyOpaque(hwnd, &window_rect)) {
+    DWORD pid;
+    GetWindowThreadProcessId(hwnd, &pid);
+    pids_for_location_change_hook_.insert(pid);
+  }
+}
+
+}  // namespace aura
diff --git a/ui/aura/native_window_occlusion_tracker_win.h b/ui/aura/native_window_occlusion_tracker_win.h
new file mode 100644
index 0000000..477e77a
--- /dev/null
+++ b/ui/aura/native_window_occlusion_tracker_win.h
@@ -0,0 +1,217 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_NATIVE_WINDOW_OCCLUSION_TRACKER_WIN_H_
+#define UI_AURA_NATIVE_WINDOW_OCCLUSION_TRACKER_WIN_H_
+
+#include <windows.h>
+#include <winuser.h>
+
+#include <vector>
+
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
+#include "base/sequenced_task_runner.h"
+#include "base/time/time.h"
+#include "ui/aura/aura_export.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+
+namespace aura {
+
+// This class keeps track of whether any HWNDs are occluding any app windows.
+// It notifies the host of any app window whose occlusion state changes. Most
+// code should not need to use this; it's an implementation detail.
+class AURA_EXPORT NativeWindowOcclusionTrackerWin : public WindowObserver {
+ public:
+  static NativeWindowOcclusionTrackerWin* GetOrCreateInstance();
+
+  // Enables notifying the host of |window| via SetNativeWindowOcclusionState()
+  // when the occlusion state has been computed.
+  void Enable(Window* window);
+
+  // Disables notifying the host of |window| via
+  // OnNativeWindowOcclusionStateChanged() when the occlusion state has been
+  // computed. It's not neccesary to call this when |window| is deleted because
+  // OnWindowDestroying calls Disable.
+  void Disable(Window* window);
+
+  // aura::WindowObserver:
+  void OnWindowVisibilityChanged(Window* window, bool visible) override;
+  void OnWindowDestroying(Window* window) override;
+
+ private:
+  friend class NativeWindowOcclusionTrackerTest;
+
+  // This class computes the occlusion state of the tracked windows.
+  // It runs on a separate thread, and notifies the main thread of
+  // the occlusion state of the tracked windows.
+  class WindowOcclusionCalculator {
+   public:
+    WindowOcclusionCalculator(
+        scoped_refptr<base::SequencedTaskRunner> task_runner,
+        scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner);
+    ~WindowOcclusionCalculator();
+
+    void EnableOcclusionTrackingForWindow(HWND hwnd);
+    void DisableOcclusionTrackingForWindow(HWND hwnd);
+
+    // If a window becomes visible, makes sure event hooks are registered.
+    void HandleVisibilityChanged(bool visible);
+
+   private:
+    friend class NativeWindowOcclusionTrackerTest;
+    struct NativeWindowOcclusionState {
+      // The region of the native window that is not occluded by other windows.
+      SkRegion unoccluded_region;
+
+      // The current occlusion state of the native window. Default to UNKNOWN
+      // because we do not know the state starting out. More information on
+      // these states can be found in aura::Window.
+      aura::Window::OcclusionState occlusion_state =
+          aura::Window::OcclusionState::UNKNOWN;
+    };
+
+    // Registers event hooks, if not registered.
+    void MaybeRegisterEventHooks();
+
+    // This is the callback registered to get notified of various Windows
+    // events, like window moving/resizing.
+    static void CALLBACK EventHookCallback(HWINEVENTHOOK hWinEventHook,
+                                           DWORD event,
+                                           HWND hwnd,
+                                           LONG idObject,
+                                           LONG idChild,
+                                           DWORD dwEventThread,
+                                           DWORD dwmsEventTime);
+
+    // EnumWindows callback used to iterate over all hwnds to determine
+    // occlusion status of all tracked root windows.  Also builds up
+    // |current_pids_with_visible_windows_| and registers event hooks for newly
+    // discovered processes with visible hwnds.
+    static BOOL CALLBACK
+    ComputeNativeWindowOcclusionStatusCallback(HWND hwnd, LPARAM lParam);
+
+    // EnumWindows callback used to update the list of process ids with
+    // visible hwnds, |pids_for_location_change_hook_|.
+    static BOOL CALLBACK UpdateVisibleWindowProcessIdsCallback(HWND hwnd,
+                                                               LPARAM lParam);
+
+    // Determines which processes owning visible application windows to set the
+    // EVENT_OBJECT_LOCATIONCHANGE event hook for and stores the pids in
+    // |pids_for_location_change_hook_|.
+    void UpdateVisibleWindowProcessIds();
+
+    // Computes the native window occlusion status for all tracked root aura
+    // windows in |root_window_hwnds_occlusion_state_| and notifies them if
+    // their occlusion status has changed.
+    void ComputeNativeWindowOcclusionStatus();
+
+    // Schedules an occlusion calculation |update_occlusion_delay_| time in the
+    // future, if one isn't already scheduled.
+    void ScheduleOcclusionCalculationIfNeeded();
+
+    // Registers a global event hook (not per process) for the events in the
+    // range from |event_min| to |event_max|, inclusive.
+    void RegisterGlobalEventHook(UINT event_min, UINT event_max);
+
+    // Registers the EVENT_OBJECT_LOCATIONCHANGE event hook for the process with
+    // passed id. The process has one or more visible, opaque windows.
+    void RegisterEventHookForProcess(DWORD pid);
+
+    // Registers/Unregisters the event hooks necessary for occlusion tracking
+    // via calls to RegisterEventHook. These event hooks are disabled when all
+    // tracked windows are minimized.
+    void RegisterEventHooks();
+    void UnregisterEventHooks();
+
+    // EnumWindows callback for occlusion calculation. Returns true to
+    // continue enumeration, false otherwise. Currently, always returns
+    // true because this function also updates
+    // |current_pids_with_visible_windows|, and needs to see all HWNDs.
+    bool ProcessComputeNativeWindowOcclusionStatusCallback(
+        HWND hwnd,
+        base::flat_set<DWORD>* current_pids_with_visible_windows);
+
+    // Processes events sent to OcclusionEventHookCallback.
+    // It generally triggers scheduling of the occlusion calculation, but
+    // ignores certain events in order to not calculate occlusion more than
+    // necessary.
+    void ProcessEventHookCallback(DWORD event,
+                                  HWND hwnd,
+                                  LONG idObject,
+                                  LONG idChild);
+
+    // EnumWindows callback for determining which processes to set the
+    // EVENT_OBJECT_LOCATIONCHANGE event hook for. We set that event hook for
+    // processes hosting fully visible, opaque windows.
+    void ProcessUpdateVisibleWindowProcessIdsCallback(HWND hwnd);
+
+    // Task runner for our thread.
+    scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+    // Task runner for the thread that created |this|.  UpdateOcclusionState
+    // task is posted to this task runner.
+    const scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner_;
+
+    // Map of root app window hwnds and their occlusion state. This contains
+    // both visible and hidden windows.
+    base::flat_map<HWND, NativeWindowOcclusionState>
+        root_window_hwnds_occlusion_state_;
+
+    // Values returned by SetWinEventHook are stored so that hooks can be
+    // unregistered when necessary.
+    std::vector<HWINEVENTHOOK> global_event_hooks_;
+
+    // Map from process id to EVENT_OBJECT_LOCATIONCHANGE event hook.
+    base::flat_map<DWORD, HWINEVENTHOOK> process_event_hooks_;
+
+    // Pids of processes for which the EVENT_OBJECT_LOCATIONCHANGE event hook is
+    // set. These are the processes hosting windows in
+    // |visible_and_fully_opaque_windows_|.
+    base::flat_set<DWORD> pids_for_location_change_hook_;
+
+    // Timer to delay occlusion update.
+    base::OneShotTimer occlusion_update_timer_;
+
+    // Used to keep track of whether we're in the middle of getting window move
+    // events, in order to wait until the window move is complete before
+    // calculating window occlusion.
+    bool window_is_moving_ = false;
+
+    SEQUENCE_CHECKER(sequence_checker_);
+
+    DISALLOW_COPY_AND_ASSIGN(WindowOcclusionCalculator);
+  };
+
+  NativeWindowOcclusionTrackerWin();
+  ~NativeWindowOcclusionTrackerWin() override;
+
+  // Returns true if we are interested in |hwnd| for purposes of occlusion
+  // calculation. We are interested in |hwnd| if it is a window that is visible,
+  // opaque, and bounded. If we are interested in |hwnd|, stores the window
+  // rectangle in |window_rect|.
+  static bool IsWindowVisibleAndFullyOpaque(HWND hwnd, gfx::Rect* window_rect);
+
+  // Updates root windows occclusion state.
+  void UpdateOcclusionState(const base::flat_map<HWND, Window::OcclusionState>&
+                                root_window_hwnds_occlusion_state);
+
+  // Task runner to call ComputeNativeWindowOcclusionStatus, and to handle
+  // Windows event notifications, off of the UI thread.
+  const scoped_refptr<base::SequencedTaskRunner> update_occlusion_task_runner_;
+
+  // Map of HWND to root app windows. Maintained on the UI thread, and used
+  // to send occlusion state notifications to Windows from
+  // |root_window_hwnds_occlusion_state_|.
+  base::flat_map<HWND, Window*> hwnd_root_window_map_;
+
+  std::unique_ptr<WindowOcclusionCalculator> occlusion_calculator_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeWindowOcclusionTrackerWin);
+};
+
+}  // namespace aura
+
+#endif  // UI_AURA_NATIVE_WINDOW_OCCLUSION_TRACKER_WIN_H_
diff --git a/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc b/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc
new file mode 100644
index 0000000..bec46b8
--- /dev/null
+++ b/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc
@@ -0,0 +1,206 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/native_window_occlusion_tracker_win.h"
+
+#include <winuser.h>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/task/task_scheduler/task_scheduler.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/win/scoped_gdi_object.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/env.h"
+#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/test_focus_client.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/test/test_window_parenting_client.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_occlusion_tracker.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/aura/window_tree_host_platform.h"
+#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ui_base_features.h"
+#include "ui/display/win/dpi.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/win/window_impl.h"
+#include "ui/gl/test/gl_surface_test_support.h"
+
+namespace aura {
+
+// This class is used to verify expectations about occlusion state changes by
+// adding instances of it as an observer of aura:Windows the tests create and
+// checking that they get the expected call(s) to OnOcclusionStateChanged.
+// The tests verify that the current state, when idle, is the expected state,
+// because the state can be VISIBLE before it reaches the expected state.
+class MockWindowTreeHostObserver : public WindowTreeHostObserver {
+ public:
+  MockWindowTreeHostObserver() {}
+  ~MockWindowTreeHostObserver() override { EXPECT_FALSE(is_expecting_call()); }
+
+  // WindowTreeHostObserver:
+  void OnOcclusionStateChanged(WindowTreeHost* host,
+                               Window::OcclusionState new_state) override {
+    EXPECT_NE(new_state, Window::OcclusionState::UNKNOWN);
+    // Should only get notified when the occlusion state changes.
+    EXPECT_NE(new_state, cur_state_);
+    cur_state_ = new_state;
+  }
+
+  void set_expectation(Window::OcclusionState expectation) {
+    expectation_ = expectation;
+  }
+
+  bool is_expecting_call() const { return expectation_ != cur_state_; }
+
+ private:
+  Window::OcclusionState expectation_ = Window::OcclusionState::UNKNOWN;
+  Window::OcclusionState cur_state_ = Window::OcclusionState::UNKNOWN;
+
+  DISALLOW_COPY_AND_ASSIGN(MockWindowTreeHostObserver);
+};
+
+// Test wrapper around native window HWND.
+class TestNativeWindow : public gfx::WindowImpl {
+ public:
+  TestNativeWindow() {}
+  ~TestNativeWindow() override;
+
+ private:
+  // Overridden from gfx::WindowImpl:
+  BOOL ProcessWindowMessage(HWND window,
+                            UINT message,
+                            WPARAM w_param,
+                            LPARAM l_param,
+                            LRESULT& result,
+                            DWORD msg_map_id) override {
+    return FALSE;  // Results in DefWindowProc().
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(TestNativeWindow);
+};
+
+TestNativeWindow::~TestNativeWindow() {
+  if (hwnd())
+    DestroyWindow(hwnd());
+}
+
+class NativeWindowOcclusionTrackerTest : public test::AuraTestBase {
+ public:
+  NativeWindowOcclusionTrackerTest() {}
+  void SetUp() override {
+    if (gl::GetGLImplementation() == gl::kGLImplementationNone)
+      gl::GLSurfaceTestSupport::InitializeOneOff();
+
+    AuraTestBase::SetUp();
+    ui::InitializeInputMethodForTesting();
+
+    display::Screen::SetScreenInstance(test_screen());
+
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kCalculateNativeWinOcclusion);
+  }
+
+  void SetNativeWindowBounds(HWND hwnd, const gfx::Rect& bounds) {
+    RECT wr = bounds.ToRECT();
+    AdjustWindowRectEx(&wr, GetWindowLong(hwnd, GWL_STYLE), FALSE,
+                       GetWindowLong(hwnd, GWL_EXSTYLE));
+
+    // Make sure to keep the window onscreen, as AdjustWindowRectEx() may have
+    // moved part of it offscreen.
+    gfx::Rect window_bounds(wr);
+    window_bounds.set_x(std::max(0, window_bounds.x()));
+    window_bounds.set_y(std::max(0, window_bounds.y()));
+    SetWindowPos(hwnd, HWND_TOP, window_bounds.x(), window_bounds.y(),
+                 window_bounds.width(), window_bounds.height(),
+                 SWP_NOREPOSITION);
+    EXPECT_TRUE(UpdateWindow(hwnd));
+  }
+
+  HWND CreateNativeWindowWithBounds(const gfx::Rect& bounds) {
+    native_win_ = std::make_unique<TestNativeWindow>();
+    native_win_->set_window_style(WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN);
+    native_win_->Init(nullptr, bounds);
+    HWND hwnd = native_win_->hwnd();
+    SetNativeWindowBounds(hwnd, bounds);
+    base::win::ScopedRegion region(CreateRectRgn(0, 0, 0, 0));
+    if (GetWindowRgn(hwnd, region.get()) == COMPLEXREGION) {
+      // On Windows 7, the newly created window has a complex region, which
+      // means it will be ignored during the occlusion calculation. So, force
+      // it to have a simple region so that we get test coverage on win 7.
+      RECT bounding_rect;
+      GetWindowRect(hwnd, &bounding_rect);
+      base::win::ScopedRegion rectangular_region(
+          CreateRectRgnIndirect(&bounding_rect));
+      SetWindowRgn(hwnd, rectangular_region.get(), TRUE);
+    }
+    ShowWindow(hwnd, SW_SHOWNORMAL);
+    EXPECT_TRUE(UpdateWindow(hwnd));
+    return hwnd;
+  }
+
+  void CreateTrackedAuraWindowWithBounds(MockWindowTreeHostObserver* observer,
+                                         gfx::Rect bounds) {
+    host()->Show();
+    host()->SetBoundsInPixels(bounds);
+    host()->AddObserver(observer);
+
+    Window* window = CreateNormalWindow(1, host()->window(), nullptr);
+    window->SetBounds(bounds);
+
+    window->env()->GetWindowOcclusionTracker()->Track(window);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+  std::unique_ptr<TestNativeWindow> native_win_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeWindowOcclusionTrackerTest);
+};
+
+// Simple test completely covering an aura window with a native window.
+TEST_F(NativeWindowOcclusionTrackerTest, SimpleOcclusion) {
+  base::RunLoop run_loop;
+
+  std::unique_ptr<MockWindowTreeHostObserver> observer =
+      std::make_unique<MockWindowTreeHostObserver>();
+  CreateTrackedAuraWindowWithBounds(observer.get(), gfx::Rect(0, 0, 100, 100));
+  observer->set_expectation(Window::OcclusionState::OCCLUDED);
+  CreateNativeWindowWithBounds(gfx::Rect(0, 0, 100, 100));
+  run_loop.RunUntilIdle();
+  EXPECT_FALSE(observer->is_expecting_call());
+}
+
+// Simple test with an aura window and native window that do not overlap.
+TEST_F(NativeWindowOcclusionTrackerTest, SimpleVisible) {
+  base::RunLoop run_loop;
+  MockWindowTreeHostObserver observer;
+  CreateTrackedAuraWindowWithBounds(&observer, gfx::Rect(0, 0, 100, 100));
+  observer.set_expectation(Window::OcclusionState::VISIBLE);
+  CreateNativeWindowWithBounds(gfx::Rect(200, 0, 100, 100));
+
+  run_loop.RunUntilIdle();
+  EXPECT_FALSE(observer.is_expecting_call());
+}
+
+// Simple test with a minimized aura window and native window.
+TEST_F(NativeWindowOcclusionTrackerTest, SimpleHidden) {
+  base::RunLoop run_loop;
+  MockWindowTreeHostObserver observer;
+  CreateTrackedAuraWindowWithBounds(&observer, gfx::Rect(0, 0, 100, 100));
+  CreateNativeWindowWithBounds(gfx::Rect(200, 0, 100, 100));
+  // Minimize the tracked aura window and check that its occlusion state
+  // is HIDDEN.
+  ::ShowWindow(host()->GetAcceleratedWidget(), SW_MINIMIZE);
+  observer.set_expectation(Window::OcclusionState::HIDDEN);
+  run_loop.RunUntilIdle();
+  EXPECT_FALSE(observer.is_expecting_call());
+}
+
+}  // namespace aura
diff --git a/ui/aura/window_occlusion_tracker.cc b/ui/aura/window_occlusion_tracker.cc
index 035b5da7..291a414 100644
--- a/ui/aura/window_occlusion_tracker.cc
+++ b/ui/aura/window_occlusion_tracker.cc
@@ -11,6 +11,7 @@
 #include "third_party/skia/include/core/SkRegion.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window_tracker.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 #include "ui/gfx/transform.h"
 
@@ -430,9 +431,18 @@
   DCHECK(root_window);
   RootWindowState& root_window_state = root_windows_[root_window];
   ++root_window_state.num_tracked_windows;
-  if (root_window_state.num_tracked_windows == 1)
-    AddObserverToWindowAndDescendants(root_window);
   MarkRootWindowAsDirty(&root_window_state);
+
+  // It's only useful to track the host if |window| is the first tracked window
+  // under |root_window|.  All windows under the same root have the same host.
+  if (root_window_state.num_tracked_windows == 1) {
+    AddObserverToWindowAndDescendants(root_window);
+    auto* host = root_window->GetHost();
+    if (host) {
+      host->AddObserver(this);
+      host->EnableNativeWindowOcclusionTracking();
+    }
+  }
   MaybeComputeOcclusion();
 }
 
@@ -445,6 +455,8 @@
   if (root_window_state_it->second.num_tracked_windows == 0) {
     RemoveObserverFromWindowAndDescendants(root_window);
     root_windows_.erase(root_window_state_it);
+    root_window->GetHost()->RemoveObserver(this);
+    root_window->GetHost()->DisableNativeWindowOcclusionTracking();
   }
 }
 
@@ -631,4 +643,8 @@
   }
 }
 
+void WindowOcclusionTracker::OnOcclusionStateChanged(
+    WindowTreeHost* host,
+    aura::Window::OcclusionState new_state) {}
+
 }  // namespace aura
diff --git a/ui/aura/window_occlusion_tracker.h b/ui/aura/window_occlusion_tracker.h
index 18183873..e6bb585 100644
--- a/ui/aura/window_occlusion_tracker.h
+++ b/ui/aura/window_occlusion_tracker.h
@@ -16,6 +16,7 @@
 #include "ui/aura/aura_export.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
+#include "ui/aura/window_tree_host_observer.h"
 #include "ui/compositor/layer_animation_observer.h"
 
 struct SkIRect;
@@ -46,7 +47,8 @@
 // Note that an occluded window may be drawn on the screen by window switching
 // features such as "Alt-Tab" or "Overview".
 class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver,
-                                           public WindowObserver {
+                                           public WindowObserver,
+                                           public WindowTreeHostObserver {
  public:
   // Prevents window occlusion state computations within its scope. If an event
   // that could cause window occlusion states to change occurs within the scope
@@ -214,6 +216,10 @@
                                       Window* new_root) override;
   void OnWindowLayerRecreated(Window* window) override;
 
+  // WindowTreeHostObserver
+  void OnOcclusionStateChanged(WindowTreeHost* host,
+                               Window::OcclusionState new_state) override;
+
   // Windows whose occlusion state is tracked.
   base::flat_map<Window*, Window::OcclusionState> tracked_windows_;
 
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index f6d5c61..1379440 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -9,6 +9,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
 #include "components/viz/common/features.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/cursor_client.h"
@@ -39,6 +40,10 @@
 #include "ui/gfx/icc_profile.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
+#if defined(OS_WIN)
+#include "ui/aura/native_window_occlusion_tracker_win.h"
+#endif  // OS_WIN
+
 namespace aura {
 
 namespace {
@@ -78,6 +83,12 @@
 };
 #endif
 
+#if defined(OS_WIN)
+bool IsNativeWindowOcclusionEnabled() {
+  return base::FeatureList::IsEnabled(features::kCalculateNativeWinOcclusion);
+}
+#endif  // OS_WIN
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -118,6 +129,10 @@
   observers_.RemoveObserver(observer);
 }
 
+bool WindowTreeHost::HasObserver(const WindowTreeHostObserver* observer) const {
+  return observers_.HasObserver(observer);
+}
+
 ui::EventSink* WindowTreeHost::event_sink() {
   return dispatcher_.get();
 }
@@ -292,11 +307,38 @@
   return true;
 }
 
+void WindowTreeHost::EnableNativeWindowOcclusionTracking() {
+#if defined(OS_WIN)
+  if (IsNativeWindowOcclusionEnabled()) {
+    NativeWindowOcclusionTrackerWin::GetOrCreateInstance()->Enable(window());
+  }
+#endif  // OS_WIN
+}
+
+void WindowTreeHost::DisableNativeWindowOcclusionTracking() {
+#if defined(OS_WIN)
+  if (IsNativeWindowOcclusionEnabled()) {
+    occlusion_state_ = Window::OcclusionState::UNKNOWN;
+    NativeWindowOcclusionTrackerWin::GetOrCreateInstance()->Disable(window());
+  }
+#endif  // OS_WIN
+}
+
+void WindowTreeHost::SetNativeWindowOcclusionState(
+    Window::OcclusionState state) {
+  if (occlusion_state_ != state) {
+    occlusion_state_ = state;
+    for (WindowTreeHostObserver& observer : observers_)
+      observer.OnOcclusionStateChanged(this, state);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WindowTreeHost, protected:
 
 WindowTreeHost::WindowTreeHost(std::unique_ptr<Window> window)
     : window_(window.release()),  // See header for details on ownership.
+      occlusion_state_(Window::OcclusionState::UNKNOWN),
       last_cursor_(ui::CursorType::kNull),
       input_method_(nullptr),
       owned_input_method_(false),
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h
index 7e19ae7..50b18ca 100644
--- a/ui/aura/window_tree_host.h
+++ b/ui/aura/window_tree_host.h
@@ -80,6 +80,7 @@
 
   void AddObserver(WindowTreeHostObserver* observer);
   void RemoveObserver(WindowTreeHostObserver* observer);
+  bool HasObserver(const WindowTreeHostObserver* observer) const;
 
   Window* window() { return window_; }
   const Window* window() const { return window_; }
@@ -229,6 +230,18 @@
   // WindowEventDispatcher during event dispatch.
   virtual bool ShouldSendKeyEventToIme();
 
+  // Enables native window occlusion tracking for the native window this host
+  // represents.
+  virtual void EnableNativeWindowOcclusionTracking();
+
+  // Disables native window occlusion tracking for the native window this host
+  // represents.
+  virtual void DisableNativeWindowOcclusionTracking();
+
+  // Remembers the current occlusion state, and if it has changed, notifies
+  // observers of the change.
+  virtual void SetNativeWindowOcclusionState(Window::OcclusionState state);
+
  protected:
   friend class ScopedKeyboardHook;
   friend class TestScreen;  // TODO(beng): see if we can remove/consolidate.
@@ -328,6 +341,10 @@
   // the end of the dtor).
   Window* window_;  // Owning.
 
+  // Keeps track of the occlusion state of the host, and used to send
+  // notifications to observers when it changes.
+  Window::OcclusionState occlusion_state_;
+
   base::ObserverList<WindowTreeHostObserver>::Unchecked observers_;
 
   std::unique_ptr<WindowEventDispatcher> dispatcher_;
diff --git a/ui/aura/window_tree_host_observer.h b/ui/aura/window_tree_host_observer.h
index e71455dc..00fe3b4 100644
--- a/ui/aura/window_tree_host_observer.h
+++ b/ui/aura/window_tree_host_observer.h
@@ -6,6 +6,7 @@
 #define UI_AURA_WINDOW_TREE_HOST_OBSERVER_H_
 
 #include "ui/aura/aura_export.h"
+#include "ui/aura/window.h"
 
 namespace gfx {
 class Point;
@@ -29,6 +30,11 @@
   // Called when the native window system sends the host request to close.
   virtual void OnHostCloseRequested(WindowTreeHost* host) {}
 
+  // Called when the occlusion status of the native window changes, iff
+  // occlusion tracking is enabled for a descendant of the root.
+  virtual void OnOcclusionStateChanged(WindowTreeHost* host,
+                                       Window::OcclusionState new_state) {}
+
  protected:
   virtual ~WindowTreeHostObserver() {}
 };
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index 674998b..98700d7f 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -12,6 +12,11 @@
 
 namespace features {
 
+#if defined(OS_WIN)
+// If enabled, calculate native window occlusion - Windows-only.
+const base::Feature kCalculateNativeWinOcclusion{
+    "CalculateNativeWinOcclusion", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif  // OW_WIN
 // If enabled, the emoji picker context menu item may be shown for editable
 // text areas.
 const base::Feature kEnableEmojiContextMenu {
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
index 4a799dda3..a6c9a2c 100644
--- a/ui/base/ui_base_features.h
+++ b/ui/base/ui_base_features.h
@@ -32,6 +32,7 @@
 UI_BASE_EXPORT bool IsUiGpuRasterizationEnabled();
 
 #if defined(OS_WIN)
+UI_BASE_EXPORT extern const base::Feature kCalculateNativeWinOcclusion;
 UI_BASE_EXPORT extern const base::Feature kInputPaneOnScreenKeyboard;
 UI_BASE_EXPORT extern const base::Feature kPointerEventsForTouch;
 UI_BASE_EXPORT extern const base::Feature kPrecisionTouchpad;
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 84997744..4b073ec 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -523,7 +523,7 @@
         background_blur_sigma_, SkBlurImageFilter::kClamp_TileMode));
   }
 
-  cc_layer_->SetBackgroundFilters(filters);
+  cc_layer_->SetBackdropFilters(filters);
 }
 
 float Layer::GetTargetOpacity() const {
diff --git a/ui/shell_dialogs/execute_select_file_win.cc b/ui/shell_dialogs/execute_select_file_win.cc
index 7905699..9f2e7d9 100644
--- a/ui/shell_dialogs/execute_select_file_win.cc
+++ b/ui/shell_dialogs/execute_select_file_win.cc
@@ -7,8 +7,7 @@
 #include <shlobj.h>
 #include <wrl/client.h>
 
-#include <tuple>
-
+#include "base/callback.h"
 #include "base/files/file.h"
 #include "base/files/file_util.h"
 #include "base/win/com_init_util.h"
@@ -365,14 +364,15 @@
   return return_value;
 }
 
-std::pair<std::vector<base::FilePath>, int> ExecuteSelectFile(
+void ExecuteSelectFile(
     SelectFileDialog::Type type,
     const base::string16& title,
     const base::FilePath& default_path,
     const std::vector<FileFilterSpec>& filter,
     int file_type_index,
     const base::string16& default_extension,
-    HWND owner) {
+    HWND owner,
+    OnSelectFileExecutedCallback on_select_file_executed_callback) {
   base::win::AssertComInitialized();
   std::vector<base::FilePath> paths;
   switch (type) {
@@ -401,7 +401,7 @@
       NOTREACHED();
   }
 
-  return std::make_pair(std::move(paths), file_type_index);
+  std::move(on_select_file_executed_callback).Run(paths, file_type_index);
 }
 
 }  // namespace ui
diff --git a/ui/shell_dialogs/execute_select_file_win.h b/ui/shell_dialogs/execute_select_file_win.h
index 0fa7d93..4d2880b 100644
--- a/ui/shell_dialogs/execute_select_file_win.h
+++ b/ui/shell_dialogs/execute_select_file_win.h
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/callback_forward.h"
 #include "base/strings/string16.h"
 #include "base/win/windows_types.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
@@ -35,18 +36,22 @@
   base::string16 extension_spec;
 };
 
-// Shows the file selection dialog modal to |owner| returns the selected
-// file(s) and file type index via the return value. The file path vector will
-// be empty on failure.
+using OnSelectFileExecutedCallback =
+    base::OnceCallback<void(const std::vector<base::FilePath>&, int)>;
+
+// Shows the file selection dialog modal to |owner| returns the selected file(s)
+// and file type index using the |on_select_file_executed_callback|. The file
+// path vector will be empty on failure.
 SHELL_DIALOGS_EXPORT
-std::pair<std::vector<base::FilePath>, int> ExecuteSelectFile(
+void ExecuteSelectFile(
     SelectFileDialog::Type type,
     const base::string16& title,
     const base::FilePath& default_path,
     const std::vector<FileFilterSpec>& filter,
     int file_type_index,
     const base::string16& default_extension,
-    HWND owner);
+    HWND owner,
+    OnSelectFileExecutedCallback on_select_file_executed_callback);
 
 }  // namespace ui
 
diff --git a/ui/shell_dialogs/select_file_dialog_win.cc b/ui/shell_dialogs/select_file_dialog_win.cc
index aecd81c..470a0fd 100644
--- a/ui/shell_dialogs/select_file_dialog_win.cc
+++ b/ui/shell_dialogs/select_file_dialog_win.cc
@@ -126,6 +126,18 @@
   return result;
 }
 
+// Forwards the result from a select file operation to the SelectFileDialog
+// object on the UI thread.
+void OnSelectFileExecutedOnDialogTaskRunner(
+    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
+    OnSelectFileExecutedCallback on_select_file_executed_callback,
+    const std::vector<base::FilePath>& paths,
+    int index) {
+  ui_task_runner->PostTask(
+      FROM_HERE, base::BindOnce(std::move(on_select_file_executed_callback),
+                                paths, index));
+}
+
 // Implementation of SelectFileDialog that shows a Windows common dialog for
 // choosing a file or folder.
 class SelectFileDialogImpl : public ui::SelectFileDialog,
@@ -163,7 +175,8 @@
   void OnSelectFileExecuted(Type type,
                             std::unique_ptr<RunState> run_state,
                             void* params,
-                            std::pair<std::vector<base::FilePath>, int> result);
+                            const std::vector<base::FilePath>& paths,
+                            int index);
 
   bool HasMultipleFileTypeChoicesImpl() override;
 
@@ -190,6 +203,26 @@
 
 SelectFileDialogImpl::~SelectFileDialogImpl() = default;
 
+// Invokes the |execute_select_file_callback| and returns the result to
+void DoSelectFileOnDialogTaskRunner(
+    const ExecuteSelectFileCallback& execute_select_file_callback,
+    SelectFileDialog::Type type,
+    const base::string16& title,
+    const base::FilePath& default_path,
+    const std::vector<ui::FileFilterSpec>& filter,
+    int file_type_index,
+    const base::string16& default_extension,
+    HWND owner,
+    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
+    OnSelectFileExecutedCallback on_select_file_executed_callback) {
+  execute_select_file_callback.Run(
+      type, title, default_path, filter, file_type_index, default_extension,
+      owner,
+      base::BindOnce(&OnSelectFileExecutedOnDialogTaskRunner,
+                     std::move(ui_task_runner),
+                     std::move(on_select_file_executed_callback)));
+}
+
 void SelectFileDialogImpl::SelectFileImpl(
     Type type,
     const base::string16& title,
@@ -211,12 +244,14 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       run_state->dialog_task_runner;
-  base::PostTaskAndReplyWithResult(
-      task_runner.get(), FROM_HERE,
-      base::BindOnce(execute_select_file_callback_, type, title, default_path,
-                     filter, file_type_index, default_extension, owner),
-      base::BindOnce(&SelectFileDialogImpl::OnSelectFileExecuted, this, type,
-                     std::move(run_state), params));
+  task_runner->PostTask(
+      FROM_HERE,
+      base::BindOnce(&DoSelectFileOnDialogTaskRunner,
+                     execute_select_file_callback_, type, title, default_path,
+                     filter, file_type_index, default_extension, owner,
+                     base::ThreadTaskRunnerHandle::Get(),
+                     base::BindOnce(&SelectFileDialogImpl::OnSelectFileExecuted,
+                                    this, type, std::move(run_state), params)));
 }
 
 bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
@@ -240,10 +275,8 @@
     Type type,
     std::unique_ptr<RunState> run_state,
     void* params,
-    std::pair<std::vector<base::FilePath>, int> result) {
-  const std::vector<base::FilePath>& paths = result.first;
-  const int index = result.second;
-
+    const std::vector<base::FilePath>& paths,
+    int index) {
   if (listener_) {
     // The paths vector is empty when the user cancels the dialog.
     if (paths.empty()) {
diff --git a/ui/shell_dialogs/select_file_dialog_win.h b/ui/shell_dialogs/select_file_dialog_win.h
index a09c8955b..6d09000 100644
--- a/ui/shell_dialogs/select_file_dialog_win.h
+++ b/ui/shell_dialogs/select_file_dialog_win.h
@@ -12,6 +12,7 @@
 #include "base/callback_forward.h"
 #include "base/strings/string16.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/shell_dialogs/execute_select_file_win.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 #include "ui/shell_dialogs/shell_dialogs_export.h"
 
@@ -24,15 +25,15 @@
 class SelectFilePolicy;
 struct FileFilterSpec;
 
-using ExecuteSelectFileCallback =
-    base::RepeatingCallback<std::pair<std::vector<base::FilePath>, int>(
-        SelectFileDialog::Type type,
-        const base::string16& title,
-        const base::FilePath& default_path,
-        const std::vector<FileFilterSpec>& filter,
-        int file_type_index,
-        const base::string16& default_extension,
-        HWND owner)>;
+using ExecuteSelectFileCallback = base::RepeatingCallback<void(
+    SelectFileDialog::Type type,
+    const base::string16& title,
+    const base::FilePath& default_path,
+    const std::vector<FileFilterSpec>& filter,
+    int file_type_index,
+    const base::string16& default_extension,
+    HWND owner,
+    OnSelectFileExecutedCallback on_select_file_executed_callback)>;
 
 SHELL_DIALOGS_EXPORT SelectFileDialog* CreateWinSelectFileDialog(
     SelectFileDialog::Listener* listener,
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index faded39..85c8039 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -68,8 +68,11 @@
       return false;
     }
 
-    if (arrow_key_traversal_enabled_ && ProcessArrowKeyTraversal(event))
+    if ((arrow_key_traversal_enabled_ ||
+         arrow_key_traversal_enabled_for_widget_) &&
+        ProcessArrowKeyTraversal(event)) {
       return false;
+    }
 
     // Intercept arrow key messages to switch between grouped views.
     bool is_left = key_code == ui::VKEY_LEFT || key_code == ui::VKEY_UP;
diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h
index d36ac49..3d8d3f3 100644
--- a/ui/views/focus/focus_manager.h
+++ b/ui/views/focus/focus_manager.h
@@ -75,7 +75,7 @@
 class Accelerator;
 class AcceleratorTarget;
 class KeyEvent;
-}
+}  // namespace ui
 
 namespace views {
 
@@ -176,9 +176,7 @@
   }
 
   // Get the reason why the focus most recently changed.
-  FocusChangeReason focus_change_reason() const {
-    return focus_change_reason_;
-  }
+  FocusChangeReason focus_change_reason() const { return focus_change_reason_; }
 
   // Clears the focused view. The window associated with the top root view gets
   // the native focus (so we still get keyboard events).
@@ -297,6 +295,13 @@
     return arrow_key_traversal_enabled_;
   }
 
+  // TODO(weidongg): converts compatible usages of
+  // |arrow_key_traversal_enabled_| to this (https://crbug.com/899431).
+  // Similar to above, but only for the widget that owns this FocusManager.
+  void set_arrow_key_traversal_enabled_for_widget(bool enabled) {
+    arrow_key_traversal_enabled_for_widget_ = enabled;
+  }
+
   // Returns the next focusable view. Traversal starts at |starting_view|. If
   // |starting_view| is NULL |starting_widget| is consuled to determine which
   // Widget to start from. See
@@ -334,9 +339,13 @@
   // ViewObserver:
   void OnViewIsDeleting(View* view) override;
 
-  // Whether arrow key traversal is enabled.
+  // Whether arrow key traversal is enabled globally.
   static bool arrow_key_traversal_enabled_;
 
+  // Whether arrow key traversal is enabled for all widgets under the top-level
+  // widget that owns the FocusManager.
+  bool arrow_key_traversal_enabled_for_widget_ = false;
+
   // The top-level Widget this FocusManager is associated with.
   Widget* widget_;
 
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc
index 1a3a28e..18f3240 100644
--- a/ui/views/mus/desktop_window_tree_host_mus.cc
+++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -237,6 +237,36 @@
 
 }  // namespace
 
+// See description in RestoreToPreminimizedState() for details.
+class DesktopWindowTreeHostMus::RestoreWindowObserver
+    : public aura::WindowObserver {
+ public:
+  explicit RestoreWindowObserver(DesktopWindowTreeHostMus* host) : host_(host) {
+    host->window()->AddObserver(this);
+  }
+  ~RestoreWindowObserver() override { host_->window()->RemoveObserver(this); }
+
+  // aura::WindowObserver:
+  void OnWindowPropertyChanged(aura::Window* window,
+                               const void* key,
+                               intptr_t old) override {
+    if (key == aura::client::kShowStateKey) {
+      host_->restore_window_observer_.reset();
+      // WARNING: this has been deleted.
+    }
+  }
+  void OnWindowDestroying(aura::Window* window) override {
+    // This is owned by DesktopWindowTreeHostMus, which should be destroyed
+    // before the Window.
+    NOTREACHED();
+  }
+
+ private:
+  DesktopWindowTreeHostMus* host_;
+
+  DISALLOW_COPY_AND_ASSIGN(RestoreWindowObserver);
+};
+
 DesktopWindowTreeHostMus::DesktopWindowTreeHostMus(
     aura::WindowTreeHostMusInitParams init_params,
     internal::NativeWidgetDelegate* native_widget_delegate,
@@ -320,6 +350,12 @@
   return type == WIP::TYPE_WINDOW || type == WIP::TYPE_PANEL;
 }
 
+void DesktopWindowTreeHostMus::RestoreToPreminimizedState() {
+  DCHECK(IsMinimized());
+  restore_window_observer_ = std::make_unique<RestoreWindowObserver>(this);
+  window()->Show();
+}
+
 void DesktopWindowTreeHostMus::Init(const Widget::InitParams& params) {
   const bool translucent =
       MusClient::ShouldMakeWidgetWindowsTranslucent(params);
@@ -490,6 +526,11 @@
                                     const gfx::Rect& restore_bounds) {
   native_widget_delegate_->OnNativeWidgetVisibilityChanging(true);
 
+  // NOTE: this code is called from Widget::Show() (no args). Widget::Show()
+  // supplies ui::SHOW_STATE_DEFAULT as the |show_state| after the first call.
+  // If SHOW_STATE_DEFAULT is supplied, and the Window is currently minimized,
+  // the window should be restored to its preminimized state.
+
   if (show_state == ui::SHOW_STATE_MAXIMIZED && !restore_bounds.IsEmpty()) {
     window()->SetProperty(aura::client::kRestoreBoundsKey,
                           new gfx::Rect(restore_bounds));
@@ -497,6 +538,9 @@
   if (show_state == ui::SHOW_STATE_MAXIMIZED ||
       show_state == ui::SHOW_STATE_FULLSCREEN) {
     window()->SetProperty(aura::client::kShowStateKey, show_state);
+    restore_window_observer_.reset();
+  } else if (show_state == ui::SHOW_STATE_DEFAULT && IsMinimized()) {
+    RestoreToPreminimizedState();
   }
   // DesktopWindowTreeHostMus is unique in that it calls window()->Show() here.
   // All other implementations call window()->Show() from the constructor. This
@@ -515,8 +559,10 @@
   native_widget_delegate_->OnNativeWidgetVisibilityChanged(true);
 
   if (native_widget_delegate_->CanActivate()) {
-    if (show_state != ui::SHOW_STATE_INACTIVE)
+    if (show_state != ui::SHOW_STATE_INACTIVE &&
+        show_state != ui::SHOW_STATE_MINIMIZED) {
       Activate();
+    }
 
     // SetInitialFocus() should be always be called, even for
     // SHOW_STATE_INACTIVE. If the window has to stay inactive, the method will
@@ -586,7 +632,13 @@
     ui::WindowShowState* show_state) const {
   // Implementation matches that of NativeWidgetAura.
   *bounds = GetRestoredBounds();
-  *show_state = window()->GetProperty(aura::client::kShowStateKey);
+  if (IsWaitingForRestoreToComplete()) {
+    // The real state is not known, use ui::SHOW_STATE_NORMAL to avoid saving
+    // the minimized state.
+    *show_state = ui::SHOW_STATE_NORMAL;
+  } else {
+    *show_state = window()->GetProperty(aura::client::kShowStateKey);
+  }
 }
 
 gfx::Rect DesktopWindowTreeHostMus::GetWindowBoundsInScreen() const {
@@ -632,6 +684,10 @@
   if (!IsVisible())
     return;
 
+  // Activate() is expected to restore a minimized window.
+  if (IsMinimized())
+    RestoreToPreminimizedState();
+
   // This should result in OnActiveFocusClientChanged() being called, which
   // triggers a call to DesktopNativeWidgetAura::HandleActivationChanged(),
   // which focuses the right window.
@@ -671,6 +727,14 @@
 
 void DesktopWindowTreeHostMus::Minimize() {
   window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
+
+  // When minimized, this should no longer be active.
+  if (IsFocusClientInstalledOnFocusSynchronizer()) {
+    MusClient::Get()
+        ->window_tree_client()
+        ->focus_synchronizer()
+        ->SetActiveFocusClient(nullptr, nullptr);
+  }
 }
 
 void DesktopWindowTreeHostMus::Restore() {
@@ -684,7 +748,8 @@
 
 bool DesktopWindowTreeHostMus::IsMinimized() const {
   return window()->GetProperty(aura::client::kShowStateKey) ==
-         ui::SHOW_STATE_MINIMIZED;
+             ui::SHOW_STATE_MINIMIZED &&
+         !IsWaitingForRestoreToComplete();
 }
 
 bool DesktopWindowTreeHostMus::HasCapture() const {
diff --git a/ui/views/mus/desktop_window_tree_host_mus.h b/ui/views/mus/desktop_window_tree_host_mus.h
index 8e2da5f..d3f452c6 100644
--- a/ui/views/mus/desktop_window_tree_host_mus.h
+++ b/ui/views/mus/desktop_window_tree_host_mus.h
@@ -48,6 +48,8 @@
   }
 
  private:
+  class RestoreWindowObserver;
+
   void SendClientAreaToServer();
 
   // Returns true if the FocusClient associated with our window is installed on
@@ -62,6 +64,24 @@
   // Returns true if the client area should be set on this.
   bool ShouldSendClientAreaToServer() const;
 
+  bool IsWaitingForRestoreToComplete() const {
+    return restore_window_observer_.get() != nullptr;
+  }
+
+  // Restores the window to its pre-minimized state. There are two paths to
+  // unminimizing/restoring a window:
+  // . Implicitly by calling Show()/Activate(). In this scenario the expectation
+  //   is the Widget returns to its pre-minimized state.
+  //   DesktopWindowTreeHostMus does *not* cache the pre-minimized state, only
+  //   the server knows it.
+  // . By calling Restore(). Restore sets the state to normal, circumventing
+  //   the pre-minimized state in the server. This mirrors what NativeWidgetAura
+  //   does.
+  // This function handles the first case. As DesktopWindowTreeHostMus doesn't
+  // know the new state, an observer is added that tracks when the show state
+  // changes. While waiting, IsMinimized() returns false.
+  void RestoreToPreminimizedState();
+
   // DesktopWindowTreeHost:
   void Init(const Widget::InitParams& params) override;
   void OnNativeWidgetCreated(const Widget::InitParams& params) override;
@@ -172,6 +192,9 @@
 
   ScopedObserver<views::View, views::ViewObserver> observed_frame_{this};
 
+  // See description in RestoreToPreminimizedState() for details.
+  std::unique_ptr<RestoreWindowObserver> restore_window_observer_;
+
   // Used so that Close() isn't immediate.
   base::WeakPtrFactory<DesktopWindowTreeHostMus> close_widget_factory_;
 
diff --git a/ui/views/mus/desktop_window_tree_host_mus_unittest.cc b/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
index 159770b..d180e88 100644
--- a/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
+++ b/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
@@ -540,4 +540,38 @@
   EXPECT_TRUE(observer.got_root_window_hidden());
 }
 
+TEST_F(DesktopWindowTreeHostMusTest, MinimizeActivate) {
+  std::unique_ptr<Widget> widget(CreateWidget());
+  widget->Show();
+  EXPECT_TRUE(widget->IsActive());
+
+  widget->Minimize();
+  EXPECT_FALSE(widget->IsActive());
+  EXPECT_TRUE(widget->IsMinimized());
+
+  // Activate() should restore the window.
+  widget->Activate();
+  EXPECT_TRUE(widget->IsActive());
+  EXPECT_FALSE(widget->IsMinimized());
+}
+
+TEST_F(DesktopWindowTreeHostMusTest, MaximizeMinimizeRestore) {
+  std::unique_ptr<Widget> widget(CreateWidget());
+  widget->Show();
+  EXPECT_TRUE(widget->IsActive());
+
+  widget->Maximize();
+  widget->Minimize();
+  EXPECT_FALSE(widget->IsActive());
+  EXPECT_TRUE(widget->IsMinimized());
+  EXPECT_FALSE(widget->IsMaximized());
+
+  widget->Restore();
+  // Restore() *always* sets the state to normal, not the pre-minimized state.
+  // This mirrors the logic in NativeWidgetAura. See
+  // DesktopWindowTreeHostMus::RestoreToPreminimizedState() for details.
+  EXPECT_FALSE(widget->IsMinimized());
+  EXPECT_FALSE(widget->IsMaximized());
+}
+
 }  // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 0886f20..a039a7a 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -15,6 +15,7 @@
 #include "ui/base/class_property.h"
 #include "ui/base/cursor/cursor_loader_win.h"
 #include "ui/base/ime/input_method.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/base/win/shell.h"
 #include "ui/compositor/paint_context.h"
 #include "ui/display/win/dpi.h"
@@ -28,6 +29,7 @@
 #include "ui/gfx/path.h"
 #include "ui/gfx/path_win.h"
 #include "ui/views/corewm/tooltip_win.h"
+#include "ui/views/views_switches.h"
 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h"
 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
@@ -175,7 +177,6 @@
 
 void DesktopWindowTreeHostWin::Close() {
   content_window()->Hide();
-
   // TODO(beng): Move this entire branch to DNWA so it can be shared with X11.
   if (should_animate_window_close_) {
     pending_close_ = true;
@@ -880,6 +881,9 @@
 }
 
 bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) {
+  // TODO(davidbienvenu): Check for getting mouse events for an occluded window
+  // with either a DCHECK or a stat.  Event can cause this object to be deleted
+  // so look at occlusion state before we do anything with the event.
   SendEventToSink(event);
   return event->handled();
 }
diff --git a/webrunner/BUILD.gn b/webrunner/BUILD.gn
index 34bfb1f..e3324bc 100644
--- a/webrunner/BUILD.gn
+++ b/webrunner/BUILD.gn
@@ -279,6 +279,7 @@
 copy("restaged_packages") {
   sources = [
     "$root_gen_dir/webrunner/chromium/chromium.far",
+    "$root_gen_dir/webrunner/net_http/http/http.far",
     "$root_gen_dir/webrunner/web_runner/web_runner.far",
   ]
   outputs = [
@@ -287,6 +288,7 @@
   deps = [
     ":service_pkg",
     ":webrunner_pkg",
+    "net_http:http_pkg",
   ]
 }
 
diff --git a/webrunner/cipd/http.yaml b/webrunner/cipd/http.yaml
new file mode 100644
index 0000000..a8d8a43
--- /dev/null
+++ b/webrunner/cipd/http.yaml
@@ -0,0 +1,32 @@
+# 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.
+
+# Creates a package for the HTTP service binary.
+# The ID of the target architecture (amd64, arm64) must be passed in as
+# a pkg-var so that the packages can be archived at the appropriate location
+# in the CIPD package hierarchy.
+#
+# pkg-var arguments:
+#   outdir: A fully qualified path to the build output directory.
+#   targetarch: The target architecture, either "amd64" or "arm64".
+#
+# To create a CIPD package, run the following command from the build output
+# directory.
+#
+# $ cipd create --pkg-def ../../webrunner/cipd/http.yaml \
+#               -pkg-var targetarch:$TARGET_ARCH \
+#               -pkg-var outdir:`pwd` \
+#               -ref latest \
+#               -tag version:$(cat fuchsia_artifacts/build_id.txt)
+#
+# The most recent package can be discovered by searching for the "latest" ref:
+#
+# $ cipd describe chromium/fuchsia/http-$TARGET_ARCH -version latest
+
+package: chromium/fuchsia/http-${targetarch}
+description: Prebuilt HTTP service binary for Fuchsia.
+root: ${outdir}/fuchsia_artifacts
+data:
+  - file: http.far
+  - file: LICENSE