diff --git a/DEPS b/DEPS
index 08bb6722..b51d1c38 100644
--- a/DEPS
+++ b/DEPS
@@ -162,11 +162,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': '2137f90b9d9898f074699e3253584d5df943e66c',
+  'skia_revision': '6abaff3041a3eb140b82d091ef2aa35063b5c69c',
   # 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': '92a0888e9960118fd643a9d151b7fd4d1c1ffe85',
+  'v8_revision': '87177fcba6dd1ac403023f850431fe8bdedba7d3',
   # 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.
@@ -174,7 +174,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': '273175cdf44e1cba2339580db96432ece6cbfee7',
+  'angle_revision': '096b08fa42e8e1635d7afb7047c3295d991d0982',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -213,7 +213,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '4881f75b7ca04a35da4b467b46b28ae52b176482',
+  'freetype_revision': 'db4083fd7f19fd3fbd5d5a8e60d5c8e0f19778bd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling HarfBuzz
   # and whatever else without interference from each other.
@@ -225,7 +225,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': 'b079ab860152f851bbd13ecedc759145d034e975',
+  'catapult_revision': '6730faf618f825994304332395b41c934d9de512',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -281,7 +281,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '3a762d54f649c756e6b4c25957d11bd0a9d71c1c',
+  'spv_tools_revision': '527a689307a4c15a0a910007327783a1435ac101',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -853,7 +853,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8b16ac056b1ac1d94340578ceda8629641394422',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'edb189d40cb2f72273b10c0f94821b137bd4dbc4',
       'condition': 'checkout_linux',
   },
 
@@ -1257,7 +1257,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '0b27dd1ff740231de4b124217afa6e6ef0dc5e72',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '0c127f488fdbbbbf9190cad96c837d5f6a41717c',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1425,7 +1425,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '7c4e67ff117d6c640e6dd17989afe2fb7da7eecb',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'fc604aa990d5313307d2950b1e68cfa61e99948d',
+    Var('webrtc_git') + '/src.git' + '@' + '90d6efbd4eb4b3a0a6fc26da0bc2f04843865b3e',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1487,7 +1487,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a130294887fc4eade0e6df82bc5e1219602dc6a8',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f2723363e181b4c93f71ec246a448b72b1b5ce20',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc
index 924eba2..d14173f9 100644
--- a/ash/app_list/views/app_list_view.cc
+++ b/ash/app_list/views/app_list_view.cc
@@ -2233,8 +2233,13 @@
   // Update the y position of the background shield.
   gfx::Transform transform;
   if (is_in_drag_) {
+    // For the purpose of determining background shield offset, use progress
+    // with kHalf baseline so the background shield does not start translating
+    // up before it reaches kHalf height (which is larger than kPeeking height).
+    // If the shield transform started at kPeeking height, the app list view
+    // background would jump up when starting drag from the kHalf state.
     float app_list_transition_progress =
-        GetAppListTransitionProgress(kProgressFlagNone);
+        GetAppListTransitionProgress(kProgressFlagSearchResults);
     if (app_list_transition_progress < 1 && !shelf_has_rounded_corners()) {
       const float shelf_height =
           GetScreenBottom() - GetDisplayNearestView().work_area().bottom();
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index 3cdd2ba..54ae92d97 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -557,6 +557,15 @@
   }
 }
 
+void LockContentsView::ShowSystemInfo() {
+  enable_system_info_if_possible_ = true;
+  bool system_info_visible = GetSystemInfoVisibility();
+  if (system_info_visible && !system_info_->GetVisible()) {
+    system_info_->SetVisible(true);
+    LayoutTopHeader();
+  }
+}
+
 void LockContentsView::ShowParentAccessDialog() {
   // ParentAccessDialog should only be shown on lock screen from here.
   DCHECK(primary_big_view_);
@@ -1001,6 +1010,7 @@
 
 void LockContentsView::OnSystemInfoChanged(
     bool show,
+    bool enforced,
     const std::string& os_version_label_text,
     const std::string& enterprise_info_text,
     const std::string& bluetooth_name) {
@@ -1024,8 +1034,15 @@
       system_info_->AddChildView(create_info_label());
   }
 
-  if (show)
-    system_info_->SetVisible(true);
+  if (enforced) {
+    enable_system_info_enforced_ = show;
+  } else {
+    enable_system_info_enforced_ = base::nullopt;
+    enable_system_info_if_possible_ |= show;
+  }
+
+  bool system_info_visible = GetSystemInfoVisibility();
+  system_info_->SetVisible(system_info_visible);
 
   auto update_label = [&](size_t index, const std::string& text) {
     views::Label* label =
@@ -2024,10 +2041,7 @@
       FocusPreviousUser();
       break;
     case AcceleratorAction::kShowSystemInfo:
-      if (!system_info_->GetVisible()) {
-        system_info_->SetVisible(true);
-        LayoutTopHeader();
-      }
+      ShowSystemInfo();
       break;
     case AcceleratorAction::kShowFeedback:
       Shell::Get()->login_screen_controller()->ShowFeedback();
@@ -2040,4 +2054,12 @@
   }
 }
 
+bool LockContentsView::GetSystemInfoVisibility() const {
+  if (enable_system_info_enforced_.has_value()) {
+    return enable_system_info_enforced_.value();
+  } else {
+    return enable_system_info_if_possible_;
+  }
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index 9c9c7b7d..c64ebe3 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -127,6 +127,7 @@
 
   void FocusNextUser();
   void FocusPreviousUser();
+  void ShowSystemInfo();
   void ShowParentAccessDialog();
   void RequestSecurityTokenPin(SecurityTokenPinRequest request);
   void ClearSecurityTokenPinRequest();
@@ -162,6 +163,7 @@
                             const EasyUnlockIconOptions& icon) override;
   void OnWarningMessageUpdated(const base::string16& message) override;
   void OnSystemInfoChanged(bool show,
+                           bool enforced,
                            const std::string& os_version_label_text,
                            const std::string& enterprise_info_text,
                            const std::string& bluetooth_name) override;
@@ -357,6 +359,10 @@
   // Performs the specified accelerator action.
   void PerformAction(AcceleratorAction action);
 
+  // Check whether the view should display the system information based on all
+  // factors including policy settings, channel and Alt-V accelerator.
+  bool GetSystemInfoVisibility() const;
+
   const LockScreen::ScreenType screen_type_;
 
   std::vector<UserState> users_;
@@ -420,6 +426,14 @@
   // screen note state.
   bool disable_lock_screen_note_ = false;
 
+  // Whether the system information should be displayed or not be displayed
+  // forcedly according to policy settings.
+  base::Optional<bool> enable_system_info_enforced_ = base::nullopt;
+
+  // Whether the system information is intended to be displayed if possible.
+  // (e.g., Alt-V is pressed, particular OS channels)
+  bool enable_system_info_if_possible_ = false;
+
   // Expanded view for public account user to select language and keyboard.
   LoginExpandedPublicAccountView* expanded_view_ = nullptr;
 
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc
index ccf2588e..bd76c5b 100644
--- a/ash/login/ui/lock_contents_view_unittest.cc
+++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -663,8 +663,9 @@
 
   // Verify that the system info view becomes visible and it doesn't block the
   // note action button.
-  DataDispatcher()->SetSystemInfo(true /*show_if_hidden*/, "Best version ever",
-                                  "Asset ID: 6666", "Bluetooth adapter");
+  DataDispatcher()->SetSystemInfo(true /*show*/, false /*enforced*/,
+                                  "Best version ever", "Asset ID: 6666",
+                                  "Bluetooth adapter");
   EXPECT_TRUE(test_api.system_info()->GetVisible());
   EXPECT_TRUE(test_api.note_action()->GetVisible());
   gfx::Size note_action_size = test_api.note_action()->GetPreferredSize();
@@ -697,8 +698,9 @@
 
   // Verify that the system info view does not become visible when given data
   // but show is false.
-  DataDispatcher()->SetSystemInfo(false /*show_if_hidden*/, "Best version ever",
-                                  "Asset ID: 6666", "Bluetooth adapter");
+  DataDispatcher()->SetSystemInfo(false /*show*/, false /*enforced*/,
+                                  "Best version ever", "Asset ID: 6666",
+                                  "Bluetooth adapter");
   EXPECT_FALSE(test_api.system_info()->GetVisible());
 
   // Alt-V shows hidden system info.
@@ -712,7 +714,7 @@
   EXPECT_TRUE(test_api.system_info()->GetVisible());
 }
 
-// Updating existing system info and setting show_if_hidden=true later will
+// Updating existing system info and setting show_=true later will
 // reveal hidden system info.
 TEST_F(LockContentsViewUnitTest, ShowRevealsHiddenSystemInfo) {
   auto* contents = new LockContentsView(
@@ -724,21 +726,31 @@
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
   LockContentsView::TestApi test_api(contents);
 
-  auto set_system_info = [&](bool show_if_hidden) {
-    DataDispatcher()->SetSystemInfo(show_if_hidden, "Best version ever",
+  auto set_system_info = [&](bool show, bool enforced) {
+    DataDispatcher()->SetSystemInfo(show, enforced, "Best version ever",
                                     "Asset ID: 6666", "Bluetooth adapter");
   };
 
   // Start with hidden system info.
-  set_system_info(false);
+  set_system_info(false, false);
   EXPECT_FALSE(test_api.system_info()->GetVisible());
 
   // Update system info but request it be shown.
-  set_system_info(true);
+  set_system_info(true, false);
   EXPECT_TRUE(test_api.system_info()->GetVisible());
 
   // Trying to hide system info from mojom call doesn't do anything.
-  set_system_info(false);
+  set_system_info(false, false);
+  EXPECT_TRUE(test_api.system_info()->GetVisible());
+
+  // Trying to hide system info from mojom call with enforced=true. It should
+  // work.
+  set_system_info(false, true);
+  EXPECT_FALSE(test_api.system_info()->GetVisible());
+
+  // System info will be shown again when enforced is reset to false
+  // because the view remembers user wants to show it if possible.
+  set_system_info(false, false);
   EXPECT_TRUE(test_api.system_info()->GetVisible());
 }
 
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc
index 3f3a06d..69e1568a 100644
--- a/ash/login/ui/lock_debug_view.cc
+++ b/ash/login/ui/lock_debug_view.cc
@@ -432,8 +432,9 @@
   void AddSystemInfo(const std::string& os_version,
                      const std::string& enterprise_info,
                      const std::string& bluetooth_name) {
-    debug_dispatcher_.SetSystemInfo(true /*show_if_hidden*/, os_version,
-                                    enterprise_info, bluetooth_name);
+    debug_dispatcher_.SetSystemInfo(true /*show*/, false /*enforced*/,
+                                    os_version, enterprise_info,
+                                    bluetooth_name);
   }
 
   void UpdateWarningMessage(const base::string16& message) {
diff --git a/ash/login/ui/login_data_dispatcher.cc b/ash/login/ui/login_data_dispatcher.cc
index 00e72d7..6c3485b4 100644
--- a/ash/login/ui/login_data_dispatcher.cc
+++ b/ash/login/ui/login_data_dispatcher.cc
@@ -57,6 +57,7 @@
 
 void LoginDataDispatcher::Observer::OnSystemInfoChanged(
     bool show,
+    bool enforced,
     const std::string& os_version_label_text,
     const std::string& enterprise_info_text,
     const std::string& bluetooth_name) {}
@@ -181,12 +182,13 @@
 }
 
 void LoginDataDispatcher::SetSystemInfo(
-    bool show_if_hidden,
+    bool show,
+    bool enforced,
     const std::string& os_version_label_text,
     const std::string& enterprise_info_text,
     const std::string& bluetooth_name) {
   for (auto& observer : observers_) {
-    observer.OnSystemInfoChanged(show_if_hidden, os_version_label_text,
+    observer.OnSystemInfoChanged(show, enforced, os_version_label_text,
                                  enterprise_info_text, bluetooth_name);
   }
 }
diff --git a/ash/login/ui/login_data_dispatcher.h b/ash/login/ui/login_data_dispatcher.h
index 345d6e10..6e9e7c7 100644
--- a/ash/login/ui/login_data_dispatcher.h
+++ b/ash/login/ui/login_data_dispatcher.h
@@ -97,6 +97,7 @@
 
     // Called when the system info has changed.
     virtual void OnSystemInfoChanged(bool show,
+                                     bool enforced,
                                      const std::string& os_version_label_text,
                                      const std::string& enterprise_info_text,
                                      const std::string& bluetooth_name);
@@ -172,7 +173,8 @@
   void ShowEasyUnlockIcon(const AccountId& user,
                           const EasyUnlockIconOptions& icon) override;
   void UpdateWarningMessage(const base::string16& message) override;
-  void SetSystemInfo(bool show_if_hidden,
+  void SetSystemInfo(bool show,
+                     bool enforced,
                      const std::string& os_version_label_text,
                      const std::string& enterprise_info_text,
                      const std::string& bluetooth_name) override;
diff --git a/ash/public/cpp/login_screen_model.h b/ash/public/cpp/login_screen_model.h
index 3632d0f..982b958 100644
--- a/ash/public/cpp/login_screen_model.h
+++ b/ash/public/cpp/login_screen_model.h
@@ -89,14 +89,14 @@
                                 const UserAvatar& avatar) = 0;
 
   // Called when new system information is available.
-  // |show_if_hidden|: If true, the system information should be displayed to
-  //                   the user if it is currently hidden. If false, the system
-  //                   information should remain hidden if not already shown.
-  //                   Hidden system information can be shown by pressing alt-v.
+  // |show|: Whether the system information should be displayed to user.
+  // |enforced|: Whether the display of system information is enforced and
+  // cannot be changed by some specific user operations (e.g., pressing alt-v).
   // |os_version_label_text|: The OS version.
   // |enterprise_info_text|:  The enterprise info.
   // |bluetooth_name|:        The name of the bluetooth adapter.
-  virtual void SetSystemInfo(bool show_if_hidden,
+  virtual void SetSystemInfo(bool show,
+                             bool enforced,
                              const std::string& os_version_label_text,
                              const std::string& enterprise_info_text,
                              const std::string& bluetooth_name) = 0;
diff --git a/base/containers/intrusive_heap.h b/base/containers/intrusive_heap.h
index d7626bb..99f61b4 100644
--- a/base/containers/intrusive_heap.h
+++ b/base/containers/intrusive_heap.h
@@ -716,7 +716,7 @@
 template <typename T, typename Compare, typename HeapHandleAccessor>
 IntrusiveHeap<T, Compare, HeapHandleAccessor>&
 IntrusiveHeap<T, Compare, HeapHandleAccessor>::operator=(
-    IntrusiveHeap&& other) {
+    IntrusiveHeap&& other) noexcept {
   clear();
   impl_ = std::move(other.impl_);
   return *this;
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index 4d961eb..fa5f214 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -23,10 +23,6 @@
 
 namespace base {
 
-namespace internal {
-class MessageLoopThreadDelegate;
-}  // namespace internal
-
 class MessageLoopImpl;
 class MessagePump;
 class TaskObserver;
@@ -160,7 +156,6 @@
   friend class MessageLoopTypedTest;
   friend class ScheduleWorkTest;
   friend class Thread;
-  friend class internal::MessageLoopThreadDelegate;
   friend class sequence_manager::internal::SequenceManagerImpl;
   FRIEND_TEST_ALL_PREFIXES(MessageLoopTest, DeleteUnboundLoop);
 
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc
index 1af026f..7c7cdd4d 100644
--- a/base/message_loop/message_pump_perftest.cc
+++ b/base/message_loop/message_pump_perftest.cc
@@ -9,7 +9,6 @@
 #include "base/bind_helpers.h"
 #include "base/format_macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/single_thread_task_runner.h"
@@ -98,12 +97,7 @@
       target_.reset(new Thread("test"));
 
       Thread::Options options(target_type, 0u);
-
-      std::unique_ptr<MessageLoop> message_loop =
-          MessageLoop::CreateUnbound(target_type);
-      message_loop_ = message_loop.get();
-      options.delegate =
-          new internal::MessageLoopThreadDelegate(std::move(message_loop));
+      options.message_pump_type = target_type;
       target_->StartWithOptions(options);
 
       // Without this, it's possible for the scheduling threads to start and run
@@ -203,7 +197,6 @@
 
  private:
   std::unique_ptr<Thread> target_;
-  MessageLoop* message_loop_;
 #if defined(OS_ANDROID)
   std::unique_ptr<JavaHandlerThreadForTest> java_thread_;
 #endif
diff --git a/base/task/sequence_manager/sequence_manager.h b/base/task/sequence_manager/sequence_manager.h
index 003fab0..8ec2cf3 100644
--- a/base/task/sequence_manager/sequence_manager.h
+++ b/base/task/sequence_manager/sequence_manager.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/message_loop/timer_slack.h"
+#include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task/sequence_manager/task_queue_impl.h"
 #include "base/task/sequence_manager/task_time_observer.h"
@@ -146,6 +147,10 @@
   // performs this initialization automatically.
   virtual void BindToCurrentThread() = 0;
 
+  // Returns the task runner the current task was posted on. Returns null if no
+  // task is currently running. Must be called on the bound thread.
+  virtual scoped_refptr<SequencedTaskRunner> GetTaskRunnerForCurrentTask() = 0;
+
   // Finishes the initialization for a SequenceManager created via
   // CreateUnboundSequenceManagerWithPump(). Must not be called in any other
   // circumstances. The ownership of the pump is transferred to SequenceManager.
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc
index 88aabe0..7eea742 100644
--- a/base/task/sequence_manager/sequence_manager_impl.cc
+++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -320,6 +320,16 @@
   BindToMessagePump(std::move(pump));
 }
 
+scoped_refptr<SequencedTaskRunner>
+SequenceManagerImpl::GetTaskRunnerForCurrentTask() {
+  DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
+  if (main_thread_only().task_execution_stack.empty())
+    return nullptr;
+  return main_thread_only()
+      .task_execution_stack.back()
+      .pending_task.task_runner;
+}
+
 void SequenceManagerImpl::CompleteInitializationOnBoundThread() {
   controller_->AddNestingObserver(this);
   main_thread_only().nesting_observer_registered_ = true;
@@ -488,10 +498,10 @@
 
 }  // namespace
 
-Optional<Task> SequenceManagerImpl::TakeTask() {
-  Optional<Task> task = TakeTaskImpl();
+Task* SequenceManagerImpl::SelectNextTask() {
+  Task* task = SelectNextTaskImpl();
   if (!task)
-    return base::nullopt;
+    return nullptr;
 
   ExecutingTask& executing_task =
       *main_thread_only().task_execution_stack.rbegin();
@@ -561,12 +571,12 @@
 }
 #endif  // DCHECK_IS_ON() && !defined(OS_NACL)
 
-Optional<Task> SequenceManagerImpl::TakeTaskImpl() {
+Task* SequenceManagerImpl::SelectNextTaskImpl() {
   CHECK(Validate());
 
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
-               "SequenceManagerImpl::TakeTask");
+               "SequenceManagerImpl::SelectNextTask");
 
   ReloadEmptyWorkQueues();
   LazyNow lazy_now(controller_->GetClock());
@@ -587,7 +597,7 @@
         this, AsValueWithSelectorResult(work_queue, /* force_verbose */ false));
 
     if (!work_queue)
-      return nullopt;
+      return nullptr;
 
     // If the head task was canceled, remove it and run the selector again.
     if (UNLIKELY(work_queue->RemoveAllCanceledTasksFromFront()))
@@ -612,7 +622,7 @@
             work_queue->task_queue()->GetQueuePriority()))) {
       TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
                    "SequenceManager.YieldToNative");
-      return nullopt;
+      return nullptr;
     }
 
 #if DCHECK_IS_ON() && !defined(OS_NACL)
@@ -627,7 +637,7 @@
         *main_thread_only().task_execution_stack.rbegin();
     NotifyWillProcessTask(&executing_task, &lazy_now);
 
-    return std::move(executing_task.pending_task);
+    return &executing_task.pending_task;
   }
 }
 
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h
index bb69917..d490475 100644
--- a/base/task/sequence_manager/sequence_manager_impl.h
+++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -25,6 +25,7 @@
 #include "base/message_loop/message_pump_type.h"
 #include "base/pending_task.h"
 #include "base/run_loop.h"
+#include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/task/common/task_annotator.h"
@@ -103,6 +104,7 @@
 
   // SequenceManager implementation:
   void BindToCurrentThread() override;
+  scoped_refptr<SequencedTaskRunner> GetTaskRunnerForCurrentTask() override;
   void BindToMessagePump(std::unique_ptr<MessagePump> message_pump) override;
   void SetObserver(Observer* observer) override;
   void AddTaskTimeObserver(TaskTimeObserver* task_time_observer) override;
@@ -128,7 +130,7 @@
       TaskQueue::QueuePriority priority) override;
 
   // SequencedTaskSource implementation:
-  Optional<Task> TakeTask() override;
+  Task* SelectNextTask() override;
   void DidRunTask() override;
   TimeDelta DelayTillNextTask(LazyNow* lazy_now) const override;
   bool HasPendingHighResolutionTasks() override;
@@ -230,7 +232,8 @@
 
   // We have to track rentrancy because we support nested runloops but the
   // selector interface is unaware of those.  This struct keeps track off all
-  // task related state needed to make pairs of TakeTask() / DidRunTask() work.
+  // task related state needed to make pairs of SelectNextTask() / DidRunTask()
+  // work.
   struct ExecutingTask {
     ExecutingTask(Task&& task,
                   internal::TaskQueueImpl* task_queue,
@@ -377,8 +380,8 @@
   void RecordCrashKeys(const PendingTask&);
 
   // Helper to terminate all scoped trace events to allow starting new ones
-  // in TakeTask().
-  Optional<Task> TakeTaskImpl();
+  // in SelectNextTask().
+  Task* SelectNextTaskImpl();
 
   // Check if a task of priority |priority| should run given the pending set of
   // native work.
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
index cb2f91b..3e1bb5d 100644
--- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc
+++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -566,6 +566,18 @@
   DISALLOW_COPY_AND_ASSIGN(TestCountUsesTimeSource);
 };
 
+TEST_P(SequenceManagerTest, GetCorrectTaskRunnerForCurrentTask) {
+  auto queue = CreateTaskQueue();
+
+  queue->task_runner()->PostTask(
+      FROM_HERE, BindLambdaForTesting([&]() {
+        EXPECT_EQ(queue->task_runner(),
+                  sequence_manager()->GetTaskRunnerForCurrentTask());
+      }));
+
+  RunLoop().RunUntilIdle();
+}
+
 TEST_P(SequenceManagerTest, NowNotCalledIfUnneeded) {
   sequence_manager()->SetWorkBatchSize(6);
 
@@ -2356,9 +2368,9 @@
   Mock::VerifyAndClearExpectations(&observer);
 
   // Unless the immediate work queue is emptied.
-  sequence_manager()->TakeTask();
+  sequence_manager()->SelectNextTask();
   sequence_manager()->DidRunTask();
-  sequence_manager()->TakeTask();
+  sequence_manager()->SelectNextTask();
   sequence_manager()->DidRunTask();
   EXPECT_CALL(observer, OnPostTask(_, TimeDelta()));
   EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_));
diff --git a/base/task/sequence_manager/sequenced_task_source.h b/base/task/sequence_manager/sequenced_task_source.h
index b1153fb32..5ea8874 100644
--- a/base/task/sequence_manager/sequenced_task_source.h
+++ b/base/task/sequence_manager/sequenced_task_source.h
@@ -19,13 +19,13 @@
  public:
   virtual ~SequencedTaskSource() = default;
 
-  // Returns the next task to run from this source or nullopt if
+  // Returns the next task to run from this source or nullptr if
   // there're no more tasks ready to run. If a task is returned,
-  // DidRunTask() must be invoked before the next call to TakeTask().
-  virtual Optional<Task> TakeTask() = 0;
+  // DidRunTask() must be invoked before the next call to SelectNextTask().
+  virtual Task* SelectNextTask() = 0;
 
   // Notifies this source that the task previously obtained
-  // from TakeTask() has been completed.
+  // from SelectNextTask() has been completed.
   virtual void DidRunTask() = 0;
 
   // Returns the delay till the next task or TimeDelta::Max()
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc
index d109f915..7c22f9c 100644
--- a/base/task/sequence_manager/task_queue_impl.cc
+++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -78,16 +78,18 @@
 bool TaskQueueImpl::TaskRunner::PostDelayedTask(const Location& location,
                                                 OnceClosure callback,
                                                 TimeDelta delay) {
-  return task_poster_->PostTask(PostedTask(std::move(callback), location, delay,
-                                           Nestable::kNestable, task_type_));
+  return task_poster_->PostTask(PostedTask(this, std::move(callback), location,
+                                           delay, Nestable::kNestable,
+                                           task_type_));
 }
 
 bool TaskQueueImpl::TaskRunner::PostNonNestableDelayedTask(
     const Location& location,
     OnceClosure callback,
     TimeDelta delay) {
-  return task_poster_->PostTask(PostedTask(std::move(callback), location, delay,
-                                           Nestable::kNonNestable, task_type_));
+  return task_poster_->PostTask(PostedTask(this, std::move(callback), location,
+                                           delay, Nestable::kNonNestable,
+                                           task_type_));
 }
 
 bool TaskQueueImpl::TaskRunner::RunsTasksInCurrentSequence() const {
@@ -423,8 +425,10 @@
 #endif
 
   // TODO(altimin): Add a copy method to Task to capture metadata here.
+  auto task_runner = pending_task.task_runner;
   PostImmediateTaskImpl(
-      PostedTask(BindOnce(&TaskQueueImpl::ScheduleDelayedWorkTask,
+      PostedTask(std::move(task_runner),
+                 BindOnce(&TaskQueueImpl::ScheduleDelayedWorkTask,
                           Unretained(this), std::move(pending_task)),
                  FROM_HERE, TimeDelta(), Nestable::kNonNestable,
                  pending_task.task_type),
diff --git a/base/task/sequence_manager/task_queue_selector_unittest.cc b/base/task/sequence_manager/task_queue_selector_unittest.cc
index c99520b..5044770 100644
--- a/base/task/sequence_manager/task_queue_selector_unittest.cc
+++ b/base/task/sequence_manager/task_queue_selector_unittest.cc
@@ -74,7 +74,7 @@
     EnqueueOrderGenerator enqueue_order_generator;
     for (size_t i = 0; i < num_tasks; i++) {
       task_queues_[queue_indices[i]]->immediate_work_queue()->Push(
-          Task(PostedTask(test_closure_, FROM_HERE), TimeTicks(),
+          Task(PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
                EnqueueOrder(), enqueue_order_generator.GenerateNext()));
     }
   }
@@ -84,15 +84,15 @@
                                  size_t num_tasks) {
     for (size_t i = 0; i < num_tasks; i++) {
       task_queues_[queue_indices[i]]->immediate_work_queue()->Push(Task(
-          PostedTask(test_closure_, FROM_HERE), TimeTicks(), EnqueueOrder(),
-          EnqueueOrder::FromIntForTesting(enqueue_orders[i])));
+          PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
+          EnqueueOrder(), EnqueueOrder::FromIntForTesting(enqueue_orders[i])));
     }
   }
 
   void PushTask(const size_t queue_index, const size_t enqueue_order) {
     task_queues_[queue_index]->immediate_work_queue()->Push(
-        Task(PostedTask(test_closure_, FROM_HERE), TimeTicks(), EnqueueOrder(),
-             EnqueueOrder::FromIntForTesting(enqueue_order)));
+        Task(PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
+             EnqueueOrder(), EnqueueOrder::FromIntForTesting(enqueue_order)));
   }
 
   std::vector<size_t> PopTasksAndReturnQueueIndices() {
@@ -666,8 +666,8 @@
 
 TEST_F(TaskQueueSelectorTest, ChooseWithPriority_OnlyDelayed) {
   task_queues_[0]->delayed_work_queue()->Push(
-      Task(PostedTask(test_closure_, FROM_HERE), TimeTicks(), EnqueueOrder(),
-           EnqueueOrder::FromIntForTesting(2)));
+      Task(PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
+           EnqueueOrder(), EnqueueOrder::FromIntForTesting(2)));
 
   bool chose_delayed_over_immediate = false;
   EXPECT_EQ(
@@ -680,8 +680,8 @@
 
 TEST_F(TaskQueueSelectorTest, ChooseWithPriority_OnlyImmediate) {
   task_queues_[0]->immediate_work_queue()->Push(
-      Task(PostedTask(test_closure_, FROM_HERE), TimeTicks(), EnqueueOrder(),
-           EnqueueOrder::FromIntForTesting(2)));
+      Task(PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
+           EnqueueOrder(), EnqueueOrder::FromIntForTesting(2)));
 
   bool chose_delayed_over_immediate = false;
   EXPECT_EQ(
@@ -706,8 +706,8 @@
   task_queue->SetQueueEnabled(false);
   selector.DisableQueue(task_queue.get());
 
-  Task task(PostedTask(test_closure_, FROM_HERE), TimeTicks(), EnqueueOrder(),
-            EnqueueOrder::FromIntForTesting(2));
+  Task task(PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
+            EnqueueOrder(), EnqueueOrder::FromIntForTesting(2));
   task_queue->immediate_work_queue()->Push(std::move(task));
 
   EXPECT_EQ(nullptr, selector.SelectWorkQueueToService());
@@ -736,10 +736,10 @@
 
   selector.SetQueuePriority(task_queue2.get(), TaskQueue::kControlPriority);
 
-  Task task1(PostedTask(test_closure_, FROM_HERE), TimeTicks(),
+  Task task1(PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
              EnqueueOrder::FromIntForTesting(2),
              EnqueueOrder::FromIntForTesting(2));
-  Task task2(PostedTask(test_closure_, FROM_HERE), TimeTicks(),
+  Task task2(PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
              EnqueueOrder::FromIntForTesting(3),
              EnqueueOrder::FromIntForTesting(3));
   task_queue->immediate_work_queue()->Push(std::move(task1));
@@ -854,13 +854,13 @@
 
 TEST_P(ChooseWithPriorityTest, RoundRobinTest) {
   task_queues_[0]->immediate_work_queue()->Push(Task(
-      PostedTask(test_closure_, FROM_HERE), TimeTicks(),
+      PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
       EnqueueOrder::FromIntForTesting(GetParam().immediate_task_enqueue_order),
       EnqueueOrder::FromIntForTesting(
           GetParam().immediate_task_enqueue_order)));
 
   task_queues_[0]->delayed_work_queue()->Push(Task(
-      PostedTask(test_closure_, FROM_HERE), TimeTicks(),
+      PostedTask(nullptr, test_closure_, FROM_HERE), TimeTicks(),
       EnqueueOrder::FromIntForTesting(GetParam().delayed_task_enqueue_order),
       EnqueueOrder::FromIntForTesting(GetParam().delayed_task_enqueue_order)));
 
diff --git a/base/task/sequence_manager/tasks.cc b/base/task/sequence_manager/tasks.cc
index 14bd306..a3bd5ce 100644
--- a/base/task/sequence_manager/tasks.cc
+++ b/base/task/sequence_manager/tasks.cc
@@ -17,6 +17,7 @@
                   desired_run_time,
                   posted_task.nestable),
       task_type(posted_task.task_type),
+      task_runner(std::move(posted_task.task_runner)),
       enqueue_order_(enqueue_order) {
   // We use |sequence_num| in DelayedWakeUp for ordering purposes and it
   // may wrap around to a negative number during the static cast, hence,
@@ -28,9 +29,15 @@
   queue_time = posted_task.queue_time;
 }
 
-namespace internal {
+Task::Task(Task&& move_from) = default;
 
-PostedTask::PostedTask(OnceClosure callback,
+Task::~Task() = default;
+
+Task& Task::operator=(Task&& other) = default;
+
+namespace internal {
+PostedTask::PostedTask(scoped_refptr<SequencedTaskRunner> task_runner,
+                       OnceClosure callback,
                        Location location,
                        TimeDelta delay,
                        Nestable nestable,
@@ -39,7 +46,8 @@
       location(location),
       delay(delay),
       nestable(nestable),
-      task_type(task_type) {}
+      task_type(task_type),
+      task_runner(std::move(task_runner)) {}
 
 PostedTask::PostedTask(PostedTask&& move_from) noexcept
     : callback(std::move(move_from.callback)),
@@ -47,6 +55,7 @@
       delay(move_from.delay),
       nestable(move_from.nestable),
       task_type(move_from.task_type),
+      task_runner(std::move(move_from.task_runner)),
       queue_time(move_from.queue_time) {}
 
 PostedTask::~PostedTask() = default;
diff --git a/base/task/sequence_manager/tasks.h b/base/task/sequence_manager/tasks.h
index 0c886c4b..d1e1912 100644
--- a/base/task/sequence_manager/tasks.h
+++ b/base/task/sequence_manager/tasks.h
@@ -6,6 +6,7 @@
 #define BASE_TASK_SEQUENCE_MANAGER_TASKS_H_
 
 #include "base/pending_task.h"
+#include "base/sequenced_task_runner.h"
 #include "base/task/sequence_manager/enqueue_order.h"
 
 namespace base {
@@ -21,7 +22,8 @@
 // Wrapper around PostTask method arguments and the assigned task type.
 // Eventually it becomes a PendingTask once accepted by a TaskQueueImpl.
 struct BASE_EXPORT PostedTask {
-  explicit PostedTask(OnceClosure callback = OnceClosure(),
+  explicit PostedTask(scoped_refptr<SequencedTaskRunner> task_runner,
+                      OnceClosure callback = OnceClosure(),
                       Location location = Location(),
                       TimeDelta delay = TimeDelta(),
                       Nestable nestable = Nestable::kNestable,
@@ -34,6 +36,9 @@
   TimeDelta delay;
   Nestable nestable;
   TaskType task_type;
+  // The task runner this task is running on. Can be used by task runners that
+  // support posting back to the "current sequence".
+  scoped_refptr<SequencedTaskRunner> task_runner;
   // The time at which the task was queued.
   TimeTicks queue_time;
 
@@ -76,6 +81,9 @@
        EnqueueOrder enqueue_order = EnqueueOrder(),
        internal::WakeUpResolution wake_up_resolution =
            internal::WakeUpResolution::kLow);
+  Task(Task&& move_from);
+  ~Task();
+  Task& operator=(Task&& other);
 
   internal::DelayedWakeUp delayed_wake_up() const {
     return internal::DelayedWakeUp{delayed_run_time, sequence_num};
@@ -97,6 +105,10 @@
 
   TaskType task_type;
 
+  // The task runner this task is running on. Can be used by task runners that
+  // support posting back to the "current sequence".
+  scoped_refptr<SequencedTaskRunner> task_runner;
+
 #if DCHECK_IS_ON()
   bool cross_thread_;
 #endif
diff --git a/base/task/sequence_manager/test/fake_task.cc b/base/task/sequence_manager/test/fake_task.cc
index 6d1c794..1199bb9 100644
--- a/base/task/sequence_manager/test/fake_task.cc
+++ b/base/task/sequence_manager/test/fake_task.cc
@@ -10,7 +10,8 @@
 FakeTask::FakeTask() : FakeTask(0 /* task_type */) {}
 
 FakeTask::FakeTask(TaskType task_type)
-    : Task(internal::PostedTask(OnceClosure(),
+    : Task(internal::PostedTask(nullptr,
+                                OnceClosure(),
                                 FROM_HERE,
                                 TimeDelta(),
                                 Nestable::kNestable,
diff --git a/base/task/sequence_manager/thread_controller_impl.cc b/base/task/sequence_manager/thread_controller_impl.cc
index 22bffdb..676b9a6 100644
--- a/base/task/sequence_manager/thread_controller_impl.cc
+++ b/base/task/sequence_manager/thread_controller_impl.cc
@@ -174,7 +174,7 @@
   WeakPtr<ThreadControllerImpl> weak_ptr = weak_factory_.GetWeakPtr();
   // TODO(scheduler-dev): Consider moving to a time based work batch instead.
   for (int i = 0; i < main_sequence_only().work_batch_size_; i++) {
-    Optional<PendingTask> task = sequence_->TakeTask();
+    Task* task = sequence_->SelectNextTask();
     if (!task)
       break;
 
@@ -189,7 +189,7 @@
       // Trace events should finish before we call DidRunTask to ensure that
       // SequenceManager trace events do not interfere with them.
       TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask", *task);
-      task_annotator_.RunTask("SequenceManager RunTask", &*task);
+      task_annotator_.RunTask("SequenceManager RunTask", task);
     }
 
     if (!weak_ptr)
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
index deeda0e..9b0a058e 100644
--- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
+++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
@@ -342,7 +342,7 @@
   DCHECK(main_thread_only().task_source);
 
   for (int i = 0; i < main_thread_only().work_batch_size; i++) {
-    Optional<Task> task = main_thread_only().task_source->TakeTask();
+    Task* task = main_thread_only().task_source->SelectNextTask();
     if (!task)
       break;
 
@@ -362,7 +362,7 @@
       // Trace events should finish before we call DidRunTask to ensure that
       // SequenceManager trace events do not interfere with them.
       TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask", *task);
-      task_annotator_.RunTask("SequenceManager RunTask", &*task);
+      task_annotator_.RunTask("SequenceManager RunTask", task);
     }
 
 #if DCHECK_IS_ON()
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc
index 64eb8f7..3c02bec 100644
--- a/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc
+++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc
@@ -79,17 +79,17 @@
   explicit FakeSequencedTaskSource(TickClock* clock) : clock_(clock) {}
   ~FakeSequencedTaskSource() override = default;
 
-  Optional<Task> TakeTask() override {
+  Task* SelectNextTask() override {
     if (tasks_.empty())
-      return nullopt;
+      return nullptr;
     if (tasks_.front().delayed_run_time > clock_->NowTicks())
-      return nullopt;
-    Task task = std::move(tasks_.front());
+      return nullptr;
+    running_stack_.push_back(std::move(tasks_.front()));
     tasks_.pop();
-    return task;
+    return &running_stack_.back();
   }
 
-  void DidRunTask() override {}
+  void DidRunTask() override { running_stack_.pop_back(); }
 
   TimeDelta DelayTillNextTask(LazyNow* lazy_now) const override {
     if (tasks_.empty())
@@ -106,8 +106,9 @@
                TimeTicks delayed_run_time) {
     DCHECK(tasks_.empty() || delayed_run_time.is_null() ||
            tasks_.back().delayed_run_time < delayed_run_time);
-    tasks_.push(Task(internal::PostedTask(std::move(task), posted_from),
-                     delayed_run_time, EnqueueOrder::FromIntForTesting(13)));
+    tasks_.push(
+        Task(internal::PostedTask(nullptr, std::move(task), posted_from),
+             delayed_run_time, EnqueueOrder::FromIntForTesting(13)));
   }
 
   bool HasPendingHighResolutionTasks() override { return false; }
@@ -117,6 +118,7 @@
  private:
   TickClock* clock_;
   std::queue<Task> tasks_;
+  std::vector<Task> running_stack_;
 };
 
 TimeTicks Seconds(int seconds) {
diff --git a/base/task/sequence_manager/work_queue_sets_unittest.cc b/base/task/sequence_manager/work_queue_sets_unittest.cc
index fa014c6..6450573 100644
--- a/base/task/sequence_manager/work_queue_sets_unittest.cc
+++ b/base/task/sequence_manager/work_queue_sets_unittest.cc
@@ -51,14 +51,14 @@
   }
 
   Task FakeTaskWithEnqueueOrder(int enqueue_order) {
-    Task fake_task(PostedTask(BindOnce([] {}), FROM_HERE), TimeTicks(),
+    Task fake_task(PostedTask(nullptr, BindOnce([] {}), FROM_HERE), TimeTicks(),
                    EnqueueOrder(),
                    EnqueueOrder::FromIntForTesting(enqueue_order));
     return fake_task;
   }
 
   Task FakeNonNestableTaskWithEnqueueOrder(int enqueue_order) {
-    Task fake_task(PostedTask(BindOnce([] {}), FROM_HERE), TimeTicks(),
+    Task fake_task(PostedTask(nullptr, BindOnce([] {}), FROM_HERE), TimeTicks(),
                    EnqueueOrder(),
                    EnqueueOrder::FromIntForTesting(enqueue_order));
     fake_task.nestable = Nestable::kNonNestable;
diff --git a/base/task/sequence_manager/work_queue_unittest.cc b/base/task/sequence_manager/work_queue_unittest.cc
index e695b99..1ab88bf5 100644
--- a/base/task/sequence_manager/work_queue_unittest.cc
+++ b/base/task/sequence_manager/work_queue_unittest.cc
@@ -73,23 +73,23 @@
  protected:
   Task FakeCancelableTaskWithEnqueueOrder(int enqueue_order,
                                           WeakPtr<Cancelable> weak_ptr) {
-    Task fake_task(
-        PostedTask(BindOnce(&Cancelable::NopTask, weak_ptr), FROM_HERE),
-        TimeTicks(), EnqueueOrder(),
-        EnqueueOrder::FromIntForTesting(enqueue_order));
+    Task fake_task(PostedTask(nullptr, BindOnce(&Cancelable::NopTask, weak_ptr),
+                              FROM_HERE),
+                   TimeTicks(), EnqueueOrder(),
+                   EnqueueOrder::FromIntForTesting(enqueue_order));
     return fake_task;
   }
 
   Task FakeTaskWithEnqueueOrder(int enqueue_order) {
-    Task fake_task(PostedTask(BindOnce(&NopTask), FROM_HERE), TimeTicks(),
-                   EnqueueOrder(),
+    Task fake_task(PostedTask(nullptr, BindOnce(&NopTask), FROM_HERE),
+                   TimeTicks(), EnqueueOrder(),
                    EnqueueOrder::FromIntForTesting(enqueue_order));
     return fake_task;
   }
 
   Task FakeNonNestableTaskWithEnqueueOrder(int enqueue_order) {
-    Task fake_task(PostedTask(BindOnce(&NopTask), FROM_HERE), TimeTicks(),
-                   EnqueueOrder(),
+    Task fake_task(PostedTask(nullptr, BindOnce(&NopTask), FROM_HERE),
+                   TimeTicks(), EnqueueOrder(),
                    EnqueueOrder::FromIntForTesting(enqueue_order));
     fake_task.nestable = Nestable::kNonNestable;
     return fake_task;
diff --git a/base/test/trace_to_file.cc b/base/test/trace_to_file.cc
index 6eef502..59724dd 100644
--- a/base/test/trace_to_file.cc
+++ b/base/test/trace_to_file.cc
@@ -9,8 +9,8 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/memory/ref_counted_memory.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_buffer.h"
 #include "base/trace_event/trace_log.h"
@@ -96,10 +96,10 @@
   buffer.SetOutputCallback(
       BindRepeating(&TraceToFile::TraceOutputCallback, Unretained(this)));
 
-  // In tests we might not have a MessageLoop, create one if needed.
-  std::unique_ptr<MessageLoop> message_loop;
+  // In tests we might not have a TaskEnvironment, create one if needed.
+  std::unique_ptr<SingleThreadTaskEnvironment> task_environment;
   if (!ThreadTaskRunnerHandle::IsSet())
-    message_loop = std::make_unique<MessageLoop>();
+    task_environment = std::make_unique<SingleThreadTaskEnvironment>();
 
   RunLoop run_loop;
   trace_event::TraceLog::GetInstance()->Flush(BindRepeating(
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index a411bb8..6fc752f 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -4,14 +4,21 @@
 
 #include "base/threading/thread.h"
 
+#include <type_traits>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/lazy_instance.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/message_loop/message_loop_current.h"
+#include "base/message_loop/message_pump.h"
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/sequence_manager/sequence_manager_impl.h"
+#include "base/task/sequence_manager/task_queue.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "base/threading/thread_id_name_manager.h"
 #include "base/threading/thread_local.h"
@@ -38,6 +45,56 @@
 base::LazyInstance<base::ThreadLocalBoolean>::Leaky lazy_tls_bool =
     LAZY_INSTANCE_INITIALIZER;
 
+class SequenceManagerThreadDelegate : public Thread::Delegate {
+ public:
+  explicit SequenceManagerThreadDelegate(
+      MessagePumpType message_pump_type,
+      OnceCallback<std::unique_ptr<MessagePump>()> message_pump_factory)
+      : sequence_manager_(
+            sequence_manager::internal::SequenceManagerImpl::CreateUnbound(
+                sequence_manager::SequenceManager::Settings::Builder()
+                    .SetMessagePumpType(message_pump_type)
+                    .Build())),
+        default_task_queue_(sequence_manager_->CreateTaskQueue(
+            sequence_manager::TaskQueue::Spec("default_tq"))),
+        message_pump_factory_(std::move(message_pump_factory)) {
+    sequence_manager_->SetDefaultTaskRunner(default_task_queue_->task_runner());
+  }
+
+  ~SequenceManagerThreadDelegate() override = default;
+
+  scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override {
+    // Surprisingly this might not be default_task_queue_->task_runner() which
+    // we set in the constructor. The Thread::Init() method could create a
+    // SequenceManager on top of the current one and call
+    // SequenceManager::SetDefaultTaskRunner which would propagate the new
+    // TaskRunner down to our SequenceManager. Turns out, code actually relies
+    // on this and somehow relies on
+    // SequenceManagerThreadDelegate::GetDefaultTaskRunner returning this new
+    // TaskRunner. So instead of returning default_task_queue_->task_runner() we
+    // need to query the SequenceManager for it.
+    // The underlying problem here is that Subclasses of Thread can do crazy
+    // stuff in Init() but they are not really in control of what happens in the
+    // Thread::Delegate, as this is passed in on calling StartWithOptions which
+    // could happen far away from where the Thread is created. We should
+    // consider getting rid of StartWithOptions, and pass them as a constructor
+    // argument instead.
+    return sequence_manager_->GetTaskRunner();
+  }
+
+  void BindToCurrentThread(TimerSlack timer_slack) override {
+    sequence_manager_->BindToMessagePump(
+        std::move(message_pump_factory_).Run());
+    sequence_manager_->SetTimerSlack(timer_slack);
+  }
+
+ private:
+  std::unique_ptr<sequence_manager::internal::SequenceManagerImpl>
+      sequence_manager_;
+  scoped_refptr<sequence_manager::TaskQueue> default_task_queue_;
+  OnceCallback<std::unique_ptr<MessagePump>()> message_pump_factory_;
+};
+
 }  // namespace
 
 Thread::Options::Options() = default;
@@ -100,11 +157,13 @@
     DCHECK(!options.message_pump_factory);
     delegate_ = WrapUnique(options.delegate);
   } else if (options.message_pump_factory) {
-    delegate_ = std::make_unique<internal::MessageLoopThreadDelegate>(
-        MessageLoop::CreateUnbound(options.message_pump_factory.Run()));
+    delegate_ = std::make_unique<SequenceManagerThreadDelegate>(
+        MessagePumpType::CUSTOM, options.message_pump_factory);
   } else {
-    delegate_ = std::make_unique<internal::MessageLoopThreadDelegate>(
-        MessageLoop::CreateUnbound(options.message_pump_type));
+    delegate_ = std::make_unique<SequenceManagerThreadDelegate>(
+        options.message_pump_type,
+        BindOnce([](MessagePumpType type) { return MessagePump::Create(type); },
+                 options.message_pump_type));
   }
 
   start_event_.Reset();
@@ -291,9 +350,10 @@
 #if defined(OS_WIN)
   std::unique_ptr<win::ScopedCOMInitializer> com_initializer;
   if (com_status_ != NONE) {
-    com_initializer.reset((com_status_ == STA) ?
-        new win::ScopedCOMInitializer() :
-        new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA));
+    com_initializer.reset(
+        (com_status_ == STA)
+            ? new win::ScopedCOMInitializer()
+            : new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA));
   }
 #endif
 
@@ -337,24 +397,4 @@
   SetThreadWasQuitProperly(true);
 }
 
-namespace internal {
-
-MessageLoopThreadDelegate::MessageLoopThreadDelegate(
-    std::unique_ptr<MessageLoop> message_loop)
-    : message_loop_(std::move(message_loop)) {}
-
-MessageLoopThreadDelegate::~MessageLoopThreadDelegate() {}
-
-scoped_refptr<SingleThreadTaskRunner>
-MessageLoopThreadDelegate::GetDefaultTaskRunner() {
-  return message_loop_->task_runner();
-}
-
-void MessageLoopThreadDelegate::BindToCurrentThread(TimerSlack timer_slack) {
-  message_loop_->BindToCurrentThread();
-  message_loop_->SetTimerSlack(timer_slack);
-}
-
-}  // namespace internal
-
 }  // namespace base
diff --git a/base/threading/thread.h b/base/threading/thread.h
index 73a444f..312caab2 100644
--- a/base/threading/thread.h
+++ b/base/threading/thread.h
@@ -13,8 +13,6 @@
 #include "base/base_export.h"
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/message_loop/timer_slack.h"
 #include "base/sequence_checker.h"
@@ -331,24 +329,6 @@
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
 
-namespace internal {
-
-class BASE_EXPORT MessageLoopThreadDelegate : public Thread::Delegate {
- public:
-  explicit MessageLoopThreadDelegate(std::unique_ptr<MessageLoop> message_loop);
-
-  ~MessageLoopThreadDelegate() override;
-
-  // Thread::Delegate:
-  scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override;
-  void BindToCurrentThread(TimerSlack timer_slack) override;
-
- private:
-  std::unique_ptr<MessageLoop> message_loop_;
-};
-
-}  // namespace internal
-
 }  // namespace base
 
 #endif  // BASE_THREADING_THREAD_H_
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index c0727e7..d64a2bdb 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8901391751860333728
\ No newline at end of file
+8901447639518533984
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 00cc966..fa22597 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8901393593484977040
\ No newline at end of file
+8901448833775125712
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index aeac9d9..31340e35 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2574,7 +2574,6 @@
     "java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java",
     "java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java",
     "java/src/org/chromium/chrome/browser/instantapps/InstantAppsSettings.java",
-    "java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java",
     "java/src/org/chromium/chrome/browser/jsdialog/JavascriptAppModalDialog.java",
     "java/src/org/chromium/chrome/browser/jsdialog/JavascriptTabModalDialog.java",
     "java/src/org/chromium/chrome/browser/locale/LocaleManager.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 506a632..c664d93 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -858,12 +858,6 @@
   "java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java",
   "java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java",
   "java/src/org/chromium/chrome/browser/instantapps/InstantAppsSettings.java",
-  "java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapter.java",
-  "java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterService.java",
-  "java/src/org/chromium/chrome/browser/invalidation/ChromeInvalidationClientService.java",
-  "java/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsController.java",
-  "java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java",
-  "java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java",
   "java/src/org/chromium/chrome/browser/invalidation/ResumableDelayedTaskRunner.java",
   "java/src/org/chromium/chrome/browser/invalidation/SessionsInvalidationManager.java",
   "java/src/org/chromium/chrome/browser/invalidation/UniqueIdInvalidationClientNameGenerator.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index d264c34..0e4de9ec 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -96,7 +96,6 @@
   "junit/src/org/chromium/chrome/browser/init/AsyncInitTaskRunnerTest.java",
   "junit/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderTest.java",
   "junit/src/org/chromium/chrome/browser/installedapp/PackageHashTest.java",
-  "junit/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java",
   "junit/src/org/chromium/chrome/browser/invalidation/ResumableDelayedTaskRunnerTest.java",
   "junit/src/org/chromium/chrome/browser/invalidation/SessionsInvalidationManagerTest.java",
   "junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 7f884d3..9c3e935 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -210,9 +210,6 @@
   "javatests/src/org/chromium/chrome/browser/input/SelectPopupOtherContentViewTest.java",
   "javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java",
   "javatests/src/org/chromium/chrome/browser/interstitials/LookalikeInterstitialTest.java",
-  "javatests/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterTest.java",
-  "javatests/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsControllerTest.java",
-  "javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java",
   "javatests/src/org/chromium/chrome/browser/jsdialog/JavascriptAppModalDialogTest.java",
   "javatests/src/org/chromium/chrome/browser/jsdialog/JavascriptTabModalDialogTest.java",
   "javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java",
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index e673d14..da7fc8f 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -1069,14 +1069,6 @@
             android:exported="false"/>
 
         <!-- Notification service for sync. -->
-        <meta-data android:name="ipc.invalidation.ticl.listener_service_class"
-            android:value="org.chromium.chrome.browser.invalidation.ChromeInvalidationClientService"/>
-        <service android:name="org.chromium.chrome.browser.invalidation.ChromeInvalidationClientService"
-            android:exported="false">
-            <intent-filter>
-              <action android:name="com.google.ipc.invalidation.AUTH_TOKEN_REQUEST"/>
-            </intent-filter>
-        </service>
         <service android:name="com.google.ipc.invalidation.ticl.android2.TiclService"
             android:exported="false"/>
         <service android:name="com.google.ipc.invalidation.ticl.android2.channel.AndroidMessageSenderService"
diff --git a/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected b/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
index 71cf43bf..562b2294 100644
--- a/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
+++ b/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
@@ -1231,9 +1231,6 @@
         android:name="ipc.invalidation.ticl.gcm_upstream_service_class"
         android:value="org.chromium.chrome.browser.services.gcm.InvalidationGcmUpstreamSender"/>
     <meta-data
-        android:name="ipc.invalidation.ticl.listener_service_class"
-        android:value="org.chromium.chrome.browser.invalidation.ChromeInvalidationClientService"/>
-    <meta-data
         android:name="org.chromium.chrome:privileged_process0.ignore_multidex"
         android:value="true"/>
     <meta-data
@@ -1533,13 +1530,6 @@
     </service>
     <service
         android:exported="false"
-        android:name="org.chromium.chrome.browser.invalidation.ChromeInvalidationClientService">
-      <intent-filter>
-        <action android:name="com.google.ipc.invalidation.AUTH_TOKEN_REQUEST"/>
-      </intent-filter>
-    </service>
-    <service
-        android:exported="false"
         android:name="org.chromium.chrome.browser.media.MediaCaptureNotificationService"/>
     <service
         android:exported="false"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/PowerBroadcastReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/PowerBroadcastReceiver.java
index dc206a56..f131a30d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/PowerBroadcastReceiver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/PowerBroadcastReceiver.java
@@ -18,7 +18,6 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.invalidation.DelayedInvalidationsController;
 import org.chromium.chrome.browser.omaha.OmahaBase;
 
 import java.lang.annotation.Retention;
@@ -107,7 +106,6 @@
         public void runActions() {
             Context context = ContextUtils.getApplicationContext();
             OmahaBase.onForegroundSessionStart(context);
-            DelayedInvalidationsController.getInstance().notifyPendingInvalidations();
         }
 
         public long getDelayToRun() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 4d46e32..cdda8d57 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -44,6 +44,7 @@
 import org.chromium.chrome.browser.webapps.WebappActivity;
 import org.chromium.chrome.browser.webapps.WebappAuthenticator;
 import org.chromium.chrome.browser.webapps.WebappDataStorage;
+import org.chromium.chrome.browser.webapps.WebappInfo;
 import org.chromium.chrome.browser.webapps.WebappLauncherActivity;
 import org.chromium.chrome.browser.webapps.WebappRegistry;
 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
@@ -91,7 +92,7 @@
 
     // When a new field is added to the intent, this version should be incremented so that it will
     // be correctly populated into the WebappRegistry/WebappDataStorage.
-    public static final int WEBAPP_SHORTCUT_VERSION = 2;
+    public static final int WEBAPP_SHORTCUT_VERSION = 3;
 
     // This value is equal to kInvalidOrMissingColor in the C++ blink::Manifest struct.
     public static final long MANIFEST_COLOR_INVALID_OR_MISSING = ((long) Integer.MAX_VALUE) + 1;
@@ -203,22 +204,14 @@
             protected Intent doInBackground() {
                 // Encoding {@link icon} as a string and computing the mac are expensive.
 
-                // Shortcuts as Webapps on O+ launch into a non-exported component for verification.
-                boolean usesMacForVerification = Build.VERSION.SDK_INT < Build.VERSION_CODES.O;
-
                 // Encode the icon as a base64 string (Launcher drops Bitmaps in the Intent).
                 String encodedIcon = encodeBitmapAsString(icon);
 
-                String action = usesMacForVerification
-                        ? sDelegate.getFullscreenAction()
-                        : WebappLauncherActivity.ACTION_START_SECURE_WEBAPP;
-                Intent shortcutIntent = createWebappShortcutIntent(id, action, url, scopeUrl, name,
+                // TODO(http://crbug.com/1000046): Use action which does not require mac on O+
+                Intent shortcutIntent = createWebappShortcutIntent(id, url, scopeUrl, name,
                         shortName, encodedIcon, WEBAPP_SHORTCUT_VERSION, displayMode, orientation,
                         themeColor, backgroundColor, iconUrl.isEmpty(), isIconAdaptive);
-
-                if (usesMacForVerification) {
-                    shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(url));
-                }
+                shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(url));
                 shortcutIntent.putExtra(EXTRA_SOURCE, source);
                 return shortcutIntent;
             }
@@ -230,9 +223,13 @@
                 // process is complete, call back to native code to start the splash image
                 // download.
                 WebappRegistry.getInstance().register(id, storage -> {
-                    storage.updateFromShortcutIntent(resultIntent);
-                    if (callbackPointer != 0) {
-                        ShortcutHelperJni.get().onWebappDataStored(callbackPointer);
+                    WebappInfo webappInfo = WebappInfo.create(resultIntent);
+                    assert webappInfo != null;
+                    if (webappInfo != null) {
+                        storage.updateFromWebappInfo(webappInfo);
+                        if (callbackPointer != 0) {
+                            ShortcutHelperJni.get().onWebappDataStored(callbackPointer);
+                        }
                     }
                 });
                 if (shouldShowToastWhenAddingShortcut()) {
@@ -360,7 +357,6 @@
     /**
      * Creates a shortcut to launch a web app on the home screen.
      * @param id              Id of the web app.
-     * @param action          Intent action to open a full screen activity.
      * @param url             Url of the web app.
      * @param scope           Url scope of the web app.
      * @param name            Name of the web app.
@@ -376,14 +372,14 @@
      * @return Intent for onclick action of the shortcut.
      * This method must not be called on the UI thread.
      */
-    public static Intent createWebappShortcutIntent(String id, String action, String url,
-            String scope, String name, String shortName, String encodedIcon, int version,
+    public static Intent createWebappShortcutIntent(String id, String url, String scope,
+            String name, String shortName, String encodedIcon, int version,
             @WebDisplayMode int displayMode, int orientation, long themeColor, long backgroundColor,
             boolean isIconGenerated, boolean isIconAdaptive) {
         // Create an intent as a launcher icon for a full-screen Activity.
         Intent shortcutIntent = new Intent();
         shortcutIntent.setPackage(ContextUtils.getApplicationContext().getPackageName())
-                .setAction(action)
+                .setAction(sDelegate.getFullscreenAction())
                 .putExtra(EXTRA_ID, id)
                 .putExtra(EXTRA_URL, url)
                 .putExtra(EXTRA_SCOPE, scope)
@@ -408,7 +404,7 @@
      * This method must not be called on the UI thread.
      */
     public static Intent createWebappShortcutIntentForTesting(String id, String url) {
-        return createWebappShortcutIntent(id, null, url, getScopeFromUrl(url), null, null, null,
+        return createWebappShortcutIntent(id, url, getScopeFromUrl(url), null, null, null,
                 WEBAPP_SHORTCUT_VERSION, WebDisplayMode.STANDALONE, 0, 0, 0, false, false);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
index a8e73851..93ac395 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
@@ -105,8 +105,9 @@
             String packageName = intent.getData().getSchemeSpecificPart();
             if (packageName != null
                     && packageName.startsWith(WebApkConstants.WEBAPK_PACKAGE_PREFIX)) {
-                // Native is likely not loaded. Defer recording UMA till the next browser launch.
-                WebApkUma.deferRecordWebApkUninstalled();
+                // Native is likely not loaded. Defer recording UMA and UKM till the next browser
+                // launch.
+                WebApkUma.deferRecordWebApkUninstalled(packageName);
             }
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
index 1325970444..fd73d4a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
@@ -78,7 +78,7 @@
                 Log.d(TAG, "Incorrect number of accounts (%d)", accounts.size());
                 return;
             }
-            signinManager.signIn(accounts.get(0), null, new SigninManager.SignInCallback() {
+            signinManager.signIn(accounts.get(0), new SigninManager.SignInCallback() {
                 @Override
                 public void onSignInComplete() {
                     if (onComplete != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapter.java
deleted file mode 100644
index 09aabaa..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapter.java
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.invalidation;
-
-import android.accounts.Account;
-import android.content.AbstractThreadedSyncAdapter;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.SyncResult;
-import android.os.Bundle;
-
-import org.chromium.base.Log;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.library_loader.ProcessInitException;
-import org.chromium.base.task.PostTask;
-import org.chromium.chrome.browser.init.BrowserParts;
-import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
-import org.chromium.chrome.browser.init.EmptyBrowserParts;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.components.invalidation.PendingInvalidation;
-import org.chromium.components.signin.ChromeSigninController;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
-
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A Sync adapter that receives invalidations from {@link InvalidationClientService} and dispatches
- * it to the native side with a caching layer in {@link DelayedInvalidationsController}.
- */
-public class ChromeBrowserSyncAdapter extends AbstractThreadedSyncAdapter {
-    private static final String TAG = "invalidation";
-
-    public ChromeBrowserSyncAdapter(Context context) {
-        super(context, false);
-    }
-
-    @Override
-    public void onPerformSync(Account account, Bundle extras, String authority,
-            ContentProviderClient provider, SyncResult syncResult) {
-        if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE)) {
-            Account signedInAccount = ChromeSigninController.get().getSignedInUser();
-            if (account.equals(signedInAccount)) {
-                ContentResolver.setIsSyncable(account, authority, 1);
-            } else {
-                ContentResolver.setIsSyncable(account, authority, 0);
-            }
-            return;
-        }
-        PendingInvalidation invalidation = new PendingInvalidation(extras);
-
-        DelayedInvalidationsController controller = DelayedInvalidationsController.getInstance();
-        if (!controller.shouldNotifyInvalidation(extras)) {
-            controller.addPendingInvalidation(account.name, invalidation);
-            return;
-        }
-
-        // Browser startup is asynchronous, so we will need to wait for startup to finish.
-        Semaphore semaphore = new Semaphore(0);
-
-        // Configure the BrowserParts with all the data it needs.
-        BrowserParts parts = getBrowserParts(account.name, invalidation, syncResult, semaphore);
-        startBrowserProcess(parts, syncResult, semaphore);
-
-        try {
-            // This code is only synchronously calling a single native method
-            // to trigger and asynchronous sync cycle, so 5 minutes is generous.
-            if (!semaphore.tryAcquire(5, TimeUnit.MINUTES)) {
-                Log.w(TAG, "Sync request timed out!");
-                syncResult.stats.numIoExceptions++;
-            }
-        } catch (InterruptedException e) {
-            Log.w(TAG, "Got InterruptedException when trying to request an invalidation.", e);
-            // Using numIoExceptions so Android will treat this as a soft error.
-            syncResult.stats.numIoExceptions++;
-        }
-    }
-
-    private void startBrowserProcess(final BrowserParts parts, final SyncResult syncResult,
-            Semaphore semaphore) {
-        try {
-            PostTask.runSynchronously(UiThreadTaskTraits.DEFAULT, () -> {
-                ChromeBrowserInitializer.getInstance(getContext()).handlePreNativeStartup(parts);
-                try {
-                    ChromeBrowserInitializer.getInstance(getContext())
-                            .handlePostNativeStartup(false, parts);
-                } catch (ProcessInitException e) {
-                    Log.e(TAG, "Unable to load native library.", e);
-                    System.exit(-1);
-                }
-            });
-        } catch (RuntimeException e) {
-            // It is still unknown why we ever experience this. See http://crbug.com/180044.
-            Log.w(TAG, "Got exception when trying to notify the invalidation.", e);
-            // Using numIoExceptions so Android will treat this as a soft error.
-            syncResult.stats.numIoExceptions++;
-            semaphore.release();
-        }
-    }
-
-    private BrowserParts getBrowserParts(final String account,
-            final PendingInvalidation invalidation, final SyncResult syncResult,
-            final Semaphore semaphore) {
-        return new EmptyBrowserParts() {
-            @Override
-            public void finishNativeInitialization() {
-                // Startup succeeded, so we can notify the invalidation.
-                notifyInvalidation(invalidation.mObjectSource, invalidation.mObjectId,
-                        invalidation.mVersion, invalidation.mPayload);
-                semaphore.release();
-            }
-
-            @Override
-            public void onStartupFailure() {
-                // The startup failed, so we defer the invalidation.
-                DelayedInvalidationsController.getInstance().addPendingInvalidation(
-                        account, invalidation);
-                // Using numIoExceptions so Android will treat this as a soft error.
-                syncResult.stats.numIoExceptions++;
-                semaphore.release();
-            }
-        };
-    }
-
-    @VisibleForTesting
-    public void notifyInvalidation(
-            int objectSource, String objectId, long version, String payload) {
-        InvalidationServiceFactory.getForProfile(Profile.getLastUsedProfile())
-                .notifyInvalidationToNativeChrome(objectSource, objectId, version, payload);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterService.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterService.java
deleted file mode 100644
index 69c0263..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterService.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.invalidation;
-
-import android.annotation.SuppressLint;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.chrome.browser.init.ProcessInitializationHandler;
-
-/**
- * A Service that provides access to {@link ChromeBrowserSyncAdapter}.
- */
-public class ChromeBrowserSyncAdapterService extends Service {
-
-    @SuppressLint("StaticFieldLeak")
-    private static ChromeBrowserSyncAdapter sSyncAdapter;
-    private static final Object LOCK = new Object();
-
-    /**
-     * Get the sync adapter reference, creating an instance if necessary.
-     */
-    private ChromeBrowserSyncAdapter getOrCreateSyncAdapter(Context applicationContext) {
-        synchronized (LOCK) {
-            if (sSyncAdapter == null) {
-                ProcessInitializationHandler.getInstance().initializePreNative();
-                sSyncAdapter = new ChromeBrowserSyncAdapter(applicationContext);
-            }
-        }
-        return sSyncAdapter;
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return getOrCreateSyncAdapter(ContextUtils.getApplicationContext()).getSyncAdapterBinder();
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeInvalidationClientService.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeInvalidationClientService.java
deleted file mode 100644
index db0b490..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ChromeInvalidationClientService.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.invalidation;
-
-import org.chromium.chrome.browser.init.ProcessInitializationHandler;
-import org.chromium.components.invalidation.InvalidationClientService;
-
-/**
- * Extension of the InvalidationClientService that allows Chrome specific initialization.
- */
-public class ChromeInvalidationClientService extends InvalidationClientService {
-
-    @Override
-    public void onCreate() {
-        ProcessInitializationHandler.getInstance().initializePreNative();
-        super.setShouldCreateService(false);
-        super.onCreate();
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsController.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsController.java
deleted file mode 100644
index c651592..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsController.java
+++ /dev/null
@@ -1,186 +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.
-
-package org.chromium.chrome.browser.invalidation;
-
-import android.accounts.Account;
-import android.content.ContentResolver;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.support.v4.util.ObjectsCompat;
-
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.task.PostTask;
-import org.chromium.base.task.TaskTraits;
-import org.chromium.components.invalidation.PendingInvalidation;
-import org.chromium.components.signin.AccountManagerFacade;
-import org.chromium.components.sync.AndroidSyncSettings;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A class for controlling whether an invalidation should be notified immediately, or should be
- * delayed until Chrome comes to the foreground again.
- */
-public class DelayedInvalidationsController {
-    private static final String TAG = "invalidation";
-    private static final String DELAYED_ACCOUNT_NAME = "delayed_account";
-    private static final String DELAYED_INVALIDATIONS = "delayed_invalidations";
-
-    private static class LazyHolder {
-        private static final DelayedInvalidationsController INSTANCE =
-                new DelayedInvalidationsController();
-    }
-
-    public static DelayedInvalidationsController getInstance() {
-        return LazyHolder.INSTANCE;
-    }
-
-    @VisibleForTesting
-    DelayedInvalidationsController() {}
-
-    /**
-     * Notify any invalidations that were delayed while Chromium was backgrounded.
-     * @return whether there were any invalidations pending to be notified.
-     */
-    public boolean notifyPendingInvalidations() {
-        SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
-        String accountName = prefs.getString(DELAYED_ACCOUNT_NAME, null);
-        if (accountName == null) {
-            Log.d(TAG, "No pending invalidations.");
-            return false;
-        } else {
-            Log.d(TAG, "Handling pending invalidations.");
-            Account account = AccountManagerFacade.createAccountFromName(accountName);
-            List<Bundle> bundles = popPendingInvalidations();
-            notifyInvalidationsOnBackgroundThread(account, bundles);
-            return true;
-        }
-    }
-
-    /**
-     * Calls ContentResolver.requestSync() in a separate thread as it performs some blocking
-     * IO operations.
-     */
-    @VisibleForTesting
-    void notifyInvalidationsOnBackgroundThread(final Account account, final List<Bundle> bundles) {
-        PostTask.postTask(TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> {
-            String contractAuthority = AndroidSyncSettings.get().getContractAuthority();
-            for (Bundle bundle : bundles) {
-                ContentResolver.requestSync(account, contractAuthority, bundle);
-            }
-        });
-    }
-
-    /**
-     * Stores preferences to indicate that an invalidation has arrived, but dropped on the floor.
-     */
-    @VisibleForTesting
-    void addPendingInvalidation(String account, PendingInvalidation invalidation) {
-        SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
-        String oldAccount = prefs.getString(DELAYED_ACCOUNT_NAME, null);
-        // Make sure to construct a new set so it can be modified safely. See crbug.com/568369.
-        Set<String> invals = new HashSet<String>(
-                prefs.getStringSet(DELAYED_INVALIDATIONS, Collections.<String>emptySet()));
-        assert invals.isEmpty() || oldAccount != null;
-        boolean invalidateAllTypes = false;
-        // We invalidate all types if:
-        // - the account has changed
-        // - we were in "invalidate all types" mode already
-        // - new invalidation indicates to invalidate all types by setting source to 0
-        // - adding invalidation to the current set failed
-        if (oldAccount != null && !oldAccount.equals(account)) invalidateAllTypes = true;
-        if (oldAccount != null && invals.isEmpty()) invalidateAllTypes = true;
-        if (invalidation.mObjectSource == 0) invalidateAllTypes = true;
-        if (!invalidateAllTypes && !addInvalidationToSet(invalidation, invals)) {
-            invalidateAllTypes = true;
-        }
-
-        SharedPreferences.Editor editor = prefs.edit();
-        editor.putString(DELAYED_ACCOUNT_NAME, account);
-        if (invalidateAllTypes) {
-            editor.remove(DELAYED_INVALIDATIONS);
-        } else {
-            editor.putStringSet(DELAYED_INVALIDATIONS, invals);
-        }
-        editor.apply();
-    }
-
-    /**
-     * Adds newInvalidation into set of encoded invalidations. Invalidations with the same id/source
-     * and lower version are removed from the set. If invalidation with same or higher version is
-     * is present, then new invalidation is discarded.
-     * @return true if update is successful, false when decoding invalidation from string fails.
-     */
-    private boolean addInvalidationToSet(
-            PendingInvalidation newInvalidation, Set<String> invalidations) {
-        for (Iterator<String> iter = invalidations.iterator(); iter.hasNext();) {
-            String encodedInvalidation = iter.next();
-            PendingInvalidation invalidation =
-                    PendingInvalidation.decodeToPendingInvalidation(encodedInvalidation);
-            if (invalidation == null) return false;
-            if (ObjectsCompat.equals(invalidation.mObjectId, newInvalidation.mObjectId)
-                    && invalidation.mObjectSource == newInvalidation.mObjectSource) {
-                if (invalidation.mVersion >= newInvalidation.mVersion) return true;
-                iter.remove();
-            }
-        }
-        invalidations.add(newInvalidation.encodeToString());
-        return true;
-    }
-
-    private List<Bundle> popPendingInvalidations() {
-        SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
-        assert prefs.contains(DELAYED_ACCOUNT_NAME);
-        Set<String> savedInvalidations = prefs.getStringSet(DELAYED_INVALIDATIONS, null);
-        clearPendingInvalidations();
-        // Absence of specific invalidations indicates invalidate all types.
-        if (savedInvalidations == null) return Arrays.asList(new Bundle());
-
-        List<Bundle> bundles = new ArrayList<Bundle>(savedInvalidations.size());
-        for (String invalidation : savedInvalidations) {
-            Bundle bundle = PendingInvalidation.decodeToBundle(invalidation);
-            if (bundle == null) {
-                Log.e(TAG, "Error parsing saved invalidation. Invalidating all.");
-                return Arrays.asList(new Bundle());
-            }
-            bundles.add(bundle);
-        }
-        return bundles;
-    }
-
-    /**
-     * If there are any pending invalidations, they will be cleared.
-     */
-    @VisibleForTesting
-    public void clearPendingInvalidations() {
-        SharedPreferences.Editor editor =
-                ContextUtils.getAppSharedPreferences().edit();
-        editor.putString(DELAYED_ACCOUNT_NAME, null);
-        editor.putStringSet(DELAYED_INVALIDATIONS, null);
-        editor.apply();
-    }
-
-    @VisibleForTesting
-    boolean shouldNotifyInvalidation(Bundle extras) {
-        return isManualRequest(extras) || ApplicationStatus.hasVisibleActivities();
-    }
-
-    private static boolean isManualRequest(Bundle extras) {
-        if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)) {
-            Log.d(TAG, "Manual sync requested.");
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java
deleted file mode 100644
index 851349a..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.invalidation;
-
-import android.annotation.SuppressLint;
-import android.content.Intent;
-import android.os.Build;
-import android.os.Handler;
-import android.os.SystemClock;
-
-import com.google.ipc.invalidation.ticl.android2.channel.AndroidGcmController;
-
-import org.chromium.base.ApplicationState;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.task.PostTask;
-import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.browser.sync.ProfileSyncService;
-import org.chromium.components.invalidation.InvalidationClientService;
-import org.chromium.components.signin.ChromeSigninController;
-import org.chromium.components.sync.AndroidSyncSettings;
-import org.chromium.components.sync.ModelType;
-import org.chromium.components.sync.notifier.InvalidationIntentProtocol;
-
-import java.util.HashSet;
-
-/**
- * Controller used to send start, stop, and registration-change commands to the invalidation
- * client library used by Sync.
- */
-public class InvalidationController implements ApplicationStatus.ApplicationStateListener {
-    private static final String TAG = "cr_invalidation";
-
-    /**
-     * Timer which can be paused. When the timer is paused, the execution of its scheduled task is
-     * delayed till the timer is resumed.
-     */
-    private static class Timer {
-        private Handler mHandler;
-
-        /**
-         * Runnable which is added to the handler's message queue.
-         */
-        private Runnable mHandlerRunnable;
-
-        /**
-         * User provided task.
-         */
-        private Runnable mRunnable;
-
-        /**
-         * Time at which the task is scheduled.
-         */
-        private long mScheduledTime;
-
-        public Timer() {
-            mHandler = new Handler();
-        }
-
-        /**
-         * Sets the task to run. The task will run after the delay or once {@link #resume()} is
-         * called, whichever occurs last. The previously scheduled task, if any, is cancelled.
-         * @param r Task to run.
-         * @param delayMs Delay in milliseconds after which to run the task.
-         */
-        public void setRunnable(Runnable r, long delayMs) {
-            cancel();
-            mRunnable = r;
-            mScheduledTime = SystemClock.elapsedRealtime() + delayMs;
-        }
-
-        /**
-         * Blocks the task from being run.
-         */
-        public void pause() {
-            if (mHandlerRunnable == null) return;
-
-            mHandler.removeCallbacks(mHandlerRunnable);
-            mHandlerRunnable = null;
-        }
-
-        /**
-         * Unblocks the task from being run. If the task was scheduled for a time in the past, runs
-         * the task. Does nothing if no task is scheduled.
-         */
-        public void resume() {
-            if (mRunnable == null || mHandlerRunnable != null) return;
-
-            long delayMs = Math.max(mScheduledTime - SystemClock.elapsedRealtime(), 0);
-            mHandlerRunnable = new Runnable() {
-                @Override
-                public void run() {
-                    Runnable r = mRunnable;
-                    mRunnable = null;
-                    mHandlerRunnable = null;
-                    r.run();
-                }
-            };
-            mHandler.postDelayed(mHandlerRunnable, delayMs);
-        }
-
-        /**
-         * Cancels the scheduled task, if any.
-         */
-        public void cancel() {
-            pause();
-            mRunnable = null;
-        }
-    }
-
-    /**
-     * The amount of time after the RecentTabsPage is opened to register for session sync
-     * invalidations. The delay is designed so that only users who linger on the RecentTabsPage
-     * register for session sync invalidations. How long users spend on the RecentTabsPage is
-     * measured by the NewTabPage.RecentTabsPage.TimeVisibleAndroid UMA metric.
-     */
-    private static final int REGISTER_FOR_SESSION_SYNC_INVALIDATIONS_DELAY_MS = 20000;
-
-    /**
-     * The amount of time after the RecentTabsPage is closed to unregister for session sync
-     * invalidations. The delay is long to avoid registering and unregistering a lot if the user
-     * visits the RecentTabsPage a lot.
-     */
-    private static final int UNREGISTER_FOR_SESSION_SYNC_INVALIDATIONS_DELAY_MS = 3600000; // 1hr
-
-    private static final Object LOCK = new Object();
-
-    @SuppressLint("StaticFieldLeak")
-    private static InvalidationController sInstance;
-
-    /**
-     * Whether the controller was started.
-     */
-    private boolean mStarted;
-
-    /**
-     * Used to schedule tasks to enable and disable session sync invalidations.
-     */
-    private Timer mEnableSessionInvalidationsTimer;
-
-    /**
-     *  Whether session sync invalidations are enabled.
-     */
-    private boolean mSessionInvalidationsEnabled;
-
-    /**
-     * The number of open RecentTabsPages
-     */
-    private int mNumRecentTabPages;
-
-    /**
-     * Whether GCM has been initialized for Invalidations.
-     */
-    private boolean mGcmInitialized;
-
-    /**
-     * Updates the sync invalidation types that the client is registered for based on the preferred
-     * sync types.  Starts the client if needed.
-     */
-    public void ensureStartedAndUpdateRegisteredTypes() {
-        ProfileSyncService syncService = ProfileSyncService.get();
-        if (syncService == null) return;
-
-        mStarted = true;
-
-        // Ensure GCM has been initialized.
-        ensureGcmIsInitialized();
-
-        // Do not apply changes to {@link #mSessionInvalidationsEnabled} yet because the timer task
-        // may be scheduled far into the future.
-        mEnableSessionInvalidationsTimer.resume();
-
-        HashSet<Integer> typesToRegister = new HashSet<Integer>();
-        typesToRegister.addAll(syncService.getPreferredDataTypes());
-        if (!mSessionInvalidationsEnabled) {
-            typesToRegister.remove(ModelType.SESSIONS);
-            typesToRegister.remove(ModelType.FAVICON_TRACKING);
-            typesToRegister.remove(ModelType.FAVICON_IMAGES);
-        }
-
-        Intent registerIntent = InvalidationIntentProtocol.createRegisterIntent(
-                ChromeSigninController.get().getSignedInUser(), typesToRegister);
-        registerIntent.setClass(ContextUtils.getApplicationContext(),
-                InvalidationClientService.getRegisteredClass());
-        startServiceIfPossible(registerIntent);
-    }
-
-    /**
-     * Registers for Google Cloud Messaging (GCM) for Invalidations.
-     */
-    private void ensureGcmIsInitialized() {
-        if (mGcmInitialized) return;
-        mGcmInitialized = true;
-        PostTask.postTask(TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> {
-            boolean useGcmUpstream = true;
-            AndroidGcmController.get(ContextUtils.getApplicationContext())
-                    .initializeGcm(useGcmUpstream);
-        });
-    }
-
-    @VisibleForTesting
-    public boolean isGcmInitialized() {
-        return mGcmInitialized;
-    }
-
-    /**
-     * Starts the invalidation client without updating the registered invalidation types.
-     */
-    private void start() {
-        mStarted = true;
-        mEnableSessionInvalidationsTimer.resume();
-        Intent intent = new Intent(ContextUtils.getApplicationContext(),
-                InvalidationClientService.getRegisteredClass());
-        startServiceIfPossible(intent);
-    }
-
-    /**
-     * Stops the invalidation client.
-     */
-    public void stop() {
-        mStarted = false;
-        mEnableSessionInvalidationsTimer.pause();
-        Intent intent = new Intent(ContextUtils.getApplicationContext(),
-                InvalidationClientService.getRegisteredClass());
-        intent.putExtra(InvalidationIntentProtocol.EXTRA_STOP, true);
-        startServiceIfPossible(intent);
-    }
-
-    private void startServiceIfPossible(Intent intent) {
-        // The use of background services is restricted when the application is not in foreground
-        // for O. See crbug.com/680812.
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            try {
-                ContextUtils.getApplicationContext().startService(intent);
-            } catch (IllegalStateException exception) {
-                Log.e(TAG, "Failed to start service from exception: ", exception);
-            }
-        } else {
-            ContextUtils.getApplicationContext().startService(intent);
-        }
-    }
-
-    /**
-     * Returns whether the invalidation client has been started.
-     */
-    public boolean isStarted() {
-        return mStarted;
-    }
-
-    /**
-     * Called when a RecentTabsPage is opened.
-     */
-    public void onRecentTabsPageOpened() {
-        ++mNumRecentTabPages;
-        if (mNumRecentTabPages == 1) {
-            setSessionInvalidationsEnabled(true, REGISTER_FOR_SESSION_SYNC_INVALIDATIONS_DELAY_MS);
-        }
-    }
-
-    /**
-     * Called when a RecentTabsPage is closed.
-     */
-    public void onRecentTabsPageClosed() {
-        --mNumRecentTabPages;
-        if (mNumRecentTabPages == 0) {
-            setSessionInvalidationsEnabled(
-                    false, UNREGISTER_FOR_SESSION_SYNC_INVALIDATIONS_DELAY_MS);
-        }
-    }
-
-    /**
-     * Returns the instance that will use {@code context} to issue intents.
-     *
-     * Calling this method will create the instance if it does not yet exist.
-     */
-    public static InvalidationController get() {
-        synchronized (LOCK) {
-            if (sInstance == null) {
-                sInstance = new InvalidationController();
-            }
-            return sInstance;
-        }
-    }
-
-    /**
-     * Schedules a task to enable/disable session sync invalidations. Cancels any previously
-     * scheduled tasks to enable/disable session sync invalidations.
-     * @param enabled whether to enable or disable session sync invalidations.
-     * @param delayMs Delay in milliseconds after which to apply change.
-     */
-    private void setSessionInvalidationsEnabled(final boolean enabled, long delayMs) {
-        mEnableSessionInvalidationsTimer.cancel();
-        if (mSessionInvalidationsEnabled == enabled) return;
-
-        mEnableSessionInvalidationsTimer.setRunnable(new Runnable() {
-            @Override
-            public void run() {
-                mSessionInvalidationsEnabled = enabled;
-                ensureStartedAndUpdateRegisteredTypes();
-            }
-        }, delayMs);
-        if (mStarted) {
-            mEnableSessionInvalidationsTimer.resume();
-        }
-    }
-
-    /**
-     * Creates an instance using {@code context} to send intents.
-     */
-    @VisibleForTesting
-    InvalidationController() {
-        if (ContextUtils.getApplicationContext() == null)
-            throw new NullPointerException("Unable to get application context");
-        mSessionInvalidationsEnabled = false;
-        mEnableSessionInvalidationsTimer = new Timer();
-
-        ApplicationStatus.registerApplicationStateListener(this);
-    }
-
-    @Override
-    public void onApplicationStateChange(int newState) {
-        // The isSyncEnabled() check is used to check whether the InvalidationController would be
-        // started if it did not stop itself when the application is paused.
-        if (AndroidSyncSettings.get().isSyncEnabled()) {
-            if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) {
-                start();
-            } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
-                stop();
-            }
-        }
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java
deleted file mode 100644
index b4e5b20..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.invalidation;
-
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.NativeMethods;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.components.invalidation.InvalidationService;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * InvalidationServiceFactory maps Profiles to instances of
- * {@link InvalidationService} instances. Each {@link Profile} will at most
- * have one instance of this service. If the service does not already exist,
- * it will be created on the first access.
- */
-@JNINamespace("invalidation")
-public final class InvalidationServiceFactory {
-
-    private static final Map<Profile, InvalidationService> sServiceMap =
-            new HashMap<Profile, InvalidationService>();
-
-    private InvalidationServiceFactory() {}
-
-    /**
-     * Returns Java InvalidationService for the given Profile.
-     */
-    public static InvalidationService getForProfile(Profile profile) {
-        ThreadUtils.assertOnUiThread();
-        InvalidationService service = sServiceMap.get(profile);
-        if (service == null) {
-            service = InvalidationServiceFactoryJni.get().getForProfile(profile);
-            sServiceMap.put(profile, service);
-        }
-        return service;
-    }
-
-    @VisibleForTesting
-    public static InvalidationService getForTest() {
-        return InvalidationServiceFactoryJni.get().getForTest();
-    }
-
-    @NativeMethods
-    interface Natives {
-        InvalidationService getForProfile(Profile profile);
-        InvalidationService getForTest();
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
index d0d262c..d3839198 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
@@ -21,6 +21,9 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.util.ConversionUtils;
 import org.chromium.chrome.browser.webapps.WebApkDistributor;
+import org.chromium.chrome.browser.webapps.WebApkUkmRecorder;
+import org.chromium.chrome.browser.webapps.WebappDataStorage;
+import org.chromium.chrome.browser.webapps.WebappRegistry;
 
 import java.io.File;
 import java.lang.annotation.Retention;
@@ -124,20 +127,46 @@
     /** Makes recordings that were deferred in order to not load native. */
     public static void recordDeferredUma() {
         ChromePreferenceManager preferenceManager = ChromePreferenceManager.getInstance();
-        int numUninstalls =
-                preferenceManager.readInt(ChromePreferenceManager.WEBAPK_NUMBER_OF_UNINSTALLS);
-        if (numUninstalls == 0) return;
+        Set<String> uninstalledPackages = preferenceManager.readStringSet(
+                ChromePreferenceManager.WEBAPK_UNINSTALLED_PACKAGES);
+        if (uninstalledPackages.isEmpty()) return;
 
-        for (int i = 0; i < numUninstalls; ++i) {
+        long fallbackUninstallTimestamp = System.currentTimeMillis();
+        WebappRegistry.warmUpSharedPrefs();
+        for (String uninstalledPackage : uninstalledPackages) {
             RecordHistogram.recordBooleanHistogram("WebApk.Uninstall.Browser", true);
+
+            String webApkId = WebappRegistry.webApkIdForPackage(uninstalledPackage);
+            WebappDataStorage webappDataStorage =
+                    WebappRegistry.getInstance().getWebappDataStorage(webApkId);
+            if (webappDataStorage != null) {
+                long uninstallTimestamp = webappDataStorage.getWebApkUninstallTimestamp();
+                if (uninstallTimestamp == 0) {
+                    uninstallTimestamp = fallbackUninstallTimestamp;
+                }
+                WebApkUkmRecorder.recordWebApkUninstall(webappDataStorage.getWebApkManifestUrl(),
+                        WebApkDistributor.BROWSER, webappDataStorage.getWebApkVersionCode(),
+                        webappDataStorage.getLaunchCount(),
+                        uninstallTimestamp - webappDataStorage.getWebApkInstallTimestamp());
+            }
         }
-        preferenceManager.writeInt(ChromePreferenceManager.WEBAPK_NUMBER_OF_UNINSTALLS, 0);
+        preferenceManager.writeStringSet(
+                ChromePreferenceManager.WEBAPK_UNINSTALLED_PACKAGES, new HashSet<String>());
+
+        // TODO(http://crbug.com/1000312): Clear WebappDataStorage for uninstalled WebAPK.
     }
 
     /** Sets WebAPK uninstall to be recorded next time that native is loaded. */
-    public static void deferRecordWebApkUninstalled() {
-        ChromePreferenceManager.getInstance().incrementInt(
-                ChromePreferenceManager.WEBAPK_NUMBER_OF_UNINSTALLS);
+    public static void deferRecordWebApkUninstalled(String packageName) {
+        ChromePreferenceManager.getInstance().addToStringSet(
+                ChromePreferenceManager.WEBAPK_UNINSTALLED_PACKAGES, packageName);
+        String webApkId = WebappRegistry.webApkIdForPackage(packageName);
+        WebappRegistry.warmUpSharedPrefsForId(webApkId);
+        WebappDataStorage webappDataStorage =
+                WebappRegistry.getInstance().getWebappDataStorage(webApkId);
+        if (webappDataStorage != null) {
+            webappDataStorage.setWebApkUninstallTimestamp();
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
index 902e439..19c9bd6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -323,8 +323,12 @@
             "twa_dialog_number_of_dismissals_on_clear_data";
 
     /** Key for deferred recording of WebAPK uninstalls. */
+    @Deprecated
     public static final String WEBAPK_NUMBER_OF_UNINSTALLS = "webapk_number_of_uninstalls";
 
+    /** Key for deferred recording of list of uninstalled WebAPK packages. */
+    public static final String WEBAPK_UNINSTALLED_PACKAGES = "webapk_uninstalled_packages";
+
     public static final String INTEREST_FEED_CONTENT_SUGGESTIONS_KEY =
             "interest_feed_content_suggestions";
 
@@ -566,8 +570,7 @@
      * Stores a set of account names on the device when signin promo is shown.
      */
     public void setSigninPromoLastAccountNames(Set<String> accountNames) {
-        SharedPreferences.Editor editor = mSharedPreferences.edit();
-        editor.putStringSet(SIGNIN_PROMO_LAST_SHOWN_ACCOUNT_NAMES, accountNames).apply();
+        writeStringSet(SIGNIN_PROMO_LAST_SHOWN_ACCOUNT_NAMES, accountNames);
     }
 
     /**
@@ -662,8 +665,7 @@
     public Set<String> getVerifiedDigitalAssetLinks() {
         // From the official docs, modifying the result of a SharedPreferences.getStringSet can
         // cause bad things to happen including exceptions or ruining the data.
-        return new HashSet<>(mSharedPreferences.getStringSet(VERIFIED_DIGITAL_ASSET_LINKS,
-                Collections.emptySet()));
+        return new HashSet<>(readStringSet(VERIFIED_DIGITAL_ASSET_LINKS));
     }
 
     /**
@@ -671,13 +673,12 @@
      * Can be retrieved by {@link #getVerifiedDigitalAssetLinks()}.
      */
     public void setVerifiedDigitalAssetLinks(Set<String> links) {
-        mSharedPreferences.edit().putStringSet(VERIFIED_DIGITAL_ASSET_LINKS, links).apply();
+        writeStringSet(VERIFIED_DIGITAL_ASSET_LINKS, links);
     }
 
     /** Do not modify the set returned by this method. */
     private Set<String> getTrustedWebActivityDisclosureAcceptedPackages() {
-        return mSharedPreferences.getStringSet(
-                TRUSTED_WEB_ACTIVITY_DISCLOSURE_ACCEPTED_PACKAGES, Collections.emptySet());
+        return readStringSet(TRUSTED_WEB_ACTIVITY_DISCLOSURE_ACCEPTED_PACKAGES);
     }
 
     /**
@@ -685,10 +686,7 @@
      * TWAs launched by the given package.
      */
     public void setUserAcceptedTwaDisclosureForPackage(String packageName) {
-        Set<String> packages = new HashSet<>(getTrustedWebActivityDisclosureAcceptedPackages());
-        packages.add(packageName);
-        mSharedPreferences.edit().putStringSet(
-                TRUSTED_WEB_ACTIVITY_DISCLOSURE_ACCEPTED_PACKAGES, packages).apply();
+        addToStringSet(TRUSTED_WEB_ACTIVITY_DISCLOSURE_ACCEPTED_PACKAGES, packageName);
     }
 
     /**
@@ -696,11 +694,7 @@
      * TWAs launched by the given package.
      */
     public void removeTwaDisclosureAcceptanceForPackage(String packageName) {
-        Set<String> packages = new HashSet<>(getTrustedWebActivityDisclosureAcceptedPackages());
-        if (packages.remove(packageName)) {
-            mSharedPreferences.edit().putStringSet(
-                    TRUSTED_WEB_ACTIVITY_DISCLOSURE_ACCEPTED_PACKAGES, packages).apply();
-        }
+        removeFromStringSet(TRUSTED_WEB_ACTIVITY_DISCLOSURE_ACCEPTED_PACKAGES, packageName);
     }
 
     /**
@@ -712,6 +706,41 @@
     }
 
     /**
+     * Reads set of String values from preferences.
+     *
+     * Note that you must not modify the set instance returned by this call.
+     */
+    public Set<String> readStringSet(String key) {
+        return mSharedPreferences.getStringSet(key, Collections.emptySet());
+    }
+
+    /**
+     * Adds a value to string set in shared preferences.
+     */
+    public void addToStringSet(String key, String value) {
+        Set<String> values = new HashSet<>(readStringSet(key));
+        values.add(value);
+        writeStringSet(key, values);
+    }
+
+    /**
+     * Removes value from string set in shared preferences.
+     */
+    public void removeFromStringSet(String key, String value) {
+        Set<String> values = new HashSet<>(readStringSet(key));
+        if (values.remove(value)) {
+            writeStringSet(key, values);
+        }
+    }
+
+    /**
+     * Writes string set to shared preferences.
+     */
+    public void writeStringSet(String key, Set<String> values) {
+        mSharedPreferences.edit().putStringSet(key, values).apply();
+    }
+
+    /**
      * Writes the given int value to the named shared preference.
      * @param key The name of the preference to modify.
      * @param value The new value for the preference.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/ManageSyncPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/ManageSyncPreferences.java
index 8953e24..64848db8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/ManageSyncPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/ManageSyncPreferences.java
@@ -29,7 +29,6 @@
 import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
-import org.chromium.chrome.browser.invalidation.InvalidationController;
 import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
 import org.chromium.chrome.browser.preferences.PreferenceUtils;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -149,10 +148,6 @@
     public void onDestroy() {
         super.onDestroy();
         mSyncSetupInProgressHandle.close();
-
-        if (mProfileSyncService.isSyncRequested()) {
-            InvalidationController.get().ensureStartedAndUpdateRegisteredTypes();
-        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
index a09deb9e..d03d866 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
@@ -40,7 +40,6 @@
 import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
-import org.chromium.chrome.browser.invalidation.InvalidationController;
 import org.chromium.chrome.browser.metrics.UmaSessionStats;
 import org.chromium.chrome.browser.preferences.ChromeBasePreference;
 import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
@@ -243,10 +242,6 @@
     public void onDestroy() {
         super.onDestroy();
         mSyncSetupInProgressHandle.close();
-
-        if (mProfileSyncService.isSyncRequested()) {
-            InvalidationController.get().ensureStartedAndUpdateRegisteredTypes();
-        }
     }
 
     @Override
@@ -525,8 +520,7 @@
             // TODO(https://crbug.com/873116): Pass the correct reason for the signout.
             IdentityServicesProvider.getSigninManager().signOut(
                     SignoutReason.USER_CLICKED_SIGNOUT_SETTINGS,
-                    () -> IdentityServicesProvider.getSigninManager().signIn(account, null, null),
-                    false);
+                    () -> IdentityServicesProvider.getSigninManager().signIn(account, null), false);
             return;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
index aa0e24ff..5c3819e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -20,8 +20,6 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.task.AsyncTask;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.invalidation.InvalidationServiceFactory;
-import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.SigninManager.SignInCallback;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.components.signin.AccountManagerFacade;
@@ -29,7 +27,6 @@
 import org.chromium.components.signin.ChromeSigninController;
 import org.chromium.components.signin.OAuth2TokenService;
 import org.chromium.components.signin.metrics.SignoutReason;
-import org.chromium.components.sync.AndroidSyncSettings;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -190,20 +187,6 @@
             // should now be available.
             mOAuth2TokenService.updateAccountList();
         }
-
-        if (mProfileSyncService != null && AndroidSyncSettings.get().isSyncEnabled()) {
-            if (mProfileSyncService.isFirstSetupComplete()) {
-                if (accountsChanged) {
-                    // Nudge the syncer to ensure it does a full sync.
-                    InvalidationServiceFactory.getForProfile(Profile.getLastUsedProfile())
-                                        .requestSyncFromNativeChromeForAllTypes();
-                }
-            } else {
-                // We should have set up sync but for some reason it's not enabled. Tell the sync
-                // engine to start.
-                mProfileSyncService.requestStart();
-            }
-        }
     }
 
     /**
@@ -233,7 +216,7 @@
         // This is the correct account now.
         final Account account = AccountManagerFacade.createAccountFromName(newName);
 
-        mSigninManager.signIn(account, null, new SignInCallback() {
+        mSigninManager.signIn(account, new SignInCallback() {
             @Override
             public void onSignInComplete() {
                 validateAccountsInternal(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
index ad24c41..91fe0c95 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -11,9 +11,7 @@
 import androidx.annotation.MainThread;
 import androidx.annotation.Nullable;
 
-import org.chromium.base.ActivityState;
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.ApplicationStatus;
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -119,7 +117,6 @@
      */
     private static class SignInState {
         final Account mAccount;
-        final Activity mActivity;
         final SignInCallback mCallback;
 
         /**
@@ -138,32 +135,12 @@
 
         /**
          * @param account The account to sign in to.
-         * @param activity Reference to the UI to use for dialogs. Null means forced signin.
          * @param callback Called when the sign-in process finishes or is cancelled. Can be null.
          */
-        SignInState(
-                Account account, @Nullable Activity activity, @Nullable SignInCallback callback) {
+        SignInState(Account account, @Nullable SignInCallback callback) {
             this.mAccount = account;
-            this.mActivity = activity;
             this.mCallback = callback;
         }
-
-        /**
-         * Returns whether this is an interactive sign-in flow.
-         */
-        boolean isInteractive() {
-            return mActivity != null;
-        }
-
-        /**
-         * Returns whether the sign-in flow activity was set but is no longer visible to the user.
-         */
-        boolean isActivityInvisible() {
-            return mActivity != null
-                    && (ApplicationStatus.getStateForActivity(mActivity) == ActivityState.STOPPED
-                            || ApplicationStatus.getStateForActivity(mActivity)
-                                    == ActivityState.DESTROYED);
-        }
     }
 
     /**
@@ -407,12 +384,10 @@
      *   - Call the callback if provided.
      *
      * @param account The account to sign in to.
-     * @param activity The activity used to launch UI prompts, or null for a forced signin.
      * @param callback Optional callback for when the sign-in process is finished.
      */
     // TODO(crbug.com/1002056) SigninManager.Signin should use CoreAccountInfo as a parameter.
-    public void signIn(
-            Account account, @Nullable Activity activity, @Nullable SignInCallback callback) {
+    public void signIn(Account account, @Nullable SignInCallback callback) {
         if (account == null) {
             Log.w(TAG, "Ignoring sign-in request due to null account.");
             if (callback != null) callback.onSignInAborted();
@@ -431,7 +406,7 @@
             return;
         }
 
-        mSignInState = new SignInState(account, activity, callback);
+        mSignInState = new SignInState(account, callback);
         notifySignInAllowedChanged();
 
         progressSignInFlowSeedSystemAccounts();
@@ -444,7 +419,7 @@
     public void signIn(String accountName, @Nullable final Activity activity,
             @Nullable final SignInCallback callback) {
         AccountManagerFacade.get().getAccountFromName(
-                accountName, account -> signIn(account, activity, callback));
+                accountName, account -> signIn(account, callback));
     }
 
     private void progressSignInFlowSeedSystemAccounts() {
@@ -475,11 +450,6 @@
         // CoreAccountInfo must be set and valid to progress
         assert mSignInState.mCoreAccountInfo != null;
 
-        if (mSignInState.isActivityInvisible()) {
-            abortSignIn();
-            return;
-        }
-
         Log.d(TAG, "Checking if account has policy management enabled");
         fetchAndApplyCloudPolicy(mSignInState.mCoreAccountInfo, this::onPolicyFetchedBeforeSignIn);
     }
@@ -517,15 +487,12 @@
         mIdentityMutator.reloadAllAccountsFromSystemWithPrimaryAccount(
                 mSignInState.mCoreAccountInfo.getId());
 
-        if (mSignInState.isInteractive()) {
-            // If signin was a user action, record that it succeeded.
-            RecordUserAction.record("Signin_Signin_Succeed");
-            logSigninCompleteAccessPoint();
-            // Log signin in reason as defined in signin_metrics.h. Right now only
-            // SIGNIN_PRIMARY_ACCOUNT available on Android.
-            RecordHistogram.recordEnumeratedHistogram("Signin.SigninReason",
-                    SigninReason.SIGNIN_PRIMARY_ACCOUNT, SigninReason.MAX);
-        }
+        RecordUserAction.record("Signin_Signin_Succeed");
+        logSigninCompleteAccessPoint();
+        // Log signin in reason as defined in signin_metrics.h. Right now only
+        // SIGNIN_PRIMARY_ACCOUNT available on Android.
+        RecordHistogram.recordEnumeratedHistogram(
+                "Signin.SigninReason", SigninReason.SIGNIN_PRIMARY_ACCOUNT, SigninReason.MAX);
 
         Log.d(TAG, "Signin completed.");
         mSignInState = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
index 24d7e33..417d4e8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
@@ -20,7 +20,6 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator;
 import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory;
-import org.chromium.chrome.browser.invalidation.InvalidationController;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.SigninManager;
@@ -184,18 +183,11 @@
     @Override
     public void syncStateChanged() {
         ThreadUtils.assertOnUiThread();
-        InvalidationController invalidationController = InvalidationController.get();
         if (mProfileSyncService.isSyncRequested()) {
-            if (!invalidationController.isStarted()) {
-                invalidationController.ensureStartedAndUpdateRegisteredTypes();
-            }
             if (!AndroidSyncSettings.get().isSyncEnabled()) {
                 AndroidSyncSettings.get().enableChromeSync();
             }
         } else {
-            if (invalidationController.isStarted()) {
-                invalidationController.stop();
-            }
             if (AndroidSyncSettings.get().isSyncEnabled()) {
                 // Both Android's master and Chrome sync setting are enabled, so we want to disable
                 // the Chrome sync setting to match isSyncRequested. We have to be careful not to
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
index b65b312..6e9ee06 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -87,6 +87,7 @@
 
         WebApkInfo info = getWebApkInfo();
         WebApkUma.recordShellApkVersion(info.shellApkVersion(), info.distributor());
+        storage.incrementLaunchCount();
 
         mUpdateManager = new WebApkUpdateManager(storage);
         mUpdateManager.updateIfNeeded(getActivityTab(), info);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
index dbd2c1b..82a9ec0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
@@ -84,6 +84,12 @@
                         new WebappRegistry.FetchWebappDataStorageCallback() {
                             @Override
                             public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
+                                WebApkInfo webApkInfo = WebApkInfo.create(packageName, null, source,
+                                        false /* forceNavigation */,
+                                        false /* canUseSplashFromContentProvider */,
+                                        null /* shareData */,
+                                        null /* shareDataActivityClassName */);
+                                storage.updateFromWebappInfo(webApkInfo);
                                 storage.updateSource(source);
                                 storage.updateTimeOfLastCheckForUpdatedWebManifest();
                             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProvider.java
index 583daa9..677831c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProvider.java
@@ -309,13 +309,15 @@
             Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget,
             boolean forceNavigation, boolean isSplashProvidedByWebApk, ShareData shareData,
             int webApkVersionCode) {
-        if (url == null || manifestStartUrl == null || webApkPackageName == null) {
-            Log.e(TAG,
-                    "Incomplete data provided: " + url + ", " + manifestStartUrl + ", "
-                            + webApkPackageName);
+        if (manifestStartUrl == null || webApkPackageName == null) {
+            Log.e(TAG, "Incomplete data provided: " + manifestStartUrl + ", " + webApkPackageName);
             return null;
         }
 
+        if (TextUtils.isEmpty(url)) {
+            url = manifestStartUrl;
+        }
+
         // The default scope should be computed from the Web Manifest start URL. If the WebAPK was
         // launched from a deep link {@link startUrl} may be different from the Web Manifest start
         // URL.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUkmRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUkmRecorder.java
index 38d8cbd..b5c7acc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUkmRecorder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUkmRecorder.java
@@ -20,7 +20,7 @@
                 manifestUrl, distributor, versionCode, duration);
     }
 
-    /**
+    /*
      * Records that WebAPK was launched and the reason for the launch.
      */
     public static void recordWebApkLaunch(
@@ -28,10 +28,22 @@
         WebApkUkmRecorderJni.get().recordVisit(manifestUrl, distributor, versionCode, source);
     }
 
+    /**
+     * Records how long the WebAPK was installed and how many times the WebAPK has been launched
+     * since the last time that the user clearer Chrome's storage.
+     */
+    public static void recordWebApkUninstall(String manifestUrl, @WebApkDistributor int distributor,
+            int versionCode, int launchCount, long installedDurationMs) {
+        WebApkUkmRecorderJni.get().recordUninstall(
+                manifestUrl, distributor, versionCode, launchCount, installedDurationMs);
+    }
+
     @NativeMethods
     interface Natives {
         void recordSessionDuration(
                 String manifestUrl, int distributor, int versionCode, long duration);
         void recordVisit(String manifestUrl, int distributor, int versionCode, int source);
+        void recordUninstall(String manifestUrl, int distributor, int versionCode, int launchCount,
+                long installedDurationMs);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 639fa7c..88da92e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -552,8 +552,8 @@
     protected void updateStorage(WebappDataStorage storage) {
         // The information in the WebappDataStorage may have been purged by the
         // user clearing their history or not launching the web app recently.
-        // Restore the data if necessary from the intent.
-        storage.updateFromShortcutIntent(getIntent());
+        // Restore the data if necessary.
+        storage.updateFromWebappInfo(mWebappInfo);
 
         // A recent last used time is the indicator that the web app is still
         // present on the home screen, and enables sources such as notifications to
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
index a08c16a..1c3f9b91 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
@@ -7,8 +7,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
-import android.text.TextUtils;
 import android.text.format.DateUtils;
 
 import androidx.annotation.Nullable;
@@ -22,7 +23,6 @@
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.ShortcutSource;
-import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.content_public.common.ScreenOrientationValues;
 import org.chromium.webapk.lib.common.WebApkConstants;
 
@@ -50,11 +50,15 @@
     static final String KEY_THEME_COLOR = "theme_color";
     static final String KEY_BACKGROUND_COLOR = "background_color";
     static final String KEY_SOURCE = "source";
-    static final String KEY_ACTION = "action";
     static final String KEY_IS_ICON_GENERATED = "is_icon_generated";
     static final String KEY_IS_ICON_ADAPTIVE = "is_icon_adaptive";
+    static final String KEY_LAUNCH_COUNT = "launch_count";
     static final String KEY_VERSION = "version";
     static final String KEY_WEBAPK_PACKAGE_NAME = "webapk_package_name";
+    static final String KEY_WEBAPK_INSTALL_TIMESTAMP = "webapk_install_timestamp";
+    static final String KEY_WEBAPK_UNINSTALL_TIMESTAMP = "webapk_uninstall_timestamp";
+    static final String KEY_WEBAPK_MANIFEST_URL = "webapk_manifest_url";
+    static final String KEY_WEBAPK_VERSION_CODE = "webapk_version_code";
 
     // The completion time of the last check for whether the WebAPK's Web Manifest was updated.
     static final String KEY_LAST_CHECK_WEB_MANIFEST_UPDATE_TIME =
@@ -214,12 +218,10 @@
 
         // Use "standalone" as the default display mode as this was the original assumed default for
         // all web apps.
-        return ShortcutHelper.createWebappShortcutIntent(mId,
-                mPreferences.getString(KEY_ACTION, null), mPreferences.getString(KEY_URL, null),
+        return ShortcutHelper.createWebappShortcutIntent(mId, mPreferences.getString(KEY_URL, null),
                 mPreferences.getString(KEY_SCOPE, null), mPreferences.getString(KEY_NAME, null),
                 mPreferences.getString(KEY_SHORT_NAME, null),
-                mPreferences.getString(KEY_ICON, null),
-                version,
+                mPreferences.getString(KEY_ICON, null), version,
                 mPreferences.getInt(KEY_DISPLAY_MODE, WebDisplayMode.STANDALONE),
                 mPreferences.getInt(KEY_ORIENTATION, ScreenOrientationValues.DEFAULT),
                 mPreferences.getLong(
@@ -231,11 +233,11 @@
     }
 
     /**
-     * Updates the data stored in this object to match that in the supplied intent.
-     * @param shortcutIntent The intent to pull web app data from.
+     * Updates the data stored in this object to match that in the supplied {@link WebappInfo}.
+     * @param info The WebappInfo to pull web app data from.
      */
-    public void updateFromShortcutIntent(Intent shortcutIntent) {
-        if (shortcutIntent == null) return;
+    public void updateFromWebappInfo(WebappInfo info) {
+        if (info == null) return;
 
         SharedPreferences.Editor editor = mPreferences.edit();
         boolean updated = false;
@@ -244,18 +246,13 @@
         // they are present, and update if necessary.
         String url = mPreferences.getString(KEY_URL, URL_INVALID);
         if (url.equals(URL_INVALID)) {
-            url = IntentUtils.safeGetStringExtra(shortcutIntent, ShortcutHelper.EXTRA_URL);
+            url = info.url();
             editor.putString(KEY_URL, url);
             updated = true;
         }
 
         if (mPreferences.getString(KEY_SCOPE, URL_INVALID).equals(URL_INVALID)) {
-            String scope = IntentUtils.safeGetStringExtra(
-                    shortcutIntent, ShortcutHelper.EXTRA_SCOPE);
-            if (scope == null) {
-                scope = ShortcutHelper.getScopeFromUrl(url);
-            }
-            editor.putString(KEY_SCOPE, scope);
+            editor.putString(KEY_SCOPE, info.scopeUrl());
             updated = true;
         }
 
@@ -265,41 +262,26 @@
         // cleared together.
         if (mPreferences.getInt(KEY_VERSION, VERSION_INVALID)
                 != ShortcutHelper.WEBAPP_SHORTCUT_VERSION) {
-            editor.putString(KEY_NAME, IntentUtils.safeGetStringExtra(
-                        shortcutIntent, ShortcutHelper.EXTRA_NAME));
-            editor.putString(KEY_SHORT_NAME, IntentUtils.safeGetStringExtra(
-                        shortcutIntent, ShortcutHelper.EXTRA_SHORT_NAME));
-            editor.putString(KEY_ICON, IntentUtils.safeGetStringExtra(
-                        shortcutIntent, ShortcutHelper.EXTRA_ICON));
             editor.putInt(KEY_VERSION, ShortcutHelper.WEBAPP_SHORTCUT_VERSION);
 
-            // "Standalone" was the original assumed default for all web apps.
-            editor.putInt(KEY_DISPLAY_MODE,
-                    IntentUtils.safeGetIntExtra(shortcutIntent, ShortcutHelper.EXTRA_DISPLAY_MODE,
-                            WebDisplayMode.STANDALONE));
-            editor.putInt(KEY_ORIENTATION, IntentUtils.safeGetIntExtra(
-                        shortcutIntent, ShortcutHelper.EXTRA_ORIENTATION,
-                        ScreenOrientationValues.DEFAULT));
-            editor.putLong(KEY_THEME_COLOR, IntentUtils.safeGetLongExtra(
-                        shortcutIntent, ShortcutHelper.EXTRA_THEME_COLOR,
-                        ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING));
-            editor.putLong(KEY_BACKGROUND_COLOR, IntentUtils.safeGetLongExtra(
-                        shortcutIntent, ShortcutHelper.EXTRA_BACKGROUND_COLOR,
-                        ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING));
-            editor.putBoolean(KEY_IS_ICON_GENERATED, IntentUtils.safeGetBooleanExtra(
-                        shortcutIntent, ShortcutHelper.EXTRA_IS_ICON_GENERATED, false));
-            editor.putBoolean(KEY_IS_ICON_ADAPTIVE, IntentUtils.safeGetBooleanExtra(
-                        shortcutIntent, ShortcutHelper.EXTRA_IS_ICON_ADAPTIVE, false));
-            editor.putString(KEY_ACTION, shortcutIntent.getAction());
-
-            String webApkPackageName = IntentUtils.safeGetStringExtra(
-                    shortcutIntent, WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME);
-            editor.putString(KEY_WEBAPK_PACKAGE_NAME, webApkPackageName);
-
-            if (TextUtils.isEmpty(webApkPackageName)) {
-                editor.putInt(KEY_SOURCE,
-                        IntentUtils.safeGetIntExtra(shortcutIntent, ShortcutHelper.EXTRA_SOURCE,
-                                ShortcutSource.UNKNOWN));
+            if (info.isForWebApk()) {
+                WebApkInfo webApkInfo = (WebApkInfo) info;
+                editor.putString(KEY_WEBAPK_PACKAGE_NAME, webApkInfo.webApkPackageName());
+                editor.putString(KEY_WEBAPK_MANIFEST_URL, webApkInfo.manifestUrl());
+                editor.putInt(KEY_WEBAPK_VERSION_CODE, webApkInfo.webApkVersionCode());
+                editor.putLong(KEY_WEBAPK_INSTALL_TIMESTAMP,
+                        fetchWebApkInstallTimestamp(webApkInfo.webApkPackageName()));
+            } else {
+                editor.putString(KEY_NAME, info.name());
+                editor.putString(KEY_SHORT_NAME, info.shortName());
+                editor.putString(KEY_ICON, info.icon().encoded());
+                editor.putInt(KEY_DISPLAY_MODE, info.displayMode());
+                editor.putInt(KEY_ORIENTATION, info.orientation());
+                editor.putLong(KEY_THEME_COLOR, info.themeColor());
+                editor.putLong(KEY_BACKGROUND_COLOR, info.backgroundColor());
+                editor.putBoolean(KEY_IS_ICON_GENERATED, info.isIconGenerated());
+                editor.putBoolean(KEY_IS_ICON_ADAPTIVE, info.isIconAdaptive());
+                editor.putInt(KEY_SOURCE, info.source());
             }
             updated = true;
         }
@@ -344,7 +326,11 @@
         editor.remove(KEY_DID_LAST_UPDATE_REQUEST_SUCCEED);
         editor.remove(KEY_RELAX_UPDATES);
         editor.remove(KEY_SHOW_DISCLOSURE);
+        editor.remove(KEY_LAUNCH_COUNT);
+        editor.remove(KEY_WEBAPK_UNINSTALL_TIMESTAMP);
         editor.apply();
+
+        // Don't clear fields which can be fetched from WebAPK manifest.
     }
 
     /**
@@ -625,4 +611,70 @@
         mPreferences = ContextUtils.getApplicationContext().getSharedPreferences(
                 SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE);
     }
+
+    /**
+     * Fetches the timestamp that the WebAPK was installed from the PackageManager.
+     */
+    private long fetchWebApkInstallTimestamp(String webApkPackageName) {
+        try {
+            PackageManager packageManager =
+                    ContextUtils.getApplicationContext().getPackageManager();
+            PackageInfo packageInfo = packageManager.getPackageInfo(webApkPackageName, 0);
+            return packageInfo.firstInstallTime;
+        } catch (PackageManager.NameNotFoundException e) {
+        }
+        return 0;
+    }
+
+    /**
+     * Returns the timestamp when the WebAPK was installed.
+     */
+    public long getWebApkInstallTimestamp() {
+        return mPreferences.getLong(KEY_WEBAPK_INSTALL_TIMESTAMP, 0);
+    }
+
+    /**
+     * Sets the timestamp when the WebAPK was uninstalled to the current time.
+     */
+    public void setWebApkUninstallTimestamp() {
+        mPreferences.edit()
+                .putLong(KEY_WEBAPK_UNINSTALL_TIMESTAMP, sClock.currentTimeMillis())
+                .apply();
+    }
+
+    /**
+     * Returns the timestamp when the WebAPK was uninstalled.
+     */
+    public long getWebApkUninstallTimestamp() {
+        return mPreferences.getLong(KEY_WEBAPK_UNINSTALL_TIMESTAMP, 0);
+    }
+
+    /**
+     * Increments the number of times that the webapp was launched.
+     */
+    public void incrementLaunchCount() {
+        int launchCount = getLaunchCount();
+        mPreferences.edit().putInt(KEY_LAUNCH_COUNT, launchCount + 1).apply();
+    }
+
+    /**
+     * Returns the number of times that the webapp was launched.
+     */
+    public int getLaunchCount() {
+        return mPreferences.getInt(KEY_LAUNCH_COUNT, 0);
+    }
+
+    /**
+     * Returns cached Web Manifest URL.
+     */
+    public String getWebApkManifestUrl() {
+        return mPreferences.getString(KEY_WEBAPK_MANIFEST_URL, null);
+    }
+
+    /**
+     * Returns cached WebAPK version code.
+     */
+    public int getWebApkVersionCode() {
+        return mPreferences.getInt(KEY_WEBAPK_VERSION_CODE, 0);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
index 68c10c3..22f6fa1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
@@ -6,6 +6,7 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.support.annotation.NonNull;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.Pair;
@@ -21,6 +22,7 @@
 import org.chromium.chrome.browser.browserservices.permissiondelegation.TrustedWebActivityPermissionStore;
 import org.chromium.chrome.browser.browsing_data.UrlFilter;
 import org.chromium.chrome.browser.browsing_data.UrlFilterBridge;
+import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.webapk.lib.common.WebApkConstants;
 
@@ -266,12 +268,7 @@
             WebappDataStorage storage = entry.getValue();
             String webApkPackage = storage.getWebApkPackageName();
             if (webApkPackage != null) {
-                // Prefix check that the key matches the current scheme instead of an old
-                // deprecated naming scheme and that the WebApk is still installed. The former is
-                // necessary as we migrate away from the old naming scheme and garbage collect.
-                if (entry.getKey().startsWith(WebApkConstants.WEBAPK_ID_PREFIX)
-                        && PackageUtils.isPackageInstalled(
-                                   ContextUtils.getApplicationContext(), webApkPackage)) {
+                if (!shouldDeleteStorageForWebApk(entry.getKey(), webApkPackage)) {
                     continue;
                 }
             } else if ((currentTime - storage.getLastUsedTimeMs())
@@ -288,6 +285,27 @@
                 .apply();
     }
 
+    /**
+     * Returns whether the {@link WebappDataStorage} should be deleted for the passed-in WebAPK
+     * package.
+     */
+    private static boolean shouldDeleteStorageForWebApk(
+            @NonNull String id, @NonNull String webApkPackageName) {
+        // Prefix check that the key matches the current scheme instead of an old deprecated naming
+        // scheme. This is necessary as we migrate away from the old naming scheme and garbage
+        // collect.
+        if (!id.startsWith(WebApkConstants.WEBAPK_ID_PREFIX)) return true;
+
+        // Do not delete WebappDataStorage if we still need it for UKM logging.
+        Set<String> webApkPackagesWithPendingUkm =
+                ChromePreferenceManager.getInstance().readStringSet(
+                        ChromePreferenceManager.WEBAPK_UNINSTALLED_PACKAGES);
+        if (webApkPackagesWithPendingUkm.contains(webApkPackageName)) return false;
+
+        return !PackageUtils.isPackageInstalled(
+                ContextUtils.getApplicationContext(), webApkPackageName);
+    }
+
     public TrustedWebActivityPermissionStore getTrustedWebActivityPermissionStore() {
         return mTrustedWebActivityPermissionStore;
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
index 903134f..8ac4d0db 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.browsing_data;
 
-import android.content.Intent;
 import android.support.test.filters.MediumTest;
 
 import org.junit.Assert;
@@ -17,13 +16,14 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.preferences.privacy.BrowsingDataBridge;
 import org.chromium.chrome.browser.preferences.privacy.BrowsingDataBridge.OnClearBrowsingDataListener;
 import org.chromium.chrome.browser.webapps.TestFetchStorageCallback;
+import org.chromium.chrome.browser.webapps.WebappInfo;
 import org.chromium.chrome.browser.webapps.WebappRegistry;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.browser.webapps.WebappTestHelper;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -70,12 +70,11 @@
     }
 
     private void registerWebapp(final String webappId, final String webappUrl) throws Exception {
-        Intent shortcutIntent =
-                ShortcutHelper.createWebappShortcutIntentForTesting(webappId, webappUrl);
+        WebappInfo webappInfo = WebappTestHelper.createWebappInfo(webappId, webappUrl);
         TestFetchStorageCallback callback = new TestFetchStorageCallback();
-        WebappRegistry.getInstance().register(webappId, callback);
+        WebappRegistry.getInstance().register(webappInfo.id(), callback);
         callback.waitForCallback(0);
-        callback.getStorage().updateFromShortcutIntent(shortcutIntent);
+        callback.getStorage().updateFromWebappInfo(webappInfo);
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
index b9d776b..94b4366 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -615,7 +615,7 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             IdentityServicesProvider.getSigninManager().onFirstRunCheckDone();
             IdentityServicesProvider.getSigninManager().addSignInStateObserver(mTestObserver);
-            IdentityServicesProvider.getSigninManager().signIn(account, null, null);
+            IdentityServicesProvider.getSigninManager().signIn(account, null);
         });
 
         mTestObserver.onSigninStateChangedCallback.waitForCallback(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterTest.java
deleted file mode 100644
index 690129e..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.invalidation;
-
-import android.accounts.Account;
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SyncResult;
-import android.os.Bundle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.CommandLine;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.components.invalidation.PendingInvalidation;
-import org.chromium.components.signin.AccountManagerFacade;
-import org.chromium.components.sync.AndroidSyncSettings;
-import org.chromium.content_public.browser.test.util.Criteria;
-import org.chromium.content_public.browser.test.util.CriteriaHelper;
-
-/**
- * Tests for ChromeBrowserSyncAdapter.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class ChromeBrowserSyncAdapterTest {
-    @Rule
-    public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeActivity.class);
-
-    private static final Account TEST_ACCOUNT =
-            AccountManagerFacade.createAccountFromName("test@gmail.com");
-    private static final long WAIT_FOR_LAUNCHER_MS = (long) (10 * 1000);
-    private static final long POLL_INTERVAL_MS = 100;
-
-    private TestSyncAdapter mSyncAdapter;
-
-    private static class TestSyncAdapter extends ChromeBrowserSyncAdapter {
-        private boolean mInvalidated;
-        private boolean mInvalidatedAllTypes;
-        private int mObjectSource;
-        private String mObjectId;
-        private long mVersion;
-        private String mPayload;
-
-        public TestSyncAdapter(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void notifyInvalidation(
-                int objectSource, String objectId, long version, String payload) {
-            mObjectSource = objectSource;
-            mObjectId = objectId;
-            mVersion = version;
-            mPayload = payload;
-            if (objectId == null) {
-                mInvalidatedAllTypes = true;
-            } else {
-                mInvalidated = true;
-            }
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        mActivityTestRule.startMainActivityOnBlankPage();
-        mSyncAdapter = new TestSyncAdapter(InstrumentationRegistry.getTargetContext());
-    }
-
-    private void performSyncWithBundle(Bundle bundle) {
-        mSyncAdapter.onPerformSync(TEST_ACCOUNT, bundle,
-                AndroidSyncSettings.get().getContractAuthority(), null, new SyncResult());
-    }
-
-    private void sendChromeToBackground(Activity activity) {
-        Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.addCategory(Intent.CATEGORY_HOME);
-        activity.startActivity(intent);
-
-        CriteriaHelper.pollInstrumentationThread(new Criteria("Activity should have been resumed") {
-            @Override
-            public boolean isSatisfied() {
-                return !isActivityResumed();
-            }
-        }, WAIT_FOR_LAUNCHER_MS, POLL_INTERVAL_MS);
-    }
-
-    private boolean isActivityResumed() {
-        return ApplicationStatus.hasVisibleActivities();
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"Sync"})
-    @RetryOnFailure
-    public void testRequestSyncNoInvalidationData() {
-        performSyncWithBundle(new Bundle());
-        Assert.assertTrue(mSyncAdapter.mInvalidatedAllTypes);
-        Assert.assertFalse(mSyncAdapter.mInvalidated);
-        Assert.assertTrue(CommandLine.isInitialized());
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"Sync"})
-    public void testRequestSyncSpecificDataType() {
-        String objectId = "objectid_value";
-        int objectSource = 61;
-        long version = 42L;
-        String payload = "payload_value";
-
-        performSyncWithBundle(
-                PendingInvalidation.createBundle(objectId, objectSource, version, payload));
-
-        Assert.assertFalse(mSyncAdapter.mInvalidatedAllTypes);
-        Assert.assertTrue(mSyncAdapter.mInvalidated);
-        Assert.assertEquals(objectSource, mSyncAdapter.mObjectSource);
-        Assert.assertEquals(objectId, mSyncAdapter.mObjectId);
-        Assert.assertEquals(version, mSyncAdapter.mVersion);
-        Assert.assertEquals(payload, mSyncAdapter.mPayload);
-        Assert.assertTrue(CommandLine.isInitialized());
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"Sync"})
-    @RetryOnFailure
-    public void testRequestSyncWhenChromeInBackground() {
-        sendChromeToBackground(mActivityTestRule.getActivity());
-        performSyncWithBundle(new Bundle());
-        Assert.assertFalse(mSyncAdapter.mInvalidatedAllTypes);
-        Assert.assertFalse(mSyncAdapter.mInvalidated);
-        Assert.assertTrue(CommandLine.isInitialized());
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"Sync"})
-    @RetryOnFailure
-    public void testRequestInitializeSync() {
-        Bundle extras = new Bundle();
-        extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
-        performSyncWithBundle(extras);
-        Assert.assertFalse(mSyncAdapter.mInvalidatedAllTypes);
-        Assert.assertFalse(mSyncAdapter.mInvalidated);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsControllerTest.java
deleted file mode 100644
index 573aff3a..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsControllerTest.java
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.invalidation;
-
-import android.accounts.Account;
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.os.Bundle;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.rule.UiThreadTestRule;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.ActivityState;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.components.invalidation.PendingInvalidation;
-
-import java.util.List;
-
-/**
- * Tests for DelayedInvalidationsController.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-public class DelayedInvalidationsControllerTest {
-    private static final String TEST_ACCOUNT = "something@gmail.com";
-
-    private static final String OBJECT_ID = "object_id";
-    private static final int OBJECT_SRC = 4;
-    private static final long VERSION = 1L;
-    private static final String PAYLOAD = "payload";
-
-    private static final String OBJECT_ID_2 = "object_id_2";
-    private static final int OBJECT_SRC_2 = 5;
-    private static final long VERSION_2 = 2L;
-    private static final String PAYLOAD_2 = "payload_2";
-
-    private MockDelayedInvalidationsController mController;
-    private Activity mPlaceholderActivity;
-
-    @Rule
-    public UiThreadTestRule mRule = new UiThreadTestRule();
-
-    /**
-     * Mocks {@link DelayedInvalidationsController} for testing.
-     * It intercepts access to the Android Sync Adapter.
-     */
-    private static class MockDelayedInvalidationsController extends DelayedInvalidationsController {
-        private boolean mInvalidated;
-        private List<Bundle> mBundles;
-
-        private MockDelayedInvalidationsController() {}
-
-        @Override
-        void notifyInvalidationsOnBackgroundThread(Account account, List<Bundle> bundles) {
-            mInvalidated = true;
-            mBundles = bundles;
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        mController = new MockDelayedInvalidationsController();
-
-        mPlaceholderActivity = new Activity();
-        setApplicationState(ActivityState.CREATED);
-        setApplicationState(ActivityState.RESUMED);
-    }
-
-    @After
-    public void tearDown() {
-        setApplicationState(ActivityState.DESTROYED);
-    }
-
-    private void setApplicationState(int newState) {
-        ApplicationStatus.onStateChangeForTesting(mPlaceholderActivity, newState);
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Sync"})
-    @UiThreadTest
-    public void testManualSyncRequestsShouldAlwaysTriggerSync() throws InterruptedException {
-        // Sync should trigger for manual requests when Chrome is in the foreground.
-        Bundle extras = new Bundle();
-        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
-        Assert.assertTrue(mController.shouldNotifyInvalidation(extras));
-
-        // Sync should trigger for manual requests when Chrome is in the background.
-        setApplicationState(ActivityState.STOPPED);
-        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
-        Assert.assertTrue(mController.shouldNotifyInvalidation(extras));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Sync", "Invalidation"})
-    @UiThreadTest
-    public void testInvalidationsTriggeredWhenChromeIsInForeground() {
-        Assert.assertTrue(mController.shouldNotifyInvalidation(new Bundle()));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Sync", "Invalidation"})
-    @UiThreadTest
-    public void testInvalidationsReceivedWhenChromeIsInBackgroundIsDelayed()
-            throws InterruptedException {
-        setApplicationState(ActivityState.STOPPED);
-        Assert.assertFalse(mController.shouldNotifyInvalidation(new Bundle()));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Sync", "Invalidation"})
-    @UiThreadTest
-    public void testOnlySpecificInvalidationsTriggeredOnResume() throws InterruptedException {
-        // First make sure there are no pending invalidations.
-        mController.clearPendingInvalidations();
-        Assert.assertFalse(mController.notifyPendingInvalidations());
-        Assert.assertFalse(mController.mInvalidated);
-
-        // Create some invalidations.
-        PendingInvalidation firstInv =
-                new PendingInvalidation(OBJECT_ID, OBJECT_SRC, VERSION, PAYLOAD);
-        PendingInvalidation secondInv =
-                new PendingInvalidation(OBJECT_ID_2, OBJECT_SRC_2, VERSION_2, PAYLOAD_2);
-
-        // Can't invalidate while Chrome is in the background.
-        setApplicationState(ActivityState.STOPPED);
-        Assert.assertFalse(mController.shouldNotifyInvalidation(new Bundle()));
-
-        // Add multiple pending invalidations.
-        mController.addPendingInvalidation(TEST_ACCOUNT, firstInv);
-        mController.addPendingInvalidation(TEST_ACCOUNT, secondInv);
-
-        // Make sure there are pending invalidations.
-        Assert.assertTrue(mController.notifyPendingInvalidations());
-        Assert.assertTrue(mController.mInvalidated);
-
-        // Ensure only specific invalidations are being notified.
-        Assert.assertEquals(2, mController.mBundles.size());
-        PendingInvalidation parsedInv1 = new PendingInvalidation(mController.mBundles.get(0));
-        PendingInvalidation parsedInv2 = new PendingInvalidation(mController.mBundles.get(1));
-        Assert.assertTrue(firstInv.equals(parsedInv1) ^ firstInv.equals(parsedInv2));
-        Assert.assertTrue(secondInv.equals(parsedInv1) ^ secondInv.equals(parsedInv2));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Sync", "Invalidation"})
-    @UiThreadTest
-    public void testAllInvalidationsTriggeredOnResume() throws InterruptedException {
-        // First make sure there are no pending invalidations.
-        mController.clearPendingInvalidations();
-        Assert.assertFalse(mController.notifyPendingInvalidations());
-        Assert.assertFalse(mController.mInvalidated);
-
-        // Create some invalidations.
-        PendingInvalidation firstInv =
-                new PendingInvalidation(OBJECT_ID, OBJECT_SRC, VERSION, PAYLOAD);
-        PendingInvalidation secondInv =
-                new PendingInvalidation(OBJECT_ID_2, OBJECT_SRC_2, VERSION_2, PAYLOAD_2);
-        PendingInvalidation allInvalidations = new PendingInvalidation(new Bundle());
-        Assert.assertEquals(allInvalidations.mObjectSource, 0);
-
-        // Can't invalidate while Chrome is in the background.
-        setApplicationState(ActivityState.STOPPED);
-        Assert.assertFalse(mController.shouldNotifyInvalidation(new Bundle()));
-
-        // Add multiple pending invalidations.
-        mController.addPendingInvalidation(TEST_ACCOUNT, firstInv);
-        mController.addPendingInvalidation(TEST_ACCOUNT, allInvalidations);
-        mController.addPendingInvalidation(TEST_ACCOUNT, secondInv);
-
-        // Make sure there are pending invalidations.
-        Assert.assertTrue(mController.notifyPendingInvalidations());
-        Assert.assertTrue(mController.mInvalidated);
-
-        // As Invalidation for all ids has been received, it will supersede all other invalidations.
-        Assert.assertEquals(1, mController.mBundles.size());
-        Assert.assertEquals(allInvalidations, new PendingInvalidation(mController.mBundles.get(0)));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Sync", "Invalidation"})
-    @UiThreadTest
-    public void testSameObjectInvalidationsGetCombined() throws InterruptedException {
-        // First make sure there are no pending invalidations.
-        mController.clearPendingInvalidations();
-        Assert.assertFalse(mController.notifyPendingInvalidations());
-        Assert.assertFalse(mController.mInvalidated);
-
-        // Create invalidations with the same id/src, but different versions and payloads.
-        PendingInvalidation lowerVersionInv =
-                new PendingInvalidation(OBJECT_ID, OBJECT_SRC, VERSION, PAYLOAD);
-        PendingInvalidation higherVersionInv =
-                new PendingInvalidation(OBJECT_ID, OBJECT_SRC, VERSION_2, PAYLOAD_2);
-
-        // Can't invalidate while Chrome is in the background.
-        setApplicationState(ActivityState.STOPPED);
-        Assert.assertFalse(mController.shouldNotifyInvalidation(new Bundle()));
-
-        // Add multiple pending invalidations.
-        mController.addPendingInvalidation(TEST_ACCOUNT, lowerVersionInv);
-        mController.addPendingInvalidation(TEST_ACCOUNT, higherVersionInv);
-
-        // Make sure there are pending invalidations.
-        Assert.assertTrue(mController.notifyPendingInvalidations());
-        Assert.assertTrue(mController.mInvalidated);
-
-        // As Invalidation for all ids has been received, it will supersede all other invalidations.
-        Assert.assertEquals(1, mController.mBundles.size());
-        Assert.assertEquals(higherVersionInv, new PendingInvalidation(mController.mBundles.get(0)));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Sync", "Invalidation"})
-    @UiThreadTest
-    public void testSameObjectLowerVersionInvalidationGetsDiscarded() throws InterruptedException {
-        // First make sure there are no pending invalidations.
-        mController.clearPendingInvalidations();
-        Assert.assertFalse(mController.notifyPendingInvalidations());
-        Assert.assertFalse(mController.mInvalidated);
-
-        // Create invalidations with the same id/src, but different versions and payloads.
-        PendingInvalidation lowerVersionInv =
-                new PendingInvalidation(OBJECT_ID, OBJECT_SRC, VERSION, PAYLOAD);
-        PendingInvalidation higherVersionInv =
-                new PendingInvalidation(OBJECT_ID, OBJECT_SRC, VERSION_2, PAYLOAD_2);
-
-        // Can't invalidate while Chrome is in the background.
-        setApplicationState(ActivityState.STOPPED);
-        Assert.assertFalse(mController.shouldNotifyInvalidation(new Bundle()));
-
-        // Add multiple pending invalidations.
-        mController.addPendingInvalidation(TEST_ACCOUNT, higherVersionInv);
-        mController.addPendingInvalidation(TEST_ACCOUNT, lowerVersionInv);
-
-        // Make sure there are pending invalidations.
-        Assert.assertTrue(mController.notifyPendingInvalidations());
-        Assert.assertTrue(mController.mInvalidated);
-
-        // As Invalidation for all ids has been received, it will supersede all other invalidations.
-        Assert.assertEquals(1, mController.mBundles.size());
-        Assert.assertEquals(higherVersionInv, new PendingInvalidation(mController.mBundles.get(0)));
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java
deleted file mode 100644
index 77bca88..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.invalidation;
-
-import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.rule.UiThreadTestRule;
-
-import com.google.ipc.invalidation.external.client.types.ObjectId;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.RuleChain;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.test.ChromeBrowserTestRule;
-import org.chromium.chrome.test.invalidation.IntentSavingContext;
-import org.chromium.components.invalidation.InvalidationService;
-import org.chromium.components.sync.AndroidSyncSettings;
-import org.chromium.components.sync.ModelType;
-import org.chromium.components.sync.ModelTypeHelper;
-import org.chromium.components.sync.notifier.InvalidationIntentProtocol;
-import org.chromium.components.sync.test.util.MockSyncContentResolverDelegate;
-
-import java.util.Set;
-
-/**
- * Tests for {@link InvalidationService}.
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class InvalidationServiceTest {
-    @Rule
-    public final RuleChain mChain =
-            RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule());
-
-    private IntentSavingContext mAppContext;
-
-    @Before
-    public void setUp() throws Exception {
-        mAppContext = new IntentSavingContext(InstrumentationRegistry.getInstrumentation()
-                                                      .getTargetContext()
-                                                      .getApplicationContext());
-        // We don't want to use the system content resolver, so we override it.
-        MockSyncContentResolverDelegate delegate = new MockSyncContentResolverDelegate();
-        // Android master sync can safely always be on.
-        delegate.setMasterSyncAutomatically(true);
-        AndroidSyncSettings.overrideForTests(delegate, null);
-        ContextUtils.initApplicationContextForTests(mAppContext);
-    }
-
-    @Test
-    @SmallTest
-    @UiThreadTest
-    @Feature({"Sync"})
-    public void testSetRegisteredObjectIds() throws Throwable {
-        InvalidationService service = InvalidationServiceFactory.getForTest();
-        ObjectId bookmark = ModelTypeHelper.toObjectId(ModelType.BOOKMARKS);
-        service.setRegisteredObjectIds(new int[] {1, 2, bookmark.getSource()},
-                new String[] {"a", "b", new String(bookmark.getName())});
-        Assert.assertEquals(1, mAppContext.getNumStartedIntents());
-
-        // Validate destination.
-        Intent intent = mAppContext.getStartedIntent(0);
-        validateIntentComponent(intent);
-        Assert.assertEquals(InvalidationIntentProtocol.ACTION_REGISTER, intent.getAction());
-
-        // Validate registered object ids. The bookmark object should not be registered
-        // since it is a Sync type.
-        Assert.assertNull(
-                intent.getStringArrayListExtra(InvalidationIntentProtocol.EXTRA_REGISTERED_TYPES));
-        Set<ObjectId> objectIds = InvalidationIntentProtocol.getRegisteredObjectIds(intent);
-        Assert.assertEquals(2, objectIds.size());
-        Assert.assertTrue(objectIds.contains(
-                ObjectId.newInstance(1, ApiCompatibilityUtils.getBytesUtf8("a"))));
-        Assert.assertTrue(objectIds.contains(
-                ObjectId.newInstance(2, ApiCompatibilityUtils.getBytesUtf8("b"))));
-    }
-
-    /**
-     * Asserts that {@code intent} is destined for the correct component.
-     */
-    private static void validateIntentComponent(Intent intent) {
-        Assert.assertNotNull(intent.getComponent());
-        Assert.assertEquals(ChromeInvalidationClientService.class.getName(),
-                intent.getComponent().getClassName());
-    }
-
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
index fd89c7df..5f2cbe3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
@@ -10,7 +10,6 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
-import android.content.Intent;
 import android.os.Build;
 import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
@@ -38,7 +37,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataTab;
 import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
@@ -48,11 +46,13 @@
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.webapps.TestFetchStorageCallback;
 import org.chromium.chrome.browser.webapps.WebappDataStorage;
+import org.chromium.chrome.browser.webapps.WebappInfo;
 import org.chromium.chrome.browser.webapps.WebappRegistry;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
+import org.chromium.chrome.test.util.browser.webapps.WebappTestHelper;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationEntry;
 import org.chromium.content_public.browser.WebContents;
@@ -163,11 +163,11 @@
     @Test
     @MediumTest
     public void testClearingHistoryClearsWebappScopesAndLaunchTimes() throws Exception {
-        Intent shortcutIntent = ShortcutHelper.createWebappShortcutIntentForTesting("id", "url");
+        WebappInfo webappInfo = WebappTestHelper.createWebappInfo("id", "url");
         TestFetchStorageCallback callback = new TestFetchStorageCallback();
         WebappRegistry.getInstance().register("first", callback);
         callback.waitForCallback(0);
-        callback.getStorage().updateFromShortcutIntent(shortcutIntent);
+        callback.getStorage().updateFromWebappInfo(webappInfo);
 
         Assert.assertEquals(new HashSet<>(Arrays.asList("first")),
                 WebappRegistry.getRegisteredWebappIdsForTesting());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
index 2ac73ae..851e4c4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
@@ -159,7 +159,7 @@
     public void signinAndEnableSync(final Account account) {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             IdentityServicesProvider.getSigninManager().signIn(
-                    account, null, new SigninManager.SignInCallback() {
+                    account, new SigninManager.SignInCallback() {
                         @Override
                         public void onSignInComplete() {
                             if (ChromeFeatureList.isEnabled(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestRule.java
index 0d80065..9747507 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestRule.java
@@ -120,8 +120,9 @@
                 // runnable.
                 callback.waitForCallback(0);
 
-                TestThreadUtils.runOnUiThreadBlocking(
-                        () -> { callback.getStorage().updateFromShortcutIntent(createIntent()); });
+                TestThreadUtils.runOnUiThreadBlocking(() -> {
+                    callback.getStorage().updateFromWebappInfo(WebappInfo.create(createIntent()));
+                });
 
                 base.evaluate();
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
index 7f89f0c..4c19398 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
@@ -110,16 +110,18 @@
                     WEBAPP_1_ID, new WebappRegistry.FetchWebappDataStorageCallback() {
                         @Override
                         public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
-                            storage.updateFromShortcutIntent(createIntent(
+                            WebappInfo webappInfo = WebappInfo.create(createIntent(
                                     WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true));
+                            storage.updateFromWebappInfo(webappInfo);
                         }
                     });
             WebappRegistry.getInstance().register(
                     WEBAPP_2_ID, new WebappRegistry.FetchWebappDataStorageCallback() {
                         @Override
                         public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
-                            storage.updateFromShortcutIntent(createIntent(
+                            WebappInfo webappInfo = WebappInfo.create(createIntent(
                                     WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true));
+                            storage.updateFromWebappInfo(webappInfo);
                         }
                     });
         });
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java
deleted file mode 100644
index ecc541f..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java
+++ /dev/null
@@ -1,488 +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.
-
-package org.chromium.chrome.browser.invalidation;
-
-import android.accounts.Account;
-import android.app.Activity;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.os.Bundle;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowActivity;
-import org.robolectric.shadows.ShadowLooper;
-import org.robolectric.shadows.ShadowPackageManager;
-
-import org.chromium.base.ActivityState;
-import org.chromium.base.ApplicationState;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.CollectionUtil;
-import org.chromium.base.task.test.CustomShadowAsyncTask;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.sync.ProfileSyncService;
-import org.chromium.components.signin.AccountManagerFacade;
-import org.chromium.components.signin.ChromeSigninController;
-import org.chromium.components.signin.SystemAccountManagerDelegate;
-import org.chromium.components.sync.AndroidSyncSettings;
-import org.chromium.components.sync.ModelType;
-import org.chromium.components.sync.ModelTypeHelper;
-import org.chromium.components.sync.notifier.InvalidationIntentProtocol;
-import org.chromium.components.sync.test.util.MockSyncContentResolverDelegate;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Tests for the {@link InvalidationController}.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 21, shadows = {CustomShadowAsyncTask.class})
-public class InvalidationControllerTest {
-    /**
-     * Stubbed out ProfileSyncService with a setter to control return value of
-     * {@link ProfileSyncService#getPreferredDataTypes()}
-     */
-    private static class ProfileSyncServiceStub extends ProfileSyncService {
-        private Set<Integer> mPreferredDataTypes;
-
-        public ProfileSyncServiceStub() {
-            super();
-        }
-
-        public void setPreferredDataTypes(Set<Integer> types) {
-            mPreferredDataTypes = types;
-        }
-
-        @Override
-        protected void init() {
-            // Skip native initialization.
-        }
-
-        @Override
-        public Set<Integer> getPreferredDataTypes() {
-            return mPreferredDataTypes;
-        }
-    }
-
-    private enum IntentType { START, START_AND_REGISTER, STOP };
-
-    private ShadowActivity mShadowActivity;
-    private Activity mActivity;
-
-    /**
-     * The names of the preferred ModelTypes.
-     */
-    private Set<String> mAllTypes;
-
-    /**
-     * The names of the non-session preferred ModelTypes.
-     */
-    private Set<String> mNonSessionTypes;
-
-    @Before
-    public void setUp() throws Exception {
-        mActivity = Robolectric.buildActivity(Activity.class).setup().get();
-        mShadowActivity = Shadows.shadowOf(mActivity);
-
-        ShadowPackageManager packageManager = Shadows.shadowOf(mActivity.getPackageManager());
-        Bundle metaData = new Bundle();
-        metaData.putString(
-                "ipc.invalidation.ticl.listener_service_class",
-                ChromeInvalidationClientService.class.getName());
-        ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.metaData = metaData;
-        PackageInfo packageInfo = new PackageInfo();
-        packageInfo.packageName = mActivity.getPackageName();
-        packageInfo.applicationInfo = applicationInfo;
-        packageManager.addPackage(packageInfo);
-
-        AccountManagerFacade.overrideAccountManagerFacadeForTests(
-                new SystemAccountManagerDelegate());
-
-        ModelTypeHelper.setTestDelegate(new ModelTypeHelper.TestDelegate() {
-            @Override
-            public String toNotificationType(int modelType) {
-                return Integer.toString(modelType);
-            }
-        });
-
-        ProfileSyncServiceStub profileSyncServiceStub = new ProfileSyncServiceStub();
-        ProfileSyncService.overrideForTests(profileSyncServiceStub);
-        profileSyncServiceStub.setPreferredDataTypes(
-                CollectionUtil.newHashSet(ModelType.BOOKMARKS, ModelType.SESSIONS));
-        mAllTypes = CollectionUtil.newHashSet(
-                ModelTypeHelper.toNotificationType(ModelType.BOOKMARKS),
-                ModelTypeHelper.toNotificationType(ModelType.SESSIONS));
-        mNonSessionTypes = CollectionUtil.newHashSet(ModelTypeHelper.toNotificationType(
-                ModelType.BOOKMARKS));
-
-        // We don't want to use the system content resolver, so we override it.
-        MockSyncContentResolverDelegate delegate = new MockSyncContentResolverDelegate();
-        // Android master sync can safely always be on.
-        delegate.setMasterSyncAutomatically(true);
-        AndroidSyncSettings.overrideForTests(delegate, null);
-
-        ChromeSigninController.get().setSignedInAccountName("test@example.com");
-        AndroidSyncSettings.get().updateAccount(ChromeSigninController.get().getSignedInUser());
-        AndroidSyncSettings.get().enableChromeSync();
-    }
-
-    @After
-    public void tearDown() {
-        AccountManagerFacade.resetAccountManagerFacadeForTests();
-        ProfileSyncService.resetForTests();
-    }
-
-    /**
-     * Verify the intent sent by InvalidationController#stop().
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testStop() throws Exception {
-        InvalidationController controller = new InvalidationController();
-        controller.stop();
-        Intent intent = getOnlyIntent();
-        validateIntentComponent(intent);
-        Assert.assertEquals(1, intent.getExtras().size());
-        Assert.assertTrue(intent.hasExtra(InvalidationIntentProtocol.EXTRA_STOP));
-        Assert.assertTrue(intent.getBooleanExtra(InvalidationIntentProtocol.EXTRA_STOP, false));
-    }
-
-    /**
-     * Verify the intent sent by InvalidationController#ensureStartedAndUpdateRegisteredTypes().
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testEnsureStartedAndUpdateRegisteredTypes() {
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Intent intent = getOnlyIntent();
-
-        // Ensure GCM is initialized. This is a regression test for http://crbug.com/475299.
-        Assert.assertTrue(controller.isGcmInitialized());
-
-        // Validate destination.
-        validateIntentComponent(intent);
-        Assert.assertEquals(InvalidationIntentProtocol.ACTION_REGISTER, intent.getAction());
-
-        // Validate account.
-        Account intentAccount =
-                intent.getParcelableExtra(InvalidationIntentProtocol.EXTRA_ACCOUNT);
-        Assert.assertEquals("test@example.com", intentAccount.name);
-
-        // Validate registered types.
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(intent));
-        Assert.assertNull(InvalidationIntentProtocol.getRegisteredObjectIds(intent));
-    }
-
-    /**
-     * Test that pausing and resuming Chrome's activities does not send any intents if sync is
-     * disabled.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testPauseAndResumeMainActivityWithSyncDisabled() throws Exception {
-        AndroidSyncSettings.get().disableChromeSync();
-
-        InvalidationController controller = new InvalidationController();
-        controller.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
-        controller.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
-        assertNoNewIntents();
-    }
-
-    /**
-     * Test that ensureStartedAndUpdateRegisteredTypes() does not send any intents if
-     * ProfileSyncService is null.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testNullProfileSyncService() throws Exception {
-        ProfileSyncService.overrideForTests(null);
-
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        assertNoNewIntents();
-    }
-
-    /**
-     * Test that creating an InvalidationController object registers an ApplicationStateListener.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testEnsureConstructorRegistersListener() throws Exception {
-        final AtomicBoolean listenerCallbackCalled = new AtomicBoolean();
-
-        // Create instance.
-        new InvalidationController() {
-            @Override
-            public void onApplicationStateChange(int newState) {
-                listenerCallbackCalled.set(true);
-            }
-        };
-
-        // Ensure initial state is correct.
-        Assert.assertFalse(listenerCallbackCalled.get());
-
-        // Ensure we get a callback, which means we have registered for them.
-        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.DESTROYED);
-        Assert.assertTrue(listenerCallbackCalled.get());
-    }
-
-    /**
-     * Test that an intent is sent to register for session invalidations after the RecentTabsPage is
-     * opened.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testRecentTabsPageShown() {
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mAllTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageClosed();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-    }
-
-    /**
-     * Test that if the InvalidationController is started while the RecentTabsPage is shown that
-     * an intent is sent to register for session invalidations only once the InvalidationController
-     * is started.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testStartWhileRecentTabsPageShown() {
-        InvalidationController controller = new InvalidationController();
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        assertNoNewIntents();
-
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(IntentType.START_AND_REGISTER, getIntentType(getOnlyIntent()));
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mAllTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageClosed();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-    }
-
-    /**
-     * Test the handling for multiple open RecentTabsPages.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testMultipleRecentTabsPages() {
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mAllTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        assertNoNewIntents();
-
-        controller.onRecentTabsPageClosed();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        assertNoNewIntents();
-
-        controller.onRecentTabsPageClosed();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-    }
-
-    /**
-     * Test the handling for when the RecentTabsPage is opened/closed quickly.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testOpenCloseRecentTabsPageQuickly() {
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageOpened();
-        controller.onRecentTabsPageClosed();
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mAllTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageClosed();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageOpened();
-        controller.onRecentTabsPageClosed();
-        controller.onRecentTabsPageOpened();
-        controller.onRecentTabsPageClosed();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        assertNoNewIntents();
-    }
-
-    /**
-     * Test that if the InvalidationController is stopped prior to session sync invalidations being
-     * disabled as a result of the RecentTabsPage being closed, that session sync invalidations are
-     * disabled when the InvalidationController is restarted.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testDisableSessionInvalidationsOnStart() {
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mAllTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageClosed();
-        controller.stop();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(IntentType.STOP, getIntentType(getOnlyIntent()));
-
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(mAllTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-    }
-
-    /**
-     * Test that if the activity is paused prior to session sync invalidations being disabled as a
-     * result of the RecentTabsPage being closed, that session sync invalidations are disabled when
-     * the activity is resumed.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testDisableSessionInvalidationsOnResume() {
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mAllTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onRecentTabsPageClosed();
-        controller.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(IntentType.STOP, getIntentType(getOnlyIntent()));
-
-        controller.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
-        Assert.assertEquals(IntentType.START, getIntentType(getOnlyIntent()));
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-    }
-
-    /**
-     * Test that pausing all of Chrome's activities and resuming one of them keeps session
-     * invalidations enabled if they were enabled prior to Chrome's activities getting paused.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testPauseAndResumeMainActivity() throws Exception {
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mAllTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(IntentType.STOP, getIntentType(getOnlyIntent()));
-
-        // Resuming the activity should not send a START_AND_REGISTER intent.
-        controller.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(IntentType.START, getIntentType(getOnlyIntent()));
-    }
-
-    /**
-     * Test that opening the RecentTabsPage has no effect after the InvalidationController is
-     * stopped.
-     */
-    @Test
-    @Feature({"Sync"})
-    public void testPauseAndResumeMainActivityAfterStop() throws Exception {
-        InvalidationController controller = new InvalidationController();
-        controller.ensureStartedAndUpdateRegisteredTypes();
-        Assert.assertEquals(mNonSessionTypes, getRegisterIntentRegisterTypes(getOnlyIntent()));
-
-        controller.stop();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(IntentType.STOP, getIntentType(getOnlyIntent()));
-
-        controller.onRecentTabsPageOpened();
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        assertNoNewIntents();
-    }
-
-    /**
-     * Asserts that {@code intent} is destined for the correct component.
-     */
-    private static void validateIntentComponent(Intent intent) {
-        Assert.assertNotNull(intent.getComponent());
-        Assert.assertEquals(
-                ChromeInvalidationClientService.class.getName(),
-                intent.getComponent().getClassName());
-    }
-
-    /**
-     * Assert that there are no new intents.
-     */
-    private void assertNoNewIntents() {
-        Assert.assertNull(mShadowActivity.getNextStartedService());
-    }
-
-    /**
-     * Assert that there is only one new intent. Returns the intent.
-     */
-    private Intent getOnlyIntent() {
-        Intent intent = mShadowActivity.getNextStartedService();
-        Assert.assertNotNull(intent);
-        Assert.assertNull(mShadowActivity.getNextStartedService());
-        return intent;
-    }
-
-    /**
-     * Returns the type of the intent.
-     */
-    private static IntentType getIntentType(Intent intent) {
-        if (intent.hasExtra(InvalidationIntentProtocol.EXTRA_STOP)) {
-            return IntentType.STOP;
-        } else if (intent.hasExtra(InvalidationIntentProtocol.EXTRA_REGISTERED_TYPES)) {
-            return IntentType.START_AND_REGISTER;
-        } else {
-            return IntentType.START;
-        }
-    }
-
-    /**
-     * Returns the names of the ModelTypes to be registered by the passed in START_AND_REGISTER
-     * intent.
-     */
-    private static Set<String> getRegisterIntentRegisterTypes(Intent intent) {
-        Set<String> registeredTypes = new HashSet<String>();
-        registeredTypes.addAll(
-                intent.getStringArrayListExtra(InvalidationIntentProtocol.EXTRA_REGISTERED_TYPES));
-        return registeredTypes;
-    }
-
-}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
index 3e04124..0dad864f 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
@@ -22,6 +22,7 @@
 
 import android.accounts.Account;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -30,6 +31,8 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.ContextUtils;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.components.signin.AccountManagerFacade;
@@ -61,6 +64,10 @@
 
     @Before
     public void setUp() {
+        // TODO(https://crbug.com/1007903): Use DisableNativeTestRule instead.
+        RecordHistogram.setDisabledForTests(true);
+        RecordUserAction.setDisabledForTests(true);
+
         initMocks(this);
 
         mocker.mock(SigninManagerJni.TEST_HOOKS, mNativeMock);
@@ -83,6 +90,13 @@
                 AccountManagerFacade.createAccountFromName("user@domain.com"), "gaia-id-user");
     }
 
+    @After
+    public void tearDown() {
+        // TODO(https://crbug.com/1007903): Use DisableNativeTestRule instead.
+        RecordHistogram.setDisabledForTests(false);
+        RecordUserAction.setDisabledForTests(false);
+    }
+
     @Test
     public void signOutFromJavaWithManagedDomain() {
         // Stub out various native calls. Some of these are verified as never called
@@ -225,7 +239,7 @@
 
         mSigninManager.onFirstRunCheckDone(); // Allow sign-in.
 
-        mSigninManager.signIn(account.getAccount(), null, null);
+        mSigninManager.signIn(account.getAccount(), null);
         assertTrue(mSigninManager.isOperationInProgress());
         AtomicInteger callCount = new AtomicInteger(0);
         mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
index 0932b47..d660f2f6 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
@@ -6,6 +6,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
@@ -26,6 +27,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.browser.ShortcutHelper;
+import org.chromium.chrome.test.util.browser.webapps.WebApkInfoBuilder;
 
 import java.util.concurrent.TimeUnit;
 
@@ -82,7 +84,6 @@
         assertEquals("theme_color", WebappDataStorage.KEY_THEME_COLOR);
         assertEquals("background_color", WebappDataStorage.KEY_BACKGROUND_COLOR);
         assertEquals("source", WebappDataStorage.KEY_SOURCE);
-        assertEquals("action", WebappDataStorage.KEY_ACTION);
         assertEquals("is_icon_generated", WebappDataStorage.KEY_IS_ICON_GENERATED);
         assertEquals("version", WebappDataStorage.KEY_VERSION);
     }
@@ -197,9 +198,8 @@
 
     @Test
     @Feature({"Webapp"})
-    public void testIntentUpdate() throws Exception {
+    public void testWebappInfoUpdate() throws Exception {
         final String id = "id";
-        final String action = "action";
         final String url = "url";
         final String scope = "scope";
         final String name = "name";
@@ -211,14 +211,15 @@
         final long backgroundColor = 3;
         final boolean isIconGenerated = false;
         final boolean isIconAdaptive = false;
-        Intent shortcutIntent = ShortcutHelper.createWebappShortcutIntent(id, action, url, scope,
-                name, shortName, encodedIcon, ShortcutHelper.WEBAPP_SHORTCUT_VERSION, displayMode,
+        Intent shortcutIntent = ShortcutHelper.createWebappShortcutIntent(id, url, scope, name,
+                shortName, encodedIcon, ShortcutHelper.WEBAPP_SHORTCUT_VERSION, displayMode,
                 orientation, themeColor, backgroundColor, isIconGenerated, isIconAdaptive);
+        WebappInfo info = WebappInfo.create(shortcutIntent);
+        assertNotNull(info);
 
         WebappDataStorage storage = WebappDataStorage.open("test");
-        storage.updateFromShortcutIntent(shortcutIntent);
+        storage.updateFromWebappInfo(info);
 
-        assertEquals(action, mSharedPreferences.getString(WebappDataStorage.KEY_ACTION, null));
         assertEquals(url, mSharedPreferences.getString(WebappDataStorage.KEY_URL, null));
         assertEquals(scope, mSharedPreferences.getString(WebappDataStorage.KEY_SCOPE, null));
         assertEquals(name, mSharedPreferences.getString(WebappDataStorage.KEY_NAME, null));
@@ -238,7 +239,6 @@
 
         // Wipe out the data and ensure that it is all gone.
         mSharedPreferences.edit()
-                .remove(WebappDataStorage.KEY_ACTION)
                 .remove(WebappDataStorage.KEY_URL)
                 .remove(WebappDataStorage.KEY_SCOPE)
                 .remove(WebappDataStorage.KEY_NAME)
@@ -252,7 +252,6 @@
                 .remove(WebappDataStorage.KEY_IS_ICON_ADAPTIVE)
                 .apply();
 
-        assertEquals(null, mSharedPreferences.getString(WebappDataStorage.KEY_ACTION, null));
         assertEquals(null, mSharedPreferences.getString(WebappDataStorage.KEY_URL, null));
         assertEquals(null, mSharedPreferences.getString(WebappDataStorage.KEY_SCOPE, null));
         assertEquals(null, mSharedPreferences.getString(WebappDataStorage.KEY_NAME, null));
@@ -267,10 +266,9 @@
         assertEquals(true,
                 mSharedPreferences.getBoolean(WebappDataStorage.KEY_IS_ICON_ADAPTIVE, true));
 
-        // Update again from the intent and ensure that the data is restored.
-        storage.updateFromShortcutIntent(shortcutIntent);
+        // Update again from the WebappInfo and ensure that the data is restored.
+        storage.updateFromWebappInfo(info);
 
-        assertEquals(action, mSharedPreferences.getString(WebappDataStorage.KEY_ACTION, null));
         assertEquals(url, mSharedPreferences.getString(WebappDataStorage.KEY_URL, null));
         assertEquals(scope, mSharedPreferences.getString(WebappDataStorage.KEY_SCOPE, null));
         assertEquals(name, mSharedPreferences.getString(WebappDataStorage.KEY_NAME, null));
@@ -290,6 +288,34 @@
     }
 
     /**
+     * Test that the WebAPK's shared preferences are populated as result of calling
+     * {@link WebappDataStorage#updateFromWebappInfo()} when the shared preferences are initiially
+     * unset.
+     */
+    @Test
+    @Feature({"Webapp"})
+    public void testWebApkInfoUpdate() throws Exception {
+        String webApkPackageName = "org.chromium.webapk.random123";
+        String url = "url";
+        String scopeUrl = "scope";
+        String manifestUrl = "manifest_url";
+        int webApkVersionCode = 5;
+
+        WebApkInfoBuilder webApkInfoBuilder = new WebApkInfoBuilder(webApkPackageName, url);
+        webApkInfoBuilder.setScope(scopeUrl);
+        webApkInfoBuilder.setManifestUrl(manifestUrl);
+        webApkInfoBuilder.setWebApkVersionCode(webApkVersionCode);
+
+        WebappDataStorage storage = WebappDataStorage.open("test");
+        storage.updateFromWebappInfo(webApkInfoBuilder.build());
+
+        assertEquals(webApkPackageName, storage.getWebApkPackageName());
+        assertEquals(scopeUrl, storage.getScope());
+        assertEquals(manifestUrl, storage.getWebApkManifestUrl());
+        assertEquals(webApkVersionCode, storage.getWebApkVersionCode());
+    }
+
+    /**
      * Test that if the relax-update flag is set to true, the is-update-needed check is done after
      * the relaxed update interval (instead of the usual delay).
      */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
index 5ce07b6c..e2f00cb0 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
@@ -10,7 +10,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.content.Intent;
 import android.content.SharedPreferences;
 import android.text.TextUtils;
 
@@ -28,7 +27,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.browsing_data.UrlFilters;
-import org.chromium.webapk.lib.common.WebApkConstants;
+import org.chromium.chrome.test.util.browser.webapps.WebApkInfoBuilder;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -58,18 +57,19 @@
 
     private static class FetchStorageCallback
             implements WebappRegistry.FetchWebappDataStorageCallback {
-        Intent mShortcutIntent;
+        WebappInfo mWebappInfo;
         boolean mCallbackCalled;
 
-        FetchStorageCallback(Intent shortcutIntent) {
-            mCallbackCalled = false;
-            mShortcutIntent = shortcutIntent;
+        FetchStorageCallback(WebappInfo webappInfo) {
+            mWebappInfo = webappInfo;
         }
 
         @Override
         public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
             mCallbackCalled = true;
-            storage.updateFromShortcutIntent(mShortcutIntent);
+            if (mWebappInfo != null) {
+                storage.updateFromWebappInfo(mWebappInfo);
+            }
         }
 
         boolean getCallbackCalled() {
@@ -87,14 +87,15 @@
         mCallbackCalled = false;
     }
 
-    private void registerWebapp(String webappId,
-            WebappRegistry.FetchWebappDataStorageCallback callback) throws Exception {
+    private void registerWebapp(String webappId, WebappInfo webappInfo) throws Exception {
+        FetchStorageCallback callback = new FetchStorageCallback(webappInfo);
         WebappRegistry.getInstance().register(webappId, callback);
 
         // Run background tasks to make sure the data is committed. Run UI thread tasks to make sure
         // the last used time is updated.
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
+        assertTrue(callback.getCallbackCalled());
     }
 
     @Test
@@ -160,8 +161,7 @@
         apps.put("webapp3", "https://www.chrome.com");
 
         for (Map.Entry<String, String> app : apps.entrySet()) {
-            registerWebapp(
-                    app.getKey(), new FetchStorageCallback(createShortcutIntent(app.getValue())));
+            registerWebapp(app.getKey(), createShortcutWebappInfo(app.getValue()));
         }
 
         // Partial deletion.
@@ -189,8 +189,7 @@
         apps.put("webapp3", "https://www.chrome.com");
 
         for (Map.Entry<String, String> app : apps.entrySet()) {
-            registerWebapp(
-                    app.getKey(), new FetchStorageCallback(createShortcutIntent(app.getValue())));
+            registerWebapp(app.getKey(), createShortcutWebappInfo(app.getValue()));
         }
 
         for (String appName : apps.keySet()) {
@@ -317,26 +316,20 @@
     @Test
     @Feature({"WebApk"})
     public void testCleanupRemovesUninstalledWebApks() throws Exception {
-        String webappId1 = WebApkConstants.WEBAPK_ID_PREFIX + "uninstalledWebApk1";
         String webApkPackage1 = "uninstalledWebApk1";
-        String webappId2 = WebApkConstants.WEBAPK_ID_PREFIX + "uninstalledWebApk2";
         String webApkPackage2 = "uninstalledWebApk2";
 
-        FetchStorageCallback storageCallback1 =
-                new FetchStorageCallback(createWebApkIntent(webappId1, START_URL, webApkPackage1));
-        registerWebapp(webappId1, storageCallback1);
-        assertTrue(storageCallback1.getCallbackCalled());
+        WebApkInfo webApkInfo1 = new WebApkInfoBuilder(webApkPackage1, START_URL).build();
+        registerWebapp(webApkInfo1.id(), webApkInfo1);
 
-        FetchStorageCallback storageCallback2 =
-                new FetchStorageCallback(createWebApkIntent(webappId1, START_URL, webApkPackage2));
-        registerWebapp(webappId2, storageCallback2);
-        assertTrue(storageCallback2.getCallbackCalled());
+        WebApkInfo webApkInfo2 = new WebApkInfoBuilder(webApkPackage2, START_URL).build();
+        registerWebapp(webApkInfo2.id(), webApkInfo2);
 
         // Verify that both WebAPKs are registered.
         Set<String> actual = getRegisteredWebapps();
         assertEquals(2, actual.size());
-        assertTrue(actual.contains(webappId1));
-        assertTrue(actual.contains(webappId2));
+        assertTrue(actual.contains(webApkInfo1.id()));
+        assertTrue(actual.contains(webApkInfo2.id()));
 
         // Set the current time such that the task runs.
         long currentTime = System.currentTimeMillis() + WebappRegistry.FULL_CLEANUP_DURATION;
@@ -355,26 +348,21 @@
     @Test
     @Feature({"WebApk"})
     public void testCleanupDoesNotRemoveInstalledWebApks() throws Exception {
-        String webappId = WebApkConstants.WEBAPK_ID_PREFIX + "installedWebApk";
         String webApkPackage = "installedWebApk";
-        String uninstalledWebappId = WebApkConstants.WEBAPK_ID_PREFIX + "uninstalledWebApk";
         String uninstalledWebApkPackage = "uninstalledWebApk";
 
-        FetchStorageCallback storageCallback =
-                new FetchStorageCallback(createWebApkIntent(webappId, START_URL, webApkPackage));
-        registerWebapp(webappId, storageCallback);
-        assertTrue(storageCallback.getCallbackCalled());
+        WebApkInfo webApkInfo = new WebApkInfoBuilder(webApkPackage, START_URL).build();
+        registerWebapp(webApkInfo.id(), webApkInfo);
 
-        FetchStorageCallback storageCallback2 = new FetchStorageCallback(
-                createWebApkIntent(uninstalledWebappId, START_URL, uninstalledWebApkPackage));
-        registerWebapp(uninstalledWebappId, storageCallback2);
-        assertTrue(storageCallback2.getCallbackCalled());
+        WebApkInfo uninstalledWebApkInfo =
+                new WebApkInfoBuilder(uninstalledWebApkPackage, START_URL).build();
+        registerWebapp(uninstalledWebApkInfo.id(), uninstalledWebApkInfo);
 
         // Verify that both WebAPKs are registered.
         Set<String> actual = getRegisteredWebapps();
         assertEquals(2, actual.size());
-        assertTrue(actual.contains(webappId));
-        assertTrue(actual.contains(uninstalledWebappId));
+        assertTrue(actual.contains(webApkInfo.id()));
+        assertTrue(actual.contains(uninstalledWebApkInfo.id()));
 
         Shadows.shadowOf(RuntimeEnvironment.application.getPackageManager())
                 .addPackage(webApkPackage);
@@ -388,7 +376,7 @@
 
         actual = getRegisteredWebapps();
         assertEquals(1, actual.size());
-        assertTrue(actual.contains(webappId));
+        assertTrue(actual.contains(webApkInfo.id()));
 
         long lastCleanup = mSharedPreferences.getLong(
                 WebappRegistry.KEY_LAST_CLEANUP, -1);
@@ -398,25 +386,19 @@
     @Test
     @Feature({"WebApk"})
     public void testCleanupDoesRemoveOldInstalledWebApks() throws Exception {
-        String deprecatedWebappId = "webapk:installedWebApk";
+        String deprecatedWebApkIdPrefix = "webapk:";
         String webApkPackage = "installedWebApk";
-        String installedWebappId = WebApkConstants.WEBAPK_ID_PREFIX + "installedWebApk";
+        WebApkInfo webApkInfo = new WebApkInfoBuilder(webApkPackage, START_URL).build();
+        String deprecatedWebApkId = deprecatedWebApkIdPrefix + webApkInfo.webApkPackageName();
 
-        FetchStorageCallback storageCallback = new FetchStorageCallback(
-                createWebApkIntent(deprecatedWebappId, START_URL, webApkPackage));
-        registerWebapp(deprecatedWebappId, storageCallback);
-        assertTrue(storageCallback.getCallbackCalled());
-
-        FetchStorageCallback storageCallback2 = new FetchStorageCallback(
-                createWebApkIntent(installedWebappId, START_URL, webApkPackage));
-        registerWebapp(installedWebappId, storageCallback2);
-        assertTrue(storageCallback2.getCallbackCalled());
+        registerWebapp(deprecatedWebApkId, webApkInfo);
+        registerWebapp(webApkInfo.id(), webApkInfo);
 
         // Verify that both WebAPKs are registered.
         Set<String> actual = getRegisteredWebapps();
         assertEquals(2, actual.size());
-        assertTrue(actual.contains(deprecatedWebappId));
-        assertTrue(actual.contains(installedWebappId));
+        assertTrue(actual.contains(deprecatedWebApkId));
+        assertTrue(actual.contains(webApkInfo.id()));
 
         Shadows.shadowOf(RuntimeEnvironment.application.getPackageManager())
                 .addPackage(webApkPackage);
@@ -430,7 +412,7 @@
 
         actual = getRegisteredWebapps();
         assertEquals(1, actual.size());
-        assertTrue(actual.contains(installedWebappId));
+        assertTrue(actual.contains(webApkInfo.id()));
 
         long lastCleanup = mSharedPreferences.getLong(WebappRegistry.KEY_LAST_CLEANUP, -1);
         assertEquals(currentTime, lastCleanup);
@@ -441,16 +423,11 @@
     public void testClearWebappHistory() throws Exception {
         final String webapp1Url = "https://www.google.com";
         final String webapp2Url = "https://drive.google.com";
-        Intent shortcutIntent1 = createShortcutIntent(webapp1Url);
-        Intent shortcutIntent2 = createShortcutIntent(webapp2Url);
+        WebappInfo webappInfo1 = createShortcutWebappInfo(webapp1Url);
+        WebappInfo webappInfo2 = createShortcutWebappInfo(webapp2Url);
 
-        FetchStorageCallback storageCallback1 = new FetchStorageCallback(shortcutIntent1);
-        registerWebapp("webapp1", storageCallback1);
-        assertTrue(storageCallback1.getCallbackCalled());
-
-        FetchStorageCallback storageCallback2 = new FetchStorageCallback(shortcutIntent2);
-        registerWebapp("webapp2", storageCallback2);
-        assertTrue(storageCallback2.getCallbackCalled());
+        registerWebapp("webapp1", webappInfo1);
+        registerWebapp("webapp2", webappInfo2);
 
         SharedPreferences webapp1Prefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp1", Context.MODE_PRIVATE);
@@ -546,8 +523,8 @@
     public void testUpdateAfterClearWebappHistory() throws Exception {
         final String webappUrl = "http://www.google.com";
         final String webappScope = "http://www.google.com/";
-        final Intent shortcutIntent = createShortcutIntent(webappUrl);
-        registerWebapp("webapp", new FetchStorageCallback(shortcutIntent));
+        final WebappInfo webappInfo = createShortcutWebappInfo(webappUrl);
+        registerWebapp("webapp", webappInfo);
 
         SharedPreferences webappPrefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp", Context.MODE_PRIVATE);
@@ -564,7 +541,7 @@
 
         // Update the webapp from the intent again.
         WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage("webapp");
-        storage.updateFromShortcutIntent(shortcutIntent);
+        storage.updateFromWebappInfo(webappInfo);
 
         // Verify that the URL and scope match the original in the intent.
         actualUrl = webappPrefs.getString(WebappDataStorage.KEY_URL, WebappDataStorage.URL_INVALID);
@@ -594,16 +571,16 @@
         final String test5Url = "https://drive.google.com/docs/recent/trash";
         final String test6Url = "https://maps.google.com/";
 
-        Intent shortcutIntent1 = createShortcutIntent(webapp1Url);
-        Intent shortcutIntent2 = createShortcutIntent(webapp2Url);
-        Intent shortcutIntent3 = createShortcutIntent(webapp3Url);
-        Intent shortcutIntent4 = createShortcutIntent(webapp4Url);
+        WebappInfo webappInfo1 = createShortcutWebappInfo(webapp1Url);
+        WebappInfo webappInfo2 = createShortcutWebappInfo(webapp2Url);
+        WebappInfo webappInfo3 = createShortcutWebappInfo(webapp3Url);
+        WebappInfo webappInfo4 = createShortcutWebappInfo(webapp4Url);
 
         // Register the four web apps.
-        registerWebapp("webapp1", new FetchStorageCallback(shortcutIntent1));
-        registerWebapp("webapp2", new FetchStorageCallback(shortcutIntent2));
-        registerWebapp("webapp3", new FetchStorageCallback(shortcutIntent3));
-        registerWebapp("webapp4", new FetchStorageCallback(shortcutIntent4));
+        registerWebapp("webapp1", webappInfo1);
+        registerWebapp("webapp2", webappInfo2);
+        registerWebapp("webapp3", webappInfo3);
+        registerWebapp("webapp4", webappInfo4);
 
         // test1Url should return webapp1.
         WebappDataStorage storage1 =
@@ -647,10 +624,8 @@
         final String startUrl = START_URL;
         final String testUrl = START_URL + "/index.html";
 
-        String webApkId = WebApkConstants.WEBAPK_ID_PREFIX + "WebApk";
-        registerWebapp(webApkId,
-                new FetchStorageCallback(
-                        createWebApkIntent(webApkId, startUrl, "org.chromium.webapk")));
+        WebApkInfo webApkInfo = new WebApkInfoBuilder("org.chromium.webapk", startUrl).build();
+        registerWebapp(webApkInfo.id(), webApkInfo);
 
         // testUrl should return null.
         WebappDataStorage storage1 =
@@ -658,7 +633,7 @@
         assertNull(storage1);
 
         String webappId = "webapp";
-        registerWebapp(webappId, new FetchStorageCallback(createShortcutIntent(startUrl)));
+        registerWebapp(webappId, createShortcutWebappInfo(startUrl));
 
         // testUrl should return the webapp.
         WebappDataStorage storage2 =
@@ -675,13 +650,11 @@
         assertFalse(WebappRegistry.getInstance().hasWebApkForUrl(testUrl));
 
         String webappId = "webapp";
-        registerWebapp(webappId, new FetchStorageCallback(createShortcutIntent(startUrl)));
+        registerWebapp(webappId, createShortcutWebappInfo(startUrl));
         assertFalse(WebappRegistry.getInstance().hasWebApkForUrl(testUrl));
 
-        String webApkId = WebApkConstants.WEBAPK_ID_PREFIX + "WebApk";
-        registerWebapp(webApkId,
-                new FetchStorageCallback(
-                        createWebApkIntent(webApkId, startUrl, "org.chromium.webapk")));
+        WebApkInfo webApkInfo = new WebApkInfoBuilder("org.chromium.webapk", startUrl).build();
+        registerWebapp(webApkInfo.id(), webApkInfo);
         assertTrue(WebappRegistry.getInstance().hasWebApkForUrl(testUrl));
     }
 
@@ -696,15 +669,7 @@
                 WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet());
     }
 
-    private Intent createShortcutIntent(final String url) {
-        return ShortcutHelper.createWebappShortcutIntentForTesting("id", url);
-    }
-
-    private Intent createWebApkIntent(String webappId, String url, String webApkPackage) {
-        Intent intent = new Intent();
-        intent.putExtra(ShortcutHelper.EXTRA_ID, webappId)
-                .putExtra(ShortcutHelper.EXTRA_URL, url)
-                .putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, webApkPackage);
-        return intent;
+    private WebappInfo createShortcutWebappInfo(final String url) {
+        return WebappInfo.create(ShortcutHelper.createWebappShortcutIntentForTesting("id", url));
     }
 }
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 5ced659..9bd2af4 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -465,10 +465,7 @@
     deps +=
         [ "//chrome/browser/ui/webui/explore_sites_internals:mojo_bindings" ]
   } else {
-    deps += [
-      "//chrome/browser/ui/webui/app_management:mojo_bindings",
-      "//chrome/services/app_service/public/cpp:manifest",
-    ]
+    deps += [ "//chrome/browser/ui/webui/app_management:mojo_bindings" ]
   }
 
   if (is_win || is_mac || is_desktop_linux || is_chromeos) {
diff --git a/chrome/app/app_management_strings.grdp b/chrome/app/app_management_strings.grdp
index ed6b3d7..c93367a 100644
--- a/chrome/app/app_management_strings.grdp
+++ b/chrome/app/app_management_strings.grdp
@@ -37,8 +37,8 @@
   <message name="IDS_APP_MANAGEMENT_MORE_APPS" desc="Label for more apps button at bottom of app list card.">
     Show <ph name="NUMBER_OF_MORE_APPS">$1<ex>4</ex></ph> more apps
   </message>
-  <message name="IDS_APP_MANAGEMENT_NO_RESULTS" desc="Text description of a search that has no results.">
-    No search results found
+  <message name="IDS_APP_MANAGEMENT_NO_APPS_FOUND" desc="Text shown when a search of apps yeilds no results.">
+    No apps found
   </message>
   <message name="IDS_APP_MANAGEMENT_NOTIFICATIONS" desc="Label for notifications section in the app settings page.">
     Notifications
diff --git a/chrome/app/chrome_content_browser_overlay_manifest.cc b/chrome/app/chrome_content_browser_overlay_manifest.cc
index 1086373..c679d36 100644
--- a/chrome/app/chrome_content_browser_overlay_manifest.cc
+++ b/chrome/app/chrome_content_browser_overlay_manifest.cc
@@ -67,7 +67,6 @@
 #include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals.mojom.h"
 #else
 #include "chrome/browser/ui/webui/app_management/app_management.mojom.h"
-#include "chrome/services/app_service/public/cpp/manifest.h"
 #endif
 
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
@@ -106,7 +105,6 @@
 #endif
                               rappor::mojom::RapporRecorder,
                               safe_browsing::mojom::SafeBrowsing>())
-        .RequireCapability("apps", "app_service")
         .RequireCapability("ash", "system_ui")
         .RequireCapability("ash", "test")
         .RequireCapability("ash", "display")
@@ -225,9 +223,6 @@
 #if defined(OS_CHROMEOS)
         .PackageService(chromeos::multidevice_setup::GetManifest())
 #endif  // defined(OS_CHROMEOS)
-#if !defined(OS_ANDROID)
-        .PackageService(apps::GetManifest())
-#endif
         .Build()
   };
   return *manifest;
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 080355a..9eb73de 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2768,8 +2768,6 @@
       "installable/installed_webapp_bridge.h",
       "installable/installed_webapp_provider.cc",
       "installable/installed_webapp_provider.h",
-      "invalidation/invalidation_service_factory_android.cc",
-      "invalidation/invalidation_service_factory_android.h",
       "lifetime/application_lifetime_android.cc",
       "lifetime/application_lifetime_android.h",
       "lookalikes/safety_tips/safety_tip_infobar.cc",
@@ -3439,6 +3437,8 @@
       "sharing/shared_clipboard/shared_clipboard_ui_controller.h",
       "sharing/shared_clipboard/shared_clipboard_utils.cc",
       "sharing/shared_clipboard/shared_clipboard_utils.h",
+      "sharing/sharing_app.cc",
+      "sharing/sharing_app.h",
       "sharing/sharing_dialog.h",
       "sharing/sharing_notification_handler.cc",
       "sharing/sharing_notification_handler.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 74f5cba..7432902 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1671,6 +1671,10 @@
     {"cryptauth-v2-enrollment", flag_descriptions::kCryptAuthV2EnrollmentName,
      flag_descriptions::kCryptAuthV2EnrollmentDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kCryptAuthV2Enrollment)},
+    {"disable-office-editing-component-app",
+     flag_descriptions::kDisableOfficeEditingComponentAppName,
+     flag_descriptions::kDisableOfficeEditingComponentAppDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kDisableOfficeEditingComponentApp)},
     {"updated_cellular_activation_ui",
      flag_descriptions::kUpdatedCellularActivationUiName,
      flag_descriptions::kUpdatedCellularActivationUiDescription, kOsCrOS,
diff --git a/chrome/browser/android/webapk/webapk_ukm_recorder.cc b/chrome/browser/android/webapk/webapk_ukm_recorder.cc
index b80df83..417df7c 100644
--- a/chrome/browser/android/webapk/webapk_ukm_recorder.cc
+++ b/chrome/browser/android/webapk/webapk_ukm_recorder.cc
@@ -7,6 +7,7 @@
 #include <jni.h>
 
 #include "base/android/jni_string.h"
+#include "base/numerics/ranges.h"
 #include "chrome/android/chrome_jni_headers/WebApkUkmRecorder_jni.h"
 #include "chrome/browser/android/webapk/webapk_types.h"
 #include "services/metrics/public/cpp/metrics_utils.h"
@@ -79,7 +80,28 @@
       .SetDistributor(distributor)
       .SetAppVersion(version_code)
       .SetLaunchSource(source)
-      .SetLaunch(true)
+      .SetLaunch(1)
+      .Record(ukm_recorder);
+}
+
+// static
+void WebApkUkmRecorder::RecordUninstall(const GURL& manifest_url,
+                                        int64_t distributor,
+                                        int64_t version_code,
+                                        int64_t launch_count,
+                                        int64_t installed_duration_ms) {
+  // UKM metric |launch_count| parameter is enum. '2' indicates >= 2 launches.
+  launch_count = base::ClampToRange<int64_t>(launch_count, 0, 2);
+  ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
+  ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
+  ukm_recorder->UpdateSourceURL(source_id, manifest_url);
+  ukm::builders::WebAPK_Uninstall(source_id)
+      .SetDistributor(distributor)
+      .SetAppVersion(version_code)
+      .SetLifetimeLaunches(launch_count)
+      .SetInstalledDuration(
+          ukm::GetExponentialBucketMinForUserTiming(installed_duration_ms))
+      .SetUninstall(1)
       .Record(ukm_recorder);
 }
 
@@ -106,3 +128,16 @@
       ConvertNullableJavaStringToGURL(env, manifest_url), distributor,
       version_code, source);
 }
+
+// Called by the Java counterpart to record the Uninstall UKM metrics.
+void JNI_WebApkUkmRecorder_RecordUninstall(
+    JNIEnv* env,
+    const JavaParamRef<jstring>& manifest_url,
+    jint distributor,
+    jint version_code,
+    jint launch_count,
+    jlong installed_duration_ms) {
+  WebApkUkmRecorder::RecordUninstall(
+      ConvertNullableJavaStringToGURL(env, manifest_url), distributor,
+      version_code, launch_count, installed_duration_ms);
+}
diff --git a/chrome/browser/android/webapk/webapk_ukm_recorder.h b/chrome/browser/android/webapk/webapk_ukm_recorder.h
index 6e87fbb..d9c324d 100644
--- a/chrome/browser/android/webapk/webapk_ukm_recorder.h
+++ b/chrome/browser/android/webapk/webapk_ukm_recorder.h
@@ -31,6 +31,12 @@
                           int64_t version_code,
                           int source);
 
+  static void RecordUninstall(const GURL& manifest_url,
+                              int64_t distributor,
+                              int64_t version_code,
+                              int64_t launch_count,
+                              int64_t install_duration);
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(WebApkUkmRecorder);
 };
diff --git a/chrome/browser/apps/app_service/DEPS b/chrome/browser/apps/app_service/DEPS
index aa85163..792345d 100644
--- a/chrome/browser/apps/app_service/DEPS
+++ b/chrome/browser/apps/app_service/DEPS
@@ -3,6 +3,12 @@
 ]
 
 specific_include_rules = {
+  "app_service_proxy\.cc": [
+    # App Service Proxy hosts the actual Mojo App Service as a private
+    # implementation detail. Allow the impl to be included there, but don't
+    # expose it to any other files except through the public mojo interface.
+    "+chrome/services/app_service/app_service_impl.h",
+  ],
   "app_service_test\.cc": [
     "+chrome/services/app_service/app_service.h",
   ],
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc
index 43998aa..a4a22f1 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -13,12 +13,10 @@
 #include "chrome/browser/apps/app_service/app_service_metrics.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/services/app_service/public/mojom/constants.mojom.h"
+#include "chrome/services/app_service/app_service_impl.h"
 #include "chrome/services/app_service/public/mojom/types.mojom.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/url_data_source.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace apps {
 
@@ -32,7 +30,7 @@
   }
 
   apps::mojom::IconKeyPtr icon_key;
-  if (host_->app_service_.is_bound()) {
+  if (host_->app_service_.is_connected()) {
     host_->cache_.ForOneApp(app_id, [&icon_key](const apps::AppUpdate& update) {
       icon_key = update.IconKey();
     });
@@ -55,7 +53,7 @@
         size_hint_in_dip, allow_placeholder_icon, std::move(callback));
   }
 
-  if (host_->app_service_.is_bound() && icon_key) {
+  if (host_->app_service_.is_connected() && icon_key) {
     // TODO(crbug.com/826982): Mojo doesn't guarantee the order of messages,
     // so multiple calls to this method might not resolve their callbacks in
     // order. As per khmel@, "you may have race here, assume you publish change
@@ -72,59 +70,56 @@
 }
 
 AppServiceProxy::AppServiceProxy(Profile* profile)
-    : AppServiceProxy(profile, nullptr) {}
-
-AppServiceProxy::AppServiceProxy(Profile* profile,
-                                 service_manager::Connector* connector)
     : inner_icon_loader_(this),
       icon_coalescer_(&inner_icon_loader_),
       outer_icon_loader_(&icon_coalescer_,
                          apps::IconCache::GarbageCollectionPolicy::kEager) {
-  Initialize(profile, connector);
+  Initialize(profile);
 }
 
 AppServiceProxy::~AppServiceProxy() = default;
 
-void AppServiceProxy::ReInitializeForTesting(
-    Profile* profile,
-    service_manager::Connector* connector) {
+void AppServiceProxy::ReInitializeForTesting(Profile* profile) {
   // Some test code creates a profile and profile-linked services, like the App
-  // Service without linking to the correct connector. To work around that, we
-  // issue a second Initialize call to set the connector.
-  Initialize(profile, connector);
+  // Service, before the profile is fully initialized. Such tests can call this
+  // after full profile initialization to ensure the App Service implementation
+  // has all of profile state it needs.
+  app_service_.reset();
+  Initialize(profile);
 }
 
-void AppServiceProxy::Initialize(Profile* profile,
-                                 service_manager::Connector* connector) {
+void AppServiceProxy::Initialize(Profile* profile) {
   if (!profile) {
     return;
   }
-  if (!connector) {
-    connector = content::BrowserContext::GetConnectorFor(profile);
-    if (!connector) {
-      return;
-    }
-  }
-  connector->Connect(apps::mojom::kServiceName,
-                     app_service_.BindNewPipeAndPassReceiver());
 
-  if (app_service_.is_bound()) {
-    // The AppServiceProxy is a subscriber: something that wants to be able
-    // to list all known apps.
-    apps::mojom::SubscriberPtr subscriber;
-    bindings_.AddBinding(this, mojo::MakeRequest(&subscriber));
+  // We only initialize the App Service for regular or guest profiles. Non-guest
+  // off-the-record profiles do not get an instance.
+  if (profile->IsOffTheRecord() && !profile->IsGuestSession()) {
+    return;
+  }
+
+  app_service_impl_ = std::make_unique<apps::AppServiceImpl>();
+  app_service_impl_->BindReceiver(app_service_.BindNewPipeAndPassReceiver());
+
+  if (app_service_.is_connected()) {
+    // The AppServiceProxy is a subscriber: something that wants to be able to
+    // list all known apps.
+    mojo::PendingRemote<apps::mojom::Subscriber> subscriber;
+    receivers_.Add(this, subscriber.InitWithNewPipeAndPassReceiver());
     app_service_->RegisterSubscriber(std::move(subscriber), nullptr);
 
 #if defined(OS_CHROMEOS)
-    // The AppServiceProxy is also a publisher, of a variety of app types.
-    // That responsibility isn't intrinsically part of the AppServiceProxy,
-    // but doing that here, for each such app type, is as good a place as any.
-    built_in_chrome_os_apps_.Initialize(app_service_, profile);
-    crostini_apps_.Initialize(app_service_, profile);
-    extension_apps_.Initialize(app_service_, profile,
-                               apps::mojom::AppType::kExtension);
-    extension_web_apps_.Initialize(app_service_, profile,
-                                   apps::mojom::AppType::kWeb);
+    // The AppServiceProxy is also a publisher, of a variety of app types. That
+    // responsibility isn't intrinsically part of the AppServiceProxy, but doing
+    // that here, for each such app type, is as good a place as any.
+    built_in_chrome_os_apps_ =
+        std::make_unique<BuiltInChromeOsApps>(app_service_, profile);
+    crostini_apps_ = std::make_unique<CrostiniApps>(app_service_, profile);
+    extension_apps_ = std::make_unique<ExtensionApps>(
+        app_service_, profile, apps::mojom::AppType::kExtension);
+    extension_web_apps_ = std::make_unique<ExtensionApps>(
+        app_service_, profile, apps::mojom::AppType::kWeb);
 
     // Asynchronously add app icon source, so we don't do too much work in the
     // constructor.
@@ -165,7 +160,7 @@
                              int32_t event_flags,
                              apps::mojom::LaunchSource launch_source,
                              int64_t display_id) {
-  if (app_service_.is_bound()) {
+  if (app_service_.is_connected()) {
     cache_.ForOneApp(app_id, [this, event_flags, launch_source,
                               display_id](const apps::AppUpdate& update) {
       RecordAppLaunch(update.AppId(), launch_source);
@@ -177,7 +172,7 @@
 
 void AppServiceProxy::SetPermission(const std::string& app_id,
                                     apps::mojom::PermissionPtr permission) {
-  if (app_service_.is_bound()) {
+  if (app_service_.is_connected()) {
     cache_.ForOneApp(
         app_id, [this, &permission](const apps::AppUpdate& update) {
           app_service_->SetPermission(update.AppType(), update.AppId(),
@@ -187,7 +182,7 @@
 }
 
 void AppServiceProxy::Uninstall(const std::string& app_id) {
-  if (app_service_.is_bound()) {
+  if (app_service_.is_connected()) {
     cache_.ForOneApp(app_id, [this](const apps::AppUpdate& update) {
       app_service_->Uninstall(update.AppType(), update.AppId());
     });
@@ -195,7 +190,7 @@
 }
 
 void AppServiceProxy::OpenNativeSettings(const std::string& app_id) {
-  if (app_service_.is_bound()) {
+  if (app_service_.is_connected()) {
     cache_.ForOneApp(app_id, [this](const apps::AppUpdate& update) {
       app_service_->OpenNativeSettings(update.AppType(), update.AppId());
     });
@@ -203,7 +198,14 @@
 }
 
 void AppServiceProxy::FlushMojoCallsForTesting() {
-  bindings_.FlushForTesting();
+  app_service_impl_->FlushMojoCallsForTesting();
+#if defined(OS_CHROMEOS)
+  built_in_chrome_os_apps_->FlushMojoCallsForTesting();
+  crostini_apps_->FlushMojoCallsForTesting();
+  extension_apps_->FlushMojoCallsForTesting();
+  extension_web_apps_->FlushMojoCallsForTesting();
+#endif
+  receivers_.FlushForTesting();
 }
 
 apps::IconLoader* AppServiceProxy::OverrideInnerIconLoaderForTesting(
@@ -216,8 +218,8 @@
 
 void AppServiceProxy::ReInitializeCrostiniForTesting(Profile* profile) {
 #if defined(OS_CHROMEOS)
-  if (app_service_.is_bound()) {
-    crostini_apps_.ReInitializeForTesting(app_service_, profile);
+  if (app_service_.is_connected()) {
+    crostini_apps_->ReInitializeForTesting(app_service_, profile);
   }
 #endif
 }
@@ -230,9 +232,9 @@
 
 void AppServiceProxy::Shutdown() {
 #if defined(OS_CHROMEOS)
-  if (app_service_.is_bound()) {
-    extension_apps_.Shutdown();
-    extension_web_apps_.Shutdown();
+  if (app_service_.is_connected()) {
+    extension_apps_->Shutdown();
+    extension_web_apps_->Shutdown();
   }
 #endif  // OS_CHROMEOS
 }
@@ -241,8 +243,9 @@
   cache_.OnApps(std::move(deltas));
 }
 
-void AppServiceProxy::Clone(apps::mojom::SubscriberRequest request) {
-  bindings_.AddBinding(this, std::move(request));
+void AppServiceProxy::Clone(
+    mojo::PendingReceiver<apps::mojom::Subscriber> receiver) {
+  receivers_.Add(this, std::move(receiver));
 }
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/app_service_proxy.h b/chrome/browser/apps/app_service/app_service_proxy.h
index fb570f1..ffda36f2 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.h
+++ b/chrome/browser/apps/app_service/app_service_proxy.h
@@ -13,7 +13,8 @@
 #include "chrome/services/app_service/public/cpp/icon_cache.h"
 #include "chrome/services/app_service/public/cpp/icon_coalescer.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 #if defined(OS_CHROMEOS)
@@ -24,12 +25,10 @@
 
 class Profile;
 
-namespace service_manager {
-class Connector;
-}
-
 namespace apps {
 
+class AppServiceImpl;
+
 // Singleton (per Profile) proxy and cache of an App Service's apps.
 //
 // Singleton-ness means that //chrome/browser code (e.g UI code) can find *the*
@@ -41,11 +40,9 @@
                         public apps::mojom::Subscriber {
  public:
   explicit AppServiceProxy(Profile* profile);
-
   ~AppServiceProxy() override;
 
-  void ReInitializeForTesting(Profile* profile,
-                              service_manager::Connector* connector);
+  void ReInitializeForTesting(Profile* profile);
 
   mojo::Remote<apps::mojom::AppService>& AppService();
   apps::AppRegistryCache& AppRegistryCache();
@@ -139,9 +136,7 @@
     apps::IconLoader* overriding_icon_loader_for_testing_;
   };
 
-  AppServiceProxy(Profile* profile, service_manager::Connector* connector);
-
-  void Initialize(Profile* profile, service_manager::Connector* connector);
+  void Initialize(Profile* profile);
 
   void AddAppIconSource(Profile* profile);
 
@@ -150,12 +145,16 @@
 
   // apps::mojom::Subscriber overrides.
   void OnApps(std::vector<apps::mojom::AppPtr> deltas) override;
-  void Clone(apps::mojom::SubscriberRequest request) override;
+  void Clone(mojo::PendingReceiver<apps::mojom::Subscriber> receiver) override;
+
+  // This proxy privately owns its instance of the App Service. This should not
+  // be exposed except through the Mojo interface connected to |app_service_|.
+  std::unique_ptr<apps::AppServiceImpl> app_service_impl_;
 
   mojo::Remote<apps::mojom::AppService> app_service_;
   apps::AppRegistryCache cache_;
 
-  mojo::BindingSet<apps::mojom::Subscriber> bindings_;
+  mojo::ReceiverSet<apps::mojom::Subscriber> receivers_;
 
   // The LoadIconFromIconKey implementation sends a chained series of requests
   // through each icon loader, starting from the outer and working back to the
@@ -167,10 +166,10 @@
   IconCache outer_icon_loader_;
 
 #if defined(OS_CHROMEOS)
-  BuiltInChromeOsApps built_in_chrome_os_apps_;
-  CrostiniApps crostini_apps_;
-  ExtensionApps extension_apps_;
-  ExtensionApps extension_web_apps_;
+  std::unique_ptr<BuiltInChromeOsApps> built_in_chrome_os_apps_;
+  std::unique_ptr<CrostiniApps> crostini_apps_;
+  std::unique_ptr<ExtensionApps> extension_apps_;
+  std::unique_ptr<ExtensionApps> extension_web_apps_;
 #endif  // OS_CHROMEOS
 
   base::WeakPtrFactory<AppServiceProxy> weak_ptr_factory_{this};
diff --git a/chrome/browser/apps/app_service/app_service_test.cc b/chrome/browser/apps/app_service/app_service_test.cc
index ae58661..3e317172 100644
--- a/chrome/browser/apps/app_service/app_service_test.cc
+++ b/chrome/browser/apps/app_service/app_service_test.cc
@@ -7,9 +7,6 @@
 #include "base/run_loop.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/common/chrome_features.h"
-#include "chrome/services/app_service/app_service.h"
-#include "chrome/services/app_service/public/mojom/constants.mojom.h"
 
 namespace apps {
 
@@ -18,19 +15,15 @@
 AppServiceTest::~AppServiceTest() = default;
 
 void AppServiceTest::SetUp(Profile* profile) {
-  app_service_ = std::make_unique<apps::AppService>(
-      test_connector_factory_.RegisterInstance(apps::mojom::kServiceName));
-  app_service_proxy_connector_ = test_connector_factory_.GetDefaultConnector();
   app_service_proxy_ = apps::AppServiceProxyFactory::GetForProfile(profile);
   DCHECK(app_service_proxy_);
-  app_service_proxy_->ReInitializeForTesting(profile,
-                                             app_service_proxy_connector_);
+  app_service_proxy_->ReInitializeForTesting(profile);
 
   // Allow async callbacks to run.
   WaitForAppService();
 }
 
-const std::string AppServiceTest::GetAppName(const std::string& app_id) {
+std::string AppServiceTest::GetAppName(const std::string& app_id) const {
   std::string name;
   if (!app_service_proxy_)
     return name;
@@ -43,7 +36,7 @@
   base::RunLoop().RunUntilIdle();
 }
 
-void AppServiceTest::FlushMojoCallsForAppService() {
+void AppServiceTest::FlushMojoCalls() {
   if (app_service_proxy_) {
     app_service_proxy_->FlushMojoCallsForTesting();
   }
diff --git a/chrome/browser/apps/app_service/app_service_test.h b/chrome/browser/apps/app_service/app_service_test.h
index 439d9b50..a970e32 100644
--- a/chrome/browser/apps/app_service/app_service_test.h
+++ b/chrome/browser/apps/app_service/app_service_test.h
@@ -10,12 +10,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
-
-namespace service_manager {
-class Connector;
-class Service;
-}  // namespace service_manager
 
 class Profile;
 
@@ -31,21 +25,17 @@
 
   void SetUp(Profile* profile);
 
-  const std::string GetAppName(const std::string& app_id);
+  std::string GetAppName(const std::string& app_id) const;
 
   // Allow AppService async callbacks to run.
   void WaitForAppService();
 
   // Flush mojo calls to allow AppService async callbacks to run.
-  void FlushMojoCallsForAppService();
+  void FlushMojoCalls();
 
  private:
-  service_manager::Connector* app_service_proxy_connector_ = nullptr;
   AppServiceProxy* app_service_proxy_ = nullptr;
 
-  service_manager::TestConnectorFactory test_connector_factory_;
-  std::unique_ptr<service_manager::Service> app_service_;
-
   DISALLOW_COPY_AND_ASSIGN(AppServiceTest);
 };
 
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc
index c2767be..e249a40 100644
--- a/chrome/browser/apps/app_service/arc_apps.cc
+++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -164,8 +164,9 @@
   arc_icon_once_loader_.StopObserving(prefs);
 }
 
-void ArcApps::Connect(apps::mojom::SubscriberPtr subscriber,
-                      apps::mojom::ConnectOptionsPtr opts) {
+void ArcApps::Connect(
+    mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
+    apps::mojom::ConnectOptionsPtr opts) {
   std::vector<apps::mojom::AppPtr> apps;
   ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_);
   if (prefs) {
@@ -177,8 +178,10 @@
       }
     }
   }
+  mojo::Remote<apps::mojom::Subscriber> subscriber(
+      std::move(subscriber_remote));
   subscriber->OnApps(std::move(apps));
-  subscribers_.AddPtr(std::move(subscriber));
+  subscribers_.Add(std::move(subscriber));
 }
 
 void ArcApps::LoadIcon(const std::string& app_id,
@@ -472,11 +475,11 @@
 }
 
 void ArcApps::Publish(apps::mojom::AppPtr app) {
-  subscribers_.ForAllPtrs([&app](apps::mojom::Subscriber* subscriber) {
+  for (auto& subscriber : subscribers_) {
     std::vector<apps::mojom::AppPtr> apps;
     apps.push_back(app.Clone());
     subscriber->OnApps(std::move(apps));
-  });
+  }
 }
 
 void ArcApps::ConvertAndPublishPackageApps(
diff --git a/chrome/browser/apps/app_service/arc_apps.h b/chrome/browser/apps/app_service/arc_apps.h
index fed5111c..51208e66 100644
--- a/chrome/browser/apps/app_service/arc_apps.h
+++ b/chrome/browser/apps/app_service/arc_apps.h
@@ -17,8 +17,9 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/services/app_service/public/mojom/app_service.mojom.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
 
 class Profile;
 
@@ -49,7 +50,7 @@
   void Shutdown() override;
 
   // apps::mojom::Publisher overrides.
-  void Connect(apps::mojom::SubscriberPtr subscriber,
+  void Connect(mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
                apps::mojom::ConnectOptionsPtr opts) override;
   void LoadIcon(const std::string& app_id,
                 apps::mojom::IconKeyPtr icon_key,
@@ -96,7 +97,7 @@
       const arc::mojom::ArcPackageInfo& package_info);
 
   mojo::Receiver<apps::mojom::Publisher> receiver_{this};
-  mojo::InterfacePtrSet<apps::mojom::Subscriber> subscribers_;
+  mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
 
   Profile* profile_;
   ArcIconOnceLoader arc_icon_once_loader_;
diff --git a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
index 77d2005..a38ccb1 100644
--- a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
+++ b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
@@ -67,17 +67,17 @@
 
 namespace apps {
 
-BuiltInChromeOsApps::BuiltInChromeOsApps() : profile_(nullptr) {}
+BuiltInChromeOsApps::BuiltInChromeOsApps(
+    const mojo::Remote<apps::mojom::AppService>& app_service,
+    Profile* profile)
+    : profile_(profile) {
+  Initialize(app_service);
+}
 
 BuiltInChromeOsApps::~BuiltInChromeOsApps() = default;
 
-void BuiltInChromeOsApps::Initialize(
-    const mojo::Remote<apps::mojom::AppService>& app_service,
-    Profile* profile) {
-  app_service->RegisterPublisher(receiver_.BindNewPipeAndPassRemote(),
-                                 apps::mojom::AppType::kBuiltIn);
-
-  profile_ = profile;
+void BuiltInChromeOsApps::FlushMojoCallsForTesting() {
+  receiver_.FlushForTesting();
 }
 
 bool BuiltInChromeOsApps::hide_settings_app_for_testing_ = false;
@@ -89,8 +89,15 @@
   return old_value;
 }
 
-void BuiltInChromeOsApps::Connect(apps::mojom::SubscriberPtr subscriber,
-                                  apps::mojom::ConnectOptionsPtr opts) {
+void BuiltInChromeOsApps::Initialize(
+    const mojo::Remote<apps::mojom::AppService>& app_service) {
+  app_service->RegisterPublisher(receiver_.BindNewPipeAndPassRemote(),
+                                 apps::mojom::AppType::kBuiltIn);
+}
+
+void BuiltInChromeOsApps::Connect(
+    mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
+    apps::mojom::ConnectOptionsPtr opts) {
   std::vector<apps::mojom::AppPtr> apps;
   if (profile_) {
     // TODO(crbug.com/826982): move source of truth for built-in apps from
@@ -117,11 +124,13 @@
       }
     }
   }
+  mojo::Remote<apps::mojom::Subscriber> subscriber(
+      std::move(subscriber_remote));
   subscriber->OnApps(std::move(apps));
 
   // Unlike other apps::mojom::Publisher implementations, we don't need to
   // retain the subscriber (e.g. add it to a
-  // mojo::InterfacePtrSet<apps::mojom::Subscriber> subscribers_) after this
+  // mojo::RemoteSet<apps::mojom::Subscriber> subscribers_) after this
   // function returns. The list of built-in Chrome OS apps is fixed for the
   // lifetime of the Chrome OS session. There won't be any further updates.
 }
diff --git a/chrome/browser/apps/app_service/built_in_chromeos_apps.h b/chrome/browser/apps/app_service/built_in_chromeos_apps.h
index b7d2937..9dd7cc1 100644
--- a/chrome/browser/apps/app_service/built_in_chromeos_apps.h
+++ b/chrome/browser/apps/app_service/built_in_chromeos_apps.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "chrome/services/app_service/public/mojom/app_service.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
@@ -21,17 +22,19 @@
 // See chrome/services/app_service/README.md.
 class BuiltInChromeOsApps : public apps::mojom::Publisher {
  public:
-  BuiltInChromeOsApps();
+  BuiltInChromeOsApps(const mojo::Remote<apps::mojom::AppService>& app_service,
+                      Profile* profile);
   ~BuiltInChromeOsApps() override;
 
-  void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service,
-                  Profile* profile);
+  void FlushMojoCallsForTesting();
 
   static bool SetHideSettingsAppForTesting(bool hide);
 
  private:
+  void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service);
+
   // apps::mojom::Publisher overrides.
-  void Connect(apps::mojom::SubscriberPtr subscriber,
+  void Connect(mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
                apps::mojom::ConnectOptionsPtr opts) override;
   void LoadIcon(const std::string& app_id,
                 apps::mojom::IconKeyPtr icon_key,
diff --git a/chrome/browser/apps/app_service/crostini_apps.cc b/chrome/browser/apps/app_service/crostini_apps.cc
index 7e579fca..8fed4f6 100644
--- a/chrome/browser/apps/app_service/crostini_apps.cc
+++ b/chrome/browser/apps/app_service/crostini_apps.cc
@@ -21,8 +21,12 @@
 
 namespace apps {
 
-CrostiniApps::CrostiniApps()
-    : profile_(nullptr), registry_(nullptr), crostini_enabled_(false) {}
+CrostiniApps::CrostiniApps(
+    const mojo::Remote<apps::mojom::AppService>& app_service,
+    Profile* profile)
+    : profile_(profile), registry_(nullptr), crostini_enabled_(false) {
+  Initialize(app_service);
+}
 
 CrostiniApps::~CrostiniApps() {
   if (registry_) {
@@ -30,34 +34,9 @@
   }
 }
 
-void CrostiniApps::Initialize(
-    const mojo::Remote<apps::mojom::AppService>& app_service,
-    Profile* profile) {
-  profile_ = nullptr;
-  registry_ = nullptr;
-  crostini_enabled_ = false;
-
-  if (!crostini::IsCrostiniUIAllowedForProfile(profile)) {
-    return;
-  }
-  registry_ = crostini::CrostiniRegistryServiceFactory::GetForProfile(profile);
-  if (!registry_) {
-    return;
-  }
-  profile_ = profile;
-  crostini_enabled_ = crostini::IsCrostiniEnabled(profile);
-
-  registry_->AddObserver(this);
-
-  pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
-  pref_change_registrar_->Init(profile->GetPrefs());
-  pref_change_registrar_->Add(
-      crostini::prefs::kCrostiniEnabled,
-      base::BindRepeating(&CrostiniApps::OnCrostiniEnabledChanged,
-                          base::Unretained(this)));
-
-  app_service->RegisterPublisher(receiver_.BindNewPipeAndPassRemote(),
-                                 apps::mojom::AppType::kCrostini);
+void CrostiniApps::FlushMojoCallsForTesting() {
+  if (receiver_.is_bound())
+    receiver_.FlushForTesting();
 }
 
 void CrostiniApps::ReInitializeForTesting(
@@ -67,11 +46,42 @@
   // like the App Service) before it creates the fake user that lets
   // IsCrostiniUIAllowedForProfile return true. To work around that, we issue a
   // second Initialize call.
-  Initialize(app_service, profile);
+  receiver_.reset();
+  profile_ = profile;
+  registry_ = nullptr;
+  crostini_enabled_ = false;
+
+  Initialize(app_service);
 }
 
-void CrostiniApps::Connect(apps::mojom::SubscriberPtr subscriber,
-                           apps::mojom::ConnectOptionsPtr opts) {
+void CrostiniApps::Initialize(
+    const mojo::Remote<apps::mojom::AppService>& app_service) {
+  DCHECK(profile_);
+  if (!crostini::IsCrostiniUIAllowedForProfile(profile_)) {
+    return;
+  }
+  registry_ = crostini::CrostiniRegistryServiceFactory::GetForProfile(profile_);
+  if (!registry_) {
+    return;
+  }
+  crostini_enabled_ = crostini::IsCrostiniEnabled(profile_);
+
+  registry_->AddObserver(this);
+
+  pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
+  pref_change_registrar_->Init(profile_->GetPrefs());
+  pref_change_registrar_->Add(
+      crostini::prefs::kCrostiniEnabled,
+      base::BindRepeating(&CrostiniApps::OnCrostiniEnabledChanged,
+                          base::Unretained(this)));
+
+  app_service->RegisterPublisher(receiver_.BindNewPipeAndPassRemote(),
+                                 apps::mojom::AppType::kCrostini);
+}
+
+void CrostiniApps::Connect(
+    mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
+    apps::mojom::ConnectOptionsPtr opts) {
   std::vector<apps::mojom::AppPtr> apps;
   for (const auto& pair : registry_->GetRegisteredApps()) {
     const std::string& app_id = pair.first;
@@ -79,8 +89,10 @@
         pair.second;
     apps.push_back(Convert(app_id, registration, true));
   }
+  mojo::Remote<apps::mojom::Subscriber> subscriber(
+      std::move(subscriber_remote));
   subscriber->OnApps(std::move(apps));
-  subscribers_.AddPtr(std::move(subscriber));
+  subscribers_.Add(std::move(subscriber));
 }
 
 void CrostiniApps::LoadIcon(const std::string& app_id,
@@ -304,11 +316,11 @@
 }
 
 void CrostiniApps::Publish(apps::mojom::AppPtr app) {
-  subscribers_.ForAllPtrs([&app](apps::mojom::Subscriber* subscriber) {
+  for (auto& subscriber : subscribers_) {
     std::vector<apps::mojom::AppPtr> apps;
     apps.push_back(app.Clone());
     subscriber->OnApps(std::move(apps));
-  });
+  }
 }
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/crostini_apps.h b/chrome/browser/apps/app_service/crostini_apps.h
index c2b272d..8388c6a 100644
--- a/chrome/browser/apps/app_service/crostini_apps.h
+++ b/chrome/browser/apps/app_service/crostini_apps.h
@@ -15,9 +15,10 @@
 #include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
 #include "chrome/services/app_service/public/mojom/app_service.mojom.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
 
 class PrefChangeRegistrar;
 class Profile;
@@ -31,11 +32,11 @@
                      public apps::mojom::Publisher,
                      public crostini::CrostiniRegistryService::Observer {
  public:
-  CrostiniApps();
+  CrostiniApps(const mojo::Remote<apps::mojom::AppService>& app_service,
+               Profile* profile);
   ~CrostiniApps() override;
 
-  void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service,
-                  Profile* profile);
+  void FlushMojoCallsForTesting();
 
   void ReInitializeForTesting(
       const mojo::Remote<apps::mojom::AppService>& app_service,
@@ -48,8 +49,10 @@
     kUpdate,
   };
 
+  void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service);
+
   // apps::mojom::Publisher overrides.
-  void Connect(apps::mojom::SubscriberPtr subscriber,
+  void Connect(mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
                apps::mojom::ConnectOptionsPtr opts) override;
   void LoadIcon(const std::string& app_id,
                 apps::mojom::IconKeyPtr icon_key,
@@ -94,7 +97,7 @@
   void Publish(apps::mojom::AppPtr app);
 
   mojo::Receiver<apps::mojom::Publisher> receiver_{this};
-  mojo::InterfacePtrSet<apps::mojom::Subscriber> subscribers_;
+  mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
 
   Profile* profile_;
 
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc
index 17df2f433..aa4bae2 100644
--- a/chrome/browser/apps/app_service/extension_apps.cc
+++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -144,36 +144,43 @@
   DISALLOW_COPY_AND_ASSIGN(ExtensionAppsEnableFlow);
 };
 
-ExtensionApps::ExtensionApps()
-    : profile_(nullptr),
+ExtensionApps::ExtensionApps(
+    const mojo::Remote<apps::mojom::AppService>& app_service,
+    Profile* profile,
+    apps::mojom::AppType app_type)
+    : profile_(profile),
       prefs_observer_(this),
       registry_observer_(this),
-      app_type_(apps::mojom::AppType::kUnknown) {}
+      content_settings_observer_(this),
+      app_type_(app_type) {
+  Initialize(app_service);
+}
 
 ExtensionApps::~ExtensionApps() = default;
 
-void ExtensionApps::Initialize(
-    const mojo::Remote<apps::mojom::AppService>& app_service,
-    Profile* profile,
-    apps::mojom::AppType type) {
-  app_type_ = type;
-  app_service->RegisterPublisher(receiver_.BindNewPipeAndPassRemote(),
-                                 app_type_);
-
-  profile_ = profile;
-  DCHECK(profile_);
-  prefs_observer_.Add(extensions::ExtensionPrefs::Get(profile_));
-  registry_observer_.Add(extensions::ExtensionRegistry::Get(profile_));
-  HostContentSettingsMapFactory::GetForProfile(profile_)->AddObserver(this);
+void ExtensionApps::FlushMojoCallsForTesting() {
+  receiver_.FlushForTesting();
 }
 
 void ExtensionApps::Shutdown() {
   if (profile_) {
-    HostContentSettingsMapFactory::GetForProfile(profile_)->RemoveObserver(
-        this);
+    content_settings_observer_.RemoveAll();
   }
 }
 
+void ExtensionApps::Initialize(
+    const mojo::Remote<apps::mojom::AppService>& app_service) {
+  DCHECK(profile_);
+  DCHECK_NE(apps::mojom::AppType::kUnknown, app_type_);
+  app_service->RegisterPublisher(receiver_.BindNewPipeAndPassRemote(),
+                                 app_type_);
+
+  prefs_observer_.Add(extensions::ExtensionPrefs::Get(profile_));
+  registry_observer_.Add(extensions::ExtensionRegistry::Get(profile_));
+  content_settings_observer_.Add(
+      HostContentSettingsMapFactory::GetForProfile(profile_));
+}
+
 bool ExtensionApps::Accepts(const extensions::Extension* extension) {
   if (!extension->is_app() || IsBlacklisted(extension->id())) {
     return false;
@@ -190,8 +197,9 @@
   }
 }
 
-void ExtensionApps::Connect(apps::mojom::SubscriberPtr subscriber,
-                            apps::mojom::ConnectOptionsPtr opts) {
+void ExtensionApps::Connect(
+    mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
+    apps::mojom::ConnectOptionsPtr opts) {
   std::vector<apps::mojom::AppPtr> apps;
   if (profile_) {
     extensions::ExtensionRegistry* registry =
@@ -207,8 +215,10 @@
     //
     // If making changes to which sets are consulted, also change ShouldShow.
   }
+  mojo::Remote<apps::mojom::Subscriber> subscriber(
+      std::move(subscriber_remote));
   subscriber->OnApps(std::move(apps));
-  subscribers_.AddPtr(std::move(subscriber));
+  subscribers_.Add(std::move(subscriber));
 }
 
 void ExtensionApps::LoadIcon(const std::string& app_id,
@@ -384,6 +394,10 @@
   extensions::ExtensionRegistry* registry =
       extensions::ExtensionRegistry::Get(profile_);
 
+  if (!registry) {
+    return;
+  }
+
   std::unique_ptr<extensions::ExtensionSet> extensions =
       registry->GenerateInstalledExtensionsSet(
           extensions::ExtensionRegistry::ENABLED |
@@ -391,7 +405,7 @@
           extensions::ExtensionRegistry::TERMINATED);
 
   for (const auto& extension : *extensions) {
-    const GURL url =
+    const GURL& url =
         extensions::AppLaunchInfo::GetFullLaunchURL(extension.get());
 
     if (extension->from_bookmark() && primary_pattern.Matches(url) &&
@@ -519,11 +533,11 @@
 }
 
 void ExtensionApps::Publish(apps::mojom::AppPtr app) {
-  subscribers_.ForAllPtrs([&app](apps::mojom::Subscriber* subscriber) {
+  for (auto& subscriber : subscribers_) {
     std::vector<apps::mojom::AppPtr> apps;
     apps.push_back(app.Clone());
     subscriber->OnApps(std::move(apps));
-  });
+  }
 }
 
 // static
diff --git a/chrome/browser/apps/app_service/extension_apps.h b/chrome/browser/apps/app_service/extension_apps.h
index a4888dc..0d8ca5e 100644
--- a/chrome/browser/apps/app_service/extension_apps.h
+++ b/chrome/browser/apps/app_service/extension_apps.h
@@ -13,11 +13,13 @@
 #include "chrome/browser/apps/app_service/icon_key_util.h"
 #include "chrome/services/app_service/public/mojom/app_service.mojom.h"
 #include "components/content_settings/core/browser/content_settings_observer.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "extensions/browser/extension_prefs_observer.h"
 #include "extensions/browser/extension_registry_observer.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
 
 class Profile;
 
@@ -40,21 +42,24 @@
                       public extensions::ExtensionRegistryObserver,
                       public content_settings::Observer {
  public:
-  ExtensionApps();
+  ExtensionApps(const mojo::Remote<apps::mojom::AppService>& app_service,
+                Profile* profile,
+                apps::mojom::AppType app_type);
   ~ExtensionApps() override;
 
-  void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service,
-                  Profile* profile,
-                  apps::mojom::AppType type);
+  void FlushMojoCallsForTesting();
+
   void Shutdown();
 
  private:
+  void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service);
+
   // Determines whether the given extension should be treated as type app_type_,
   // and should therefore by handled by this publisher.
   bool Accepts(const extensions::Extension* extension);
 
   // apps::mojom::Publisher overrides.
-  void Connect(apps::mojom::SubscriberPtr subscriber,
+  void Connect(mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
                apps::mojom::ConnectOptionsPtr opts) override;
   void LoadIcon(const std::string& app_id,
                 apps::mojom::IconKeyPtr icon_key,
@@ -126,7 +131,7 @@
                      std::vector<apps::mojom::AppPtr>* apps_out);
 
   mojo::Receiver<apps::mojom::Publisher> receiver_{this};
-  mojo::InterfacePtrSet<apps::mojom::Subscriber> subscribers_;
+  mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
 
   Profile* profile_;
 
@@ -135,6 +140,8 @@
   ScopedObserver<extensions::ExtensionRegistry,
                  extensions::ExtensionRegistryObserver>
       registry_observer_;
+  ScopedObserver<HostContentSettingsMap, content_settings::Observer>
+      content_settings_observer_;
 
   apps_util::IncrementingIconKeyFactory icon_key_factory_;
 
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 486dd7c5a..7ef3ebaf 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1646,6 +1646,8 @@
     "policy/device_cloud_policy_store_chromeos.h",
     "policy/device_cloud_policy_validator.cc",
     "policy/device_cloud_policy_validator.h",
+    "policy/device_dock_mac_address_source_handler.cc",
+    "policy/device_dock_mac_address_source_handler.h",
     "policy/device_local_account.cc",
     "policy/device_local_account.h",
     "policy/device_local_account_extension_tracker.cc",
@@ -2680,6 +2682,7 @@
     "policy/device_cloud_policy_initializer_unittest.cc",
     "policy/device_cloud_policy_manager_chromeos_unittest.cc",
     "policy/device_cloud_policy_store_chromeos_unittest.cc",
+    "policy/device_dock_mac_address_source_handler_unittest.cc",
     "policy/device_local_account_policy_service_unittest.cc",
     "policy/device_policy_decoder_chromeos_unittest.cc",
     "policy/dm_token_storage_unittest.cc",
diff --git a/chrome/browser/chromeos/DEPS b/chrome/browser/chromeos/DEPS
index 5199264..8aaf75e 100644
--- a/chrome/browser/chromeos/DEPS
+++ b/chrome/browser/chromeos/DEPS
@@ -40,10 +40,16 @@
   "assistant_util_unittest\.cc": [
     "+ui/events/devices/device_data_manager.h",
   ],
+  "child_status_collector_browsertest.cc": [
+    "+mojo/core/embedder/embedder.h",
+  ],
   "chrome_browser_main_chromeos\.cc": [
     "+ash/shell.h",
     "+ash/sticky_keys/sticky_keys_controller.h",
   ],
+  "device_status_collector_browsertest.cc": [
+    "+mojo/core/embedder/embedder.h",
+  ],
   "event_rewriter_unittest\.cc": [
     "+ui/events/devices/device_data_manager.h",
   ],
diff --git a/chrome/browser/chromeos/extensions/OWNERS b/chrome/browser/chromeos/extensions/OWNERS
index a17d079..6881c17 100644
--- a/chrome/browser/chromeos/extensions/OWNERS
+++ b/chrome/browser/chromeos/extensions/OWNERS
@@ -10,9 +10,11 @@
 
 per-file *wallpaper*=file://ash/wallpaper/OWNERS
 
-# input method related reviewers. shuchen@ is primary, and googleo@ is backup.
-per-file input_method*=shuchen@chromium.org
+# input method related reviewers. keithlee@ is primary, and shuchen@ and googleo@ are backup.
 per-file input_method*=googleo@chromium.org
+per-file input_method*=keithlee@chromium.org
+per-file input_method*=shuchen@chromium.org
+per-file ime_menu*=keithlee@chromium.org
 per-file ime_menu*=shuchen@chromium.org
 
 # DeviceLocalAccount reviewers. emaxx@ is primary, others are backup.
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc b/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
index 7d698f42..cb40aae 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
@@ -60,6 +61,10 @@
         std::make_unique<chromeos::MockLoginDisplayHost>();
     mock_existing_user_controller_ =
         std::make_unique<MockExistingUserController>();
+
+    // Run pending async tasks resulting from profile construction to ensure
+    // these are complete before the test begins.
+    base::RunLoop().RunUntilIdle();
   }
 
   void TearDown() override {
diff --git a/chrome/browser/chromeos/file_manager/path_util_unittest.cc b/chrome/browser/chromeos/file_manager/path_util_unittest.cc
index 0b87610..adede2f 100644
--- a/chrome/browser/chromeos/file_manager/path_util_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/path_util_unittest.cc
@@ -573,6 +573,10 @@
                                      storage::kFileSystemTypeNativeLocal,
                                      storage::FileSystemMountOption(),
                                      crostini_mount_point_);
+
+    // Run pending async tasks resulting from profile construction to ensure
+    // these are complete before the test begins.
+    base::RunLoop().RunUntilIdle();
   }
 
   void TearDown() override {
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc
index 85d2bb2..b0855dd4 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -66,11 +66,7 @@
 InputMethodEngine::CandidateWindowProperty::~CandidateWindowProperty() =
     default;
 
-InputMethodEngine::InputMethodEngine()
-    : candidate_window_(new ui::CandidateWindow()),
-      window_visible_(false),
-      is_mirroring_(false),
-      is_casting_(false) {}
+InputMethodEngine::InputMethodEngine() = default;
 
 InputMethodEngine::~InputMethodEngine() = default;
 
@@ -127,18 +123,18 @@
   dest_property.show_window_at_composition =
       property.show_window_at_composition;
   dest_property.cursor_position =
-      candidate_window_->GetProperty().cursor_position;
+      candidate_window_.GetProperty().cursor_position;
   dest_property.auxiliary_text = property.auxiliary_text;
   dest_property.is_auxiliary_text_visible = property.is_auxiliary_text_visible;
 
-  candidate_window_->SetProperty(dest_property);
+  candidate_window_.SetProperty(dest_property);
   candidate_window_property_ = property;
 
   if (IsActive()) {
     IMECandidateWindowHandlerInterface* cw_handler =
         ui::IMEBridge::Get()->GetCandidateWindowHandler();
     if (cw_handler)
-      cw_handler->UpdateLookupTable(*candidate_window_, window_visible_);
+      cw_handler->UpdateLookupTable(candidate_window_, window_visible_);
   }
 }
 
@@ -153,7 +149,7 @@
   IMECandidateWindowHandlerInterface* cw_handler =
       ui::IMEBridge::Get()->GetCandidateWindowHandler();
   if (cw_handler)
-    cw_handler->UpdateLookupTable(*candidate_window_, window_visible_);
+    cw_handler->UpdateLookupTable(candidate_window_, window_visible_);
   return true;
 }
 
@@ -173,7 +169,7 @@
   // TODO: Nested candidates
   candidate_ids_.clear();
   candidate_indexes_.clear();
-  candidate_window_->mutable_candidates()->clear();
+  candidate_window_.mutable_candidates()->clear();
   for (const auto& candidate : candidates) {
     ui::CandidateWindow::Entry entry;
     entry.value = base::UTF8ToUTF16(candidate.value);
@@ -186,13 +182,13 @@
     candidate_indexes_[candidate.id] = candidate_ids_.size();
     candidate_ids_.push_back(candidate.id);
 
-    candidate_window_->mutable_candidates()->push_back(entry);
+    candidate_window_.mutable_candidates()->push_back(entry);
   }
   if (IsActive()) {
     IMECandidateWindowHandlerInterface* cw_handler =
         ui::IMEBridge::Get()->GetCandidateWindowHandler();
     if (cw_handler)
-      cw_handler->UpdateLookupTable(*candidate_window_, window_visible_);
+      cw_handler->UpdateLookupTable(candidate_window_, window_visible_);
   }
   return true;
 }
@@ -216,11 +212,11 @@
     return false;
   }
 
-  candidate_window_->set_cursor_position(position->second);
+  candidate_window_.set_cursor_position(position->second);
   IMECandidateWindowHandlerInterface* cw_handler =
       ui::IMEBridge::Get()->GetCandidateWindowHandler();
   if (cw_handler)
-    cw_handler->UpdateLookupTable(*candidate_window_, window_visible_);
+    cw_handler->UpdateLookupTable(candidate_window_, window_visible_);
   return true;
 }
 
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.h b/chrome/browser/chromeos/input_method/input_method_engine.h
index ab62764..fe888ed 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.h
+++ b/chrome/browser/chromeos/input_method/input_method_engine.h
@@ -13,13 +13,13 @@
 #include <vector>
 
 #include "chrome/browser/ui/input_method/input_method_engine_base.h"
+#include "ui/base/ime/candidate_window.h"
 #include "ui/base/ime/chromeos/input_method_descriptor.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "ui/base/ime/ime_engine_handler_interface.h"
 #include "url/gurl.h"
 
 namespace ui {
-class CandidateWindow;
 struct CompositionText;
 class KeyEvent;
 
@@ -150,13 +150,13 @@
       ui::ime::InputMethodMenuItem* property);
 
   // The current candidate window.
-  std::unique_ptr<ui::CandidateWindow> candidate_window_;
+  ui::CandidateWindow candidate_window_;
 
   // The current candidate window property.
   CandidateWindowProperty candidate_window_property_;
 
   // Indicates whether the candidate window is visible.
-  bool window_visible_;
+  bool window_visible_ = false;
 
   // Mapping of candidate index to candidate id.
   std::vector<int> candidate_ids_;
@@ -165,10 +165,10 @@
   std::map<int, int> candidate_indexes_;
 
   // Whether the screen is in mirroring mode.
-  bool is_mirroring_;
+  bool is_mirroring_ = false;
 
   // Whether the desktop is being casted.
-  bool is_casting_;
+  bool is_casting_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(InputMethodEngine);
 };
diff --git a/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc b/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
index 5157446..7a1cb8a1 100644
--- a/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
@@ -349,7 +349,7 @@
 
 // Check that HID detection screen is shown if it is not specified by
 // configuration.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTestNoHID, TestLeaveWelcomeScreen) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTestNoHID, TestShowHID) {
   LoadConfiguration();
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
 }
diff --git a/chrome/browser/chromeos/login/mojo_system_info_dispatcher.cc b/chrome/browser/chromeos/login/mojo_system_info_dispatcher.cc
index 21465c721..ef201f94 100644
--- a/chrome/browser/chromeos/login/mojo_system_info_dispatcher.cc
+++ b/chrome/browser/chromeos/login/mojo_system_info_dispatcher.cc
@@ -49,11 +49,19 @@
 }
 
 void MojoSystemInfoDispatcher::OnSystemInfoUpdated() {
-  version_info::Channel channel = chrome::GetChannel();
-  bool show_if_hidden = channel != version_info::Channel::STABLE &&
-                        channel != version_info::Channel::BETA;
+  const base::Optional<bool> policy_show =
+      version_info_updater_.IsSystemInfoEnforced();
+  bool enforced = policy_show.has_value();
+  bool show = false;
+  if (enforced) {
+    show = policy_show.value();
+  } else {
+    version_info::Channel channel = chrome::GetChannel();
+    show = channel != version_info::Channel::STABLE &&
+           channel != version_info::Channel::BETA;
+  }
   ash::LoginScreen::Get()->GetModel()->SetSystemInfo(
-      show_if_hidden, os_version_label_text_, enterprise_info_,
+      show, enforced, os_version_label_text_, enterprise_info_,
       bluetooth_name_);
 }
 
diff --git a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
index 072670a..14243e0 100644
--- a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
+++ b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
@@ -17,7 +17,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/post_task.h"
-#include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
@@ -1030,13 +1029,7 @@
   DVLOG(1) << "Loaded page at the end : " << title;
 }
 
-// TODO(crbug.com/1005084) Disabled on Chrome OS due to timeouts
-#if defined(OS_CHROMEOS)
-#define MAYBE_XHRThrottle DISABLED_XHRThrottle
-#else
-#define MAYBE_XHRThrottle XHRThrottle
-#endif
-IN_PROC_BROWSER_TEST_P(MergeSessionTest, MAYBE_XHRThrottle) {
+IN_PROC_BROWSER_TEST_P(MergeSessionTest, Throttle) {
   StartNewUserSession(/*wait_for_merge=*/false,
                       /*is_under_advanced_protection=*/false);
 
diff --git a/chrome/browser/chromeos/login/version_info_updater.cc b/chrome/browser/chromeos/login/version_info_updater.cc
index 3d0b078..96dc97e 100644
--- a/chrome/browser/chromeos/login/version_info_updater.cc
+++ b/chrome/browser/chromeos/login/version_info_updater.cc
@@ -32,11 +32,9 @@
 namespace {
 
 const char* const kReportingFlags[] = {
-  chromeos::kReportDeviceVersionInfo,
-  chromeos::kReportDeviceActivityTimes,
-  chromeos::kReportDeviceBootMode,
-  chromeos::kReportDeviceLocation,
-};
+    chromeos::kReportDeviceVersionInfo, chromeos::kReportDeviceActivityTimes,
+    chromeos::kReportDeviceBootMode, chromeos::kReportDeviceLocation,
+    chromeos::kDeviceLoginScreenSystemInfoEnforced};
 
 // Strings used to generate the serial number part of the version string.
 const char kSerialNumberPrefix[] = "SN:";
@@ -100,6 +98,15 @@
       &VersionInfoUpdater::OnGetAdapter, weak_pointer_factory_.GetWeakPtr()));
 }
 
+base::Optional<bool> VersionInfoUpdater::IsSystemInfoEnforced() const {
+  bool is_system_info_enforced = false;
+  if (cros_settings_->GetBoolean(chromeos::kDeviceLoginScreenSystemInfoEnforced,
+                                 &is_system_info_enforced)) {
+    return is_system_info_enforced;
+  }
+  return base::nullopt;
+}
+
 void VersionInfoUpdater::UpdateVersionLabel() {
   if (version_text_.empty())
     return;
diff --git a/chrome/browser/chromeos/login/version_info_updater.h b/chrome/browser/chromeos/login/version_info_updater.h
index 10192c4..e1ad9446 100644
--- a/chrome/browser/chromeos/login/version_info_updater.h
+++ b/chrome/browser/chromeos/login/version_info_updater.h
@@ -52,6 +52,9 @@
   // is received.
   void StartUpdate(bool is_official_build);
 
+  // Determine whether the system information will be displayed forcedly.
+  base::Optional<bool> IsSystemInfoEnforced() const;
+
  private:
   // policy::CloudPolicyStore::Observer interface:
   void OnStoreLoaded(policy::CloudPolicyStore* store) override;
diff --git a/chrome/browser/chromeos/login/version_updater/version_updater.cc b/chrome/browser/chromeos/login/version_updater/version_updater.cc
index 912c635..ca315bc 100644
--- a/chrome/browser/chromeos/login/version_updater/version_updater.cc
+++ b/chrome/browser/chromeos/login/version_updater/version_updater.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/time/default_tick_clock.h"
@@ -116,6 +117,20 @@
   delegate_->FinishExitUpdate(result);
 }
 
+void VersionUpdater::GetEolStatus(EolStatusCallback callback) {
+  // Request the End of Life (Auto Update Expiration) status. Bind to a weak_ptr
+  // bound method rather than passing |callback| directly so that |callback|
+  // does not outlive |this|.
+  DBusThreadManager::Get()->GetUpdateEngineClient()->GetEolStatus(
+      base::BindOnce(&VersionUpdater::OnGetEolStatus,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void VersionUpdater::OnGetEolStatus(EolStatusCallback callback,
+                                    update_engine::EndOfLifeStatus status) {
+  std::move(callback).Run(status);
+}
+
 base::OneShotTimer* VersionUpdater::GetRebootTimerForTesting() {
   return &reboot_timer_;
 }
diff --git a/chrome/browser/chromeos/login/version_updater/version_updater.h b/chrome/browser/chromeos/login/version_updater/version_updater.h
index a6b20567..b0f03b2 100644
--- a/chrome/browser/chromeos/login/version_updater/version_updater.h
+++ b/chrome/browser/chromeos/login/version_updater/version_updater.h
@@ -95,6 +95,10 @@
     virtual void DelayErrorMessage() = 0;
   };
 
+  // Callback type for |GetEolStatus|.
+  using EolStatusCallback =
+      base::OnceCallback<void(update_engine::EndOfLifeStatus status)>;
+
   explicit VersionUpdater(VersionUpdater::Delegate* delegate);
   ~VersionUpdater() override;
 
@@ -109,6 +113,9 @@
 
   const UpdateInfo& update_info() { return update_info_; }
 
+  // Has the device already reached its End of Life (Auto Update Expiration)?
+  void GetEolStatus(EolStatusCallback callback);
+
   void set_tick_clock_for_testing(const base::TickClock* tick_clock) {
     tick_clock_ = tick_clock;
   }
@@ -117,6 +124,10 @@
   void UpdateStatusChangedForTesting(const update_engine::StatusResult& status);
 
  private:
+  // Callback from UpdateEngineClient::GetEolStatus().
+  void OnGetEolStatus(EolStatusCallback callback,
+                      update_engine::EndOfLifeStatus status);
+
   void RequestUpdateCheck();
 
   // UpdateEngineClient::Observer implementation:
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
index c88049d..8641f12 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
@@ -143,6 +143,14 @@
  public:
   virtual ~StateDownloadMessageProcessor() {}
 
+  // Parsed fields of DeviceManagementResponse.
+  struct ParsedResponse {
+    std::string restore_mode;
+    base::Optional<std::string> management_domain;
+    base::Optional<std::string> disabled_message;
+    base::Optional<bool> is_license_packaged_with_device;
+  };
+
   // Returns the request job type. This must match the request filled in
   // |FillRequest|.
   virtual DeviceManagementService::JobConfiguration::JobType GetJobType()
@@ -152,14 +160,10 @@
   virtual void FillRequest(
       enterprise_management::DeviceManagementRequest* request) = 0;
 
-  // Parses the |response|. If it is valid, extracts |restore_mode|,
-  // |management_domain| and |disabled_message| and returns true. Otherwise,
-  // returns false.
-  virtual bool ParseResponse(
-      const enterprise_management::DeviceManagementResponse& response,
-      std::string* restore_mode,
-      base::Optional<std::string>* management_domain,
-      base::Optional<std::string>* disabled_message) = 0;
+  // Parses the |response|. If it is valid, returns a ParsedResponse struct
+  // instance. If it is invalid, returns nullopt.
+  virtual base::Optional<ParsedResponse> ParseResponse(
+      const enterprise_management::DeviceManagementResponse& response) = 0;
 };
 
 namespace {
@@ -239,31 +243,32 @@
         ->set_server_backed_state_key(server_backed_state_key_);
   }
 
-  bool ParseResponse(const em::DeviceManagementResponse& response,
-                     std::string* restore_mode,
-                     base::Optional<std::string>* management_domain,
-                     base::Optional<std::string>* disabled_message) override {
+  base::Optional<ParsedResponse> ParseResponse(
+      const em::DeviceManagementResponse& response) override {
+    StateDownloadMessageProcessorFRE::ParsedResponse parsed_response;
     if (!response.has_device_state_retrieval_response()) {
       LOG(ERROR) << "Server failed to provide auto-enrollment response.";
-      return false;
+      return base::nullopt;
     }
     const em::DeviceStateRetrievalResponse& state_response =
         response.device_state_retrieval_response();
-    *restore_mode = ConvertRestoreMode(state_response.restore_mode());
+    parsed_response.restore_mode =
+        ConvertRestoreMode(state_response.restore_mode());
     if (state_response.has_management_domain())
-      *management_domain = state_response.management_domain();
-    else
-      management_domain->reset();
+      parsed_response.management_domain = state_response.management_domain();
 
-    if (state_response.has_disabled_state())
-      *disabled_message = state_response.disabled_state().message();
-    else
-      disabled_message->reset();
+    if (state_response.has_disabled_state()) {
+      parsed_response.disabled_message =
+          state_response.disabled_state().message();
+    }
+
+    // Package license is not available during the re-enrollment
+    parsed_response.is_license_packaged_with_device.reset();
 
     // Logging as "WARNING" to make sure it's preserved in the logs.
     LOG(WARNING) << "Received restore_mode=" << state_response.restore_mode();
 
-    return true;
+    return parsed_response;
   }
 
  private:
@@ -295,32 +300,34 @@
     inner_request->set_serial_number(device_serial_number_);
   }
 
-  bool ParseResponse(const em::DeviceManagementResponse& response,
-                     std::string* restore_mode,
-                     base::Optional<std::string>* management_domain,
-                     base::Optional<std::string>* disabled_message) override {
+  base::Optional<ParsedResponse> ParseResponse(
+      const em::DeviceManagementResponse& response) override {
+    StateDownloadMessageProcessorFRE::ParsedResponse parsed_response;
     if (!response.has_device_initial_enrollment_state_response()) {
       LOG(ERROR) << "Server failed to provide initial enrollment response.";
-      return false;
+      return base::nullopt;
     }
 
     const em::DeviceInitialEnrollmentStateResponse& state_response =
         response.device_initial_enrollment_state_response();
     if (state_response.has_initial_enrollment_mode()) {
-      *restore_mode = ConvertInitialEnrollmentMode(
+      parsed_response.restore_mode = ConvertInitialEnrollmentMode(
           state_response.initial_enrollment_mode());
     } else {
       // Unknown initial enrollment mode - treat as no enrollment.
-      *restore_mode = std::string();
+      parsed_response.restore_mode.clear();
     }
 
     if (state_response.has_management_domain())
-      *management_domain = state_response.management_domain();
-    else
-      management_domain->reset();
+      parsed_response.management_domain = state_response.management_domain();
+
+    if (state_response.has_is_license_packaged_with_device()) {
+      parsed_response.is_license_packaged_with_device =
+          state_response.is_license_packaged_with_device();
+    }
 
     // Device disabling is not supported in initial forced enrollment.
-    disabled_message->reset();
+    parsed_response.disabled_message.reset();
 
     // Logging as "WARNING" to make sure it's preserved in the logs.
     LOG(WARNING) << "Received initial_enrollment_mode="
@@ -329,7 +336,7 @@
                          ? "Device has a packaged license for management."
                          : "No packaged license.");
 
-    return true;
+    return parsed_response;
   }
 
  private:
@@ -728,29 +735,37 @@
     DeviceManagementStatus status,
     int net_error,
     const em::DeviceManagementResponse& response) {
-  std::string device_state_mode;
-  base::Optional<std::string> management_domain;
-  base::Optional<std::string> disabled_message;
+  base::Optional<StateDownloadMessageProcessorFRE::ParsedResponse>
+      parsed_response_opt;
 
-  bool progress = state_download_message_processor_->ParseResponse(
-      response, &device_state_mode, &management_domain, &disabled_message);
-  if (!progress)
+  parsed_response_opt =
+      state_download_message_processor_->ParseResponse(response);
+  if (!parsed_response_opt)
     return false;
 
+  StateDownloadMessageProcessorFRE::ParsedResponse parsed_response =
+      std::move(parsed_response_opt.value());
   {
     DictionaryPrefUpdate dict(local_state_, prefs::kServerBackedDeviceState);
     UpdateDict(dict.Get(), kDeviceStateManagementDomain,
-               management_domain.has_value(),
+               parsed_response.management_domain.has_value(),
                std::make_unique<base::Value>(
-                   management_domain.value_or(std::string())));
+                   parsed_response.management_domain.value_or(std::string())));
 
-    UpdateDict(dict.Get(), kDeviceStateMode, !device_state_mode.empty(),
-               std::make_unique<base::Value>(device_state_mode));
+    UpdateDict(dict.Get(), kDeviceStateMode,
+               !parsed_response.restore_mode.empty(),
+               std::make_unique<base::Value>(parsed_response.restore_mode));
 
     UpdateDict(dict.Get(), kDeviceStateDisabledMessage,
-               disabled_message.has_value(),
+               parsed_response.disabled_message.has_value(),
                std::make_unique<base::Value>(
-                   disabled_message.value_or(std::string())));
+                   parsed_response.disabled_message.value_or(std::string())));
+
+    UpdateDict(
+        dict.Get(), kDeviceStatePackagedLicense,
+        parsed_response.is_license_packaged_with_device.has_value(),
+        std::make_unique<base::Value>(
+            parsed_response.is_license_packaged_with_device.value_or(false)));
   }
   local_state_->CommitPendingWrite();
   device_state_available_ = true;
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client_impl_unittest.cc b/chrome/browser/chromeos/policy/auto_enrollment_client_impl_unittest.cc
index f165d641..ac1decae 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client_impl_unittest.cc
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client_impl_unittest.cc
@@ -46,6 +46,9 @@
 
 const int kInitialEnrollmentIdHashLength = 8;
 
+const bool kNotWithLicense = false;
+const bool kWithLicense = true;
+
 // This is modulus power value used in initial enrollment to detect that the
 // server is outdated and does not support initial enrollment. See the
 // |DetectOutdatedServer| test case.
@@ -189,13 +192,14 @@
   void ServerWillSendState(
       const std::string& management_domain,
       em::DeviceStateRetrievalResponse::RestoreMode restore_mode,
-      const std::string& device_disabled_message) {
+      const std::string& device_disabled_message,
+      bool is_license_packaged_with_device) {
     if (GetParam() == AutoEnrollmentProtocol::kFRE) {
       ServerWillSendFREState(management_domain, restore_mode,
                              device_disabled_message);
     } else {
       ServerWillSendInitialEnrollmentState(
-          management_domain,
+          management_domain, is_license_packaged_with_device,
           MapRestoreModeToInitialEnrollmentMode(restore_mode));
     }
   }
@@ -232,6 +236,7 @@
 
   void ServerWillSendInitialEnrollmentState(
       const std::string& management_domain,
+      bool is_license_packaged_with_device,
       em::DeviceInitialEnrollmentStateResponse::InitialEnrollmentMode
           initial_enrollment_mode) {
     em::DeviceManagementResponse response;
@@ -239,6 +244,8 @@
         response.mutable_device_initial_enrollment_state_response();
     state_response->set_initial_enrollment_mode(initial_enrollment_mode);
     state_response->set_management_domain(management_domain);
+    state_response->set_is_license_packaged_with_device(
+        is_license_packaged_with_device);
     EXPECT_CALL(*service_, StartJob(_))
         .WillOnce(
             DoAll(service_->CaptureJobType(&state_retrieval_job_type_),
@@ -281,7 +288,8 @@
 
   void VerifyServerBackedState(const std::string& expected_management_domain,
                                const std::string& expected_restore_mode,
-                               const std::string& expected_disabled_message) {
+                               const std::string& expected_disabled_message,
+                               bool expected_is_license_packaged_with_device) {
     const base::Value* state =
         local_state_->GetUserPref(prefs::kServerBackedDeviceState);
     ASSERT_TRUE(state);
@@ -315,6 +323,17 @@
       EXPECT_FALSE(state_dict->GetString(kDeviceStateDisabledMessage,
                                          &actual_disabled_message));
     }
+
+    if (GetParam() == AutoEnrollmentProtocol::kFRE) {
+      EXPECT_FALSE(state_dict->FindBoolPath(kDeviceStatePackagedLicense));
+    } else {
+      base::Optional<bool> actual_is_license_packaged_with_device;
+      actual_is_license_packaged_with_device =
+          state_dict->FindBoolPath(kDeviceStatePackagedLicense);
+      EXPECT_TRUE(actual_is_license_packaged_with_device.has_value());
+      EXPECT_EQ(expected_is_license_packaged_with_device,
+                actual_is_license_packaged_with_device.value());
+    }
   }
 
   const em::DeviceAutoEnrollmentRequest& auto_enrollment_request() {
@@ -432,7 +451,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -442,7 +461,7 @@
   VerifyCachedResult(true, 8);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kWithLicense);
 }
 
 TEST_P(AutoEnrollmentClientImplTest, AskForSame) {
@@ -452,7 +471,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -462,7 +481,7 @@
   VerifyCachedResult(true, 8);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 }
 
 TEST_P(AutoEnrollmentClientImplTest, AskForSameTwice) {
@@ -565,7 +584,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -575,7 +594,7 @@
   VerifyCachedResult(true, 8);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 
   // Network changes don't trigger retries after obtaining a response from
   // the server.
@@ -590,7 +609,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ZERO_TOUCH,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -600,7 +619,7 @@
   VerifyCachedResult(true, 8);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentZeroTouch,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 
   // Network changes don't trigger retries after obtaining a response from
   // the server.
@@ -620,7 +639,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_REQUESTED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -630,7 +649,7 @@
   VerifyCachedResult(true, 8);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentRequested,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 }
 
 TEST_P(AutoEnrollmentClientImplTest, DeviceDisabled) {
@@ -642,7 +661,7 @@
   ServerWillReply(-1, true, true);
   ServerWillSendState("example.com",
                       em::DeviceStateRetrievalResponse::RESTORE_MODE_DISABLED,
-                      kDisabledMessage);
+                      kDisabledMessage, kNotWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -651,7 +670,7 @@
   EXPECT_EQ(AUTO_ENROLLMENT_STATE_DISABLED, state_);
   VerifyCachedResult(true, 8);
   VerifyServerBackedState("example.com", kDeviceStateRestoreModeDisabled,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 }
 
 TEST_P(AutoEnrollmentClientImplTest, NoBitsUploaded) {
@@ -706,7 +725,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -716,7 +735,7 @@
   VerifyCachedResult(true, 37);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 }
 
 TEST_P(AutoEnrollmentClientImplTest, ReuseCachedDecision) {
@@ -733,7 +752,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
 
   client()->Start();
   base::RunLoop().RunUntilIdle();
@@ -741,7 +760,7 @@
   EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 }
 
 TEST_P(AutoEnrollmentClientImplTest, RetryIfPowerLargerThanCached) {
@@ -756,7 +775,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -765,7 +784,7 @@
   EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 }
 
 TEST_P(AutoEnrollmentClientImplTest, NetworkChangeRetryAfterErrors) {
@@ -793,7 +812,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
   client()->OnConnectionChanged(
       network::mojom::ConnectionType::CONNECTION_ETHERNET);
   base::RunLoop().RunUntilIdle();
@@ -804,7 +823,7 @@
   EXPECT_TRUE(HasCachedDecision());
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 
   // Subsequent network changes don't trigger retries.
   client()->OnConnectionChanged(
@@ -817,7 +836,7 @@
   EXPECT_TRUE(HasCachedDecision());
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 }
 
 TEST_P(AutoEnrollmentClientImplTest, CancelAndDeleteSoonWithPendingRequest) {
@@ -887,7 +906,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
   client()->Start();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
@@ -896,7 +915,7 @@
   EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
 
   // The client will delete itself immediately if there are no pending
   // requests.
@@ -947,7 +966,7 @@
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED,
-      kDisabledMessage);
+      kDisabledMessage, kNotWithLicense);
 
   // Trigger a network change event.
   client()->OnConnectionChanged(
@@ -957,7 +976,7 @@
   EXPECT_TRUE(HasCachedDecision());
   VerifyServerBackedState("example.com",
                           kDeviceStateRestoreModeReEnrollmentEnforced,
-                          kDisabledMessage);
+                          kDisabledMessage, kNotWithLicense);
   Mock::VerifyAndClearExpectations(service_.get());
   EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_AUTO_ENROLLMENT,
             auto_enrollment_job_type_);
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
index 6072405..eac3a70c 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/chromeos/policy/bluetooth_policy_handler.h"
 #include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
 #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
+#include "chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.h"
 #include "chrome/browser/chromeos/policy/device_local_account.h"
 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
 #include "chrome/browser/chromeos/policy/device_network_configuration_updater.h"
@@ -232,6 +233,11 @@
       std::make_unique<MinimumVersionPolicyHandler>(
           chromeos::CrosSettings::Get());
 
+  device_dock_mac_address_source_handler_ =
+      std::make_unique<DeviceDockMacAddressHandler>(
+          chromeos::CrosSettings::Get(),
+          chromeos::NetworkHandler::Get()->network_device_handler());
+
   device_wifi_allowed_handler_ =
       std::make_unique<DeviceWiFiAllowedHandler>(chromeos::CrosSettings::Get());
 
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
index 3a5e152..42c9b93 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
@@ -43,6 +43,7 @@
 class BluetoothPolicyHandler;
 class DeviceActiveDirectoryPolicyManager;
 class DeviceCloudPolicyInitializer;
+class DeviceDockMacAddressHandler;
 class DeviceLocalAccountPolicyService;
 class DeviceNetworkConfigurationUpdater;
 class DeviceWiFiAllowedHandler;
@@ -243,6 +244,8 @@
   std::unique_ptr<BluetoothPolicyHandler> bluetooth_policy_handler_;
   std::unique_ptr<HostnameHandler> hostname_handler_;
   std::unique_ptr<MinimumVersionPolicyHandler> minimum_version_policy_handler_;
+  std::unique_ptr<DeviceDockMacAddressHandler>
+      device_dock_mac_address_source_handler_;
   std::unique_ptr<DeviceWiFiAllowedHandler> device_wifi_allowed_handler_;
   std::unique_ptr<TPMAutoUpdateModePolicyHandler>
       tpm_auto_update_mode_policy_handler_;
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
index 2e37807..13707ca 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
@@ -224,10 +224,21 @@
       local_state_->GetDictionary(prefs::kServerBackedDeviceState);
   std::string device_state_mode;
   std::string device_state_management_domain;
+  base::Optional<bool> is_license_packaged_with_device;
+
   if (device_state) {
     device_state->GetString(kDeviceStateMode, &device_state_mode);
     device_state->GetString(kDeviceStateManagementDomain,
                             &device_state_management_domain);
+    is_license_packaged_with_device =
+        device_state->FindBoolPath(kDeviceStatePackagedLicense);
+  }
+
+  if (is_license_packaged_with_device) {
+    config.is_license_packaged_with_device =
+        is_license_packaged_with_device.value();
+  } else {
+    config.is_license_packaged_with_device = false;
   }
 
   const bool pref_enrollment_auto_start_present =
diff --git a/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.cc b/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.cc
new file mode 100644
index 0000000..31d654b
--- /dev/null
+++ b/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.cc
@@ -0,0 +1,71 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "chromeos/network/network_device_handler.h"
+#include "chromeos/settings/cros_settings_names.h"
+#include "chromeos/settings/cros_settings_provider.h"
+#include "components/policy/proto/chrome_device_policy.pb.h"
+#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
+
+namespace em = enterprise_management;
+
+namespace policy {
+
+DeviceDockMacAddressHandler::DeviceDockMacAddressHandler(
+    chromeos::CrosSettings* cros_settings,
+    chromeos::NetworkDeviceHandler* network_device_handler)
+    : cros_settings_(cros_settings),
+      network_device_handler_(network_device_handler) {
+  dock_mac_address_source_policy_subscription_ =
+      cros_settings_->AddSettingsObserver(
+          chromeos::kDeviceDockMacAddressSource,
+          base::BindRepeating(
+              &DeviceDockMacAddressHandler::OnDockMacAddressSourcePolicyChanged,
+              weak_factory_.GetWeakPtr()));
+  // Fire it once so we're sure we get an invocation on startup.
+  OnDockMacAddressSourcePolicyChanged();
+}
+
+DeviceDockMacAddressHandler::~DeviceDockMacAddressHandler() = default;
+
+void DeviceDockMacAddressHandler::OnDockMacAddressSourcePolicyChanged() {
+  // Wait for the |cros_settings_| to become trusted.
+  const chromeos::CrosSettingsProvider::TrustedStatus status =
+      cros_settings_->PrepareTrustedValues(base::BindRepeating(
+          &DeviceDockMacAddressHandler::OnDockMacAddressSourcePolicyChanged,
+          weak_factory_.GetWeakPtr()));
+  if (status != chromeos::CrosSettingsProvider::TRUSTED)
+    return;
+
+  int dock_mac_address_source;
+  if (!cros_settings_->GetInteger(chromeos::kDeviceDockMacAddressSource,
+                                  &dock_mac_address_source)) {
+    return;
+  }
+
+  const char* source = nullptr;
+  switch (dock_mac_address_source) {
+    case em::DeviceDockMacAddressSourceProto::DEVICE_DOCK_MAC_ADDRESS:
+      source = shill::kUsbEthernetMacAddressSourceDesignatedDockMac;
+      break;
+    case em::DeviceDockMacAddressSourceProto::DEVICE_NIC_MAC_ADDRESS:
+      source = shill::kUsbEthernetMacAddressSourceBuiltinAdapterMac;
+      break;
+    case em::DeviceDockMacAddressSourceProto::DOCK_NIC_MAC_ADDRESS:
+      source = shill::kUsbEthernetMacAddressSourceUsbAdapterMac;
+      break;
+    default:
+      LOG(ERROR) << "Unknown dock MAC address source: "
+                 << dock_mac_address_source;
+      return;
+  }
+
+  network_device_handler_->SetUsbEthernetMacAddressSource(source);
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.h b/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.h
new file mode 100644
index 0000000..08effbe
--- /dev/null
+++ b/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.h
@@ -0,0 +1,43 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_DOCK_MAC_ADDRESS_SOURCE_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_DOCK_MAC_ADDRESS_SOURCE_HANDLER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+
+namespace chromeos {
+class NetworkDeviceHandler;
+}  // namespace chromeos
+
+namespace policy {
+
+// This class observes the device setting |DeviceDockMacAddressSource|, and
+// updates shill EthernetMacAddressSource property based on this setting.
+class DeviceDockMacAddressHandler {
+ public:
+  DeviceDockMacAddressHandler(
+      chromeos::CrosSettings* cros_settings,
+      chromeos::NetworkDeviceHandler* network_device_handler);
+  ~DeviceDockMacAddressHandler();
+
+ private:
+  void OnDockMacAddressSourcePolicyChanged();
+
+  chromeos::CrosSettings* cros_settings_;
+  chromeos::NetworkDeviceHandler* network_device_handler_;
+  std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
+      dock_mac_address_source_policy_subscription_;
+  base::WeakPtrFactory<DeviceDockMacAddressHandler> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(DeviceDockMacAddressHandler);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_DOCK_MAC_ADDRESS_SOURCE_HANDLER_H_
diff --git a/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler_unittest.cc b/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler_unittest.cc
new file mode 100644
index 0000000..51a7f47
--- /dev/null
+++ b/chrome/browser/chromeos/policy/device_dock_mac_address_source_handler_unittest.cc
@@ -0,0 +1,93 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/device_dock_mac_address_source_handler.h"
+
+#include <memory>
+#include <string>
+#include <tuple>
+
+#include "base/macros.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/device_settings_service.h"
+#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
+#include "chromeos/network/mock_network_device_handler.h"
+#include "chromeos/network/network_device_handler.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+class DeviceDockMacAddressHandlerBaseTest : public testing::Test {
+ public:
+  DeviceDockMacAddressHandlerBaseTest() {
+    scoped_cros_settings_test_helper_.ReplaceDeviceSettingsProviderWithStub();
+    scoped_cros_settings_test_helper_.SetTrustedStatus(
+        chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED);
+
+    device_dock_mac_address_handler_ =
+        std::make_unique<DeviceDockMacAddressHandler>(
+            chromeos::CrosSettings::Get(), &network_device_handler_mock_);
+  }
+
+ protected:
+  void MakeCrosSettingsTrusted() {
+    scoped_cros_settings_test_helper_.SetTrustedStatus(
+        chromeos::CrosSettingsProvider::TRUSTED);
+  }
+
+  chromeos::ScopedCrosSettingsTestHelper scoped_cros_settings_test_helper_;
+
+  testing::StrictMock<chromeos::MockNetworkDeviceHandler>
+      network_device_handler_mock_;
+
+  std::unique_ptr<DeviceDockMacAddressHandler> device_dock_mac_address_handler_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DeviceDockMacAddressHandlerBaseTest);
+};
+
+// Tests that DockMacAddressHandler does not change device handler property if
+// received policy is invalid.
+TEST_F(DeviceDockMacAddressHandlerBaseTest, InvalidPolicyValue) {
+  MakeCrosSettingsTrusted();
+  scoped_cros_settings_test_helper_.SetInteger(
+      chromeos::kDeviceDockMacAddressSource, 4);
+}
+
+class DeviceDockMacAddressHandlerTest
+    : public DeviceDockMacAddressHandlerBaseTest,
+      public testing::WithParamInterface<std::tuple<int, std::string>> {
+ public:
+  DeviceDockMacAddressHandlerTest() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DeviceDockMacAddressHandlerTest);
+};
+
+// Tests that DockMacAddressHandler does not change device handler property if
+// CrosSettings are untrusted.
+TEST_P(DeviceDockMacAddressHandlerTest, OnPolicyChangeUntrusted) {
+  scoped_cros_settings_test_helper_.SetInteger(
+      chromeos::kDeviceDockMacAddressSource, std::get<0>(GetParam()));
+}
+
+// Tests that DockMacAddressHandler changes device handler property if
+// CrosSetting are trusted.
+TEST_P(DeviceDockMacAddressHandlerTest, OnPolicyChange) {
+  MakeCrosSettingsTrusted();
+  EXPECT_CALL(network_device_handler_mock_,
+              SetUsbEthernetMacAddressSource(std::get<1>(GetParam())));
+  scoped_cros_settings_test_helper_.SetInteger(
+      chromeos::kDeviceDockMacAddressSource, std::get<0>(GetParam()));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    DeviceDockMacAddressHandlerTest,
+    testing::Values(std::make_tuple(1, "designated_dock_mac"),
+                    std::make_tuple(2, "builtin_adapter_mac"),
+                    std::make_tuple(3, "usb_adapter_mac")));
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index e7a6f8e4..7c4c1ba3 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -428,6 +428,17 @@
     }
   }
 
+  if (policy.has_device_login_screen_system_info_enforced()) {
+    const em::DeviceLoginScreenSystemInfoEnforcedProto& container(
+        policy.device_login_screen_system_info_enforced());
+    if (container.has_enabled()) {
+      policies->Set(
+          key::kDeviceLoginScreenSystemInfoEnforced, POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
+          std::make_unique<base::Value>(container.enabled()), nullptr);
+    }
+  }
+
   if (policy.has_saml_login_authentication_type()) {
     const em::SamlLoginAuthenticationTypeProto& container(
         policy.saml_login_authentication_type());
diff --git a/chrome/browser/chromeos/policy/enrollment_config.h b/chrome/browser/chromeos/policy/enrollment_config.h
index 092f1f6..d2aac121 100644
--- a/chrome/browser/chromeos/policy/enrollment_config.h
+++ b/chrome/browser/chromeos/policy/enrollment_config.h
@@ -159,6 +159,9 @@
   // Enrollment token to use for authentication (for USB-enrollment).
   std::string enrollment_token;
 
+  // Is a license packaged with device or not.
+  bool is_license_packaged_with_device = false;
+
   // The authentication mechanism to use.
   // TODO(drcrash): Change to best available once ZTE is everywhere.
   AuthMechanism auth_mechanism = AUTH_MECHANISM_INTERACTIVE;
diff --git a/chrome/browser/chromeos/policy/server_backed_device_state.cc b/chrome/browser/chromeos/policy/server_backed_device_state.cc
index 619356b..650e7fa 100644
--- a/chrome/browser/chromeos/policy/server_backed_device_state.cc
+++ b/chrome/browser/chromeos/policy/server_backed_device_state.cc
@@ -18,6 +18,7 @@
 const char kDeviceStateManagementDomain[] = "management_domain";
 const char kDeviceStateMode[] = "device_mode";
 const char kDeviceStateDisabledMessage[] = "disabled_message";
+const char kDeviceStatePackagedLicense[] = "packaged_license";
 
 const char kDeviceStateRestoreModeReEnrollmentRequested[] =
     "re-enrollment-requested";
diff --git a/chrome/browser/chromeos/policy/server_backed_device_state.h b/chrome/browser/chromeos/policy/server_backed_device_state.h
index befb9bd..107278a 100644
--- a/chrome/browser/chromeos/policy/server_backed_device_state.h
+++ b/chrome/browser/chromeos/policy/server_backed_device_state.h
@@ -11,6 +11,7 @@
 extern const char kDeviceStateManagementDomain[];
 extern const char kDeviceStateMode[];
 extern const char kDeviceStateDisabledMessage[];
+extern const char kDeviceStatePackagedLicense[];
 
 // String constants used to persist the restorative action in the
 // kDeviceStateMode dictionary entry.
diff --git a/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
index 3cfdc2f2..88af6aaa 100644
--- a/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
@@ -51,6 +51,7 @@
 #include "components/user_manager/user_type.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
+#include "mojo/core/embedder/embedder.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -197,6 +198,10 @@
                                                            "device_id");
     EXPECT_CALL(*user_manager_, Shutdown()).Times(1);
 
+    // Ensure mojo is started, otherwise browser context keyed services that
+    // rely on mojo will explode.
+    mojo::core::Init();
+
     // Although this is really a unit test which runs in the browser_tests
     // binary, it doesn't get the unit setup which normally happens in the unit
     // test binary.
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
index 7bd13f8..7ef4549 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
@@ -81,6 +81,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
+#include "mojo/core/embedder/embedder.h"
 #include "storage/browser/fileapi/external_mount_points.h"
 #include "storage/browser/fileapi/mount_points.h"
 #include "storage/common/fileapi/file_system_mount_option.h"
@@ -380,6 +381,10 @@
                                                            "device_id");
     EXPECT_CALL(*user_manager_, Shutdown()).Times(1);
 
+    // Ensure mojo is started, otherwise browser context keyed services that
+    // rely on mojo will explode.
+    mojo::core::Init();
+
     // Although this is really a unit test which runs in the browser_tests
     // binary, it doesn't get the unit setup which normally happens in the unit
     // test binary.
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index a715fb9..2ee0568 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -80,6 +80,7 @@
     kDeviceLoginScreenExtensions,
     kDeviceLoginScreenInputMethods,
     kDeviceLoginScreenLocales,
+    kDeviceLoginScreenSystemInfoEnforced,
     kDeviceOffHours,
     kDeviceOwner,
     kDeviceNativePrintersAccessMode,
@@ -390,6 +391,13 @@
                                base::Value(std::move(input_methods)));
   }
 
+  if (policy.has_device_login_screen_system_info_enforced() &&
+      policy.device_login_screen_system_info_enforced().has_enabled()) {
+    new_values_cache->SetBoolean(
+        kDeviceLoginScreenSystemInfoEnforced,
+        policy.device_login_screen_system_info_enforced().enabled());
+  }
+
   if (policy.has_saml_login_authentication_type() &&
       policy.saml_login_authentication_type()
           .has_saml_login_authentication_type()) {
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
index 0d18ac0..166f4db 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -311,6 +311,15 @@
     BuildAndInstallDevicePolicy();
   }
 
+  // Helper routine to set DeviceLoginScreenSystemInfoEnforced policy.
+  void SetSystemInfoEnforced(bool enabled) {
+    em::DeviceLoginScreenSystemInfoEnforcedProto* proto =
+        device_policy_->payload()
+            .mutable_device_login_screen_system_info_enforced();
+    proto->set_enabled(enabled);
+    BuildAndInstallDevicePolicy();
+  }
+
   ScopedTestingLocalState local_state_;
 
   std::unique_ptr<DeviceSettingsProvider> provider_;
@@ -837,4 +846,17 @@
   EXPECT_EQ(base::Value(false), *provider_->Get(kDevicePowerwashAllowed));
 }
 
+TEST_F(DeviceSettingsProviderTest, DeviceLoginScreenSystemInfoEnforced) {
+  // Policy should not be set by default
+  VerifyPolicyValue(kDeviceLoginScreenSystemInfoEnforced, nullptr);
+
+  SetSystemInfoEnforced(true);
+  EXPECT_EQ(base::Value(true),
+            *provider_->Get(kDeviceLoginScreenSystemInfoEnforced));
+
+  SetSystemInfoEnforced(false);
+  EXPECT_EQ(base::Value(false),
+            *provider_->Get(kDeviceLoginScreenSystemInfoEnforced));
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/smb_client/smb_service_unittest.cc b/chrome/browser/chromeos/smb_client/smb_service_unittest.cc
index 353609a..6a21741 100644
--- a/chrome/browser/chromeos/smb_client/smb_service_unittest.cc
+++ b/chrome/browser/chromeos/smb_client/smb_service_unittest.cc
@@ -97,6 +97,10 @@
                                           "abc"),
         false, user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, ad_profile_);
 
+    // Run pending async tasks resulting from profile construction to ensure
+    // these are complete before the test begins.
+    base::RunLoop().RunUntilIdle();
+
     user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
         std::move(user_manager_temp));
 
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
index 8f55317..62adbd8 100644
--- a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -59,6 +59,7 @@
     extension_service_ = static_cast<TestExtensionSystem*>(
         ExtensionSystem::Get(profile_.get()))->CreateExtensionService
             (&no_program_command_line, base::FilePath(), false);
+    base::RunLoop().RunUntilIdle();
   }
 
   ~CountingPolicyTest() override {
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
index 41ee157..b067f07 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -57,6 +57,10 @@
     extension_service_ = static_cast<TestExtensionSystem*>(
         ExtensionSystem::Get(profile_.get()))->CreateExtensionService
             (&no_program_command_line, base::FilePath(), false);
+
+    // Run pending async tasks resulting from profile construction to ensure
+    // these are complete before the test begins.
+    base::RunLoop().RunUntilIdle();
   }
 
   ~FullStreamUIPolicyTest() override {
diff --git a/chrome/browser/extensions/api/image_writer_private/test_utils.cc b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
index c7ca253..4828d5c 100644
--- a/chrome/browser/extensions/api/image_writer_private/test_utils.cc
+++ b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
@@ -314,7 +314,7 @@
 }
 
 ImageWriterUnitTestBase::ImageWriterUnitTestBase()
-    : task_environment_(content::BrowserTaskEnvironment::REAL_IO_THREAD) {}
+    : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {}
 ImageWriterUnitTestBase::~ImageWriterUnitTestBase() {
 }
 
diff --git a/chrome/browser/extensions/api/storage/settings_sync_unittest.cc b/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
index 1263879..26678d7 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
@@ -184,6 +184,8 @@
   void SetUp() override {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     profile_.reset(new TestingProfile(temp_dir_.GetPath()));
+    content::RunAllTasksUntilIdle();
+
     storage_factory_->Reset();
     frontend_ =
         StorageFrontend::CreateForTesting(storage_factory_, profile_.get());
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index b4e07f4..7aa6296 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -526,10 +526,9 @@
   }
 };
 
-// Note: this is flaky on multiple platforms (crbug.com/1003598). Temporarily
-// enabled to find flakiness cause.
+// Note: this is flaky on multiple platforms (crbug.com/1003598).
 IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiAuthRequiredTest,
-                       WebRequestAuthRequired) {
+                       DISABLED_WebRequestAuthRequired) {
   CancelLoginDialog login_dialog_helper;
 
   ASSERT_TRUE(StartEmbeddedTestServer());
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index 365d4c6..a8d0ed0 100644
--- a/chrome/browser/extensions/component_loader.cc
+++ b/chrome/browser/extensions/component_loader.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -541,9 +540,12 @@
 #endif  // BUILDFLAG(ENABLE_NACL)
 
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-    Add(IDR_QUICKOFFICE_MANIFEST,
-        base::FilePath(
-            FILE_PATH_LITERAL("/usr/share/chromeos-assets/quickoffice")));
+    if (base::FeatureList::IsEnabled(
+            features::kDisableOfficeEditingComponentApp)) {
+      Add(IDR_QUICKOFFICE_MANIFEST,
+          base::FilePath(
+              FILE_PATH_LITERAL("/usr/share/chromeos-assets/quickoffice")));
+    }
 
     // TODO(https://crbug.com/1005083): Force the off the record profile to be
     // created to allow the virtual keyboard to work in guest mode.
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index 61bd7e8..c407a10 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -723,22 +723,11 @@
 
 void ExtensionBrowserTest::NavigateInRenderer(content::WebContents* contents,
                                               const GURL& url) {
-  // Ensure any existing navigations complete before trying to navigate anew, to
-  // avoid triggering of the unload event for the wrong navigation.
+  // Note: We use ExecuteScript instead of ExecJS here, because ExecuteScript
+  // works on pages with a Content Security Policy.
+  EXPECT_TRUE(content::ExecuteScript(
+      contents, "window.location = '" + url.spec() + "';"));
   content::WaitForLoadStop(contents);
-  bool result = false;
-  content::WindowedNotificationObserver windowed_observer(
-      content::NOTIFICATION_LOAD_STOP,
-      content::NotificationService::AllSources());
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      contents,
-      "window.addEventListener('unload', function() {"
-      "    window.domAutomationController.send(true);"
-      "}, false);"
-      "window.location = '" + url.spec() + "';",
-      &result));
-  ASSERT_TRUE(result);
-  windowed_observer.Wait();
   EXPECT_EQ(url, contents->GetController().GetLastCommittedEntry()->GetURL());
 }
 
diff --git a/chrome/browser/extensions/standard_management_policy_provider.cc b/chrome/browser/extensions/standard_management_policy_provider.cc
index 775f131..b94d1f2c 100644
--- a/chrome/browser/extensions/standard_management_policy_provider.cc
+++ b/chrome/browser/extensions/standard_management_policy_provider.cc
@@ -10,6 +10,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_management.h"
+#include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest.h"
 #include "extensions/strings/grit/extensions_strings.h"
@@ -74,9 +75,15 @@
 bool StandardManagementPolicyProvider::UserMayLoad(
     const Extension* extension,
     base::string16* error) const {
-  // Component extensions are always allowed.
-  if (Manifest::IsComponentLocation(extension->location()))
+  // Component extensions are always allowed, besides the camera app that can be
+  // disabled by extension policy. This is a temporary solution until there's a
+  // dedicated policy to disable the camera, at which point the special check in
+  // the 'if' statement should be removed.
+  // TODO(http://crbug.com/1002935)
+  if (Manifest::IsComponentLocation(extension->location()) &&
+      extension->id() != extension_misc::kCameraAppId) {
     return true;
+  }
 
   // Shared modules are always allowed too: they only contain resources that
   // are used by other extensions. The extension that depends on the shared
diff --git a/chrome/browser/extensions/update_install_gate_unittest.cc b/chrome/browser/extensions/update_install_gate_unittest.cc
index 733e973..d73ecab 100644
--- a/chrome/browser/extensions/update_install_gate_unittest.cc
+++ b/chrome/browser/extensions/update_install_gate_unittest.cc
@@ -126,6 +126,7 @@
     fake_user_manager_->LoginUser(account_id);
 #endif
     profile_ = profile_manager_->CreateTestingProfile(kUserProfile);
+    base::RunLoop().RunUntilIdle();
 
     TestExtensionSystem* test_extension_system =
         static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile_));
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 5a1a5eab..e469854 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -706,6 +706,13 @@
     "expiry_milestone": 83
   },
   {
+    "name": "disable-office-editing-component-app",
+    "owners": [
+      "chrome-apps-platform-rationalization@google.com",
+      "quickoffice-chrome-eng@google.com" ],
+    "expiry_milestone": 88
+  },
+  {
     // See https://crbug.com/882238.
     "name": "disable-pushstate-throttle",
     "owners": [ "arthursonzogni@chromium.org", "palmer@chromium.org" ],
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 51fb902..9d5d6113 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3266,6 +3266,13 @@
     "Always rely on implicit syncrhonization between GPU and display "
     "controller instead of using dma-fences explcitily when available.";
 
+const char kDisableOfficeEditingComponentAppName[] =
+    "Disable Office Editing for Docs, Sheets & Slides";
+const char kDisableOfficeEditingComponentAppDescription[] =
+    "Disables Office Editing for Docs, Sheets & Slides component app so "
+    "handlers won't be registered, making it possible to install another "
+    "version for testing.";
+
 const char kDisableTabletAutohideTitlebarsName[] =
     "Disable autohide titlebars in tablet mode";
 const char kDisableTabletAutohideTitlebarsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 7d80a243..f102cf7 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1944,6 +1944,9 @@
 extern const char kDisableExplicitDmaFencesName[];
 extern const char kDisableExplicitDmaFencesDescription[];
 
+extern const char kDisableOfficeEditingComponentAppName[];
+extern const char kDisableOfficeEditingComponentAppDescription[];
+
 extern const char kDisableTabletAutohideTitlebarsName[];
 extern const char kDisableTabletAutohideTitlebarsDescription[];
 
diff --git a/chrome/browser/invalidation/invalidation_service_factory_android.cc b/chrome/browser/invalidation/invalidation_service_factory_android.cc
deleted file mode 100644
index cc736d9..0000000
--- a/chrome/browser/invalidation/invalidation_service_factory_android.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/invalidation/invalidation_service_factory_android.h"
-
-#include "base/android/jni_android.h"
-#include "chrome/android/chrome_jni_headers/InvalidationServiceFactory_jni.h"
-#include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_android.h"
-#include "components/invalidation/impl/invalidation_service_android.h"
-#include "components/invalidation/impl/profile_invalidation_provider.h"
-
-using base::android::JavaParamRef;
-using base::android::JavaRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace invalidation {
-
-ScopedJavaLocalRef<jobject> InvalidationServiceFactoryAndroid::GetForProfile(
-    const JavaRef<jobject>& j_profile) {
-  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
-  invalidation::ProfileInvalidationProvider* provider =
-      DeprecatedProfileInvalidationProviderFactory::GetForProfile(profile);
-  InvalidationServiceAndroid* service_android =
-      static_cast<InvalidationServiceAndroid*>(
-          provider->GetInvalidationService());
-  return ScopedJavaLocalRef<jobject>(service_android->java_ref_);
-}
-
-ScopedJavaLocalRef<jobject> InvalidationServiceFactoryAndroid::GetForTest() {
-  InvalidationServiceAndroid* service_android =
-      new InvalidationServiceAndroid();
-  return ScopedJavaLocalRef<jobject>(service_android->java_ref_);
-}
-
-ScopedJavaLocalRef<jobject> JNI_InvalidationServiceFactory_GetForProfile(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& j_profile) {
-  return InvalidationServiceFactoryAndroid::GetForProfile(j_profile);
-}
-
-ScopedJavaLocalRef<jobject> JNI_InvalidationServiceFactory_GetForTest(
-    JNIEnv* env) {
-  return InvalidationServiceFactoryAndroid::GetForTest();
-}
-
-}  // namespace invalidation
diff --git a/chrome/browser/invalidation/invalidation_service_factory_android.h b/chrome/browser/invalidation/invalidation_service_factory_android.h
deleted file mode 100644
index c2f2fbe..0000000
--- a/chrome/browser/invalidation/invalidation_service_factory_android.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_FACTORY_ANDROID_H_
-#define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_FACTORY_ANDROID_H_
-
-#include "base/android/scoped_java_ref.h"
-
-namespace invalidation {
-
-// This class should not be used except from the Java class
-// InvalidationServiceFactory.
-class InvalidationServiceFactoryAndroid {
- public:
-  static base::android::ScopedJavaLocalRef<jobject> GetForProfile(
-      const base::android::JavaRef<jobject>& j_profile);
-
-  static base::android::ScopedJavaLocalRef<jobject> GetForTest();
-};
-
-}  // namespace invalidation
-
-#endif  // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_FACTORY_ANDROID_H_
diff --git a/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc b/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
index 8a4b9c8..466f51b 100644
--- a/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
@@ -335,8 +335,15 @@
 
 #if BUILDFLAG(RTC_USE_H264)
 
+// Flaky on mac: crbug.com/754684
+#if defined(OS_MACOSX)
+#define MAYBE_MANUAL_TestVideoQualityH264 DISABLED_MANUAL_TestVideoQualityH264
+#else
+#define MAYBE_MANUAL_TestVideoQualityH264 MANUAL_TestVideoQualityH264
+#endif
+
 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
-                       MANUAL_TestVideoQualityH264) {
+                       MAYBE_MANUAL_TestVideoQualityH264) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   // Only run test if run-time feature corresponding to |rtc_use_h264| is on.
   if (!base::FeatureList::IsEnabled(
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index bea7e2a..d7acbd7 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -567,42 +567,6 @@
   EXPECT_TRUE(prompt_observer->IsSavePromptShownAutomatically());
 }
 
-IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
-                       PromptAfterSubmitFromSubFrameToMainFrame) {
-  NavigateToFile("/password/password_form_in_crosssite_iframe.html");
-  // Create an iframe and navigate cross-site.
-  NavigationObserver iframe_observer(WebContents());
-  iframe_observer.SetPathToWaitFor("/password/password_form_with_hash.html");
-  GURL iframe_url =
-      embedded_test_server()->GetURL("/password/password_form_with_hash.html");
-  std::string create_iframe =
-      base::StringPrintf("create_iframe('%s');", iframe_url.spec().c_str());
-  ASSERT_TRUE(content::ExecuteScriptWithoutUserGesture(RenderFrameHost(),
-                                                       create_iframe));
-  iframe_observer.Wait();
-
-  // Make sure that we prompt to save the password even if the sub-frame submits
-  // the form to the main frame.
-  NavigationObserver observer(WebContents());
-  std::string fill_and_submit =
-      "var first_frame = document.getElementById('iframe');"
-      "var frame_doc = first_frame.contentDocument;"
-      "frame_doc.getElementById('username_field').value = 'Admin';"
-      "frame_doc.getElementById('password_field').value = '12345';"
-      "frame_doc.getElementById('input_submit_button').click();";
-  ASSERT_TRUE(content::ExecuteScript(WebContents(), fill_and_submit));
-  observer.Wait();
-
-  BubbleObserver prompt_observer(WebContents());
-  EXPECT_TRUE(prompt_observer.IsSavePromptShownAutomatically());
-  prompt_observer.AcceptSavePrompt();
-  WaitForPasswordStore();
-
-  // The typed credentials are saved despite the password is hashed before
-  // submission.
-  CheckThatCredentialsStored("Admin", "12345");
-}
-
 IN_PROC_BROWSER_TEST_F(
     PasswordManagerBrowserTest,
     NoPromptForFailedLoginFromMainFrameWithMultiFramesSameDocument) {
diff --git a/chrome/browser/platform_util_unittest.cc b/chrome/browser/platform_util_unittest.cc
index 2d5f87a..7d9c38e6 100644
--- a/chrome/browser/platform_util_unittest.cc
+++ b/chrome/browser/platform_util_unittest.cc
@@ -113,6 +113,11 @@
     extensions::ExtensionRegistry::Get(GetProfile())->AddEnabled(extension);
   }
 
+  void SetUp() override {
+    BrowserWithTestWindowTest::SetUp();
+    base::RunLoop().RunUntilIdle();
+  }
+
   void TearDown() override {
     content::ContentBrowserClient* content_browser_client =
         content::SetBrowserClientForTesting(old_content_browser_client_);
@@ -151,7 +156,7 @@
     static const char kTestFileData[] = "Cow says moo!";
     const int kTestFileDataLength = base::size(kTestFileData) - 1;
 
-    // This prevents platfrom_util from invoking any shell or external APIs
+    // This prevents platform_util from invoking any shell or external APIs
     // during tests. Doing so may result in external applications being launched
     // and intefering with tests.
     internal::DisableShellOperationsForTesting();
diff --git a/chrome/browser/policy/extension_policy_browsertest.cc b/chrome/browser/policy/extension_policy_browsertest.cc
index a19ba8d..ab5231d 100644
--- a/chrome/browser/policy/extension_policy_browsertest.cc
+++ b/chrome/browser/policy/extension_policy_browsertest.cc
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/background/background_contents_service.h"
+#include "chrome/browser/extensions/component_loader.h"
 #include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/extension_management_constants.h"
 #include "chrome/browser/extensions/extension_management_test_util.h"
@@ -35,6 +37,7 @@
 #include "extensions/browser/notification_types.h"
 #include "extensions/browser/scoped_ignore_content_verifier_for_test.h"
 #include "extensions/browser/test_extension_registry_observer.h"
+#include "extensions/common/constants.h"
 #include "extensions/common/features/feature_channel.h"
 #include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "extensions/common/value_builder.h"
@@ -194,6 +197,52 @@
 
 }  // namespace
 
+#if defined(OS_CHROMEOS)
+// Check that component extension can't be blacklisted, besides the camera app
+// that can be disabled by extension policy. This is a temporary solution until
+// there's a dedicated policy to disable the camera, at which point the special
+// check should be removed.
+// TODO(http://crbug.com/1002935)
+IN_PROC_BROWSER_TEST_F(ExtensionPolicyTest,
+                       ExtensionInstallBlacklistComponentApps) {
+  extensions::ExtensionPrefs* extension_prefs =
+      extensions::ExtensionPrefs::Get(browser()->profile());
+
+  // Load all component extensions.
+  extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
+  extension_service()->component_loader()->AddDefaultComponentExtensions(false);
+  base::RunLoop().RunUntilIdle();
+
+  extensions::ExtensionRegistry* registry = extension_registry();
+  ASSERT_TRUE(
+      registry->enabled_extensions().GetByID(extension_misc::kCameraAppId));
+  ASSERT_TRUE(
+      registry->enabled_extensions().GetByID(extensions::kWebStoreAppId));
+  const size_t enabled_count = registry->enabled_extensions().size();
+
+  // Verify that only Camera app can be blacklisted.
+  base::ListValue blacklist;
+  blacklist.AppendString(extension_misc::kCameraAppId);
+  blacklist.AppendString(extensions::kWebStoreAppId);
+  PolicyMap policies;
+  policies.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
+               POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+               blacklist.CreateDeepCopy(), nullptr);
+  UpdateProviderPolicy(policies);
+
+  ASSERT_FALSE(
+      registry->enabled_extensions().GetByID(extension_misc::kCameraAppId));
+  ASSERT_TRUE(
+      registry->disabled_extensions().GetByID(extension_misc::kCameraAppId));
+  EXPECT_EQ(1u, registry->disabled_extensions().size());
+  EXPECT_EQ(extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY,
+            extension_prefs->GetDisableReasons(extension_misc::kCameraAppId));
+  ASSERT_TRUE(
+      registry->enabled_extensions().GetByID(extensions::kWebStoreAppId));
+  EXPECT_EQ(enabled_count - 1, registry->enabled_extensions().size());
+}
+#endif  // defined(OS_CHROMEOS)
+
 IN_PROC_BROWSER_TEST_F(ExtensionPolicyTest,
                        ExtensionInstallBlacklistSelective) {
   // Verifies that blacklisted extensions can't be installed.
diff --git a/chrome/browser/predictors/loading_stats_collector_unittest.cc b/chrome/browser/predictors/loading_stats_collector_unittest.cc
index 5ca6347..bc153023 100644
--- a/chrome/browser/predictors/loading_stats_collector_unittest.cc
+++ b/chrome/browser/predictors/loading_stats_collector_unittest.cc
@@ -51,8 +51,7 @@
   std::unique_ptr<base::HistogramTester> histogram_tester_;
 };
 
-LoadingStatsCollectorTest::LoadingStatsCollectorTest()
-    : profile_(std::make_unique<TestingProfile>()) {}
+LoadingStatsCollectorTest::LoadingStatsCollectorTest() = default;
 
 LoadingStatsCollectorTest::~LoadingStatsCollectorTest() = default;
 
@@ -60,6 +59,7 @@
   LoadingPredictorConfig config;
   PopulateTestConfig(&config);
   profile_ = std::make_unique<TestingProfile>();
+  content::RunAllTasksUntilIdle();
   mock_predictor_ = std::make_unique<StrictMock<MockResourcePrefetchPredictor>>(
       config, profile_.get());
   stats_collector_ =
diff --git a/chrome/browser/profiles/DEPS b/chrome/browser/profiles/DEPS
index 4b9c873..e890d7c 100644
--- a/chrome/browser/profiles/DEPS
+++ b/chrome/browser/profiles/DEPS
@@ -1,9 +1,5 @@
 specific_include_rules = {
   "profile_impl.cc": [
-    # Profile creates the App Service that manages a profile's installed apps.
-    "+chrome/services/app_service/app_service.h",
-    "+chrome/services/app_service/public/mojom/constants.mojom.h",
-
     # Profile embeds the Identity Service, but the dependence
     # should be used *only* for Identity Service creation.
     "+services/identity/identity_service.h",
@@ -11,10 +7,4 @@
     # Profile embeds the image_annotation service.
     "+services/image_annotation/image_annotation_service.h",
   ],
-
-  "off_the_record_profile_impl.cc": [
-    # Chrome OS guest profiles create an App Service to manage installed apps.
-    "+chrome/services/app_service/app_service.h",
-    "+chrome/services/app_service/public/mojom/constants.mojom.h",
-  ],
 }
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index b00c2af0..b2850e53 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -83,8 +83,6 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #else  // !defined(OS_ANDROID)
 #include "chrome/browser/ui/zoom/chrome_zoom_level_otr_delegate.h"
-#include "chrome/services/app_service/app_service.h"
-#include "chrome/services/app_service/public/mojom/constants.mojom.h"
 #include "components/zoom/zoom_event_manager.h"
 #include "content/public/browser/host_zoom_map.h"
 #endif  // defined(OS_ANDROID)
@@ -621,18 +619,6 @@
         this, user_manager::UserManager::Get()->GetActiveUser());
   }
 
-  std::unique_ptr<service_manager::Service> HandleServiceRequest(
-      const std::string& service_name,
-      service_manager::mojom::ServiceRequest request) override {
-    // Ensure apps are serviced in guest profiles.
-    if (service_name == apps::mojom::kServiceName) {
-      return std::make_unique<apps::AppService>(std::move(request));
-    }
-
-    return OffTheRecordProfileImpl::HandleServiceRequest(service_name,
-                                                         std::move(request));
-  }
-
  private:
   // The guest user should be able to customize Chrome OS preferences.
   std::unique_ptr<chromeos::Preferences> chromeos_preferences_;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index ad2a562..32d899f 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -201,8 +201,6 @@
 #if defined(OS_ANDROID)
 #include "chrome/browser/android/profile_key_startup_accessor.h"
 #else
-#include "chrome/services/app_service/app_service.h"
-#include "chrome/services/app_service/public/mojom/constants.mojom.h"
 #include "components/zoom/zoom_event_manager.h"
 #include "content/public/common/page_zoom.h"
 #endif
@@ -1305,14 +1303,6 @@
         std::move(request), APIKeyForChannel(), GetURLLoaderFactory());
   }
 
-#if !defined(OS_ANDROID)
-  if (service_name == apps::mojom::kServiceName) {
-    // TODO(crbug.com/826982): Use the current profile to fetch existing
-    // registries.
-    return std::make_unique<apps::AppService>(std::move(request));
-  }
-#endif  // !defined(OS_ANDROID)
-
 #if defined(OS_CHROMEOS)
   if (service_name == chromeos::multidevice_setup::mojom::kServiceName) {
     chromeos::android_sms::AndroidSmsService* android_sms_service =
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/actions.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/actions.js
index 24cddde..14a3d68 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/actions.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/actions.js
@@ -55,27 +55,6 @@
     };
   }
 
-  /** @return {!cr.ui.Action} */
-  function clearSearch() {
-    return {
-      name: 'clear-search',
-    };
-  }
-
-  /**
-   * @param {string} term
-   * @return {!cr.ui.Action}
-   */
-  function setSearchTerm(term) {
-    if (!term) {
-      return clearSearch();
-    }
-    return {
-      name: 'start-search',
-      term: term,
-    };
-  }
-
   /**
    * @param {boolean} isSupported
    * @return {!cr.ui.Action}
@@ -93,8 +72,6 @@
     changeApp: changeApp,
     removeApp: removeApp,
     changePage: changePage,
-    clearSearch: clearSearch,
-    setSearchTerm: setSearchTerm,
     updateArcSupported: updateArcSupported,
   };
 });
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.html
index db69cd2..a95dbd9 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.html
@@ -16,7 +16,7 @@
   <template>
     <style include="settings-shared"></style>
     <div id="main-container">
-      <app-management-main-view>
+      <app-management-main-view search-term="[[searchTerm]]">
       </app-management-main-view>
     </div>
     <app-management-router></app-management-router>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.js
index 831a308..872c256 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.js
@@ -5,5 +5,10 @@
 Polymer({
   is: 'settings-app-management-page',
 
-  properties: {},
+  properties: {
+    /**
+     * @type {string}
+     */
+    searchTerm: String,
+  },
 });
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.html
index 7a87fc3..0983379b 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.html
@@ -43,10 +43,15 @@
         margin-inline-end: 8px;
         padding: 12px;
       }
+
+      #no-apps-label {
+        @apply --cr-secondary-text;
+        text-align: center;
+      }
     </style>
 
     <div id="app-list">
-      <template is="dom-repeat" items="[[appsList]]" as="app">
+      <template is="dom-repeat" items="[[appList_]]" as="app">
         <app-management-app-item app="[[app]]">
           <cr-icon-button slot="right-content"
               class="subpage-arrow app-management-item-arrow"
@@ -57,6 +62,12 @@
       </template>
     </div>
 
+    <template is="dom-if" if="[[isAppListEmpty_(appList_)]]">
+      <div id="no-apps-label">
+        $i18n{appManagementNoAppsFound}
+      </div>
+    </template>
+
     <div class="card-container" hidden>
       <span class="notification-row" on-click="onClickNotificationSublabel_">
         <div class="notification-row-sublabel">
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js
index bd397f4..0f3af74 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js
@@ -11,20 +11,27 @@
 
   properties: {
     /**
+     * @type {string}
+     */
+    searchTerm: {
+      type: String,
+    },
+
+    /**
      * @private {AppMap}
      */
     apps_: {
       type: Object,
-      observer: 'onAppsChanged_',
     },
 
     /**
-     * List of apps displayed before expanding the app list.
+     * List of apps displayed.
      * @private {Array<App>}
      */
-    appsList: {
+    appList_: {
       type: Array,
       value: () => [],
+      computed: 'computeAppList_(apps_, searchTerm)'
     },
 
     /**
@@ -41,17 +48,48 @@
     this.watch('apps_', state => state.apps);
     this.watch('notificationAppIds_', state => state.notifications.allowedIds);
     this.updateFromStore();
-    this.onAppsChanged_();
   },
 
   /**
    * @private
+   * @param {Array<App>} appList
+   * @return {boolean}
    */
-  onAppsChanged_: function() {
-    this.appsList = Object.values(this.apps_)
-                        .sort(
-                            (a, b) => app_management.util.alphabeticalSort(
-                                assert(a.title), assert(b.title)));
+  isAppListEmpty_: function(appList) {
+    return appList.length === 0;
+  },
+
+  /**
+   * @private
+   * @param {AppMap} apps
+   * @param {String} searchTerm
+   * @return {Array<App>}
+   */
+  computeAppList_: function(apps, searchTerm) {
+    if (!apps) {
+      return [];
+    }
+
+    // This is calculated locally as once the user leaves this page the state
+    // should reset.
+    const appArray = Object.values(apps);
+
+    let filteredApps;
+    if (searchTerm) {
+      const lowerCaseSearchTerm = searchTerm.toLowerCase();
+      filteredApps = appArray.filter(app => {
+        assert(app.title);
+        return app.title.toLowerCase().includes(lowerCaseSearchTerm);
+      });
+    } else {
+      filteredApps = appArray;
+    }
+
+    filteredApps.sort(
+        (a, b) => app_management.util.alphabeticalSort(
+            /** @type {string} */ (a.title), /** @type {string} */ (b.title)));
+
+    return filteredApps;
   },
 
   /** @private */
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/reducers.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/reducers.js
index 61cc5eb8..7052e18 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/reducers.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/reducers.js
@@ -134,63 +134,6 @@
     }
   };
 
-  const SearchState = {};
-
-  /**
-   * @param {AppMap} apps
-   * @param {SearchState} search
-   * @param {Object} action
-   * @return {SearchState}
-   */
-  SearchState.startSearch = function(apps, search, action) {
-    if (action.term === search.term) {
-      return search;
-    }
-
-    const results = [];
-
-    for (const app of Object.values(apps)) {
-      if (app.title.toLowerCase().includes(action.term.toLowerCase())) {
-        results.push(app);
-      }
-    }
-
-    results.sort(
-        (a, b) => app_management.util.alphabeticalSort(
-            assert(a.title), assert(b.title)));
-
-    return /** @type {SearchState} */ (Object.assign({}, search, {
-      term: action.term,
-      results: results,
-    }));
-  };
-
-  /** @return {SearchState} */
-  SearchState.clearSearch = function() {
-    return {
-      term: null,
-      results: null,
-    };
-  };
-
-  /**
-   * @param {AppMap} apps
-   * @param {SearchState} search
-   * @param {Object} action
-   * @return {SearchState}
-   */
-  SearchState.updateSearch = function(apps, search, action) {
-    switch (action.name) {
-      case 'start-search':
-        return SearchState.startSearch(apps, search, action);
-      case 'clear-search':
-      case 'change-page':
-        return SearchState.clearSearch();
-      default:
-        return search;
-    }
-  };
-
   const NotificationsState = {};
 
   /**
@@ -301,7 +244,6 @@
       currentPage: CurrentPageState.updateCurrentPage(
           state.apps, state.currentPage, action),
       arcSupported: ArcSupported.updateArcSupported(state.arcSupported, action),
-      search: SearchState.updateSearch(state.apps, state.search, action),
       notifications:
           NotificationsState.updateNotifications(state.notifications, action),
     };
@@ -313,6 +255,5 @@
     CurrentPageState: CurrentPageState,
     ArcSupported: ArcSupported,
     NotificationsState: NotificationsState,
-    SearchState: SearchState,
   };
 });
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/search_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/search_view.html
deleted file mode 100644
index c2d9426..0000000
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/search_view.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="app_item.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
-
-<dom-module id="app-management-search-view">
-  <template>
-    <style include="app-management-shared-css">
-      #centered-message {
-        align-items: center;
-        color: #6e6e6e;
-        cursor: default;
-        display: flex;
-        font-size: 14px;
-        font-weight: 500;
-        height: 100%;
-        justify-content: center;
-        user-select: none;
-        white-space: nowrap;
-      }
-
-      .app-management-item-arrow {
-        margin-inline-end: 8px;
-        padding: 12px;
-      }
-    </style>
-    <div class="card-container" hidden$="[[isEmptyList_(apps_)]]">
-      <template is="dom-repeat" items="[[apps_]]">
-        <app-management-app-item app="[[item]]">
-          <cr-icon-button slot="right-content"
-              class="subpage-arrow app-management-item-arrow" actionable>
-          </cr-icon-button>
-        </app-management-app-item>
-      </template>
-    </div>
-    <div id="centered-message"
-        hidden$="[[!isEmptyList_(apps_)]]">
-      $i18n{noSearchResults}
-    </div>
-  </template>
-  <script src="search_view.js"></script>
-</dom-module>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/search_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/search_view.js
deleted file mode 100644
index b149e94..0000000
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/search_view.js
+++ /dev/null
@@ -1,40 +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.
-Polymer({
-  is: 'app-management-search-view',
-
-  behaviors: [
-    app_management.StoreClient,
-  ],
-
-  properties: {
-    /**
-     * List of apps returned from search results.
-     * @private {Array<App>}
-     */
-    apps_: {
-      type: Array,
-      value: () => [],
-    },
-  },
-
-  attached: function() {
-    this.watch('apps_', (state) => {
-      return state.search.results;
-    });
-  },
-
-  /**
-   * Check whether there is search results.
-   * @param {Array<App>} apps
-   * @return {boolean}
-   * @private
-   */
-  isEmptyList_: function(apps) {
-    if (!apps) {
-      return true;
-    }
-    return apps.length === 0;
-  },
-});
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js
index 725836f..072e37c 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js
@@ -37,14 +37,6 @@
 
 /**
  * @typedef {{
- *   term: ?string,
- *   results: ?Array<App>,
- * }}
- */
-let SearchState;
-
-/**
- * @typedef {{
  *   allowedIds: !Set<string>,
  *   blockedIds: !Set<string>,
  * }}
@@ -56,7 +48,6 @@
  *   apps: !AppMap,
  *   currentPage: !Page,
  *   arcSupported: boolean,
- *   search: !SearchState,
  *   notifications: !NotificationsState,
  * }}
  */
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js
index a2489bd..032ccf4 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js
@@ -18,10 +18,6 @@
         selectedAppId: null,
       },
       arcSupported: false,
-      search: {
-        term: null,
-        results: null,
-      },
       notifications: {
         allowedIds: new Set(),
         blockedIds: new Set(),
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.html b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.html
index 0304bc4..57a28f7 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.html
@@ -76,12 +76,14 @@
         </template>
       </template>
     </div>
-
     <!-- APP MANAGEMENT -->
     <template is="dom-if" if="showAppManagement">
       <template is="dom-if" route-path="/app-management" no-search>
-        <settings-subpage page-title="$i18n{appManagementTitle}">
-          <settings-app-management-page>
+        <settings-subpage
+            page-title="$i18n{appManagementTitle}"
+            search-label="$i18n{appManagementSearchPrompt}"
+            search-term="{{searchTerm}}">
+          <settings-app-management-page search-term="[[searchTerm]]">
           </settings-app-management-page>
         </settings-subpage>
       </template>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js
index 1c5a506..8c730b8 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js
@@ -36,6 +36,11 @@
     havePlayStoreApp: Boolean,
 
     /**
+     * @type {string}
+     */
+    searchTerm: String,
+
+    /**
      * Show ARC++ related settings and sub-page.
      * @type {boolean}
      */
diff --git a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
index ce020229..64833651 100644
--- a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
@@ -176,7 +176,10 @@
         std::string(),                    // supervised_user_id
         TestingProfile::TestingFactories());
 
-    return std::make_unique<ExtensionTestingProfile>(profile);
+    auto testing_profile = std::make_unique<ExtensionTestingProfile>(profile);
+    task_environment_.RunUntilIdle();
+
+    return testing_profile;
   }
 
   content::BrowserTaskEnvironment task_environment_;
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
index 88a7877..c012dc5e8 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
@@ -263,12 +263,15 @@
     profile_properties_[profile_name].on_addition_action = on_addition_action;
 
     // Boom (or fizzle).
-    return profile_manager_.CreateTestingProfile(
+    auto* profile = profile_manager_.CreateTestingProfile(
         profile_name, std::move(prefs), base::ASCIIToUTF16(profile_name),
         0,              // avatar_id (unused)
         std::string(),  // supervised_user_id (unused)
         TestingProfile::TestingFactories(),
         /*override_new_profile=*/base::Optional<bool>(false));
+    mock_time_task_runner_->FastForwardUntilNoTasksRemain();
+
+    return profile;
   }
 
   // Configures a callback to run when the next upload is started that will post
diff --git a/chrome/browser/search_engines/template_url_service_test_util.cc b/chrome/browser/search_engines/template_url_service_test_util.cc
index 4cf7369..35894735 100644
--- a/chrome/browser/search_engines/template_url_service_test_util.cc
+++ b/chrome/browser/search_engines/template_url_service_test_util.cc
@@ -82,6 +82,7 @@
 
 TemplateURLServiceTestUtil::~TemplateURLServiceTestUtil() {
   ClearModel();
+  web_data_service_->ShutdownOnUISequence();
   profile_.reset();
 
   // Flush the message loop to make application verifiers happy.
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.cc b/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.cc
index be7eb9c..7d810fd2 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.cc
+++ b/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.cc
@@ -26,7 +26,6 @@
 #include "ui/strings/grit/ui_strings.h"
 
 using SharingMessage = chrome_browser_sharing::SharingMessage;
-using App = ClickToCallUiController::App;
 
 // static
 ClickToCallUiController* ClickToCallUiController::GetOrCreateFromWebContents(
@@ -85,7 +84,7 @@
 }
 
 void ClickToCallUiController::DoUpdateApps(UpdateAppsCallback callback) {
-  std::vector<App> apps;
+  std::vector<SharingApp> apps;
   if (hide_default_handler_) {
     std::move(callback).Run(std::move(apps));
     return;
@@ -118,7 +117,7 @@
   SendMessageToDevice(device, std::move(sharing_message));
 }
 
-void ClickToCallUiController::OnAppChosen(const App& app) {
+void ClickToCallUiController::OnAppChosen(const SharingApp& app) {
   if (ukm_recorder_)
     std::move(ukm_recorder_).Run(SharingClickToCallSelection::kApp);
 
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h b/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h
index 495208b..4d28e57 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h
+++ b/chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h
@@ -43,7 +43,7 @@
   PageActionIconType GetIconType() override;
   sync_pb::SharingSpecificFields::EnabledFeatures GetRequiredFeature() override;
   void OnDeviceChosen(const syncer::DeviceInfo& device) override;
-  void OnAppChosen(const App& app) override;
+  void OnAppChosen(const SharingApp& app) override;
   void OnDialogClosed(SharingDialog* dialog) override;
   base::string16 GetContentType() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.cc
index 643cc66..af3538e 100644
--- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.cc
+++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.cc
@@ -17,8 +17,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/strings/grit/ui_strings.h"
 
-using App = SharingUiController::App;
-
 // static
 SharedClipboardUiController*
 SharedClipboardUiController::GetOrCreateFromWebContents(
@@ -56,7 +54,7 @@
 
 // No need for apps for shared clipboard feature
 void SharedClipboardUiController::DoUpdateApps(UpdateAppsCallback callback) {
-  std::move(callback).Run(std::vector<App>());
+  std::move(callback).Run(std::vector<SharingApp>());
 }
 
 // Error message dialog.
@@ -74,7 +72,7 @@
   SendMessageToDevice(device, std::move(sharing_message));
 }
 
-void SharedClipboardUiController::OnAppChosen(const App& app) {
+void SharedClipboardUiController::OnAppChosen(const SharingApp& app) {
   // Do nothing - there is no apps
 }
 
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h b/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h
index 4f618471..3100708 100644
--- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h
+++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h
@@ -36,7 +36,7 @@
   PageActionIconType GetIconType() override;
   sync_pb::SharingSpecificFields::EnabledFeatures GetRequiredFeature() override;
   void OnDeviceChosen(const syncer::DeviceInfo& device) override;
-  void OnAppChosen(const App& app) override;
+  void OnAppChosen(const SharingApp& app) override;
   base::string16 GetContentType() const override;
   base::string16 GetErrorDialogTitle() const override;
   base::string16 GetErrorDialogText() const override;
diff --git a/chrome/browser/sharing/sharing_app.cc b/chrome/browser/sharing/sharing_app.cc
new file mode 100644
index 0000000..40a09481
--- /dev/null
+++ b/chrome/browser/sharing/sharing_app.cc
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sharing/sharing_app.h"
+
+SharingApp::SharingApp(const gfx::VectorIcon* vector_icon,
+                       const gfx::Image& image,
+                       base::string16 name,
+                       std::string identifier)
+    : vector_icon(vector_icon),
+      image(image),
+      name(std::move(name)),
+      identifier(std::move(identifier)) {}
+
+SharingApp::SharingApp(SharingApp&& other) = default;
+
+SharingApp::~SharingApp() = default;
diff --git a/chrome/browser/sharing/sharing_app.h b/chrome/browser/sharing/sharing_app.h
new file mode 100644
index 0000000..216c812
--- /dev/null
+++ b/chrome/browser/sharing/sharing_app.h
@@ -0,0 +1,37 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SHARING_SHARING_APP_H_
+#define CHROME_BROWSER_SHARING_SHARING_APP_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "ui/gfx/image/image.h"
+
+namespace gfx {
+struct VectorIcon;
+}  // namespace gfx
+
+// Represents an external app shown in sharing dialogs.
+struct SharingApp {
+ public:
+  SharingApp(const gfx::VectorIcon* vector_icon,
+             const gfx::Image& image,
+             base::string16 name,
+             std::string identifier);
+  SharingApp(SharingApp&& other);
+  ~SharingApp();
+
+  const gfx::VectorIcon* vector_icon = nullptr;
+  gfx::Image image;
+  base::string16 name;
+  std::string identifier;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SharingApp);
+};
+
+#endif  // CHROME_BROWSER_SHARING_SHARING_APP_H_
diff --git a/chrome/browser/sharing/sharing_ui_controller.cc b/chrome/browser/sharing/sharing_ui_controller.cc
index 28925d00..7655127 100644
--- a/chrome/browser/sharing/sharing_ui_controller.cc
+++ b/chrome/browser/sharing/sharing_ui_controller.cc
@@ -33,19 +33,6 @@
 
 }  // namespace
 
-SharingUiController::App::App(const gfx::VectorIcon* vector_icon,
-                              const gfx::Image& image,
-                              base::string16 name,
-                              std::string identifier)
-    : vector_icon(vector_icon),
-      image(image),
-      name(std::move(name)),
-      identifier(std::move(identifier)) {}
-
-SharingUiController::App::App(App&& other) = default;
-
-SharingUiController::App::~App() = default;
-
 SharingUiController::SharingUiController(content::WebContents* web_contents)
     : web_contents_(web_contents),
       sharing_service_(SharingServiceFactory::GetForBrowserContext(
@@ -199,7 +186,8 @@
   return 0;
 }
 
-void SharingUiController::OnAppsReceived(int dialog_id, std::vector<App> apps) {
+void SharingUiController::OnAppsReceived(int dialog_id,
+                                         std::vector<SharingApp> apps) {
   if (dialog_id != last_dialog_id_)
     return;
 
diff --git a/chrome/browser/sharing/sharing_ui_controller.h b/chrome/browser/sharing/sharing_ui_controller.h
index 37fb75d..46255db0 100644
--- a/chrome/browser/sharing/sharing_ui_controller.h
+++ b/chrome/browser/sharing/sharing_ui_controller.h
@@ -14,13 +14,13 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/sharing/proto/sharing_message.pb.h"
+#include "chrome/browser/sharing/sharing_app.h"
 #include "chrome/browser/sharing/sharing_constants.h"
 #include "chrome/browser/sharing/sharing_metrics.h"
 #include "chrome/browser/sharing/sharing_service.h"
 #include "chrome/browser/ui/page_action/page_action_icon_type.h"
 #include "components/sync/protocol/device_info_specifics.pb.h"
 #include "components/sync_device_info/device_info.h"
-#include "ui/gfx/image/image.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/styled_label_listener.h"
 
@@ -39,21 +39,7 @@
 // The controller for desktop dialog with the list of synced devices and apps.
 class SharingUiController {
  public:
-  struct App {
-    App(const gfx::VectorIcon* vector_icon,
-        const gfx::Image& image,
-        base::string16 name,
-        std::string identifier);
-    App(App&& other);
-    ~App();
-
-    const gfx::VectorIcon* vector_icon = nullptr;
-    gfx::Image image;
-    base::string16 name;
-    std::string identifier;
-  };
-
-  using UpdateAppsCallback = base::OnceCallback<void(std::vector<App>)>;
+  using UpdateAppsCallback = base::OnceCallback<void(std::vector<SharingApp>)>;
 
   explicit SharingUiController(content::WebContents* web_contents);
   virtual ~SharingUiController();
@@ -63,7 +49,7 @@
   // Called when user chooses a synced device to complete the task.
   virtual void OnDeviceChosen(const syncer::DeviceInfo& device) = 0;
   // Called when user chooses a local app to complete the task.
-  virtual void OnAppChosen(const App& app) = 0;
+  virtual void OnAppChosen(const SharingApp& app) = 0;
   virtual PageActionIconType GetIconType() = 0;
   virtual sync_pb::SharingSpecificFields::EnabledFeatures
   GetRequiredFeature() = 0;
@@ -113,12 +99,14 @@
   bool HasSendFailed() const;
 
   content::WebContents* web_contents() const { return web_contents_; }
-  const std::vector<App>& apps() const { return apps_; }
+  const std::vector<SharingApp>& apps() const { return apps_; }
   const std::vector<std::unique_ptr<syncer::DeviceInfo>>& devices() const {
     return devices_;
   }
 
-  void set_apps_for_testing(std::vector<App> apps) { apps_ = std::move(apps); }
+  void set_apps_for_testing(std::vector<SharingApp> apps) {
+    apps_ = std::move(apps);
+  }
   void set_devices_for_testing(
       std::vector<std::unique_ptr<syncer::DeviceInfo>> devices) {
     devices_ = std::move(devices);
@@ -150,7 +138,7 @@
   // |success| is false and updates the omnibox icon.
   void OnMessageSentToDevice(int dialog_id, SharingSendMessageResult result);
 
-  void OnAppsReceived(int dialog_id, std::vector<App> apps);
+  void OnAppsReceived(int dialog_id, std::vector<SharingApp> apps);
 
   SharingDialog* dialog_ = nullptr;
   content::WebContents* web_contents_ = nullptr;
@@ -161,7 +149,7 @@
   std::string target_device_name_;
 
   // Currently used apps and devices since the last call to UpdateAndShowDialog.
-  std::vector<App> apps_;
+  std::vector<SharingApp> apps_;
   std::vector<std::unique_ptr<syncer::DeviceInfo>> devices_;
 
   // ID of the last shown dialog used to ignore events from old dialogs.
diff --git a/chrome/browser/signin/e2e_tests/demo_signin_e2e_test.cc b/chrome/browser/signin/e2e_tests/demo_signin_e2e_test.cc
index d7a40fc..bc63076 100644
--- a/chrome/browser/signin/e2e_tests/demo_signin_e2e_test.cc
+++ b/chrome/browser/signin/e2e_tests/demo_signin_e2e_test.cc
@@ -2,23 +2,35 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/run_loop.h"
+#include "base/time/time.h"
 #include "chrome/browser/signin/e2e_tests/live_test.h"
 #include "chrome/browser/signin/e2e_tests/test_accounts_util.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/browser/ui/webui/signin/login_ui_test_utils.h"
+#include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/test_identity_manager_observer.h"
+#include "components/sync/driver/sync_service.h"
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 
+#if !defined(OS_CHROMEOS)
+#include "chrome/browser/sync/sync_ui_util.h"
+#endif  // !defined(OS_CHROMEOS)
+
 namespace signin {
 namespace test {
 
 // IdentityManager observer allowing to wait for sign out events for several
 // accounts.
+// Counts both token removals and token persistent errors as sign out events.
 class SignOutTestObserver : public IdentityManager::Observer {
  public:
   explicit SignOutTestObserver(IdentityManager* identity_manager)
@@ -30,19 +42,31 @@
   void OnRefreshTokenRemovedForAccount(
       const CoreAccountId& account_id) override {
     ++signed_out_accounts_;
-    if (expected_accounts_ != -1 && signed_out_accounts_ >= expected_accounts_)
-      run_loop_.Quit();
+    QuitIfConditionIsSatisfied();
+  }
+
+  void OnErrorStateOfRefreshTokenUpdatedForAccount(
+      const CoreAccountInfo& account_info,
+      const GoogleServiceAuthError& error) override {
+    if (!error.IsPersistentError())
+      return;
+
+    ++signed_out_accounts_;
+    QuitIfConditionIsSatisfied();
   }
 
   void WaitForRefreshTokenRemovedForAccounts(int expected_accounts) {
     expected_accounts_ = expected_accounts;
-    if (signed_out_accounts_ >= expected_accounts_)
-      return;
-
+    QuitIfConditionIsSatisfied();
     run_loop_.Run();
   }
 
  private:
+  void QuitIfConditionIsSatisfied() {
+    if (expected_accounts_ != -1 && signed_out_accounts_ >= expected_accounts_)
+      run_loop_.Quit();
+  }
+
   signin::IdentityManager* identity_manager_;
   base::RunLoop run_loop_;
   int signed_out_accounts_ = 0;
@@ -68,6 +92,18 @@
     SignInFromCurrentPage(test_account);
   }
 
+  void SignInFromSettings(const TestAccount& test_account) {
+    GURL settings_url("chrome://settings");
+    AddTabAtIndex(0, settings_url, ui::PageTransition::PAGE_TRANSITION_TYPED);
+    auto* settings_tab = browser()->tab_strip_model()->GetActiveWebContents();
+    EXPECT_TRUE(content::ExecuteScript(
+        settings_tab,
+        "testElement = document.createElement('settings-sync-account-control');"
+        "document.body.appendChild(testElement);"
+        "testElement.$$('#sign-in').click();"));
+    SignInFromCurrentPage(test_account);
+  }
+
   void SignInFromCurrentPage(const TestAccount& test_account) {
     TestIdentityManagerObserver observer(identity_manager());
     base::RunLoop cookie_update_loop;
@@ -97,22 +133,19 @@
   signin::IdentityManager* identity_manager() {
     return IdentityManagerFactory::GetForProfile(browser()->profile());
   }
+
+  syncer::SyncService* sync_service() {
+    return ProfileSyncServiceFactory::GetForProfile(browser()->profile());
+  }
 };
 
 // Sings in an account through the settings page and checks that the account is
-// added to Chrome. Sync should be disabled.
+// added to Chrome. Sync should be disabled because the test doesn't pass
+// through the Sync confirmation dialog.
 IN_PROC_BROWSER_TEST_F(DemoSignInTest, SimpleSignInFlow) {
-  GURL url("chrome://settings");
-  AddTabAtIndex(0, url, ui::PageTransition::PAGE_TRANSITION_TYPED);
-  auto* settings_tab = browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(content::ExecuteScript(
-      settings_tab,
-      "testElement = document.createElement('settings-sync-account-control');"
-      "document.body.appendChild(testElement);"
-      "testElement.$$('#sign-in').click();"));
   TestAccount ta;
   CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", ta));
-  SignInFromCurrentPage(ta);
+  SignInFromSettings(ta);
 
   const AccountsInCookieJarInfo& accounts_in_cookie_jar =
       identity_manager()->GetAccountsInCookieJar();
@@ -126,6 +159,47 @@
   EXPECT_FALSE(identity_manager()->HasPrimaryAccount());
 }
 
+// Signs in an account through the settings page and enables Sync. Checks that
+// Sync is enabled.
+// Then, signs out on the web and checks that the account is removed from
+// cookies and Sync paused error is displayed.
+IN_PROC_BROWSER_TEST_F(DemoSignInTest, WebSignOut) {
+  TestAccount test_account;
+  CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account));
+  SignInFromSettings(test_account);
+
+  TestIdentityManagerObserver observer(identity_manager());
+  base::RunLoop primary_account_set_loop;
+  observer.SetOnPrimaryAccountSetCallback(
+      primary_account_set_loop.QuitClosure());
+  login_ui_test_utils::DismissSyncConfirmationDialog(
+      browser(), base::TimeDelta::FromSeconds(3));
+  primary_account_set_loop.Run();
+  const CoreAccountInfo& primary_account =
+      observer.PrimaryAccountFromSetCallback();
+  EXPECT_TRUE(gaia::AreEmailsSame(test_account.user, primary_account.email));
+  EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
+
+  SignOutFromWeb(1);
+
+  const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+      identity_manager()->GetAccountsInCookieJar();
+  EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh);
+  ASSERT_TRUE(accounts_in_cookie_jar.signed_in_accounts.empty());
+  ASSERT_EQ(1u, accounts_in_cookie_jar.signed_out_accounts.size());
+  EXPECT_TRUE(gaia::AreEmailsSame(
+      test_account.user, accounts_in_cookie_jar.signed_out_accounts[0].email));
+  EXPECT_TRUE(
+      identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+          primary_account.account_id));
+#if !defined(OS_CHROMEOS)
+  int unused1, unused2;
+  EXPECT_EQ(sync_ui_util::GetMessagesForAvatarSyncError(browser()->profile(),
+                                                        &unused1, &unused2),
+            sync_ui_util::AUTH_ERROR);
+#endif  // !defined(OS_CHROMEOS)
+}
+
 // Sings in two accounts on the web and checks that cookies and refresh tokens
 // are added to Chrome. Sync should be disabled.
 // Then, signs out on the web and checks that accounts are removed from Chrome.
@@ -168,6 +242,7 @@
   EXPECT_TRUE(accounts_in_cookie_jar_3.accounts_are_fresh);
   ASSERT_TRUE(accounts_in_cookie_jar_3.signed_in_accounts.empty());
   EXPECT_EQ(2u, accounts_in_cookie_jar_3.signed_out_accounts.size());
+  EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
 }
 
 }  // namespace test
diff --git a/chrome/browser/signin/e2e_tests/live_test.cc b/chrome/browser/signin/e2e_tests/live_test.cc
index ae4212f..2426a7e0 100644
--- a/chrome/browser/signin/e2e_tests/live_test.cc
+++ b/chrome/browser/signin/e2e_tests/live_test.cc
@@ -21,6 +21,8 @@
   host_resolver()->AllowDirectLookup("*.geotrust.com");
   host_resolver()->AllowDirectLookup("*.gstatic.com");
   host_resolver()->AllowDirectLookup("*.googleapis.com");
+  // Allows country-specific TLDs.
+  host_resolver()->AllowDirectLookup("accounts.google.*");
 
   InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
 }
diff --git a/chrome/browser/ui/ash/launcher/DEPS b/chrome/browser/ui/ash/launcher/DEPS
index ee1b2b8..4710e30 100644
--- a/chrome/browser/ui/ash/launcher/DEPS
+++ b/chrome/browser/ui/ash/launcher/DEPS
@@ -10,8 +10,6 @@
   "chrome_launcher_controller_unittest\.cc": [
     # https://crbug.com/875111
     "+ash/multi_user/multi_user_window_manager_impl.h",
-    # https://crbug.com/826982
-    "+chrome/services/app_service/app_service.h",
   ],
   "browser_shortcut_launcher_item_controller\.cc": [
     "+ash/wm/desks/desks_util.h",
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
index 1e801cf..793dcdaf 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -121,7 +121,6 @@
 #include "extensions/common/manifest_constants.h"
 #include "extensions/grit/extensions_browser_resources.h"
 #include "services/network/test/test_network_connection_tracker.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/client/window_parenting_client.h"
 #include "ui/aura/window.h"
@@ -324,7 +323,6 @@
 
     DCHECK(profile());
     extension_registry_ = extensions::ExtensionRegistry::Get(profile());
-
     app_service_test_.SetUp(profile());
 
     if (auto_start_arc_test_)
@@ -477,7 +475,6 @@
   void TearDown() override {
     arc_test_.TearDown();
     launcher_controller_ = nullptr;
-
     BrowserWithTestWindowTest::TearDown();
   }
 
@@ -502,7 +499,7 @@
   // Create and initialize the controller, owned by the test shell delegate.
   void InitLauncherController() {
     CreateLauncherController()->Init();
-    app_service_test_.FlushMojoCallsForAppService();
+    app_service_test_.FlushMojoCalls();
   }
 
   // Create and initialize the controller; create a tab and show the browser.
@@ -670,7 +667,7 @@
       app_list_syncable_service_->ProcessSyncChanges(FROM_HERE,
                                                      combined_sync_list);
     }
-    app_service_test_.FlushMojoCallsForAppService();
+    app_service_test_.FlushMojoCalls();
   }
 
   // Set the index at which the chrome icon should be.
@@ -3711,7 +3708,7 @@
 
   // Switch to a new profile
   SwitchActiveUser(account_id2);
-  app_service_test().FlushMojoCallsForAppService();
+  app_service_test().FlushMojoCalls();
   EXPECT_FALSE(launcher_controller_->IsAppPinned(app_id));
   EXPECT_EQ(1, model_->item_count());
   EXPECT_FALSE(
@@ -3719,7 +3716,7 @@
 
   // Switch back
   SwitchActiveUser(account_id);
-  app_service_test().FlushMojoCallsForAppService();
+  app_service_test().FlushMojoCalls();
   EXPECT_TRUE(launcher_controller_->IsAppPinned(app_id));
   EXPECT_EQ(2, model_->item_count());
   EXPECT_TRUE(
@@ -4597,7 +4594,7 @@
   profile()->GetTestingPrefService()->SetManagedPref(
       prefs::kPolicyPinnedLauncherApps, policy_value.CreateDeepCopy());
 
-  app_service_test().FlushMojoCallsForAppService();
+  app_service_test().FlushMojoCalls();
 
   // Since the device is online, all policy pinned apps are pinned.
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
@@ -4648,7 +4645,7 @@
 
   profile()->GetTestingPrefService()->SetManagedPref(
       prefs::kPolicyPinnedLauncherApps, policy_value.CreateDeepCopy());
-  app_service_test().FlushMojoCallsForAppService();
+  app_service_test().FlushMojoCalls();
 
   // Since the device is online, the policy pinned apps that shouldn't be pinned
   // in Demo Mode are unpinned.
diff --git a/chrome/browser/ui/ash/test_login_screen_model.cc b/chrome/browser/ui/ash/test_login_screen_model.cc
index af1e771..204852fc 100644
--- a/chrome/browser/ui/ash/test_login_screen_model.cc
+++ b/chrome/browser/ui/ash/test_login_screen_model.cc
@@ -36,7 +36,8 @@
 void TestLoginScreenModel::UpdateWarningMessage(const base::string16& message) {
 }
 void TestLoginScreenModel::SetSystemInfo(
-    bool show_if_hidden,
+    bool show,
+    bool enforced,
     const std::string& os_version_label_text,
     const std::string& enterprise_info_text,
     const std::string& bluetooth_name) {}
diff --git a/chrome/browser/ui/ash/test_login_screen_model.h b/chrome/browser/ui/ash/test_login_screen_model.h
index c578069..95739dc3 100644
--- a/chrome/browser/ui/ash/test_login_screen_model.h
+++ b/chrome/browser/ui/ash/test_login_screen_model.h
@@ -36,7 +36,8 @@
                                               bool enabled) override;
 
   void UpdateWarningMessage(const base::string16& message) override;
-  void SetSystemInfo(bool show_if_hidden,
+  void SetSystemInfo(bool show,
+                     bool enforced,
                      const std::string& os_version_label_text,
                      const std::string& enterprise_info_text,
                      const std::string& bluetooth_name) override;
diff --git a/chrome/browser/ui/passwords/password_dialog_prompts.h b/chrome/browser/ui/passwords/password_dialog_prompts.h
index 23b7b412..098bdc0 100644
--- a/chrome/browser/ui/passwords/password_dialog_prompts.h
+++ b/chrome/browser/ui/passwords/password_dialog_prompts.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_PASSWORDS_PASSWORD_DIALOG_PROMPTS_H_
 #define CHROME_BROWSER_UI_PASSWORDS_PASSWORD_DIALOG_PROMPTS_H_
 
+#include "base/macros.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace content {
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view.cc b/chrome/browser/ui/views/sharing/sharing_dialog_view.cc
index ca59246..ff7805f 100644
--- a/chrome/browser/ui/views/sharing/sharing_dialog_view.cc
+++ b/chrome/browser/ui/views/sharing/sharing_dialog_view.cc
@@ -7,6 +7,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/sharing/sharing_app.h"
 #include "chrome/browser/sharing/sharing_metrics.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/views/accessibility/non_accessible_image_view.h"
@@ -60,7 +61,7 @@
                               : kHardwareSmartphoneIcon);
 }
 
-gfx::ImageSkia CreateAppIcon(const SharingUiController::App& app) {
+gfx::ImageSkia CreateAppIcon(const SharingApp& app) {
   return app.vector_icon ? CreateVectorIcon(*app.vector_icon)
                          : app.image.AsImageSkia();
 }
@@ -170,7 +171,7 @@
   size_t index = static_cast<size_t>(sender->tag());
   const std::vector<std::unique_ptr<syncer::DeviceInfo>>& devices =
       controller_->devices();
-  const std::vector<SharingUiController::App>& apps = controller_->apps();
+  const std::vector<SharingApp>& apps = controller_->apps();
   DCHECK(index < devices.size() + apps.size());
 
   if (index < devices.size()) {
@@ -230,7 +231,7 @@
 
   const std::vector<std::unique_ptr<syncer::DeviceInfo>>& devices =
       controller_->devices();
-  const std::vector<SharingUiController::App>& apps = controller_->apps();
+  const std::vector<SharingApp>& apps = controller_->apps();
   DCHECK_EQ(devices.size() + apps.size(), button_icons_.size());
 
   size_t button_index = 0;
@@ -248,7 +249,7 @@
 void SharingDialogView::InitListView() {
   const std::vector<std::unique_ptr<syncer::DeviceInfo>>& devices =
       controller_->devices();
-  const std::vector<SharingUiController::App>& apps = controller_->apps();
+  const std::vector<SharingApp>& apps = controller_->apps();
   int tag = 0;
 
   // Devices:
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view.h b/chrome/browser/ui/views/sharing/sharing_dialog_view.h
index b81b2a4..cf75b7a 100644
--- a/chrome/browser/ui/views/sharing/sharing_dialog_view.h
+++ b/chrome/browser/ui/views/sharing/sharing_dialog_view.h
@@ -36,31 +36,27 @@
 
   ~SharingDialogView() override;
 
-  // SharingDialogView:
+  // SharingDialog:
   void Hide() override;
 
-  // views::WidgetDelegateView:
+  // LocationBarBubbleDelegateView:
   bool ShouldShowCloseButton() const override;
   base::string16 GetWindowTitle() const override;
   void WindowClosing() override;
+  int GetDialogButtons() const override;
+  std::unique_ptr<views::View> CreateFootnoteView() override;
+  gfx::Size CalculatePreferredSize() const override;
+  void AddedToWidget() override;
+  void OnThemeChanged() override;
 
   // views::StyledLabelListener:
   void StyledLabelLinkClicked(views::StyledLabel* label,
                               const gfx::Range& range,
                               int event_flags) override;
 
-  // views::DialogDelegate:
-  int GetDialogButtons() const override;
-  std::unique_ptr<views::View> CreateFootnoteView() override;
-
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
-  // views::View:
-  gfx::Size CalculatePreferredSize() const override;
-  void AddedToWidget() override;
-  void OnThemeChanged() override;
-
   static views::BubbleDialogDelegateView* GetAsBubble(SharingDialog* dialog);
   std::unique_ptr<views::StyledLabel> CreateHelpText(
       views::StyledLabelListener* listener);
@@ -74,7 +70,7 @@
 
   SharingDialogType GetDialogType() const;
 
-  // views::BubbleDialogDelegateView:
+  // LocationBarBubbleDelegateView:
   void Init() override;
 
   // Shows a header image in the dialog view.
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc b/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc
index 41a544a..12821b8f 100644
--- a/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc
+++ b/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/simple_test_clock.h"
 #include "chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h"
+#include "chrome/browser/sharing/sharing_app.h"
 #include "chrome/browser/sharing/sharing_metrics.h"
 #include "chrome/browser/ui/views/hover_button.h"
 #include "chrome/test/base/testing_profile.h"
@@ -35,7 +36,7 @@
   ~ClickToCallUiControllerMock() override = default;
 
   MOCK_METHOD1(OnDeviceChosen, void(const syncer::DeviceInfo& device));
-  MOCK_METHOD1(OnAppChosen, void(const App& app));
+  MOCK_METHOD1(OnAppChosen, void(const SharingApp& app));
   MOCK_METHOD1(OnHelpTextClicked, void(SharingDialogType dialog_type));
 };
 
@@ -101,8 +102,8 @@
     return devices;
   }
 
-  std::vector<ClickToCallUiController::App> CreateApps(int count) {
-    std::vector<ClickToCallUiController::App> apps;
+  std::vector<SharingApp> CreateApps(int count) {
+    std::vector<SharingApp> apps;
     for (int i = 0; i < count; i++) {
       apps.emplace_back(
           &vector_icons::kOpenInNewIcon, gfx::Image(),
@@ -153,8 +154,8 @@
 }
 
 TEST_F(SharingDialogViewTest, AppPressed) {
-  ClickToCallUiController::App app(&vector_icons::kOpenInNewIcon, gfx::Image(),
-                                   base::UTF8ToUTF16("app0"), std::string());
+  SharingApp app(&vector_icons::kOpenInNewIcon, gfx::Image(),
+                 base::UTF8ToUTF16("app0"), std::string());
   EXPECT_CALL(*controller_.get(), OnAppChosen(AppEquals(&app)));
 
   auto dialog = CreateDialogView(/*devices=*/3, /*apps=*/2);
diff --git a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
index 3117ed67..b089777 100644
--- a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
@@ -115,4 +115,5 @@
     WebAppFileHandlingBrowserTest,
     ::testing::Values(
         web_app::ControllerType::kHostedAppController,
-        web_app::ControllerType::kUnifiedControllerWithBookmarkApp));
+        web_app::ControllerType::kUnifiedControllerWithBookmarkApp,
+        web_app::ControllerType::kUnifiedControllerWithWebApp));
diff --git a/chrome/browser/ui/web_applications/web_app_launch_manager.cc b/chrome/browser/ui/web_applications/web_app_launch_manager.cc
index 9333654..bf116e8 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_manager.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_manager.cc
@@ -13,7 +13,9 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/browser/web_launch/web_launch_files_helper.h"
 #include "content/public/browser/render_view_host.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 
 namespace web_app {
@@ -70,6 +72,12 @@
 
   browser->window()->Show();
   web_contents->SetInitialFocus();
+
+  if (base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI)) {
+    web_launch::WebLaunchFilesHelper::SetLaunchPaths(web_contents, launch_url,
+                                                     params.launch_files);
+  }
+
   return web_contents;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc b/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
index f0d42d6..4941d5c 100644
--- a/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
+++ b/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
@@ -163,8 +163,9 @@
 InternetConfigDialogUI::~InternetConfigDialogUI() {}
 
 void InternetConfigDialogUI::BindCrosNetworkConfig(
-    chromeos::network_config::mojom::CrosNetworkConfigRequest request) {
-  ash::GetNetworkConfigService(std::move(request));
+    mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+        receiver) {
+  ash::GetNetworkConfigService(std::move(receiver));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/internet_config_dialog.h b/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
index 22d186a..4d445f3 100644
--- a/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
+++ b/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"  // nogncheck
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "ui/web_dialogs/web_dialog_ui.h"
 
 namespace chromeos {
@@ -56,7 +57,8 @@
 
  private:
   void BindCrosNetworkConfig(
-      chromeos::network_config::mojom::CrosNetworkConfigRequest request);
+      mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+          receiver);
 
   DISALLOW_COPY_AND_ASSIGN(InternetConfigDialogUI);
 };
diff --git a/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc b/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc
index 32bc3e45..05a922d 100644
--- a/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc
+++ b/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc
@@ -161,8 +161,9 @@
 InternetDetailDialogUI::~InternetDetailDialogUI() {}
 
 void InternetDetailDialogUI::BindCrosNetworkConfig(
-    chromeos::network_config::mojom::CrosNetworkConfigRequest request) {
-  ash::GetNetworkConfigService(std::move(request));
+    mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+        receiver) {
+  ash::GetNetworkConfigService(std::move(receiver));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h b/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h
index eec6c4d..a014050 100644
--- a/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h
+++ b/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"  // nogncheck
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "ui/web_dialogs/web_dialog_ui.h"
 
 namespace chromeos {
@@ -51,7 +52,8 @@
 
  private:
   void BindCrosNetworkConfig(
-      chromeos::network_config::mojom::CrosNetworkConfigRequest request);
+      mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+          receiver);
 
   DISALLOW_COPY_AND_ASSIGN(InternetDetailDialogUI);
 };
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 0adbdada..549df94 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -502,8 +502,9 @@
 }
 
 void OobeUI::BindCrosNetworkConfig(
-    chromeos::network_config::mojom::CrosNetworkConfigRequest request) {
-  ash::GetNetworkConfigService(std::move(request));
+    mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+        receiver) {
+  ash::GetNetworkConfigService(std::move(receiver));
 }
 
 OobeUI::OobeUI(content::WebUI* web_ui, const GURL& url)
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index 84dc0d2..285c6305 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h"
 #include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"  // nogncheck
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "ui/webui/mojo_web_ui_controller.h"
 
 namespace base {
@@ -163,7 +164,8 @@
   void BindPrivilegedHostDeviceSetter(
       multidevice_setup::mojom::PrivilegedHostDeviceSetterRequest request);
   void BindCrosNetworkConfig(
-      chromeos::network_config::mojom::CrosNetworkConfigRequest request);
+      mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+          receiver);
 
   // Type of UI.
   std::string display_type_;
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc
index 973bb72..0f9cea6 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -406,8 +406,8 @@
 NetworkUI::~NetworkUI() {}
 
 void NetworkUI::BindCrosNetworkConfig(
-    network_config::mojom::CrosNetworkConfigRequest request) {
-  ash::GetNetworkConfigService(std::move(request));
+    mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver) {
+  ash::GetNetworkConfigService(std::move(receiver));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.h b/chrome/browser/ui/webui/chromeos/network_ui.h
index 4ed87901..1b3e506 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.h
+++ b/chrome/browser/ui/webui/chromeos/network_ui.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "ui/webui/mojo_web_ui_controller.h"
 
 namespace base {
@@ -25,7 +26,7 @@
 
  private:
   void BindCrosNetworkConfig(
-      network_config::mojom::CrosNetworkConfigRequest request);
+      mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver);
 
   DISALLOW_COPY_AND_ASSIGN(NetworkUI);
 };
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
index d078e53..f755492c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
@@ -187,8 +187,8 @@
 }
 
 void OSSettingsUI::BindCrosNetworkConfig(
-    network_config::mojom::CrosNetworkConfigRequest request) {
-  ash::GetNetworkConfigService(std::move(request));
+    mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver) {
+  ash::GetNetworkConfigService(std::move(receiver));
 }
 
 void OSSettingsUI::BindAppManagementPageHandlerFactory(
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
index f029a415c..ff325c2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
@@ -32,7 +32,7 @@
   void AddSettingsPageUIHandler(
       std::unique_ptr<content::WebUIMessageHandler> handler);
   void BindCrosNetworkConfig(
-      network_config::mojom::CrosNetworkConfigRequest request);
+      mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver);
   void BindAppManagementPageHandlerFactory(
       mojo::PendingReceiver<app_management::mojom::PageHandlerFactory>
           receiver);
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 1c69a5f..c6a734b 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -646,6 +646,7 @@
 void AddAppManagementStrings(content::WebUIDataSource* html_source) {
   static constexpr LocalizedString localized_strings[] = {
       {"appListTitle", IDS_APP_MANAGEMENT_APP_LIST_TITLE},
+      {"appManagementSearchPrompt", IDS_APP_MANAGEMENT_SEARCH_PROMPT},
       {"appNoPermission", IDS_APPLICATION_INFO_APP_NO_PERMISSIONS_TEXT},
       {"camera", IDS_APP_MANAGEMENT_CAMERA},
       {"contacts", IDS_APP_MANAGEMENT_CONTACTS},
@@ -655,6 +656,7 @@
       {"microphone", IDS_APP_MANAGEMENT_MICROPHONE},
       {"moreApps", IDS_APP_MANAGEMENT_MORE_APPS},
       {"moreSettings", IDS_APP_MANAGEMENT_MORE_SETTINGS},
+      {"appManagementNoAppsFound", IDS_APP_MANAGEMENT_NO_APPS_FOUND},
       {"notifications", IDS_APP_MANAGEMENT_NOTIFICATIONS},
       {"notificationSublabel", IDS_APP_MANAGEMENT_NOTIFICATIONS_SUBLABEL},
       {"openAndroidSettings", IDS_APP_MANAGEMENT_ANDROID_SETTINGS},
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index d20ae17..7e669d90 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -534,8 +534,9 @@
 
 #if defined(OS_CHROMEOS)
 void SettingsUI::BindCrosNetworkConfig(
-    chromeos::network_config::mojom::CrosNetworkConfigRequest request) {
-  ash::GetNetworkConfigService(std::move(request));
+    mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+        receiver) {
+  ash::GetNetworkConfigService(std::move(receiver));
 }
 #endif  // defined(OS_CHROMEOS)
 
diff --git a/chrome/browser/ui/webui/settings/settings_ui.h b/chrome/browser/ui/webui/settings/settings_ui.h
index 16d535fe..0ab7448 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.h
+++ b/chrome/browser/ui/webui/settings/settings_ui.h
@@ -11,6 +11,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"  // nogncheck
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "ui/webui/mojo_web_ui_controller.h"
 #else
 #include "content/public/browser/web_ui_controller.h"
@@ -55,7 +56,8 @@
       std::unique_ptr<content::WebUIMessageHandler> handler);
 #if defined(OS_CHROMEOS)
   void BindCrosNetworkConfig(
-      chromeos::network_config::mojom::CrosNetworkConfigRequest request);
+      mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+          receiver);
 #endif
 
   WebuiLoadTimer webui_load_timer_;
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_options_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_options_unittest.cc
index d52c2c9..e6d0e81 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_options_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_options_unittest.cc
@@ -11,9 +11,8 @@
 #include "extensions/common/manifest_handlers/options_page_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using namespace extensions;
-
-namespace errors = extensions::manifest_errors;
+using extensions::FeatureSwitch;
+using extensions::OptionsPageInfo;
 
 namespace {
 
@@ -24,7 +23,7 @@
   testing::AssertionResult TestOptionsUIChromeStyleAndOpenInTab() {
     // Explicitly specifying true in the manifest for options_ui.chrome_style
     // and options_ui.open_in_tab sets them both to true.
-    scoped_refptr<Extension> extension =
+    scoped_refptr<extensions::Extension> extension =
         LoadAndExpectSuccess("options_ui_flags_true.json");
     EXPECT_TRUE(OptionsPageInfo::ShouldUseChromeStyle(extension.get()));
     EXPECT_TRUE(OptionsPageInfo::ShouldOpenInTab(extension.get()));
@@ -55,7 +54,7 @@
   // chromes-style behaviour.
   testing::AssertionResult TestOptionsPageChromeStyleAndOpenInTab(
       bool expect_open_in_tab) {
-    scoped_refptr<Extension> extension =
+    scoped_refptr<extensions::Extension> extension =
         LoadAndExpectSuccess("init_valid_options.json");
     EXPECT_FALSE(OptionsPageInfo::ShouldUseChromeStyle(extension.get()));
     if (expect_open_in_tab) {
@@ -69,7 +68,7 @@
 
 TEST_F(OptionsPageManifestTest, OptionsPageInApps) {
   // Allow options page with absolute URL in hosted apps.
-  scoped_refptr<Extension> extension =
+  scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess("hosted_app_absolute_options.json");
   EXPECT_EQ("http://example.com/options.html",
             OptionsPageInfo::GetOptionsPage(extension.get()).spec());
@@ -78,18 +77,18 @@
   EXPECT_TRUE(!OptionsPageInfo::HasOptionsPage(extension.get()));
 
   Testcase testcases[] = {
-    // Forbid options page with relative URL in hosted apps.
-    Testcase("hosted_app_relative_options.json",
-             errors::kInvalidOptionsPageInHostedApp),
+      // Forbid options page with relative URL in hosted apps.
+      Testcase("hosted_app_relative_options.json",
+               extensions::manifest_errors::kInvalidOptionsPageInHostedApp),
 
-    // Forbid options page with non-(http|https) scheme in hosted app.
-    Testcase("hosted_app_file_options.json",
-             errors::kInvalidOptionsPageInHostedApp),
+      // Forbid options page with non-(http|https) scheme in hosted app.
+      Testcase("hosted_app_file_options.json",
+               extensions::manifest_errors::kInvalidOptionsPageInHostedApp),
 
-    // Forbid absolute URL for options page in packaged apps.
-    Testcase("packaged_app_absolute_options.json",
-             errors::kInvalidOptionsPageExpectUrlInPackage)
-  };
+      // Forbid absolute URL for options page in packaged apps.
+      Testcase(
+          "packaged_app_absolute_options.json",
+          extensions::manifest_errors::kInvalidOptionsPageExpectUrlInPackage)};
   RunTestcases(testcases, base::size(testcases), EXPECT_TYPE_ERROR);
 }
 
@@ -98,7 +97,7 @@
   FeatureSwitch::ScopedOverride enable_flag(
       FeatureSwitch::embedded_extension_options(), true);
 
-  scoped_refptr<Extension> extension =
+  scoped_refptr<extensions::Extension> extension =
       LoadAndExpectSuccess("options_ui_page_basic.json");
   EXPECT_EQ(base::StringPrintf("chrome-extension://%s/options.html",
                                extension->id().c_str()),
diff --git a/chrome/credential_provider/gaiacp/dllmain.cc b/chrome/credential_provider/gaiacp/dllmain.cc
index b3eb9c0..fdfa040 100644
--- a/chrome/credential_provider/gaiacp/dllmain.cc
+++ b/chrome/credential_provider/gaiacp/dllmain.cc
@@ -58,8 +58,6 @@
   return _AtlModule.DllMain(hinstance, reason, reserved);
 }
 
-using namespace ATL;
-
 // Used to determine whether the DLL can be unloaded by OLE.
 STDAPI DllCanUnloadNow(void) {
   HRESULT hr = _AtlModule.DllCanUnloadNow();
diff --git a/chrome/renderer/autofill/fake_mojo_password_manager_driver.cc b/chrome/renderer/autofill/fake_mojo_password_manager_driver.cc
index 2e6f78c..1bbe745 100644
--- a/chrome/renderer/autofill/fake_mojo_password_manager_driver.cc
+++ b/chrome/renderer/autofill/fake_mojo_password_manager_driver.cc
@@ -43,9 +43,12 @@
 }
 
 void FakeMojoPasswordManagerDriver::SameDocumentNavigation(
-    const autofill::PasswordForm& password_form) {
+    autofill::mojom::SubmissionIndicatorEvent submission_indication_event) {
   called_same_document_navigation_ = true;
-  password_form_same_document_navigation_ = password_form;
+  password_form_maybe_submitted_->form_data.submission_event =
+      submission_indication_event;
+  password_form_maybe_submitted_->submission_event =
+      submission_indication_event;
 }
 
 void FakeMojoPasswordManagerDriver::ShowPasswordSuggestions(
@@ -80,6 +83,7 @@
 void FakeMojoPasswordManagerDriver::ShowManualFallbackForSaving(
     const autofill::PasswordForm& password_form) {
   called_show_manual_fallback_for_saving_count_++;
+  password_form_maybe_submitted_ = password_form;
 }
 
 void FakeMojoPasswordManagerDriver::HideManualFallbackForSaving() {
diff --git a/chrome/renderer/autofill/fake_mojo_password_manager_driver.h b/chrome/renderer/autofill/fake_mojo_password_manager_driver.h
index 5c2f4f0..2502b89 100644
--- a/chrome/renderer/autofill/fake_mojo_password_manager_driver.h
+++ b/chrome/renderer/autofill/fake_mojo_password_manager_driver.h
@@ -75,9 +75,9 @@
     return called_same_document_navigation_;
   }
 
-  const base::Optional<autofill::PasswordForm>&
-  password_form_same_document_navigation() const {
-    return password_form_same_document_navigation_;
+  const base::Optional<autofill::PasswordForm>& password_form_maybe_submitted()
+      const {
+    return password_form_maybe_submitted_;
   }
 
   bool called_password_forms_parsed() const {
@@ -150,8 +150,8 @@
   void PasswordFormSubmitted(
       const autofill::PasswordForm& password_form) override;
 
-  void SameDocumentNavigation(
-      const autofill::PasswordForm& password_form) override;
+  void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent
+                                  submission_indication_event) override;
 
   void ShowPasswordSuggestions(base::i18n::TextDirection text_direction,
                                const base::string16& typed_username,
@@ -187,11 +187,10 @@
   bool called_password_form_submitted_ = false;
   // Records data received via PasswordFormSubmitted() call.
   base::Optional<autofill::PasswordForm> password_form_submitted_;
+  // Records data received via ShowManualFallbackForSaving() call.
+  base::Optional<autofill::PasswordForm> password_form_maybe_submitted_;
   // Records whether SameDocumentNavigation() gets called.
   bool called_same_document_navigation_ = false;
-  // Records data received via SameDocumentNavigation() call.
-  base::Optional<autofill::PasswordForm>
-      password_form_same_document_navigation_;
   // Records whether PasswordFormsParsed() gets called.
   bool called_password_forms_parsed_ = false;
   // Records if the list received via PasswordFormsParsed() call was empty.
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
index 18855703..cd1b90d 100644
--- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -297,13 +297,6 @@
     password_autofill_agent_->FillPasswordForm(fill_data);
   }
 
-  // Simulates the show initial password account suggestions message being sent
-  // to the renderer.
-  void SimulateOnShowInitialPasswordAccountSuggestions(
-      const PasswordFormFillData& fill_data) {
-    autofill_agent_->ShowInitialPasswordAccountSuggestions(fill_data);
-  }
-
   void SendVisiblePasswordForms() {
     static_cast<content::RenderFrameObserver*>(password_autofill_agent_)
         ->DidFinishLoad();
@@ -647,7 +640,8 @@
   void ExpectFieldPropertiesMasks(
       PasswordFormSourceType expected_type,
       const std::map<base::string16, FieldPropertiesMask>&
-          expected_properties_masks) {
+          expected_properties_masks,
+      autofill::mojom::SubmissionIndicatorEvent expected_submission_event) {
     base::RunLoop().RunUntilIdle();
     autofill::PasswordForm form;
     if (expected_type == PasswordFormSubmitted) {
@@ -657,9 +651,11 @@
     } else {
       ASSERT_EQ(PasswordFormSameDocumentNavigation, expected_type);
       ASSERT_TRUE(fake_driver_.called_same_document_navigation());
-      ASSERT_TRUE(static_cast<bool>(
-          fake_driver_.password_form_same_document_navigation()));
-      form = *(fake_driver_.password_form_same_document_navigation());
+      ASSERT_TRUE(
+          static_cast<bool>(fake_driver_.password_form_maybe_submitted()));
+      form = *(fake_driver_.password_form_maybe_submitted());
+      EXPECT_EQ(expected_submission_event, form.submission_event);
+      EXPECT_EQ(expected_submission_event, form.form_data.submission_event);
     }
 
     size_t unchecked_masks = expected_properties_masks.size();
@@ -682,10 +678,10 @@
       SubmissionIndicatorEvent event) {
     base::RunLoop().RunUntilIdle();
     ASSERT_TRUE(fake_driver_.called_same_document_navigation());
-    ASSERT_TRUE(static_cast<bool>(
-        fake_driver_.password_form_same_document_navigation()));
+    ASSERT_TRUE(
+        static_cast<bool>(fake_driver_.password_form_maybe_submitted()));
     const autofill::PasswordForm& form =
-        *(fake_driver_.password_form_same_document_navigation());
+        *(fake_driver_.password_form_maybe_submitted());
     EXPECT_EQ(ASCIIToUTF16(username_value), form.username_value);
     EXPECT_EQ(ASCIIToUTF16(password_value), form.password_value);
     EXPECT_EQ(ASCIIToUTF16(new_password_value), form.new_password_value);
@@ -1874,61 +1870,6 @@
 }
 
 // Tests that there is an autosuggestion from the password manager when the
-// user clicks on the password field when FillOnAccountSelect is enabled.
-TEST_F(PasswordAutofillAgentTest,
-       FillOnAccountSelectOnlyNoCredentialsOnPasswordClick) {
-  SetFillOnAccountSelect();
-
-  // Simulate the browser sending back the login info.
-  SimulateOnShowInitialPasswordAccountSuggestions(fill_data_);
-
-  // Clear the text fields to start fresh.
-  ClearUsernameAndPasswordFields();
-
-  // Call SimulateElementClick() to produce a user gesture on the page so
-  // autofill will actually fill.
-  SimulateElementClick(kUsernameName);
-
-  // Simulate a user clicking on the password element. This should produce no
-  // message.
-  fake_driver_.reset_show_pw_suggestions();
-  autofill_agent_->FormControlElementClicked(password_element_, false);
-  EXPECT_TRUE(GetCalledShowPasswordSuggestions());
-}
-
-// Tests the autosuggestions that are given when a password element is clicked,
-// the username element is not editable, and FillOnAccountSelect is enabled.
-// Specifically, tests when the user clicks on the password element after page
-// load, and the corresponding username element is readonly (and thus
-// uneditable), that the credentials for the already-filled username are
-// suggested.
-TEST_F(PasswordAutofillAgentTest,
-       FillOnAccountSelectOnlyCredentialsOnPasswordClick) {
-  SetFillOnAccountSelect();
-
-  // Simulate the browser sending back the login info.
-  SimulateOnShowInitialPasswordAccountSuggestions(fill_data_);
-
-  // Clear the text fields to start fresh.
-  ClearUsernameAndPasswordFields();
-
-  // Simulate the page loading with a prefilled username element that is
-  // uneditable.
-  username_element_.SetValue("alicia");
-  SetElementReadOnly(username_element_, true);
-
-  // Call SimulateElementClick() to produce a user gesture on the page so
-  // autofill will actually fill.
-  SimulateElementClick(kUsernameName);
-
-  // Simulate a user clicking on the password element. This should produce a
-  // dropdown with suggestion of all available usernames and so username
-  // filter will be the empty string.
-  autofill_agent_->FormControlElementClicked(password_element_, false);
-  CheckSuggestions("", false);
-}
-
-// Tests that there is an autosuggestion from the password manager when the
 // user clicks on the password field.
 TEST_F(PasswordAutofillAgentTest, NoCredentialsOnPasswordClick) {
   // Simulate the browser sending back the login info.
@@ -2124,7 +2065,8 @@
   expected_properties_masks[ASCIIToUTF16("password")] =
       FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::HAD_FOCUS;
 
-  ExpectFieldPropertiesMasks(PasswordFormSubmitted, expected_properties_masks);
+  ExpectFieldPropertiesMasks(PasswordFormSubmitted, expected_properties_masks,
+                             SubmissionIndicatorEvent::HTML_FORM_SUBMISSION);
 }
 
 TEST_F(PasswordAutofillAgentTest,
@@ -2151,7 +2093,8 @@
       FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::HAD_FOCUS;
 
   ExpectFieldPropertiesMasks(PasswordFormSameDocumentNavigation,
-                             expected_properties_masks);
+                             expected_properties_masks,
+                             SubmissionIndicatorEvent::XHR_SUCCEEDED);
 }
 
 TEST_F(PasswordAutofillAgentTest,
@@ -2180,7 +2123,8 @@
       FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::HAD_FOCUS;
 
   ExpectFieldPropertiesMasks(PasswordFormSameDocumentNavigation,
-                             expected_properties_masks);
+                             expected_properties_masks,
+                             SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
 }
 
 // The username/password is autofilled by password manager then just before
@@ -2266,49 +2210,6 @@
   ExpectFormSubmittedWithUsernameAndPasswords("foo.smith", "random", "");
 }
 
-TEST_F(PasswordAutofillAgentTest, FillOnAccountSelectOnly) {
-  SetFillOnAccountSelect();
-
-  ClearUsernameAndPasswordFields();
-
-  // Simulate the browser sending back the login info for an initial page load.
-  SimulateOnShowInitialPasswordAccountSuggestions(fill_data_);
-
-  CheckTextFieldsSuggestedState(std::string(), false, std::string(), false);
-  CheckSuggestions(std::string(), true);
-}
-
-TEST_F(PasswordAutofillAgentTest, FillOnAccountSelectOnlyReadonlyUsername) {
-  SetFillOnAccountSelect();
-
-  ClearUsernameAndPasswordFields();
-
-  username_element_.SetValue("alice");
-  SetElementReadOnly(username_element_, true);
-
-  // Simulate the browser sending back the login info for an initial page load.
-  SimulateOnShowInitialPasswordAccountSuggestions(fill_data_);
-
-  CheckUsernameDOMStatePasswordSuggestedState(std::string("alice"), false,
-                                              std::string(), false);
-}
-
-TEST_F(PasswordAutofillAgentTest,
-       FillOnAccountSelectOnlyReadonlyNotPreferredUsername) {
-  SetFillOnAccountSelect();
-
-  ClearUsernameAndPasswordFields();
-
-  username_element_.SetValue("Carol");
-  SetElementReadOnly(username_element_, true);
-
-  // Simulate the browser sending back the login info for an initial page load.
-  SimulateOnShowInitialPasswordAccountSuggestions(fill_data_);
-
-  CheckUsernameDOMStatePasswordSuggestedState(std::string("Carol"), false,
-                                              std::string(), false);
-}
-
 // If credentials contain username+password but the form contains only a
 // password field, we don't autofill on page load.
 TEST_F(PasswordAutofillAgentTest, DontFillFormWithNoUsername) {
@@ -2323,27 +2224,6 @@
   CheckFirstFillingResult(FillingResult::kFoundNoPasswordForUsername);
 }
 
-TEST_F(PasswordAutofillAgentTest, FillOnAccountSelectOnlyNoUsername) {
-  SetFillOnAccountSelect();
-
-  // Load a form with no username and update test data.
-  LoadHTML(kVisibleFormWithNoUsernameHTML);
-  UpdateOnlyPasswordElement();
-  fill_data_.username_field = FormFieldData();
-  UpdateOriginForHTML(kVisibleFormWithNoUsernameHTML);
-  fill_data_.additional_logins.clear();
-
-  password_element_.SetValue("");
-  password_element_.SetAutofillState(WebAutofillState::kNotFilled);
-
-  // Simulate the browser sending back the login info for an initial page load.
-  SimulateOnShowInitialPasswordAccountSuggestions(fill_data_);
-
-  EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
-  EXPECT_FALSE(password_element_.IsAutofilled());
-  CheckSuggestions(std::string(), false);
-}
-
 TEST_F(PasswordAutofillAgentTest, ShowPopupOnEmptyPasswordField) {
   // Load a form with no username and update test data.
   LoadHTML(kVisibleFormWithNoUsernameHTML);
diff --git a/chrome/service/cloud_print/cdd_conversion_win.cc b/chrome/service/cloud_print/cdd_conversion_win.cc
index 0fd1c0d..a9f39295 100644
--- a/chrome/service/cloud_print/cdd_conversion_win.cc
+++ b/chrome/service/cloud_print/cdd_conversion_win.cc
@@ -11,6 +11,9 @@
 #include "components/cloud_devices/common/printer_description.h"
 #include "printing/backend/win_helper.h"
 
+using cloud_devices::printer::ColorType;
+using cloud_devices::printer::DuplexType;
+
 namespace cloud_print {
 
 bool IsValidCjt(const std::string& print_ticket_data) {
@@ -27,13 +30,12 @@
   if (!description.InitFromString(print_ticket))
     return dev_mode;
 
-  using namespace cloud_devices::printer;
   printing::ScopedPrinterHandle printer;
   if (!printer.OpenPrinterWithName(printer_name.c_str()))
     return dev_mode;
 
   {
-    ColorTicketItem color;
+    cloud_devices::printer::ColorTicketItem color;
     if (color.LoadFrom(description)) {
       bool is_color = color.value().type == ColorType::STANDARD_COLOR;
       dev_mode = printing::CreateDevModeWithColor(printer.Get(), printer_name,
@@ -46,21 +48,22 @@
   if (!dev_mode)
     return dev_mode;
 
-  ColorTicketItem color;
-  DuplexTicketItem duplex;
-  OrientationTicketItem orientation;
-  MarginsTicketItem margins;
-  DpiTicketItem dpi;
-  FitToPageTicketItem fit_to_page;
-  MediaTicketItem media;
-  CopiesTicketItem copies;
-  PageRangeTicketItem page_range;
-  CollateTicketItem collate;
-  ReverseTicketItem reverse;
+  cloud_devices::printer::ColorTicketItem color;
+  cloud_devices::printer::DuplexTicketItem duplex;
+  cloud_devices::printer::OrientationTicketItem orientation;
+  cloud_devices::printer::MarginsTicketItem margins;
+  cloud_devices::printer::DpiTicketItem dpi;
+  cloud_devices::printer::FitToPageTicketItem fit_to_page;
+  cloud_devices::printer::MediaTicketItem media;
+  cloud_devices::printer::CopiesTicketItem copies;
+  cloud_devices::printer::PageRangeTicketItem page_range;
+  cloud_devices::printer::CollateTicketItem collate;
+  cloud_devices::printer::ReverseTicketItem reverse;
 
   if (orientation.LoadFrom(description)) {
     dev_mode->dmFields |= DM_ORIENTATION;
-    if (orientation.value() == OrientationType::LANDSCAPE) {
+    if (orientation.value() ==
+        cloud_devices::printer::OrientationType::LANDSCAPE) {
       dev_mode->dmOrientation = DMORIENT_LANDSCAPE;
     } else {
       dev_mode->dmOrientation = DMORIENT_PORTRAIT;
diff --git a/chrome/services/app_service/BUILD.gn b/chrome/services/app_service/BUILD.gn
index 7f129f27..2b249e8 100644
--- a/chrome/services/app_service/BUILD.gn
+++ b/chrome/services/app_service/BUILD.gn
@@ -4,8 +4,6 @@
 
 source_set("lib") {
   sources = [
-    "app_service.cc",
-    "app_service.h",
     "app_service_impl.cc",
     "app_service_impl.h",
   ]
@@ -13,8 +11,6 @@
   deps = [
     "//base",
     "//mojo/public/cpp/bindings",
-    "//services/preferences/public/cpp",
-    "//services/service_manager/public/cpp",
   ]
 
   public_deps = [
diff --git a/chrome/services/app_service/app_service.cc b/chrome/services/app_service/app_service.cc
deleted file mode 100644
index 623cfc2..0000000
--- a/chrome/services/app_service/app_service.cc
+++ /dev/null
@@ -1,29 +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 "chrome/services/app_service/app_service.h"
-
-#include <utility>
-
-#include "base/bind.h"
-
-namespace apps {
-
-AppService::AppService(service_manager::mojom::ServiceRequest request)
-    : service_binding_(this, std::move(request)) {}
-
-AppService::~AppService() = default;
-
-void AppService::OnStart() {
-  binder_registry_.AddInterface<apps::mojom::AppService>(base::BindRepeating(
-      &AppServiceImpl::BindReceiver, base::Unretained(&impl_)));
-}
-
-void AppService::OnBindInterface(const service_manager::BindSourceInfo& source,
-                                 const std::string& interface_name,
-                                 mojo::ScopedMessagePipeHandle interface_pipe) {
-  binder_registry_.BindInterface(interface_name, std::move(interface_pipe));
-}
-
-}  // namespace apps
diff --git a/chrome/services/app_service/app_service.h b/chrome/services/app_service/app_service.h
deleted file mode 100644
index 151c9260..0000000
--- a/chrome/services/app_service/app_service.h
+++ /dev/null
@@ -1,46 +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_SERVICES_APP_SERVICE_APP_SERVICE_H_
-#define CHROME_SERVICES_APP_SERVICE_APP_SERVICE_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "chrome/services/app_service/app_service_impl.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
-
-namespace apps {
-
-// The service (in the service_manager::Service sense) aspect of the App
-// Service. For the implementation of the apps::mojom::AppService Mojo
-// interface, see the AppServiceImpl class.
-//
-// See chrome/services/app_service/README.md.
-class AppService : public service_manager::Service {
- public:
-  explicit AppService(service_manager::mojom::ServiceRequest request);
-  ~AppService() override;
-
-  // service_manager::Service overrides.
-  void OnStart() override;
-  void OnBindInterface(const service_manager::BindSourceInfo& source,
-                       const std::string& interface_name,
-                       mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- private:
-  service_manager::ServiceBinding service_binding_;
-  service_manager::BinderRegistry binder_registry_;
-
-  AppServiceImpl impl_;
-
-  DISALLOW_COPY_AND_ASSIGN(AppService);
-};
-
-}  // namespace apps
-
-#endif  // CHROME_SERVICES_APP_SERVICE_APP_SERVICE_H_
diff --git a/chrome/services/app_service/app_service_impl.cc b/chrome/services/app_service/app_service_impl.cc
index 82aa88c..da0a26ce 100644
--- a/chrome/services/app_service/app_service_impl.cc
+++ b/chrome/services/app_service/app_service_impl.cc
@@ -8,14 +8,13 @@
 
 #include "base/bind.h"
 #include "chrome/services/app_service/public/mojom/types.mojom.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
 
 namespace {
 
 void Connect(apps::mojom::Publisher* publisher,
              apps::mojom::Subscriber* subscriber) {
-  apps::mojom::SubscriberPtr clone;
-  subscriber->Clone(mojo::MakeRequest(&clone));
+  mojo::PendingRemote<apps::mojom::Subscriber> clone;
+  subscriber->Clone(clone.InitWithNewPipeAndPassReceiver());
   // TODO: replace nullptr with a ConnectOptions.
   publisher->Connect(std::move(clone), nullptr);
 }
@@ -33,14 +32,19 @@
   receivers_.Add(this, std::move(receiver));
 }
 
+void AppServiceImpl::FlushMojoCallsForTesting() {
+  subscribers_.FlushForTesting();
+  receivers_.FlushForTesting();
+}
+
 void AppServiceImpl::RegisterPublisher(
     mojo::PendingRemote<apps::mojom::Publisher> publisher_remote,
     apps::mojom::AppType app_type) {
   mojo::Remote<apps::mojom::Publisher> publisher(std::move(publisher_remote));
   // Connect the new publisher with every registered subscriber.
-  subscribers_.ForAllPtrs([&publisher](auto* subscriber) {
-    ::Connect(publisher.get(), subscriber);
-  });
+  for (auto& subscriber : subscribers_) {
+    ::Connect(publisher.get(), subscriber.get());
+  }
 
   // Check that no previous publisher has registered for the same app_type.
   CHECK(publishers_.find(app_type) == publishers_.end());
@@ -53,9 +57,12 @@
   CHECK(result.second);
 }
 
-void AppServiceImpl::RegisterSubscriber(apps::mojom::SubscriberPtr subscriber,
-                                        apps::mojom::ConnectOptionsPtr opts) {
+void AppServiceImpl::RegisterSubscriber(
+    mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
+    apps::mojom::ConnectOptionsPtr opts) {
   // Connect the new subscriber with every registered publisher.
+  mojo::Remote<apps::mojom::Subscriber> subscriber(
+      std::move(subscriber_remote));
   for (const auto& iter : publishers_) {
     ::Connect(iter.second.get(), subscriber.get());
   }
@@ -63,7 +70,7 @@
   // TODO: store the opts somewhere.
 
   // Add the new subscriber to the set.
-  subscribers_.AddPtr(std::move(subscriber));
+  subscribers_.Add(std::move(subscriber));
 }
 
 void AppServiceImpl::LoadIcon(apps::mojom::AppType app_type,
diff --git a/chrome/services/app_service/app_service_impl.h b/chrome/services/app_service/app_service_impl.h
index 1bb7323..1049798 100644
--- a/chrome/services/app_service/app_service_impl.h
+++ b/chrome/services/app_service/app_service_impl.h
@@ -9,17 +9,15 @@
 
 #include "base/macros.h"
 #include "chrome/services/app_service/public/mojom/app_service.mojom.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
 
 namespace apps {
 
-// The implementation of the apps::mojom::AppService Mojo interface. For the
-// service (in the service_manager::Service sense) aspect of the App Service,
-// see the AppService class.
+// The implementation of the apps::mojom::AppService Mojo interface.
 //
 // See chrome/services/app_service/README.md.
 class AppServiceImpl : public apps::mojom::AppService {
@@ -29,12 +27,15 @@
 
   void BindReceiver(mojo::PendingReceiver<apps::mojom::AppService> receiver);
 
+  void FlushMojoCallsForTesting();
+
   // apps::mojom::AppService overrides.
   void RegisterPublisher(
       mojo::PendingRemote<apps::mojom::Publisher> publisher_remote,
       apps::mojom::AppType app_type) override;
-  void RegisterSubscriber(apps::mojom::SubscriberPtr subscriber,
-                          apps::mojom::ConnectOptionsPtr opts) override;
+  void RegisterSubscriber(
+      mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
+      apps::mojom::ConnectOptionsPtr opts) override;
   void LoadIcon(apps::mojom::AppType app_type,
                 const std::string& app_id,
                 apps::mojom::IconKeyPtr icon_key,
@@ -62,7 +63,7 @@
   // be able to find *the* publisher for a given apps::mojom::AppType.
   std::map<apps::mojom::AppType, mojo::Remote<apps::mojom::Publisher>>
       publishers_;
-  mojo::InterfacePtrSet<apps::mojom::Subscriber> subscribers_;
+  mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
 
   // Must come after the publisher and subscriber maps to ensure it is
   // destroyed first, closing the connection to avoid dangling callbacks.
diff --git a/chrome/services/app_service/app_service_impl_unittest.cc b/chrome/services/app_service/app_service_impl_unittest.cc
index 83cec1a..4d4f527 100644
--- a/chrome/services/app_service/app_service_impl_unittest.cc
+++ b/chrome/services/app_service/app_service_impl_unittest.cc
@@ -13,8 +13,10 @@
 #include "base/test/task_environment.h"
 #include "chrome/services/app_service/app_service_impl.h"
 #include "chrome/services/app_service/public/mojom/types.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -32,9 +34,9 @@
   }
 
   void PublishMoreApps(std::vector<std::string> app_ids) {
-    subscribers_.ForAllPtrs([this, &app_ids](auto* subscriber) {
-      CallOnApps(subscriber, app_ids);
-    });
+    for (auto& subscriber : subscribers_) {
+      CallOnApps(subscriber.get(), app_ids);
+    }
     for (const auto& app_id : app_ids) {
       known_app_ids_.push_back(app_id);
     }
@@ -43,10 +45,12 @@
   std::string load_icon_app_id;
 
  private:
-  void Connect(apps::mojom::SubscriberPtr subscriber,
+  void Connect(mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
                apps::mojom::ConnectOptionsPtr opts) override {
+    mojo::Remote<apps::mojom::Subscriber> subscriber(
+        std::move(subscriber_remote));
     CallOnApps(subscriber.get(), known_app_ids_);
-    subscribers_.AddPtr(std::move(subscriber));
+    subscribers_.Add(std::move(subscriber));
   }
 
   void LoadIcon(const std::string& app_id,
@@ -86,15 +90,15 @@
   apps::mojom::AppType app_type_;
   std::vector<std::string> known_app_ids_;
   mojo::ReceiverSet<apps::mojom::Publisher> receivers_;
-  mojo::InterfacePtrSet<apps::mojom::Subscriber> subscribers_;
+  mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
 };
 
 class FakeSubscriber : public apps::mojom::Subscriber {
  public:
   explicit FakeSubscriber(AppServiceImpl* impl) {
-    apps::mojom::SubscriberPtr ptr;
-    bindings_.AddBinding(this, mojo::MakeRequest(&ptr));
-    impl->RegisterSubscriber(std::move(ptr), nullptr);
+    mojo::PendingRemote<apps::mojom::Subscriber> remote;
+    receivers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
+    impl->RegisterSubscriber(std::move(remote), nullptr);
   }
 
   std::string AppIdsSeen() {
@@ -112,11 +116,11 @@
     }
   }
 
-  void Clone(apps::mojom::SubscriberRequest request) override {
-    bindings_.AddBinding(this, std::move(request));
+  void Clone(mojo::PendingReceiver<apps::mojom::Subscriber> receiver) override {
+    receivers_.Add(this, std::move(receiver));
   }
 
-  mojo::BindingSet<apps::mojom::Subscriber> bindings_;
+  mojo::ReceiverSet<apps::mojom::Subscriber> receivers_;
   std::set<std::string> app_ids_seen_;
 };
 
diff --git a/chrome/services/app_service/public/cpp/BUILD.gn b/chrome/services/app_service/public/cpp/BUILD.gn
index f8024d0..05b7369 100644
--- a/chrome/services/app_service/public/cpp/BUILD.gn
+++ b/chrome/services/app_service/public/cpp/BUILD.gn
@@ -41,20 +41,6 @@
   ]
 }
 
-source_set("manifest") {
-  sources = [
-    "manifest.cc",
-    "manifest.h",
-  ]
-
-  deps = [
-    "//base",
-    "//chrome/services/app_service/public/mojom",
-    "//services/preferences/public/mojom",
-    "//services/service_manager/public/cpp",
-  ]
-}
-
 source_set("intent_filter_util") {
   sources = [
     "intent_filter_util.cc",
diff --git a/chrome/services/app_service/public/cpp/OWNERS b/chrome/services/app_service/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa47..0000000
--- a/chrome/services/app_service/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chrome/services/app_service/public/cpp/manifest.cc b/chrome/services/app_service/public/cpp/manifest.cc
deleted file mode 100644
index 3b004dd9..0000000
--- a/chrome/services/app_service/public/cpp/manifest.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/services/app_service/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "chrome/services/app_service/public/mojom/app_service.mojom.h"
-#include "chrome/services/app_service/public/mojom/constants.mojom.h"
-#include "services/preferences/public/mojom/preferences.mojom.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace apps {
-
-const service_manager::Manifest& GetManifest() {
-  static base::NoDestructor<service_manager::Manifest> manifest{
-      service_manager::ManifestBuilder()
-          .WithServiceName(mojom::kServiceName)
-          .WithDisplayName("App Service")
-          .WithOptions(service_manager::ManifestOptionsBuilder()
-                           .WithSandboxType("none")
-                           .Build())
-          .ExposeCapability(
-              "app_service",
-              service_manager::Manifest::InterfaceList<mojom::AppService>())
-          .RequireCapability(prefs::mojom::kServiceName, "pref_client")
-          .Build()};
-  return *manifest;
-}
-
-}  // namespace apps
diff --git a/chrome/services/app_service/public/cpp/manifest.h b/chrome/services/app_service/public/cpp/manifest.h
deleted file mode 100644
index 201e7b4..0000000
--- a/chrome/services/app_service/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_SERVICES_APP_SERVICE_PUBLIC_CPP_MANIFEST_H_
-#define CHROME_SERVICES_APP_SERVICE_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace apps {
-
-const service_manager::Manifest& GetManifest();
-
-}  // namespace apps
-
-#endif  // CHROME_SERVICES_APP_SERVICE_PUBLIC_CPP_MANIFEST_H_
diff --git a/chrome/services/app_service/public/mojom/BUILD.gn b/chrome/services/app_service/public/mojom/BUILD.gn
index e2a080b..39e16e7 100644
--- a/chrome/services/app_service/public/mojom/BUILD.gn
+++ b/chrome/services/app_service/public/mojom/BUILD.gn
@@ -10,17 +10,10 @@
   ]
 
   public_deps = [
-    ":constants",
     ":types",
   ]
 }
 
-mojom("constants") {
-  sources = [
-    "constants.mojom",
-  ]
-}
-
 mojom("types") {
   sources = [
     "types.mojom",
diff --git a/chrome/services/app_service/public/mojom/app_service.mojom b/chrome/services/app_service/public/mojom/app_service.mojom
index 2b754c30..96422fa 100644
--- a/chrome/services/app_service/public/mojom/app_service.mojom
+++ b/chrome/services/app_service/public/mojom/app_service.mojom
@@ -14,9 +14,13 @@
 //
 // See chrome/services/app_service/README.md.
 interface AppService {
-  // App Registry methods.
+  // Called by a publisher of apps to register itself and its apps with the App
+  // Service.
   RegisterPublisher(pending_remote<Publisher> publisher, AppType app_type);
-  RegisterSubscriber(Subscriber subscriber, ConnectOptions? opts);
+
+  // Called by a consumer that wishes to know about available apps to register
+  // itself with the App Service.
+  RegisterSubscriber(pending_remote<Subscriber> subscriber, ConnectOptions? opts);
 
   // App Icon Factory methods.
   LoadIcon(
@@ -51,7 +55,7 @@
 
 interface Publisher {
   // App Registry methods.
-  Connect(Subscriber subscriber, ConnectOptions? opts);
+  Connect(pending_remote<Subscriber> subscriber, ConnectOptions? opts);
 
   // App Icon Factory methods.
   LoadIcon(
@@ -82,11 +86,11 @@
 interface Subscriber {
   OnApps(array<App> deltas);
 
-  // Binds this to the given request (message pipe endpoint), being to Mojo
+  // Binds this to the given receiver (message pipe endpoint), being to Mojo
   // interfaces what POSIX's dup is to file descriptors.
   //
   // See https://groups.google.com/a/chromium.org/d/msg/chromium-mojo/nFhBzGsb5Pg/V7t_8kNRAgAJ
-  Clone(Subscriber& request);
+  Clone(pending_receiver<Subscriber> receiver);
 };
 
 struct ConnectOptions {
diff --git a/chrome/services/app_service/public/mojom/constants.mojom b/chrome/services/app_service/public/mojom/constants.mojom
deleted file mode 100644
index 388c17b..0000000
--- a/chrome/services/app_service/public/mojom/constants.mojom
+++ /dev/null
@@ -1,7 +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.
-
-module apps.mojom;
-
-const string kServiceName = "apps";
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebApkInfoBuilder.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebApkInfoBuilder.java
index 1daa67c..73a76f1a 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebApkInfoBuilder.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebApkInfoBuilder.java
@@ -22,6 +22,7 @@
     private String mScope;
     private @WebDisplayMode int mDisplayMode = WebDisplayMode.STANDALONE;
     private String mManifestUrl;
+    private int mWebApkVersionCode;
 
     public WebApkInfoBuilder(String webApkPackageName, String url) {
         mWebApkPackageName = webApkPackageName;
@@ -40,6 +41,10 @@
         mManifestUrl = manifestUrl;
     }
 
+    public void setWebApkVersionCode(int versionCode) {
+        mWebApkVersionCode = versionCode;
+    }
+
     /**
      * Builds {@link WebApkInfo} object using options that have been set.
      */
@@ -53,6 +58,6 @@
                 WebApkDistributor.BROWSER,
                 new HashMap<String, String>() /* iconUrlToMurmur2HashMap */, null,
                 false /* forceNavigation */, false /* isSplashProvidedByWebApk */, null,
-                1 /* webApkVersionCode */);
+                mWebApkVersionCode);
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebappTestHelper.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebappTestHelper.java
index b292e72..647d9a7 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebappTestHelper.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebappTestHelper.java
@@ -7,6 +7,7 @@
 import android.content.Intent;
 
 import org.chromium.chrome.browser.ShortcutHelper;
+import org.chromium.chrome.browser.webapps.WebappInfo;
 
 /** Helper class for webapp tests. */
 public class WebappTestHelper {
@@ -19,4 +20,8 @@
         intent.putExtra(ShortcutHelper.EXTRA_URL, url);
         return intent;
     }
+
+    public static WebappInfo createWebappInfo(String id, String url) {
+        return WebappInfo.create(createMinimalWebappIntent(id, url));
+    }
 }
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 54d5a8b..6f2e236 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -141,11 +141,6 @@
 #include "extensions/browser/extension_system.h"
 #endif
 
-#if !defined(OS_ANDROID)
-#include "chrome/services/app_service/app_service.h"
-#include "chrome/services/app_service/public/mojom/constants.mojom.h"
-#endif
-
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/arc/arc_service_launcher.h"
 #include "chrome/browser/chromeos/net/delay_network_call.h"
@@ -1059,18 +1054,6 @@
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(closure));
 }
 
-std::unique_ptr<service_manager::Service> TestingProfile::HandleServiceRequest(
-    const std::string& service_name,
-    service_manager::mojom::ServiceRequest request) {
-#if !defined(OS_ANDROID)
-  if (service_name == apps::mojom::kServiceName) {
-    return std::make_unique<apps::AppService>(std::move(request));
-  }
-#endif  // !defined(OS_ANDROID)
-
-  return nullptr;
-}
-
 bool TestingProfile::WasCreatedByVersionOrLater(const std::string& version) {
   return true;
 }
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index f73f0e90..42546b0 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -51,10 +51,6 @@
 class UserCloudPolicyManager;
 }  // namespace policy
 
-namespace service_manager {
-class Service;
-}
-
 namespace storage {
 class SpecialStoragePolicy;
 }
@@ -300,9 +296,6 @@
       std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
       std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
       base::OnceClosure closure) override;
-  std::unique_ptr<service_manager::Service> HandleServiceRequest(
-      const std::string& service_name,
-      service_manager::mojom::ServiceRequest request) override;
 
   TestingProfile* AsTestingProfile() override;
 
diff --git a/chrome/test/base/tracing.cc b/chrome/test/base/tracing.cc
index a797d0b..1149b30 100644
--- a/chrome/test/base/tracing.cc
+++ b/chrome/test/base/tracing.cc
@@ -71,8 +71,6 @@
 
   bool EndTracing(std::string* json_trace_output) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    using namespace base::debug;
-
     if (!content::TracingController::GetInstance()->StopTracing(
             new StringTraceEndpoint(
                 json_trace_output,
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index a5f1a416..4475875 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -4051,6 +4051,9 @@
   "DeviceLoginScreenInputMethods" : {
   },
 
+  "DeviceLoginScreenSystemInfoEnforced" : {
+  },
+
   "UptimeLimit": {
   },
 
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/app_management_page_tests.js b/chrome/test/data/webui/settings/chromeos/app_management/app_management_page_tests.js
index 61dbf8fd..3277f2e 100644
--- a/chrome/test/data/webui/settings/chromeos/app_management/app_management_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/app_management/app_management_page_tests.js
@@ -20,18 +20,32 @@
         1;  // Ignore the dom-repeat element.
   }
 
+  /** @return {Element} */
+  function getNoAppsFoundLabel() {
+    return appManagementPage.$$('app-management-main-view')
+        .$$('#no-apps-label');
+  }
+
+  /**
+   * @param {Element} element
+   * @return {boolean}
+   */
+  function isElementShown(element) {
+    if (!element) {
+      return false;
+    }
+    if (element.style.display === 'none') {
+      return false;
+    }
+    return true;
+  }
+
   setup(async () => {
     fakeHandler = setupFakeHandler();
     store = replaceStore();
-
     appManagementPage = document.createElement('settings-app-management-page');
     assertTrue(!!appManagementPage);
     replaceBody(appManagementPage);
-
-    // TODO: enable when dom-switch is added.
-    // await appManagementPage.$$('app-management-dom-switch')
-    // .firstRenderForTesting_.promise;
-    // await test_util.flushTasks();
   });
 
   test('loads', async () => {
@@ -40,35 +54,48 @@
         await app_management.BrowserProxy.getInstance().handler.getApps();
   });
 
-  test('App list renders on page change', () => {
-    const appList = getAppList();
-    let numApps = 0;
+  test('App list renders on page change', async () => {
+    await fakeHandler.addApp();
+    expectEquals(1, getAppListChildren());
+    await fakeHandler.addApp();
+    expectEquals(2, getAppListChildren());
+  });
 
-    fakeHandler.addApp()
-        .then(() => {
-          numApps = 1;
-          expectEquals(numApps, getAppListChildren());
+  test('No Apps Found Label', async () => {
+    expectEquals(0, getAppListChildren());
+    expectTrue(isElementShown(getNoAppsFoundLabel()));
 
-          // TODO(jshikaram): Re-enable once dom-switch works.
-          // // Click app to go to detail page.
-          // appList.querySelector('app-management-app-item').click();
-          // return test_util.flushTasks();
-        })
-        .then(() => {
-          return fakeHandler.addApp();
-        })
-        .then(() => {
-          numApps++;
+    const app = await fakeHandler.addApp();
+    expectEquals(1, getAppListChildren());
+    expectFalse(isElementShown(getNoAppsFoundLabel()));
 
-          // TODO(jshikaram): Re-enable once dom-switch works.
-          // // Click back button to go to main page.
-          // app.$$('app-management-pwa-permission-view')
-          //     .$$('app-management-permission-view-header')
-          //     .$$('#backButton')
-          //     .click();
+    fakeHandler.uninstall(app.id);
+    await test_util.flushTasks();
+    expectEquals(0, getAppListChildren());
+    expectTrue(isElementShown(getNoAppsFoundLabel()));
+  });
 
-          test_util.flushTasks();
-          expectEquals(numApps, getAppListChildren());
-        });
+  test('App list filters when searching', async () => {
+    await fakeHandler.addApp(null, {title: 'slides'});
+    await fakeHandler.addApp(null, {title: 'calculator'});
+    const sheets = await fakeHandler.addApp(null, {title: 'sheets'});
+    expectEquals(3, getAppListChildren());
+
+    appManagementPage.searchTerm = 's';
+    await test_util.flushTasks();
+    expectEquals(2, getAppListChildren());
+
+    fakeHandler.uninstall(sheets.id);
+    await test_util.flushTasks();
+    expectEquals(1, getAppListChildren());
+
+    appManagementPage.searchTerm = 'ss';
+    await test_util.flushTasks();
+    expectEquals(0, getAppListChildren());
+    expectTrue(isElementShown(getNoAppsFoundLabel()));
+
+    appManagementPage.searchTerm = '';
+    await test_util.flushTasks();
+    expectEquals(2, getAppListChildren());
   });
 });
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/reducers_test.js b/chrome/test/data/webui/settings/chromeos/app_management/reducers_test.js
index 9ba3f21..6cb1518 100644
--- a/chrome/test/data/webui/settings/chromeos/app_management/reducers_test.js
+++ b/chrome/test/data/webui/settings/chromeos/app_management/reducers_test.js
@@ -137,32 +137,6 @@
   });
 });
 
-suite('search state', function() {
-  let state;
-
-  setup(function() {
-    state = app_management.util.createInitialState([
-      createApp('1'),
-      createApp('2'),
-    ]);
-  });
-
-  test('state updates when search starts', function() {
-    // State updates when a search term has been typed in.
-    let action = app_management.actions.setSearchTerm('searchTerm');
-    state = app_management.reduceAction(state, action);
-
-    assertEquals('searchTerm', state.search.term);
-
-    // Search disappears when there is no term entered.
-    action = app_management.actions.clearSearch();
-    state = app_management.reduceAction(state, action);
-    assertEquals(PageType.MAIN, state.currentPage.pageType);
-
-    assertEquals(null, state.search.term);
-  });
-});
-
 suite('notifications state', function() {
   let state;
 
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index b6de9a7..8a138ac 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -72,6 +72,12 @@
 const base::Feature kCryptAuthV2Enrollment{"CryptAuthV2Enrollment",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Disables "Office Editing for Docs, Sheets & Slides" component app so handlers
+// won't be registered, making it possible to install another version for
+// testing.
+const base::Feature kDisableOfficeEditingComponentApp{
+    "DisableOfficeEditingComponentApp", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables or disables Discover Application on Chrome OS.
 // If enabled, Discover App will be shown in launcher.
 const base::Feature kDiscoverApp{"DiscoverApp",
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 8fd0609..a55de0d 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -41,6 +41,8 @@
 extern const base::Feature kCrostiniWebUIInstaller;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kCryptAuthV2Enrollment;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kDisableOfficeEditingComponentApp;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kDiscoverApp;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kDriveFs;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
diff --git a/chromeos/dbus/shill/fake_shill_device_client.cc b/chromeos/dbus/shill/fake_shill_device_client.cc
index 3ad7ddb..a364be4 100644
--- a/chromeos/dbus/shill/fake_shill_device_client.cc
+++ b/chromeos/dbus/shill/fake_shill_device_client.cc
@@ -399,6 +399,33 @@
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
 }
 
+void FakeShillDeviceClient::SetUsbEthernetMacAddressSource(
+    const dbus::ObjectPath& device_path,
+    const std::string& source,
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+  if (!stub_devices_.HasKey(device_path.value())) {
+    PostNotFoundError(error_callback);
+    return;
+  }
+
+  const auto error_name_iter =
+      set_usb_ethernet_mac_address_source_error_names_.find(
+          device_path.value());
+  if (error_name_iter !=
+          set_usb_ethernet_mac_address_source_error_names_.end() &&
+      !error_name_iter->first.empty()) {
+    PostError(error_name_iter->second, error_callback);
+    return;
+  }
+
+  base::Value* properties = GetDeviceProperties(device_path.value());
+  properties->SetKey(shill::kUsbEthernetMacAddressSourceProperty,
+                     base::Value(source));
+
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+}
+
 ShillDeviceClient::TestInterface* FakeShillDeviceClient::GetTestInterface() {
   return this;
 }
@@ -515,6 +542,12 @@
                      shill::kFoundNetworksProperty));
 }
 
+void FakeShillDeviceClient::SetUsbEthernetMacAddressSourceError(
+    const std::string& device_path,
+    const std::string& error_name) {
+  set_usb_ethernet_mac_address_source_error_names_[device_path] = error_name;
+}
+
 // Private Methods -------------------------------------------------------------
 
 FakeShillDeviceClient::SimLockStatus FakeShillDeviceClient::GetSimLockStatus(
diff --git a/chromeos/dbus/shill/fake_shill_device_client.h b/chromeos/dbus/shill/fake_shill_device_client.h
index 331bc79..0f557da 100644
--- a/chromeos/dbus/shill/fake_shill_device_client.h
+++ b/chromeos/dbus/shill/fake_shill_device_client.h
@@ -95,6 +95,11 @@
       const dbus::ObjectPath& device_path,
       const base::Closure& callback,
       const ErrorCallback& error_callback) override;
+  void SetUsbEthernetMacAddressSource(
+      const dbus::ObjectPath& device_path,
+      const std::string& source,
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) override;
 
   ShillDeviceClient::TestInterface* GetTestInterface() override;
 
@@ -113,6 +118,9 @@
   void SetTDLSState(const std::string& state) override;
   void SetSimLocked(const std::string& device_path, bool locked) override;
   void AddCellularFoundNetwork(const std::string& device_path) override;
+  void SetUsbEthernetMacAddressSourceError(
+      const std::string& device_path,
+      const std::string& error_name) override;
 
   static const char kSimPuk[];
   static const char kDefaultSimPin[];
@@ -180,6 +188,12 @@
   // Current SIM PIN per device path.
   std::map<std::string, std::string> sim_pin_;
 
+  // Error names for SetUsbEthernetMacAddressSource error callback for each
+  // device. Error callback must not be called if error name is not present or
+  // empty.
+  std::map<std::string, std::string>
+      set_usb_ethernet_mac_address_source_error_names_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<FakeShillDeviceClient> weak_ptr_factory_{this};
diff --git a/chromeos/dbus/shill/shill_device_client.cc b/chromeos/dbus/shill/shill_device_client.cc
index e1eb066..f836c87b 100644
--- a/chromeos/dbus/shill/shill_device_client.cc
+++ b/chromeos/dbus/shill/shill_device_client.cc
@@ -260,6 +260,21 @@
                                           error_callback);
   }
 
+  void SetUsbEthernetMacAddressSource(
+      const dbus::ObjectPath& device_path,
+      const std::string& source,
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) override {
+    dbus::MethodCall method_call(
+        shill::kFlimflamDeviceInterface,
+        shill::kSetUsbEthernetMacAddressSourceFunction);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendString(source);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
+  }
+
   TestInterface* GetTestInterface() override { return nullptr; }
 
  private:
diff --git a/chromeos/dbus/shill/shill_device_client.h b/chromeos/dbus/shill/shill_device_client.h
index d5c6aa8..fcf5339 100644
--- a/chromeos/dbus/shill/shill_device_client.h
+++ b/chromeos/dbus/shill/shill_device_client.h
@@ -62,6 +62,11 @@
     virtual void SetSimLocked(const std::string& device_path, bool enabled) = 0;
     // Adds a new entry to Cellular.FoundNetworks.
     virtual void AddCellularFoundNetwork(const std::string& device_path) = 0;
+    // Sets error for SetUsbEthernetMacAddressSourceError error callback. Error
+    // callback must be called only if |error_name| is not empty.
+    virtual void SetUsbEthernetMacAddressSourceError(
+        const std::string& device_path,
+        const std::string& error_name) = 0;
 
    protected:
     virtual ~TestInterface() {}
@@ -202,6 +207,15 @@
       const base::Closure& callback,
       const ErrorCallback& error_callback) = 0;
 
+  // Set MAC address source for USB Ethernet adapter. |source| corresponds to
+  // "USB Ethernet MAC address sources." in
+  // third_party/cros_system_api/dbus/shill/dbus-constants.h.
+  virtual void SetUsbEthernetMacAddressSource(
+      const dbus::ObjectPath& device_path,
+      const std::string& source,
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) = 0;
+
   // Returns an interface for testing (stub only), or returns null.
   virtual TestInterface* GetTestInterface() = 0;
 
diff --git a/chromeos/network/device_state.cc b/chromeos/network/device_state.cc
index 53727c60..936b2d2b 100644
--- a/chromeos/network/device_state.cc
+++ b/chromeos/network/device_state.cc
@@ -110,6 +110,10 @@
     // calls to IPConfigPropertiesChanged.
     ip_configs_.Clear();
     return false;  // No actual state change.
+  } else if (key == shill::kLinkUpProperty) {
+    return GetBooleanValue(key, value, &link_up_);
+  } else if (key == shill::kDeviceBusTypeProperty) {
+    return GetStringValue(key, value, &device_bus_type_);
   }
   return false;
 }
diff --git a/chromeos/network/device_state.h b/chromeos/network/device_state.h
index a97dc91..df3a4f89 100644
--- a/chromeos/network/device_state.h
+++ b/chromeos/network/device_state.h
@@ -64,6 +64,8 @@
   bool eap_authentication_completed() const {
     return eap_authentication_completed_;
   }
+  bool link_up() const { return link_up_; }
+  const std::string& device_bus_type() const { return device_bus_type_; }
 
   // WiFi specific accessors
   const std::string& available_managed_network_path() const {
@@ -109,6 +111,8 @@
 
   // Ethernet specific properties
   bool eap_authentication_completed_ = false;
+  bool link_up_ = false;
+  std::string device_bus_type_;
 
   // WiFi specific properties
   std::string available_managed_network_path_;
diff --git a/chromeos/network/fake_network_device_handler.cc b/chromeos/network/fake_network_device_handler.cc
index 7ff7378..29811f3 100644
--- a/chromeos/network/fake_network_device_handler.cc
+++ b/chromeos/network/fake_network_device_handler.cc
@@ -62,6 +62,9 @@
 
 void FakeNetworkDeviceHandler::SetCellularAllowRoaming(bool allow_roaming) {}
 
+void FakeNetworkDeviceHandler::SetUsbEthernetMacAddressSource(
+    const std::string& source) {}
+
 void FakeNetworkDeviceHandler::SetWifiTDLSEnabled(
     const std::string& ip_or_mac_address,
     bool enabled,
diff --git a/chromeos/network/fake_network_device_handler.h b/chromeos/network/fake_network_device_handler.h
index 70594da..362fe06 100644
--- a/chromeos/network/fake_network_device_handler.h
+++ b/chromeos/network/fake_network_device_handler.h
@@ -74,6 +74,8 @@
 
   void SetCellularAllowRoaming(bool allow_roaming) override;
 
+  void SetUsbEthernetMacAddressSource(const std::string& source) override;
+
   void SetWifiTDLSEnabled(
       const std::string& ip_or_mac_address,
       bool enabled,
diff --git a/chromeos/network/mock_network_device_handler.h b/chromeos/network/mock_network_device_handler.h
index 996cbe6..9689a09a 100644
--- a/chromeos/network/mock_network_device_handler.h
+++ b/chromeos/network/mock_network_device_handler.h
@@ -80,6 +80,9 @@
 
   MOCK_METHOD1(SetMACAddressRandomizationEnabled, void(bool enabled));
 
+  MOCK_METHOD1(SetUsbEthernetMacAddressSource,
+               void(const std::string& enabled));
+
   MOCK_METHOD4(SetWifiTDLSEnabled,
                void(const std::string& ip_or_mac_address,
                     bool enabled,
diff --git a/chromeos/network/network_device_handler.h b/chromeos/network/network_device_handler.h
index 038eb40..fd7b31b 100644
--- a/chromeos/network/network_device_handler.h
+++ b/chromeos/network/network_device_handler.h
@@ -176,6 +176,10 @@
   // which become available in the future.
   virtual void SetMACAddressRandomizationEnabled(bool enabled) = 0;
 
+  // Sets up USB Ethernet MAC address source. This applies to primary enabled
+  // USB Ethernet device.
+  virtual void SetUsbEthernetMacAddressSource(const std::string& source) = 0;
+
   // Attempts to enable or disable TDLS for the specified IP or MAC address for
   // the active wifi device.
   virtual void SetWifiTDLSEnabled(
diff --git a/chromeos/network/network_device_handler_impl.cc b/chromeos/network/network_device_handler_impl.cc
index 3b23684c..bb46d0a3 100644
--- a/chromeos/network/network_device_handler_impl.cc
+++ b/chromeos/network/network_device_handler_impl.cc
@@ -259,6 +259,8 @@
 
 }  // namespace
 
+NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl() = default;
+
 NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
   if (network_state_handler_)
     network_state_handler_->RemoveObserver(this, FROM_HERE);
@@ -378,6 +380,13 @@
   ApplyMACAddressRandomizationToShill();
 }
 
+void NetworkDeviceHandlerImpl::SetUsbEthernetMacAddressSource(
+    const std::string& source) {
+  usb_ethernet_mac_address_source_ = source;
+  usb_ethernet_mac_address_source_needs_update_ = true;
+  ApplyUsbEthernetMacAddressSourceToShill();
+}
+
 void NetworkDeviceHandlerImpl::SetWifiTDLSEnabled(
     const std::string& ip_or_mac_address,
     bool enabled,
@@ -490,9 +499,13 @@
 void NetworkDeviceHandlerImpl::DeviceListChanged() {
   ApplyCellularAllowRoamingToShill();
   ApplyMACAddressRandomizationToShill();
+  ApplyUsbEthernetMacAddressSourceToShill();
 }
 
-NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl() {}
+void NetworkDeviceHandlerImpl::DevicePropertiesUpdated(
+    const DeviceState* device) {
+  ApplyUsbEthernetMacAddressSourceToShill();
+}
 
 void NetworkDeviceHandlerImpl::Init(
     NetworkStateHandler* network_state_handler) {
@@ -561,6 +574,106 @@
   }
 }
 
+void NetworkDeviceHandlerImpl::ApplyUsbEthernetMacAddressSourceToShill() {
+  const std::string new_primary_enabled_usb_ethernet_device_path =
+      FindPrimaryEnabledUsbEthernetDevicePath();
+  // Restore USB Ethernet MAC address source value to "builtin" at the old
+  // device path if primary enabled USB Ethernet device path has changed.
+  if (new_primary_enabled_usb_ethernet_device_path !=
+          primary_enabled_usb_ethernet_device_path_ &&
+      !primary_enabled_usb_ethernet_device_path_.empty()) {
+    ShillDeviceClient::Get()->SetUsbEthernetMacAddressSource(
+        dbus::ObjectPath(primary_enabled_usb_ethernet_device_path_),
+        shill::kUsbEthernetMacAddressSourceUsbAdapterMac, base::DoNothing(),
+        base::Bind(&HandleShillCallFailure,
+                   primary_enabled_usb_ethernet_device_path_,
+                   network_handler::ErrorCallback()));
+  }
+
+  // Do nothing else if device path and MAC address source have not changed.
+  if (!usb_ethernet_mac_address_source_needs_update_ &&
+      new_primary_enabled_usb_ethernet_device_path ==
+          primary_enabled_usb_ethernet_device_path_) {
+    return;
+  }
+
+  primary_enabled_usb_ethernet_device_path_ =
+      new_primary_enabled_usb_ethernet_device_path;
+  usb_ethernet_mac_address_source_needs_update_ = false;
+
+  const DeviceState* primary_enabled_usb_ethernet_device_state =
+      network_state_handler_->GetDeviceState(
+          primary_enabled_usb_ethernet_device_path_);
+
+  // Do nothing else if device path is empty or device state is nullptr.
+  if (primary_enabled_usb_ethernet_device_path_.empty() ||
+      !primary_enabled_usb_ethernet_device_state) {
+    return;
+  }
+
+  ShillDeviceClient::Get()->SetUsbEthernetMacAddressSource(
+      dbus::ObjectPath(primary_enabled_usb_ethernet_device_path_),
+      usb_ethernet_mac_address_source_, base::DoNothing(),
+      base::Bind(
+          &NetworkDeviceHandlerImpl::OnSetUsbEthernetMacAddressSourceError,
+          weak_ptr_factory_.GetWeakPtr(),
+          primary_enabled_usb_ethernet_device_path_,
+          primary_enabled_usb_ethernet_device_state->mac_address(),
+          network_handler::ErrorCallback()));
+}
+
+void NetworkDeviceHandlerImpl::OnSetUsbEthernetMacAddressSourceError(
+    const std::string& device_path,
+    const std::string& device_mac_address,
+    const network_handler::ErrorCallback& error_callback,
+    const std::string& shill_error_name,
+    const std::string& shill_error_message) {
+  mac_address_change_not_supported_.insert(device_mac_address);
+  HandleShillCallFailure(device_path, error_callback, shill_error_name,
+                         shill_error_message);
+  ApplyUsbEthernetMacAddressSourceToShill();
+}
+
+bool NetworkDeviceHandlerImpl::IsUsbEnabledDevice(
+    const DeviceState* device_state) const {
+  return device_state && device_state->link_up() &&
+         device_state->Matches(NetworkTypePattern::Ethernet()) &&
+         device_state->device_bus_type() == shill::kDeviceBusTypeUsb &&
+         mac_address_change_not_supported_.find(device_state->mac_address()) ==
+             mac_address_change_not_supported_.end();
+}
+
+std::string NetworkDeviceHandlerImpl::FindPrimaryEnabledUsbEthernetDevicePath()
+    const {
+  NetworkStateHandler::DeviceStateList device_state_list;
+  network_state_handler_->GetDeviceListByType(NetworkTypePattern::Ethernet(),
+                                              &device_state_list);
+
+  // Try to avoid situation when both PCI and USB Ethernet devices are enabled
+  // and have the same MAC address. In this situation we will change back USB
+  // Ethernet MAC address.
+  if (usb_ethernet_mac_address_source_ ==
+      shill::kUsbEthernetMacAddressSourceBuiltinAdapterMac) {
+    for (const auto* device_state : device_state_list) {
+      if (device_state && device_state->link_up() &&
+          device_state->device_bus_type() == shill::kDeviceBusTypePci) {
+        return "";
+      }
+    }
+  }
+
+  if (IsUsbEnabledDevice(network_state_handler_->GetDeviceState(
+          primary_enabled_usb_ethernet_device_path_))) {
+    return primary_enabled_usb_ethernet_device_path_;
+  }
+
+  for (const auto* device_state : device_state_list) {
+    if (IsUsbEnabledDevice(device_state))
+      return device_state->path();
+  }
+  return "";
+}
+
 void NetworkDeviceHandlerImpl::HandleMACAddressRandomization(
     const std::string& device_path,
     const base::DictionaryValue& properties) {
@@ -591,12 +704,12 @@
       network_state_handler_->GetDeviceStateByType(NetworkTypePattern::WiFi());
   if (!device_state) {
     if (error_callback.is_null())
-      return NULL;
+      return nullptr;
     std::unique_ptr<base::DictionaryValue> error_data(
         new base::DictionaryValue);
     error_data->SetString(network_handler::kErrorName, kErrorDeviceMissing);
     error_callback.Run(kErrorDeviceMissing, std::move(error_data));
-    return NULL;
+    return nullptr;
   }
 
   return device_state;
diff --git a/chromeos/network/network_device_handler_impl.h b/chromeos/network/network_device_handler_impl.h
index 36b1ef5..8e1191c3 100644
--- a/chromeos/network/network_device_handler_impl.h
+++ b/chromeos/network/network_device_handler_impl.h
@@ -5,8 +5,8 @@
 #ifndef CHROMEOS_NETWORK_NETWORK_DEVICE_HANDLER_IMPL_H_
 #define CHROMEOS_NETWORK_NETWORK_DEVICE_HANDLER_IMPL_H_
 
-#include <map>
 #include <string>
+#include <unordered_set>
 #include <vector>
 
 #include "base/callback.h"
@@ -82,6 +82,8 @@
 
   void SetMACAddressRandomizationEnabled(bool enabled) override;
 
+  void SetUsbEthernetMacAddressSource(const std::string& source) override;
+
   void SetWifiTDLSEnabled(
       const std::string& ip_or_mac_address,
       bool enabled,
@@ -119,6 +121,7 @@
 
   // NetworkStateHandlerObserver overrides
   void DeviceListChanged() override;
+  void DevicePropertiesUpdated(const DeviceState* device) override;
 
  private:
   friend class NetworkHandler;
@@ -149,6 +152,23 @@
   // devices.
   void ApplyMACAddressRandomizationToShill();
 
+  // Apply the current value of |usb_ethernet_mac_address_source_| to primary
+  // enabled USB Ethernet device.
+  void ApplyUsbEthernetMacAddressSourceToShill();
+
+  void OnSetUsbEthernetMacAddressSourceError(
+      const std::string& device_path,
+      const std::string& device_mac_address,
+      const network_handler::ErrorCallback& error_callback,
+      const std::string& shill_error_name,
+      const std::string& shill_error_message);
+
+  // Checks whether Device is enabled USB Ethernet adapter.
+  bool IsUsbEnabledDevice(const DeviceState* device_state) const;
+
+  // Returns path for primary enabled USB Ethernet device.
+  std::string FindPrimaryEnabledUsbEthernetDevicePath() const;
+
   // Sets the value of |mac_addr_randomization_supported_| based on
   // whether shill thinks it is supported on the wifi device. If it is
   // supported, also apply |mac_addr_randomization_enabled_| to the
@@ -165,6 +185,14 @@
   MACAddressRandomizationSupport mac_addr_randomization_supported_ =
       MACAddressRandomizationSupport::NOT_REQUESTED;
   bool mac_addr_randomization_enabled_ = false;
+
+  std::string usb_ethernet_mac_address_source_;
+  bool usb_ethernet_mac_address_source_needs_update_ = false;
+  std::string primary_enabled_usb_ethernet_device_path_;
+  // Set of device's MAC addresses that do not support MAC address change. Use
+  // MAC address as unique device identifier, because link name can change.
+  std::unordered_set<std::string> mac_address_change_not_supported_;
+
   base::WeakPtrFactory<NetworkDeviceHandlerImpl> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(NetworkDeviceHandlerImpl);
diff --git a/chromeos/network/network_device_handler_unittest.cc b/chromeos/network/network_device_handler_unittest.cc
index 17031b2..07d503b 100644
--- a/chromeos/network/network_device_handler_unittest.cc
+++ b/chromeos/network/network_device_handler_unittest.cc
@@ -62,8 +62,8 @@
     // Add devices after handlers have been initialized.
     ShillDeviceClient::TestInterface* device_test =
         fake_device_client_->GetTestInterface();
-    device_test->AddDevice(
-        kDefaultCellularDevicePath, shill::kTypeCellular, "cellular1");
+    device_test->AddDevice(kDefaultCellularDevicePath, shill::kTypeCellular,
+                           "cellular1");
     device_test->AddDevice(kDefaultWifiDevicePath, shill::kTypeWifi, "wifi1");
 
     base::ListValue test_ip_configs;
@@ -88,9 +88,7 @@
     result_ = error_name;
   }
 
-  void SuccessCallback() {
-    result_ = kResultSuccess;
-  }
+  void SuccessCallback() { result_ = kResultSuccess; }
 
   void PropertiesSuccessCallback(const std::string& device_path,
                                  const base::DictionaryValue& properties) {
@@ -103,6 +101,14 @@
     result_ = result;
   }
 
+  void GetDeviceProperties(const std::string& device_path,
+                           const std::string& expected_result) {
+    network_device_handler_->GetDeviceProperties(
+        device_path, properties_success_callback_, error_callback_);
+    base::RunLoop().RunUntilIdle();
+    ASSERT_EQ(expected_result, result_);
+  }
+
  protected:
   base::test::SingleThreadTaskEnvironment task_environment_;
   std::string result_;
@@ -217,6 +223,129 @@
   EXPECT_FALSE(allow_roaming);
 }
 
+TEST_F(NetworkDeviceHandlerTest, UsbEthernetMacAddressSource) {
+  ShillDeviceClient::TestInterface* device_test =
+      fake_device_client_->GetTestInterface();
+
+  constexpr char kUsbEthernetDevicePath1[] = "ubs_ethernet_device1";
+  device_test->AddDevice(kUsbEthernetDevicePath1, shill::kTypeEthernet, "eth1");
+  device_test->SetDeviceProperty(
+      kUsbEthernetDevicePath1, shill::kDeviceBusTypeProperty,
+      base::Value(shill::kDeviceBusTypeUsb), /*notify_changed=*/true);
+
+  constexpr char kUsbEthernetDevicePath2[] = "usb_ethernet_device2";
+  device_test->AddDevice(kUsbEthernetDevicePath2, shill::kTypeEthernet, "eth2");
+  device_test->SetDeviceProperty(
+      kUsbEthernetDevicePath2, shill::kDeviceBusTypeProperty,
+      base::Value(shill::kDeviceBusTypeUsb), /*notify_changed=*/true);
+  device_test->SetDeviceProperty(kUsbEthernetDevicePath2,
+                                 shill::kAddressProperty,
+                                 base::Value("abcdef123456"),
+                                 /*notify_changed=*/true);
+  device_test->SetDeviceProperty(kUsbEthernetDevicePath2,
+                                 shill::kLinkUpProperty, base::Value(true),
+                                 /*notify_changed=*/true);
+  device_test->SetUsbEthernetMacAddressSourceError(kUsbEthernetDevicePath2,
+                                                   "not_supported");
+
+  constexpr char kUsbEthernetDevicePath3[] = "usb_ethernet_device3";
+  device_test->AddDevice(kUsbEthernetDevicePath3, shill::kTypeEthernet, "eth3");
+  device_test->SetDeviceProperty(
+      kUsbEthernetDevicePath3, shill::kDeviceBusTypeProperty,
+      base::Value(shill::kDeviceBusTypeUsb), /*notify_changed=*/true);
+  device_test->SetDeviceProperty(kUsbEthernetDevicePath3,
+                                 shill::kAddressProperty,
+                                 base::Value("123456abcdef"),
+                                 /*notify_changed=*/true);
+  device_test->SetDeviceProperty(kUsbEthernetDevicePath3,
+                                 shill::kLinkUpProperty, base::Value(true),
+                                 /*notify_changed=*/true);
+
+  constexpr char kPciEthernetDevicePath[] = "pci_ethernet_device";
+  device_test->AddDevice(kPciEthernetDevicePath, shill::kTypeEthernet, "eth4");
+  device_test->SetDeviceProperty(
+      kPciEthernetDevicePath, shill::kDeviceBusTypeProperty,
+      base::Value(shill::kDeviceBusTypePci), /*notify_changed=*/true);
+
+  // Expect property change on eth3, because:
+  //   1) eth2 device is connected to the internet, but does not support MAC
+  //      address change;
+  //   2) eth3 device is connected to the internet and supports MAC address
+  //      change.
+  constexpr char kSource1[] = "some_source1";
+  network_device_handler_->SetUsbEthernetMacAddressSource(kSource1);
+  base::RunLoop().RunUntilIdle();
+  network_device_handler_->GetDeviceProperties(
+      kUsbEthernetDevicePath3, properties_success_callback_, error_callback_);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(kResultSuccess, result_);
+  std::string usb_ethernet_mac_address_source;
+  EXPECT_TRUE(properties_->GetStringWithoutPathExpansion(
+      shill::kUsbEthernetMacAddressSourceProperty,
+      &usb_ethernet_mac_address_source));
+  EXPECT_EQ(usb_ethernet_mac_address_source, kSource1);
+
+  // Expect property change on eth3, because device is connected to the
+  // internet.
+  const char* kSource2 = shill::kUsbEthernetMacAddressSourceBuiltinAdapterMac;
+  network_device_handler_->SetUsbEthernetMacAddressSource(kSource2);
+  base::RunLoop().RunUntilIdle();
+  network_device_handler_->GetDeviceProperties(
+      kUsbEthernetDevicePath3, properties_success_callback_, error_callback_);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(kResultSuccess, result_);
+  EXPECT_TRUE(properties_->GetStringWithoutPathExpansion(
+      shill::kUsbEthernetMacAddressSourceProperty,
+      &usb_ethernet_mac_address_source));
+  EXPECT_EQ(usb_ethernet_mac_address_source, kSource2);
+
+  // Expect property change back to "usb_adapter_mac" on eth3, because device
+  // is not connected to the internet.
+  device_test->SetDeviceProperty(kUsbEthernetDevicePath3,
+                                 shill::kLinkUpProperty, base::Value(false),
+                                 /*notify_changed=*/true);
+  network_device_handler_->GetDeviceProperties(
+      kUsbEthernetDevicePath3, properties_success_callback_, error_callback_);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(kResultSuccess, result_);
+  EXPECT_TRUE(properties_->GetStringWithoutPathExpansion(
+      shill::kUsbEthernetMacAddressSourceProperty,
+      &usb_ethernet_mac_address_source));
+  EXPECT_EQ(usb_ethernet_mac_address_source, "usb_adapter_mac");
+
+  // Expect property change back to "usb_adapter_mac" on eth1, because both
+  // builtin PCI eth4 and eth1 have the same MAC address and connected to the
+  // internet.
+  device_test->SetDeviceProperty(kUsbEthernetDevicePath1,
+                                 shill::kLinkUpProperty, base::Value(true),
+                                 /*notify_changed=*/true);
+  device_test->SetDeviceProperty(kPciEthernetDevicePath, shill::kLinkUpProperty,
+                                 base::Value(true),
+                                 /*notify_changed=*/true);
+  network_device_handler_->GetDeviceProperties(
+      kUsbEthernetDevicePath1, properties_success_callback_, error_callback_);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(kResultSuccess, result_);
+  EXPECT_TRUE(properties_->GetStringWithoutPathExpansion(
+      shill::kUsbEthernetMacAddressSourceProperty,
+      &usb_ethernet_mac_address_source));
+  EXPECT_EQ(usb_ethernet_mac_address_source, "usb_adapter_mac");
+
+  // Expect property change on eth1, because device is connected to the internet
+  // and builtin PCI eth4 and eth1 have different MAC addresses.
+  constexpr char kSource3[] = "some_source3";
+  network_device_handler_->SetUsbEthernetMacAddressSource(kSource3);
+  base::RunLoop().RunUntilIdle();
+  network_device_handler_->GetDeviceProperties(
+      kUsbEthernetDevicePath1, properties_success_callback_, error_callback_);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(kResultSuccess, result_);
+  EXPECT_TRUE(properties_->GetStringWithoutPathExpansion(
+      shill::kUsbEthernetMacAddressSourceProperty,
+      &usb_ethernet_mac_address_source));
+  EXPECT_EQ(usb_ethernet_mac_address_source, kSource3);
+}
+
 TEST_F(NetworkDeviceHandlerTest, SetWifiTDLSEnabled) {
   // We add a wifi device by default, initial call should succeed.
   fake_device_client_->GetTestInterface()->SetTDLSState(
@@ -296,19 +425,15 @@
 
 TEST_F(NetworkDeviceHandlerTest, RequirePin) {
   // Test that the success callback gets called.
-  network_device_handler_->RequirePin(kDefaultCellularDevicePath,
-                                      true,
-                                      kDefaultPin,
-                                      success_callback_,
+  network_device_handler_->RequirePin(kDefaultCellularDevicePath, true,
+                                      kDefaultPin, success_callback_,
                                       error_callback_);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(kResultSuccess, result_);
 
   // Test that the shill error propagates to the error callback.
-  network_device_handler_->RequirePin(kUnknownCellularDevicePath,
-                                      true,
-                                      kDefaultPin,
-                                      success_callback_,
+  network_device_handler_->RequirePin(kUnknownCellularDevicePath, true,
+                                      kDefaultPin, success_callback_,
                                       error_callback_);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(NetworkDeviceHandler::kErrorDeviceMissing, result_);
@@ -316,18 +441,14 @@
 
 TEST_F(NetworkDeviceHandlerTest, EnterPin) {
   // Test that the success callback gets called.
-  network_device_handler_->EnterPin(kDefaultCellularDevicePath,
-                                    kDefaultPin,
-                                    success_callback_,
-                                    error_callback_);
+  network_device_handler_->EnterPin(kDefaultCellularDevicePath, kDefaultPin,
+                                    success_callback_, error_callback_);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(kResultSuccess, result_);
 
   // Test that the shill error propagates to the error callback.
-  network_device_handler_->EnterPin(kUnknownCellularDevicePath,
-                                    kDefaultPin,
-                                    success_callback_,
-                                    error_callback_);
+  network_device_handler_->EnterPin(kUnknownCellularDevicePath, kDefaultPin,
+                                    success_callback_, error_callback_);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(NetworkDeviceHandler::kErrorDeviceMissing, result_);
 }
@@ -337,20 +458,14 @@
   const char kPin[] = "1234";
 
   // Test that the success callback gets called.
-  network_device_handler_->UnblockPin(kDefaultCellularDevicePath,
-                                      kPin,
-                                      kPuk,
-                                      success_callback_,
-                                      error_callback_);
+  network_device_handler_->UnblockPin(kDefaultCellularDevicePath, kPin, kPuk,
+                                      success_callback_, error_callback_);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(kResultSuccess, result_);
 
   // Test that the shill error propagates to the error callback.
-  network_device_handler_->UnblockPin(kUnknownCellularDevicePath,
-                                      kPin,
-                                      kPuk,
-                                      success_callback_,
-                                      error_callback_);
+  network_device_handler_->UnblockPin(kUnknownCellularDevicePath, kPin, kPuk,
+                                      success_callback_, error_callback_);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(NetworkDeviceHandler::kErrorDeviceMissing, result_);
 }
diff --git a/chromeos/services/assistant/platform/network_provider_impl.cc b/chromeos/services/assistant/platform/network_provider_impl.cc
index 5862878..6dc6d199 100644
--- a/chromeos/services/assistant/platform/network_provider_impl.cc
+++ b/chromeos/services/assistant/platform/network_provider_impl.cc
@@ -23,11 +23,12 @@
     : connection_status_(ConnectionStatus::UNKNOWN) {
   if (!client)
     return;
-  client->RequestNetworkConfig(mojo::MakeRequest(&cros_network_config_ptr_));
+  client->RequestNetworkConfig(
+      cros_network_config_remote_.BindNewPipeAndPassReceiver());
   network_config::mojom::CrosNetworkConfigObserverPtr observer_ptr;
   binding_.Bind(mojo::MakeRequest(&observer_ptr));
-  cros_network_config_ptr_->AddObserver(std::move(observer_ptr));
-  cros_network_config_ptr_->GetNetworkStateList(
+  cros_network_config_remote_->AddObserver(std::move(observer_ptr));
+  cros_network_config_remote_->GetNetworkStateList(
       network_config::mojom::NetworkFilter::New(
           network_config::mojom::FilterType::kActive,
           network_config::mojom::NetworkType::kAll,
diff --git a/chromeos/services/assistant/platform/network_provider_impl.h b/chromeos/services/assistant/platform/network_provider_impl.h
index 57f65c5..a463fc94 100644
--- a/chromeos/services/assistant/platform/network_provider_impl.h
+++ b/chromeos/services/assistant/platform/network_provider_impl.h
@@ -10,6 +10,7 @@
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
 #include "libassistant/shared/public/platform_net.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromeos {
 namespace assistant {
@@ -41,7 +42,8 @@
   ConnectionStatus connection_status_;
   mojo::Binding<network_config::mojom::CrosNetworkConfigObserver> binding_{
       this};
-  network_config::mojom::CrosNetworkConfigPtr cros_network_config_ptr_;
+  mojo::Remote<network_config::mojom::CrosNetworkConfig>
+      cros_network_config_remote_;
 
   DISALLOW_COPY_AND_ASSIGN(NetworkProviderImpl);
 };
diff --git a/chromeos/services/assistant/platform_api_impl.h b/chromeos/services/assistant/platform_api_impl.h
index f0c6a6d..633bcdf8 100644
--- a/chromeos/services/assistant/platform_api_impl.h
+++ b/chromeos/services/assistant/platform_api_impl.h
@@ -104,9 +104,6 @@
 
   CrasAudioHandler* const cras_audio_handler_;
 
-  chromeos::network_config::mojom::CrosNetworkConfigPtr
-      cros_network_config_ptr_;
-
   DISALLOW_COPY_AND_ASSIGN(PlatformApiImpl);
 };
 
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc
index e7d389f..a0f1a5c 100644
--- a/chromeos/services/network_config/cros_network_config.cc
+++ b/chromeos/services/network_config/cros_network_config.cc
@@ -1645,9 +1645,10 @@
   }
 }
 
-void CrosNetworkConfig::BindRequest(mojom::CrosNetworkConfigRequest request) {
-  NET_LOG(EVENT) << "CrosNetworkConfig::BindRequest()";
-  bindings_.AddBinding(this, std::move(request));
+void CrosNetworkConfig::BindReceiver(
+    mojo::PendingReceiver<mojom::CrosNetworkConfig> receiver) {
+  NET_LOG(EVENT) << "CrosNetworkConfig::BindReceiver()";
+  receivers_.Add(this, std::move(receiver));
 }
 
 void CrosNetworkConfig::AddObserver(
diff --git a/chromeos/services/network_config/cros_network_config.h b/chromeos/services/network_config/cros_network_config.h
index 723e9b7..a36d943 100644
--- a/chromeos/services/network_config/cros_network_config.h
+++ b/chromeos/services/network_config/cros_network_config.h
@@ -10,8 +10,9 @@
 #include "chromeos/network/network_certificate_handler.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 
 namespace base {
 class DictionaryValue;
@@ -44,7 +45,7 @@
       NetworkCertificateHandler* network_certificate_handler);
   ~CrosNetworkConfig() override;
 
-  void BindRequest(mojom::CrosNetworkConfigRequest request);
+  void BindReceiver(mojo::PendingReceiver<mojom::CrosNetworkConfig> receiver);
 
   // mojom::CrosNetworkConfig
   void AddObserver(mojom::CrosNetworkConfigObserverPtr observer) override;
@@ -163,7 +164,7 @@
   NetworkCertificateHandler* network_certificate_handler_;  // Unowned
 
   mojo::InterfacePtrSet<mojom::CrosNetworkConfigObserver> observers_;
-  mojo::BindingSet<mojom::CrosNetworkConfig> bindings_;
+  mojo::ReceiverSet<mojom::CrosNetworkConfig> receivers_;
 
   int callback_id_ = 1;
   base::flat_map<int, GetManagedPropertiesCallback>
diff --git a/chromeos/services/network_config/in_process_instance.cc b/chromeos/services/network_config/in_process_instance.cc
index df3a364..2b80cd7 100644
--- a/chromeos/services/network_config/in_process_instance.cc
+++ b/chromeos/services/network_config/in_process_instance.cc
@@ -38,7 +38,7 @@
   }
 
   static base::NoDestructor<CrosNetworkConfig> instance;
-  instance->BindRequest(std::move(receiver));
+  instance->BindReceiver(std::move(receiver));
 }
 
 void OverrideInProcessInstanceForTesting(
diff --git a/chromeos/services/secure_channel/channel_impl.cc b/chromeos/services/secure_channel/channel_impl.cc
index 69c518b6..33dc0ec 100644
--- a/chromeos/services/secure_channel/channel_impl.cc
+++ b/chromeos/services/secure_channel/channel_impl.cc
@@ -14,31 +14,30 @@
 const char kReasonForDisconnection[] = "Remote device disconnected.";
 }  // namespace
 
-ChannelImpl::ChannelImpl(Delegate* delegate)
-    : delegate_(delegate), binding_(this) {}
+ChannelImpl::ChannelImpl(Delegate* delegate) : delegate_(delegate) {}
 
 ChannelImpl::~ChannelImpl() = default;
 
-mojom::ChannelPtr ChannelImpl::GenerateInterfacePtr() {
-  // Only one InterfacePtr should be generated from this instance.
-  DCHECK(!binding_);
+mojo::PendingRemote<mojom::Channel> ChannelImpl::GenerateRemote() {
+  // Only one PendingRemote should be generated from this instance.
+  DCHECK(!receiver_.is_bound());
 
-  mojom::ChannelPtr interface_ptr;
-  binding_.Bind(mojo::MakeRequest(&interface_ptr));
+  mojo::PendingRemote<mojom::Channel> interface_remote =
+      receiver_.BindNewPipeAndPassRemote();
 
-  binding_.set_connection_error_handler(base::BindOnce(
+  receiver_.set_disconnect_handler(base::BindOnce(
       &ChannelImpl::OnBindingDisconnected, base::Unretained(this)));
 
-  return interface_ptr;
+  return interface_remote;
 }
 
 void ChannelImpl::HandleRemoteDeviceDisconnection() {
-  DCHECK(binding_);
+  DCHECK(receiver_.is_bound());
 
   // If the RemoteDevice disconnected, alert clients by providing them a
   // reason specific to this event.
-  binding_.CloseWithReason(mojom::Channel::kConnectionDroppedReason,
-                           kReasonForDisconnection);
+  receiver_.ResetWithReason(mojom::Channel::kConnectionDroppedReason,
+                            kReasonForDisconnection);
 }
 
 void ChannelImpl::SendMessage(const std::string& message,
diff --git a/chromeos/services/secure_channel/channel_impl.h b/chromeos/services/secure_channel/channel_impl.h
index 5f555b2..0850de9 100644
--- a/chromeos/services/secure_channel/channel_impl.h
+++ b/chromeos/services/secure_channel/channel_impl.h
@@ -11,7 +11,8 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace chromeos {
 
@@ -37,8 +38,9 @@
   explicit ChannelImpl(Delegate* delegate);
   ~ChannelImpl() override;
 
-  // Generates a ChannelPtr for this instance; can only be called once.
-  mojom::ChannelPtr GenerateInterfacePtr();
+  // Generates a mojo::PendingRemote<Channel> for this instance; can only be
+  // called once.
+  mojo::PendingRemote<mojom::Channel> GenerateRemote();
 
   // Should be called when the underlying connection to the remote device has
   // been disconnected (e.g., because the other device closed the connection or
@@ -58,7 +60,7 @@
   void OnBindingDisconnected();
 
   Delegate* delegate_;
-  mojo::Binding<mojom::Channel> binding_;
+  mojo::Receiver<mojom::Channel> receiver_{this};
 
   base::WeakPtrFactory<ChannelImpl> weak_ptr_factory_{this};
 
diff --git a/chromeos/services/secure_channel/client_connection_parameters.cc b/chromeos/services/secure_channel/client_connection_parameters.cc
index 122ab41..1baca39 100644
--- a/chromeos/services/secure_channel/client_connection_parameters.cc
+++ b/chromeos/services/secure_channel/client_connection_parameters.cc
@@ -39,13 +39,13 @@
 }
 
 void ClientConnectionParameters::SetConnectionSucceeded(
-    mojom::ChannelPtr channel,
-    mojom::MessageReceiverRequest message_receiver_request) {
+    mojo::PendingRemote<mojom::Channel> channel,
+    mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver) {
   static const std::string kFunctionName = "SetConnectionSucceeded";
   VerifyDelegateWaitingForResponse(kFunctionName);
   has_invoked_delegate_function_ = true;
   PerformSetConnectionSucceeded(std::move(channel),
-                                std::move(message_receiver_request));
+                                std::move(message_receiver_receiver));
 }
 
 bool ClientConnectionParameters::operator==(
diff --git a/chromeos/services/secure_channel/client_connection_parameters.h b/chromeos/services/secure_channel/client_connection_parameters.h
index df4c946..1824e17 100644
--- a/chromeos/services/secure_channel/client_connection_parameters.h
+++ b/chromeos/services/secure_channel/client_connection_parameters.h
@@ -12,6 +12,8 @@
 #include "base/observer_list.h"
 #include "base/unguessable_token.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace chromeos {
 
@@ -48,12 +50,12 @@
   void SetConnectionAttemptFailed(mojom::ConnectionAttemptFailureReason reason);
 
   // Alerts the client that the connection has succeeded, providing the client
-  // with a Channel and a request to bind a MessageReceiver. This function can
+  // with a Channel and a receiver to bind a MessageReceiver. This function can
   // only be called if IsActive() is true and SetConnectionAttemptFailed() has
   // not been invoked.
   void SetConnectionSucceeded(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request);
+      mojo::PendingRemote<mojom::Channel> channel,
+      mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver);
 
   bool operator==(const ClientConnectionParameters& other) const;
   bool operator<(const ClientConnectionParameters& other) const;
@@ -63,8 +65,9 @@
   virtual void PerformSetConnectionAttemptFailed(
       mojom::ConnectionAttemptFailureReason reason) = 0;
   virtual void PerformSetConnectionSucceeded(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request) = 0;
+      mojo::PendingRemote<mojom::Channel> channel,
+      mojo::PendingReceiver<mojom::MessageReceiver>
+          message_receiver_receiver) = 0;
 
   void NotifyConnectionRequestCanceled();
 
diff --git a/chromeos/services/secure_channel/client_connection_parameters_impl.cc b/chromeos/services/secure_channel/client_connection_parameters_impl.cc
index ecba951..8c16f94 100644
--- a/chromeos/services/secure_channel/client_connection_parameters_impl.cc
+++ b/chromeos/services/secure_channel/client_connection_parameters_impl.cc
@@ -66,10 +66,10 @@
 }
 
 void ClientConnectionParametersImpl::PerformSetConnectionSucceeded(
-    mojom::ChannelPtr channel,
-    mojom::MessageReceiverRequest message_receiver_request) {
+    mojo::PendingRemote<mojom::Channel> channel,
+    mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver) {
   connection_delegate_ptr_->OnConnection(std::move(channel),
-                                         std::move(message_receiver_request));
+                                         std::move(message_receiver_receiver));
 }
 
 void ClientConnectionParametersImpl::OnConnectionDelegatePtrDisconnected() {
diff --git a/chromeos/services/secure_channel/client_connection_parameters_impl.h b/chromeos/services/secure_channel/client_connection_parameters_impl.h
index e438c14..d1d45b8 100644
--- a/chromeos/services/secure_channel/client_connection_parameters_impl.h
+++ b/chromeos/services/secure_channel/client_connection_parameters_impl.h
@@ -8,6 +8,8 @@
 #include "base/macros.h"
 #include "chromeos/services/secure_channel/client_connection_parameters.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace chromeos {
 
@@ -42,8 +44,9 @@
   void PerformSetConnectionAttemptFailed(
       mojom::ConnectionAttemptFailureReason reason) override;
   void PerformSetConnectionSucceeded(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request) override;
+      mojo::PendingRemote<mojom::Channel> channel,
+      mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver)
+      override;
 
   void OnConnectionDelegatePtrDisconnected();
 
diff --git a/chromeos/services/secure_channel/client_connection_parameters_impl_unittest.cc b/chromeos/services/secure_channel/client_connection_parameters_impl_unittest.cc
index e531f34..49ae4a1 100644
--- a/chromeos/services/secure_channel/client_connection_parameters_impl_unittest.cc
+++ b/chromeos/services/secure_channel/client_connection_parameters_impl_unittest.cc
@@ -54,13 +54,13 @@
   }
 
   void CallOnConnection(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request) {
+      mojo::PendingRemote<mojom::Channel> channel,
+      mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver) {
     base::RunLoop run_loop;
     fake_connection_delegate_->set_closure_for_next_delegate_callback(
         run_loop.QuitClosure());
     client_connection_parameters_->SetConnectionSucceeded(
-        std::move(channel), std::move(message_receiver_request));
+        std::move(channel), std::move(message_receiver_receiver));
     run_loop.Run();
   }
 
@@ -107,15 +107,15 @@
 
 TEST_F(SecureChannelClientConnectionParametersImplTest, OnConnection) {
   auto fake_channel = std::make_unique<FakeChannel>();
-  mojom::MessageReceiverPtr message_receiver_ptr;
+  mojo::PendingRemote<mojom::MessageReceiver> message_receiver_remote;
 
-  CallOnConnection(fake_channel->GenerateInterfacePtr(),
-                   mojo::MakeRequest(&message_receiver_ptr));
+  CallOnConnection(fake_channel->GenerateRemote(),
+                   message_receiver_remote.InitWithNewPipeAndPassReceiver());
   VerifyStatus(false /* expected_to_be_waiting_for_response */,
                false /* expected_to_be_canceled */);
 
   EXPECT_TRUE(fake_connection_delegate()->channel());
-  EXPECT_TRUE(fake_connection_delegate()->message_receiver_request());
+  EXPECT_TRUE(fake_connection_delegate()->message_receiver_receiver());
 }
 
 TEST_F(SecureChannelClientConnectionParametersImplTest, OnConnectionFailed) {
diff --git a/chromeos/services/secure_channel/fake_channel.cc b/chromeos/services/secure_channel/fake_channel.cc
index a1a9131..bb667bc4 100644
--- a/chromeos/services/secure_channel/fake_channel.cc
+++ b/chromeos/services/secure_channel/fake_channel.cc
@@ -12,19 +12,17 @@
 const char kDisconnectionDescription[] = "Remote device disconnected.";
 }  // namespace
 
-FakeChannel::FakeChannel() : binding_(this) {}
+FakeChannel::FakeChannel() = default;
 
 FakeChannel::~FakeChannel() = default;
 
-mojom::ChannelPtr FakeChannel::GenerateInterfacePtr() {
-  mojom::ChannelPtr interface_ptr;
-  binding_.Bind(mojo::MakeRequest(&interface_ptr));
-  return interface_ptr;
+mojo::PendingRemote<mojom::Channel> FakeChannel::GenerateRemote() {
+  return receiver_.BindNewPipeAndPassRemote();
 }
 
-void FakeChannel::DisconnectGeneratedPtr() {
-  binding_.CloseWithReason(mojom::Channel::kConnectionDroppedReason,
-                           kDisconnectionDescription);
+void FakeChannel::DisconnectGeneratedRemote() {
+  receiver_.ResetWithReason(mojom::Channel::kConnectionDroppedReason,
+                            kDisconnectionDescription);
 }
 
 void FakeChannel::SendMessage(const std::string& message,
diff --git a/chromeos/services/secure_channel/fake_channel.h b/chromeos/services/secure_channel/fake_channel.h
index dab371f87..429dd46 100644
--- a/chromeos/services/secure_channel/fake_channel.h
+++ b/chromeos/services/secure_channel/fake_channel.h
@@ -11,7 +11,8 @@
 
 #include "base/macros.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace chromeos {
 
@@ -23,8 +24,8 @@
   FakeChannel();
   ~FakeChannel() override;
 
-  mojom::ChannelPtr GenerateInterfacePtr();
-  void DisconnectGeneratedPtr();
+  mojo::PendingRemote<mojom::Channel> GenerateRemote();
+  void DisconnectGeneratedRemote();
 
   void set_connection_metadata_for_next_call(
       mojom::ConnectionMetadataPtr connection_metadata_for_next_call) {
@@ -42,7 +43,7 @@
                    SendMessageCallback callback) override;
   void GetConnectionMetadata(GetConnectionMetadataCallback callback) override;
 
-  mojo::Binding<mojom::Channel> binding_;
+  mojo::Receiver<mojom::Channel> receiver_{this};
 
   std::vector<std::pair<std::string, SendMessageCallback>> sent_messages_;
   mojom::ConnectionMetadataPtr connection_metadata_for_next_call_;
diff --git a/chromeos/services/secure_channel/fake_client_connection_parameters.cc b/chromeos/services/secure_channel/fake_client_connection_parameters.cc
index 87bfb43..82da73a 100644
--- a/chromeos/services/secure_channel/fake_client_connection_parameters.cc
+++ b/chromeos/services/secure_channel/fake_client_connection_parameters.cc
@@ -36,19 +36,19 @@
 }
 
 void FakeClientConnectionParameters::PerformSetConnectionSucceeded(
-    mojom::ChannelPtr channel,
-    mojom::MessageReceiverRequest message_receiver_request) {
+    mojo::PendingRemote<mojom::Channel> channel,
+    mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver) {
   DCHECK(message_receiver_);
-  DCHECK(!message_receiver_binding_);
+  DCHECK(!message_receiver_receiver_);
 
-  channel_ = std::move(channel);
-  channel_->set_connection_error_with_reason_handler(
+  channel_.Bind(std::move(channel));
+  channel_.set_disconnect_with_reason_handler(
       base::BindOnce(&FakeClientConnectionParameters::OnChannelDisconnected,
                      weak_ptr_factory_.GetWeakPtr()));
 
-  message_receiver_binding_ =
-      std::make_unique<mojo::Binding<mojom::MessageReceiver>>(
-          message_receiver_.get(), std::move(message_receiver_request));
+  message_receiver_receiver_ =
+      std::make_unique<mojo::Receiver<mojom::MessageReceiver>>(
+          message_receiver_.get(), std::move(message_receiver_receiver));
 }
 
 void FakeClientConnectionParameters::OnChannelDisconnected(
diff --git a/chromeos/services/secure_channel/fake_client_connection_parameters.h b/chromeos/services/secure_channel/fake_client_connection_parameters.h
index 540a15e..67018a6d2 100644
--- a/chromeos/services/secure_channel/fake_client_connection_parameters.h
+++ b/chromeos/services/secure_channel/fake_client_connection_parameters.h
@@ -10,7 +10,10 @@
 #include "base/memory/weak_ptr.h"
 #include "chromeos/services/secure_channel/client_connection_parameters.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromeos {
 
@@ -32,7 +35,7 @@
     return failure_reason_;
   }
 
-  base::Optional<mojom::ChannelPtr>& channel() { return channel_; }
+  mojo::Remote<mojom::Channel>& channel() { return channel_; }
 
   void set_message_receiver(
       std::unique_ptr<mojom::MessageReceiver> message_receiver) {
@@ -50,8 +53,9 @@
   void PerformSetConnectionAttemptFailed(
       mojom::ConnectionAttemptFailureReason reason) override;
   void PerformSetConnectionSucceeded(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request) override;
+      mojo::PendingRemote<mojom::Channel> channel,
+      mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver)
+      override;
 
   void OnChannelDisconnected(uint32_t disconnection_reason,
                              const std::string& disconnection_description);
@@ -59,12 +63,12 @@
   bool has_canceled_client_request_ = false;
 
   std::unique_ptr<mojom::MessageReceiver> message_receiver_;
-  std::unique_ptr<mojo::Binding<mojom::MessageReceiver>>
-      message_receiver_binding_;
+  std::unique_ptr<mojo::Receiver<mojom::MessageReceiver>>
+      message_receiver_receiver_;
 
   base::Optional<mojom::ConnectionAttemptFailureReason> failure_reason_;
 
-  base::Optional<mojom::ChannelPtr> channel_;
+  mojo::Remote<mojom::Channel> channel_;
   uint32_t disconnection_reason_ = 0u;
 
   base::OnceCallback<void(const base::UnguessableToken&)> destructor_callback_;
diff --git a/chromeos/services/secure_channel/fake_connection_delegate.cc b/chromeos/services/secure_channel/fake_connection_delegate.cc
index cc4125d..4dfb115 100644
--- a/chromeos/services/secure_channel/fake_connection_delegate.cc
+++ b/chromeos/services/secure_channel/fake_connection_delegate.cc
@@ -34,10 +34,10 @@
 }
 
 void FakeConnectionDelegate::OnConnection(
-    mojom::ChannelPtr channel,
-    mojom::MessageReceiverRequest message_receiver_request) {
-  channel_ = std::move(channel);
-  message_receiver_request_ = std::move(message_receiver_request);
+    mojo::PendingRemote<mojom::Channel> channel,
+    mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver) {
+  channel_.Bind(std::move(channel));
+  message_receiver_receiver_ = std::move(message_receiver_receiver);
 
   if (closure_for_next_delegate_callback_)
     std::move(closure_for_next_delegate_callback_).Run();
diff --git a/chromeos/services/secure_channel/fake_connection_delegate.h b/chromeos/services/secure_channel/fake_connection_delegate.h
index 437755c..05a012e 100644
--- a/chromeos/services/secure_channel/fake_connection_delegate.h
+++ b/chromeos/services/secure_channel/fake_connection_delegate.h
@@ -8,6 +8,9 @@
 #include "base/macros.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromeos {
 
@@ -31,20 +34,20 @@
     closure_for_next_delegate_callback_ = std::move(closure);
   }
 
-  const base::Optional<mojom::ChannelPtr>& channel() const { return channel_; }
+  const mojo::Remote<mojom::Channel>& channel() const { return channel_; }
 
-  const base::Optional<mojom::MessageReceiverRequest>&
-  message_receiver_request() const {
-    return message_receiver_request_;
+  const mojo::PendingReceiver<mojom::MessageReceiver>&
+  message_receiver_receiver() const {
+    return message_receiver_receiver_;
   }
 
  private:
   // mojom::ConnectionDelegate:
   void OnConnectionAttemptFailure(
       mojom::ConnectionAttemptFailureReason reason) override;
-  void OnConnection(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request) override;
+  void OnConnection(mojo::PendingRemote<mojom::Channel> channel,
+                    mojo::PendingReceiver<mojom::MessageReceiver>
+                        message_receiver_receiver) override;
 
   void OnChannelDisconnected(uint32_t disconnection_reason,
                              const std::string& disconnection_description);
@@ -54,8 +57,8 @@
 
   base::Optional<mojom::ConnectionAttemptFailureReason>
       connection_attempt_failure_reason_;
-  base::Optional<mojom::ChannelPtr> channel_;
-  base::Optional<mojom::MessageReceiverRequest> message_receiver_request_;
+  mojo::Remote<mojom::Channel> channel_;
+  mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeConnectionDelegate);
 };
diff --git a/chromeos/services/secure_channel/public/cpp/client/client_channel_impl.cc b/chromeos/services/secure_channel/public/cpp/client/client_channel_impl.cc
index 4ddd4f7..fead7b8 100644
--- a/chromeos/services/secure_channel/public/cpp/client/client_channel_impl.cc
+++ b/chromeos/services/secure_channel/public/cpp/client/client_channel_impl.cc
@@ -32,18 +32,18 @@
 ClientChannelImpl::Factory::~Factory() = default;
 
 std::unique_ptr<ClientChannel> ClientChannelImpl::Factory::BuildInstance(
-    mojom::ChannelPtr channel,
-    mojom::MessageReceiverRequest message_receiver_request) {
+    mojo::PendingRemote<mojom::Channel> channel,
+    mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver) {
   return base::WrapUnique(new ClientChannelImpl(
-      std::move(channel), std::move(message_receiver_request)));
+      std::move(channel), std::move(message_receiver_receiver)));
 }
 
 ClientChannelImpl::ClientChannelImpl(
-    mojom::ChannelPtr channel,
-    mojom::MessageReceiverRequest message_receiver_request)
+    mojo::PendingRemote<mojom::Channel> channel,
+    mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver)
     : channel_(std::move(channel)),
-      binding_(this, std::move(message_receiver_request)) {
-  channel_.set_connection_error_with_reason_handler(
+      receiver_(this, std::move(message_receiver_receiver)) {
+  channel_.set_disconnect_with_reason_handler(
       base::BindOnce(&ClientChannelImpl::OnChannelDisconnected,
                      weak_ptr_factory_.GetWeakPtr()));
 }
@@ -81,7 +81,7 @@
   }
 
   channel_.reset();
-  binding_.Close();
+  receiver_.reset();
   NotifyDisconnected();
 }
 
diff --git a/chromeos/services/secure_channel/public/cpp/client/client_channel_impl.h b/chromeos/services/secure_channel/public/cpp/client/client_channel_impl.h
index 2a57ee7..ffd1319 100644
--- a/chromeos/services/secure_channel/public/cpp/client/client_channel_impl.h
+++ b/chromeos/services/secure_channel/public/cpp/client/client_channel_impl.h
@@ -9,7 +9,10 @@
 #include "base/memory/weak_ptr.h"
 #include "chromeos/services/secure_channel/public/cpp/client/client_channel.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromeos {
 
@@ -24,8 +27,9 @@
     static void SetFactoryForTesting(Factory* test_factory);
     virtual ~Factory();
     virtual std::unique_ptr<ClientChannel> BuildInstance(
-        mojom::ChannelPtr channel,
-        mojom::MessageReceiverRequest message_receiver_request);
+        mojo::PendingRemote<mojom::Channel> channel,
+        mojo::PendingReceiver<mojom::MessageReceiver>
+            message_receiver_receiver);
 
    private:
     static Factory* test_factory_;
@@ -36,8 +40,9 @@
  private:
   friend class SecureChannelClientChannelImplTest;
 
-  ClientChannelImpl(mojom::ChannelPtr channel,
-                    mojom::MessageReceiverRequest message_receiver_request);
+  ClientChannelImpl(
+      mojo::PendingRemote<mojom::Channel> channel,
+      mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver);
 
   // ClientChannel:
   void PerformGetConnectionMetadata(
@@ -57,8 +62,8 @@
 
   void FlushForTesting();
 
-  mojom::ChannelPtr channel_;
-  mojo::Binding<mojom::MessageReceiver> binding_;
+  mojo::Remote<mojom::Channel> channel_;
+  mojo::Receiver<mojom::MessageReceiver> receiver_;
 
   base::WeakPtrFactory<ClientChannelImpl> weak_ptr_factory_{this};
 
diff --git a/chromeos/services/secure_channel/public/cpp/client/client_channel_impl_unittest.cc b/chromeos/services/secure_channel/public/cpp/client/client_channel_impl_unittest.cc
index e6c2352f..d5e05d3 100644
--- a/chromeos/services/secure_channel/public/cpp/client/client_channel_impl_unittest.cc
+++ b/chromeos/services/secure_channel/public/cpp/client/client_channel_impl_unittest.cc
@@ -40,8 +40,8 @@
     fake_channel_ = std::make_unique<FakeChannel>();
 
     client_channel_ = ClientChannelImpl::Factory::Get()->BuildInstance(
-        fake_channel_->GenerateInterfacePtr(),
-        mojo::MakeRequest(&message_receiver_ptr_));
+        fake_channel_->GenerateRemote(),
+        message_receiver_remote_.BindNewPipeAndPassReceiver());
 
     fake_observer_ = std::make_unique<FakeClientChannelObserver>();
     client_channel_->AddObserver(fake_observer_.get());
@@ -99,7 +99,7 @@
   base::test::TaskEnvironment task_environment_;
 
   std::unique_ptr<FakeChannel> fake_channel_;
-  mojom::MessageReceiverPtr message_receiver_ptr_;
+  mojo::Remote<mojom::MessageReceiver> message_receiver_remote_;
   std::unique_ptr<FakeClientChannelObserver> fake_observer_;
 
   mojom::ConnectionMetadataPtr connection_metadata_;
@@ -159,15 +159,15 @@
 }
 
 TEST_F(SecureChannelClientChannelImplTest, TestReceiveMessage) {
-  message_receiver_ptr_->OnMessageReceived("payload");
-  message_receiver_ptr_.FlushForTesting();
+  message_receiver_remote_->OnMessageReceived("payload");
+  message_receiver_remote_.FlushForTesting();
 
   EXPECT_EQ(1u, fake_observer_->received_messages().size());
   EXPECT_EQ("payload", fake_observer_->received_messages()[0]);
 }
 
 TEST_F(SecureChannelClientChannelImplTest, TestDisconnectRemotely) {
-  fake_channel_->DisconnectGeneratedPtr();
+  fake_channel_->DisconnectGeneratedRemote();
 
   SendPendingMojoMessages();
 
diff --git a/chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.cc b/chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.cc
index d51a2d2..3f7af3c7 100644
--- a/chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.cc
+++ b/chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.cc
@@ -54,10 +54,10 @@
 }
 
 void ConnectionAttemptImpl::OnConnection(
-    mojom::ChannelPtr channel,
-    mojom::MessageReceiverRequest message_receiver_request) {
+    mojo::PendingRemote<mojom::Channel> channel,
+    mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver) {
   NotifyConnection(ClientChannelImpl::Factory::Get()->BuildInstance(
-      std::move(channel), std::move(message_receiver_request)));
+      std::move(channel), std::move(message_receiver_receiver)));
 }
 
 }  // namespace secure_channel
diff --git a/chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.h b/chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.h
index 82f83a4f1..bc55b30 100644
--- a/chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.h
+++ b/chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.h
@@ -9,6 +9,8 @@
 #include "base/memory/weak_ptr.h"
 #include "chromeos/services/secure_channel/public/cpp/client/connection_attempt.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace chromeos {
 
@@ -39,9 +41,9 @@
   // mojom::ConnectionDelegate:
   void OnConnectionAttemptFailure(
       mojom::ConnectionAttemptFailureReason reason) override;
-  void OnConnection(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request) override;
+  void OnConnection(mojo::PendingRemote<mojom::Channel> channel,
+                    mojo::PendingReceiver<mojom::MessageReceiver>
+                        message_receiver_receiver) override;
 
  private:
   mojo::Binding<mojom::ConnectionDelegate> binding_;
diff --git a/chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.cc b/chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.cc
index 235ac0f..ededaec 100644
--- a/chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.cc
+++ b/chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.cc
@@ -19,10 +19,10 @@
 }
 
 void FakeConnectionAttempt::OnConnection(
-    mojom::ChannelPtr channel,
-    mojom::MessageReceiverRequest message_receiver_request) {
+    mojo::PendingRemote<mojom::Channel> channel,
+    mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver) {
   ConnectionAttemptImpl::OnConnection(std::move(channel),
-                                      std::move(message_receiver_request));
+                                      std::move(message_receiver_receiver));
   std::move(on_connection_callback_).Run();
 }
 
diff --git a/chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.h b/chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.h
index 5b2eaf0..0423cbab 100644
--- a/chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.h
+++ b/chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.h
@@ -8,7 +8,8 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace chromeos {
 
@@ -26,9 +27,9 @@
   // ConnectionAttemptImpl:
   void OnConnectionAttemptFailure(
       mojom::ConnectionAttemptFailureReason reason) override;
-  void OnConnection(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request) override;
+  void OnConnection(mojo::PendingRemote<mojom::Channel> channel,
+                    mojo::PendingReceiver<mojom::MessageReceiver>
+                        message_receiver_receiver) override;
 
   void set_on_connection_attempt_failure_callback(base::OnceClosure callback) {
     on_connection_attempt_failure_callback_ = std::move(callback);
diff --git a/chromeos/services/secure_channel/public/cpp/client/secure_channel_client_impl_unittest.cc b/chromeos/services/secure_channel/public/cpp/client/secure_channel_client_impl_unittest.cc
index e833993..b74ba3c 100644
--- a/chromeos/services/secure_channel/public/cpp/client/secure_channel_client_impl_unittest.cc
+++ b/chromeos/services/secure_channel/public/cpp/client/secure_channel_client_impl_unittest.cc
@@ -74,8 +74,9 @@
 
   // ClientChannelImpl::Factory:
   std::unique_ptr<ClientChannel> BuildInstance(
-      mojom::ChannelPtr channel,
-      mojom::MessageReceiverRequest message_receiver_request) override {
+      mojo::PendingRemote<mojom::Channel> channel,
+      mojo::PendingReceiver<mojom::MessageReceiver> message_receiver_receiver)
+      override {
     auto client_channel = std::make_unique<FakeClientChannel>();
     last_client_channel_created_ = client_channel.get();
     return client_channel;
@@ -233,11 +234,11 @@
   fake_connection_attempt->set_on_connection_callback(run_loop.QuitClosure());
 
   auto fake_channel = std::make_unique<FakeChannel>();
-  mojom::MessageReceiverPtr message_receiver_ptr;
+  mojo::PendingRemote<mojom::MessageReceiver> message_receiver_remote;
 
   fake_secure_channel_->delegate_from_last_initiate_call()->OnConnection(
-      fake_channel->GenerateInterfacePtr(),
-      mojo::MakeRequest(&message_receiver_ptr));
+      fake_channel->GenerateRemote(),
+      message_receiver_remote.InitWithNewPipeAndPassReceiver());
 
   run_loop.Run();
 
@@ -276,11 +277,11 @@
   fake_connection_attempt->set_on_connection_callback(run_loop.QuitClosure());
 
   auto fake_channel = std::make_unique<FakeChannel>();
-  mojom::MessageReceiverPtr message_receiver_ptr;
+  mojo::PendingRemote<mojom::MessageReceiver> message_receiver_remote;
 
   fake_secure_channel_->delegate_from_last_listen_call()->OnConnection(
-      fake_channel->GenerateInterfacePtr(),
-      mojo::MakeRequest(&message_receiver_ptr));
+      fake_channel->GenerateRemote(),
+      message_receiver_remote.InitWithNewPipeAndPassReceiver());
 
   run_loop.Run();
 
@@ -317,10 +318,10 @@
   fake_connection_attempt_1->set_on_connection_callback(
       run_loop_1.QuitClosure());
   auto fake_channel_1 = std::make_unique<FakeChannel>();
-  mojom::MessageReceiverPtr message_receiver_ptr_1;
+  mojo::PendingRemote<mojom::MessageReceiver> message_receiver_remote_1;
   fake_secure_channel_->delegate_from_last_initiate_call()->OnConnection(
-      fake_channel_1->GenerateInterfacePtr(),
-      mojo::MakeRequest(&message_receiver_ptr_1));
+      fake_channel_1->GenerateRemote(),
+      message_receiver_remote_1.InitWithNewPipeAndPassReceiver());
   run_loop_1.Run();
 
   ClientChannel* client_channel_1 =
@@ -335,10 +336,10 @@
   fake_connection_attempt_2->set_on_connection_callback(
       run_loop_2.QuitClosure());
   auto fake_channel_2 = std::make_unique<FakeChannel>();
-  mojom::MessageReceiverPtr message_receiver_ptr_2;
+  mojo::PendingRemote<mojom::MessageReceiver> message_receiver_remote_2;
   fake_secure_channel_->delegate_from_last_listen_call()->OnConnection(
-      fake_channel_2->GenerateInterfacePtr(),
-      mojo::MakeRequest(&message_receiver_ptr_2));
+      fake_channel_2->GenerateRemote(),
+      message_receiver_remote_2.InitWithNewPipeAndPassReceiver());
   run_loop_2.Run();
 
   ClientChannel* client_channel_2 =
diff --git a/chromeos/services/secure_channel/public/mojom/secure_channel.mojom b/chromeos/services/secure_channel/public/mojom/secure_channel.mojom
index 8df2e04..2547cb2 100644
--- a/chromeos/services/secure_channel/public/mojom/secure_channel.mojom
+++ b/chromeos/services/secure_channel/public/mojom/secure_channel.mojom
@@ -134,7 +134,8 @@
   // |channel| to be notified when it has been invalidated due to a dropped
   // connection. Note that clients are expected to hold the reference to
   // |channel| until they are done using the connection.
-  OnConnection(Channel channel, MessageReceiver& message_receiver);
+  OnConnection(pending_remote<Channel> channel,
+               pending_receiver<MessageReceiver> message_receiver_receiver);
 };
 
 // Brokers connections between the current Chromebook and remote devices,
diff --git a/chromeos/services/secure_channel/single_client_message_proxy_impl.cc b/chromeos/services/secure_channel/single_client_message_proxy_impl.cc
index c981d33..df4aafe 100644
--- a/chromeos/services/secure_channel/single_client_message_proxy_impl.cc
+++ b/chromeos/services/secure_channel/single_client_message_proxy_impl.cc
@@ -48,8 +48,8 @@
       channel_(std::make_unique<ChannelImpl>(this /* delegate */)) {
   DCHECK(client_connection_parameters_);
   client_connection_parameters_->SetConnectionSucceeded(
-      channel_->GenerateInterfacePtr(),
-      mojo::MakeRequest(&message_receiver_ptr_));
+      channel_->GenerateRemote(),
+      message_receiver_remote_.BindNewPipeAndPassReceiver());
 }
 
 SingleClientMessageProxyImpl::~SingleClientMessageProxyImpl() = default;
@@ -65,7 +65,7 @@
   if (feature != client_connection_parameters_->feature())
     return;
 
-  message_receiver_ptr_->OnMessageReceived(payload);
+  message_receiver_remote_->OnMessageReceived(payload);
 }
 
 void SingleClientMessageProxyImpl::HandleRemoteDeviceDisconnection() {
@@ -89,8 +89,8 @@
 }
 
 void SingleClientMessageProxyImpl::FlushForTesting() {
-  DCHECK(message_receiver_ptr_);
-  message_receiver_ptr_.FlushForTesting();
+  DCHECK(message_receiver_remote_);
+  message_receiver_remote_.FlushForTesting();
 }
 
 }  // namespace secure_channel
diff --git a/chromeos/services/secure_channel/single_client_message_proxy_impl.h b/chromeos/services/secure_channel/single_client_message_proxy_impl.h
index 5b4dca3..6d3aee76 100644
--- a/chromeos/services/secure_channel/single_client_message_proxy_impl.h
+++ b/chromeos/services/secure_channel/single_client_message_proxy_impl.h
@@ -12,14 +12,14 @@
 #include "chromeos/services/secure_channel/client_connection_parameters.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 #include "chromeos/services/secure_channel/single_client_message_proxy.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromeos {
 
 namespace secure_channel {
 
 // Concrete SingleClientMessageProxy implementation, which utilizes a
-// ChannelImpl and MessageReceiverPtr to send/receive messages.
+// ChannelImpl and mojo::Remote<MessageReceiver> to send/receive messages.
 class SingleClientMessageProxyImpl : public SingleClientMessageProxy,
                                      public ChannelImpl::Delegate {
  public:
@@ -65,7 +65,7 @@
 
   std::unique_ptr<ClientConnectionParameters> client_connection_parameters_;
   std::unique_ptr<ChannelImpl> channel_;
-  mojom::MessageReceiverPtr message_receiver_ptr_;
+  mojo::Remote<mojom::MessageReceiver> message_receiver_remote_;
 
   DISALLOW_COPY_AND_ASSIGN(SingleClientMessageProxyImpl);
 };
diff --git a/chromeos/services/secure_channel/single_client_message_proxy_impl_unittest.cc b/chromeos/services/secure_channel/single_client_message_proxy_impl_unittest.cc
index 4be0e89..5b58b4a9 100644
--- a/chromeos/services/secure_channel/single_client_message_proxy_impl_unittest.cc
+++ b/chromeos/services/secure_channel/single_client_message_proxy_impl_unittest.cc
@@ -71,7 +71,8 @@
 
     int message_counter = next_message_counter_++;
 
-    mojom::ChannelPtr& channel = *fake_client_connection_parameters_->channel();
+    mojo::Remote<mojom::Channel>& channel =
+        fake_client_connection_parameters_->channel();
     channel->SendMessage(
         message,
         base::BindOnce(
@@ -158,7 +159,8 @@
   mojom::ConnectionMetadataPtr GetConnectionMetadataFromChannel() {
     EXPECT_FALSE(last_metadata_from_channel_);
 
-    mojom::ChannelPtr& channel = *fake_client_connection_parameters_->channel();
+    mojo::Remote<mojom::Channel>& channel =
+        fake_client_connection_parameters_->channel();
     channel->GetConnectionMetadata(base::BindOnce(
         &SecureChannelSingleClientMessageProxyImplTest::OnConnectionMetadata,
         base::Unretained(this)));
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc
index 928655a..9f72e6c1 100644
--- a/chromeos/settings/cros_settings_names.cc
+++ b/chromeos/settings/cros_settings_names.cc
@@ -278,6 +278,11 @@
 const char kDeviceLoginScreenInputMethods[] =
     "cros.device_login_screen_input_methods";
 
+// A boolean pref that indicates whether the system information is forcedly
+// shown (or hidden) on the login screen.
+const char kDeviceLoginScreenSystemInfoEnforced[] =
+    "cros.device_login_screen_system_info_enforced";
+
 // A boolean pref that matches enable-per-user-time-zone chrome://flags value.
 const char kPerUserTimezoneEnabled[] = "cros.flags.per_user_timezone_enabled";
 
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h
index 1031971..90665ae 100644
--- a/chromeos/settings/cros_settings_names.h
+++ b/chromeos/settings/cros_settings_names.h
@@ -170,6 +170,8 @@
 extern const char kDeviceLoginScreenLocales[];
 COMPONENT_EXPORT(CHROMEOS_SETTINGS)
 extern const char kDeviceLoginScreenInputMethods[];
+COMPONENT_EXPORT(CHROMEOS_SETTINGS)
+extern const char kDeviceLoginScreenSystemInfoEnforced[];
 
 COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kPerUserTimezoneEnabled[];
 COMPONENT_EXPORT(CHROMEOS_SETTINGS)
diff --git a/chromeos/test/data/oobe_configuration/TestShowHID.json b/chromeos/test/data/oobe_configuration/TestShowHID.json
new file mode 100644
index 0000000..58d1c21
--- /dev/null
+++ b/chromeos/test/data/oobe_configuration/TestShowHID.json
@@ -0,0 +1,4 @@
+{
+  "welcomeNext": false,
+  "desc" : "Skip welcomeNext as this will trigger an action on the hidden welcome screen"
+}
\ No newline at end of file
diff --git a/components/BUILD.gn b/components/BUILD.gn
index b5b669ef..975b269e 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -170,6 +170,7 @@
     "//components/variations/service:unit_tests",
     "//components/web_resource:unit_tests",
     "//components/webdata/common:unit_tests",
+    "//components/webdata_services:unit_tests",
   ]
 
   if (toolkit_views) {
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h
index c2496dc..91df17d 100644
--- a/components/autofill/content/browser/content_autofill_driver.h
+++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/supports_user_data.h"
 #include "build/build_config.h"
@@ -24,7 +25,7 @@
 namespace content {
 class NavigationHandle;
 class RenderFrameHost;
-}
+}  // namespace content
 
 namespace autofill {
 
@@ -120,10 +121,6 @@
   // subframe navigations. See navigation_handle.h for details.
   void DidNavigateMainFrame(content::NavigationHandle* navigation_handle);
 
-  AutofillExternalDelegate* autofill_external_delegate() {
-    return autofill_external_delegate_.get();
-  }
-
   AutofillManager* autofill_manager() { return autofill_manager_; }
   AutofillHandler* autofill_handler() { return autofill_handler_.get(); }
   content::RenderFrameHost* render_frame_host() { return render_frame_host_; }
diff --git a/components/autofill/content/browser/content_autofill_driver_unittest.cc b/components/autofill/content/browser/content_autofill_driver_unittest.cc
index 547fbd9d..24b76fe 100644
--- a/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -204,9 +204,6 @@
   void PreviewPasswordSuggestion(const base::string16& username,
                                  const base::string16& password) override {}
 
-  void ShowInitialPasswordAccountSuggestions(
-      const PasswordFormFillData& form_data) override {}
-
   void SetUserGestureRequired(bool required) override {}
 
   void SetSecureContextRequired(bool required) override {}
diff --git a/components/autofill/content/common/mojom/autofill_agent.mojom b/components/autofill/content/common/mojom/autofill_agent.mojom
index 2a80bac..e7b25eab 100644
--- a/components/autofill/content/common/mojom/autofill_agent.mojom
+++ b/components/autofill/content/common/mojom/autofill_agent.mojom
@@ -52,10 +52,6 @@
   PreviewPasswordSuggestion(mojo_base.mojom.String16 username,
                             mojo_base.mojom.String16 password);
 
-  // Sent when a password form is initially detected and suggestions should be
-  // shown. Used by the fill-on-select experiment.
-  ShowInitialPasswordAccountSuggestions(PasswordFormFillData form_data);
-
   // Configures the render to require, or not, a user gesture before notifying
   // the autofill agent of a field change. The default is true. Bypassing the
   // user gesture check should only used for Android Webview, which needs to
diff --git a/components/autofill/content/common/mojom/autofill_driver.mojom b/components/autofill/content/common/mojom/autofill_driver.mojom
index b7fa28a..73e2536c 100644
--- a/components/autofill/content/common/mojom/autofill_driver.mojom
+++ b/components/autofill/content/common/mojom/autofill_driver.mojom
@@ -102,9 +102,12 @@
   // save/update prompt anchored to the omnibox icon should be removed.
   HideManualFallbackForSaving();
 
-  // Notification that same-document navigation happened and at this moment we
-  // have filled password form. We use this as a signal for successful login.
-  SameDocumentNavigation(PasswordForm password_form);
+  // Notification that same-document navigation happened. We use this as a
+  // signal for successful login.
+  // TODO(crbug.com/949519): Rename this method to a more generic name since
+  // it's called in many scenarios other than SameDocumentNavigation such as
+  // FRAME_DETACHED.
+  SameDocumentNavigation(SubmissionIndicatorEvent submission_indication_event);
 
   // Sends |log| to browser for displaying to the user. Only strings passed as
   // an argument to methods overriding SavePasswordProgressLogger::SendLog may
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index 5c47936..5917687 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -563,31 +563,6 @@
   DCHECK(handled);
 }
 
-void AutofillAgent::ShowInitialPasswordAccountSuggestions(
-    const PasswordFormFillData& form_data) {
-  std::vector<blink::WebInputElement> elements;
-  std::unique_ptr<RendererSavePasswordProgressLogger> logger;
-  if (password_autofill_agent_->logging_state_active()) {
-    logger.reset(new RendererSavePasswordProgressLogger(
-        GetPasswordManagerDriver().get()));
-    logger->LogMessage(SavePasswordProgressLogger::
-                           STRING_ON_SHOW_INITIAL_PASSWORD_ACCOUNT_SUGGESTIONS);
-  }
-  password_autofill_agent_->GetFillableElementFromFormData(
-      form_data, logger.get(), &elements);
-
-  // If wait_for_username is true, we don't want to initially show form options
-  // until the user types in a valid username.
-  if (form_data.wait_for_username)
-    return;
-
-  ShowSuggestionsOptions options;
-  options.autofill_on_empty_values = true;
-  options.show_full_suggestion_list = true;
-  for (auto element : elements)
-    ShowSuggestions(element, options);
-}
-
 bool AutofillAgent::CollectFormlessElements(FormData* output) {
   if (render_frame() == nullptr || render_frame()->GetWebFrame() == nullptr)
     return false;
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h
index e552ea1..69231a1 100644
--- a/components/autofill/content/renderer/autofill_agent.h
+++ b/components/autofill/content/renderer/autofill_agent.h
@@ -41,7 +41,6 @@
 
 struct FormData;
 struct FormFieldData;
-struct PasswordFormFillData;
 class PasswordAutofillAgent;
 class PasswordGenerationAgent;
 
@@ -89,8 +88,6 @@
                               const base::string16& password) override;
   void PreviewPasswordSuggestion(const base::string16& username,
                                  const base::string16& password) override;
-  void ShowInitialPasswordAccountSuggestions(
-      const PasswordFormFillData& form_data) override;
   void SetUserGestureRequired(bool required) override;
   void SetSecureContextRequired(bool required) override;
   void SetFocusRequiresScroll(bool require) override;
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 82363b1..fa7f585 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -117,180 +117,11 @@
                base::ASCIIToUTF16(kDummyUsernameField)));
 }
 
-bool IsFieldPasswordField(const FormFieldData& field) {
-  return (field.form_control_type == "password");
-}
-
-// Returns true if any password field within |control_elements| is supplied with
-// either |autocomplete='current-password'| or |autocomplete='new-password'|
-// attribute.
-bool HasPasswordWithAutocompleteAttribute(
-    const std::vector<WebFormControlElement>& control_elements) {
-  for (const WebFormControlElement& control_element : control_elements) {
-    if (!control_element.HasHTMLTagName("input"))
-      continue;
-
-    const WebInputElement input_element =
-        control_element.ToConst<WebInputElement>();
-    const AutocompleteFlag flag = AutocompleteFlagForElement(input_element);
-    if (input_element.IsPasswordFieldForAutofill() &&
-        (flag == AutocompleteFlag::CURRENT_PASSWORD ||
-         flag == AutocompleteFlag::NEW_PASSWORD)) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-// Returns the |field|'s autofillable name. If |ambiguous_or_empty_names| is set
-// to true returns a dummy name instead.
-base::string16 FieldName(const FormFieldData& field,
-                         bool ambiguous_or_empty_names) {
-  return ambiguous_or_empty_names
-             ? (IsFieldPasswordField(field)
-                    ? base::ASCIIToUTF16(kDummyPasswordField)
-                    : base::ASCIIToUTF16(kDummyUsernameField))
-             : field.name;
-}
-
 bool IsUnownedPasswordFormVisible(const WebInputElement& input_element) {
   return !input_element.IsNull() &&
          form_util::IsWebElementVisible(input_element);
 }
 
-// Utility function to find the unique entry of |control_elements| for the
-// specified input |field|. On successful find, adds it to |result| and returns
-// |true|. Otherwise clears the references from each |HTMLInputElement| from
-// |result| and returns |false|.
-bool FindFormInputElement(
-    const std::vector<WebFormControlElement>& control_elements,
-    const FormFieldData& field,
-    bool ambiguous_or_empty_names,
-    FormInputElementMap* result) {
-  // Match the first input element, if any.
-  bool found_input = false;
-  bool is_password_field = IsFieldPasswordField(field);
-  bool does_password_field_has_ambigous_or_empty_name =
-      ambiguous_or_empty_names && is_password_field;
-  bool ambiguous_and_multiple_password_fields_with_autocomplete =
-      does_password_field_has_ambigous_or_empty_name &&
-      HasPasswordWithAutocompleteAttribute(control_elements);
-  base::string16 field_name = FieldName(field, ambiguous_or_empty_names);
-  for (const WebFormControlElement& control_element : control_elements) {
-    if (!ambiguous_or_empty_names &&
-        control_element.NameForAutofill().Utf16() != field_name) {
-      continue;
-    }
-
-    if (!control_element.HasHTMLTagName("input"))
-      continue;
-
-    // Only fill saved passwords into password fields and usernames into text
-    // fields.
-    const WebInputElement input_element =
-        control_element.ToConst<WebInputElement>();
-    if (!input_element.IsTextField() ||
-        input_element.IsPasswordFieldForAutofill() != is_password_field)
-      continue;
-
-    // For change password form with ambiguous or empty names keep only the
-    // first password field having |autocomplete='current-password'| attribute
-    // set. Also make sure we avoid keeping password fields having
-    // |autocomplete='new-password'| attribute set.
-    if (ambiguous_and_multiple_password_fields_with_autocomplete &&
-        AutocompleteFlagForElement(input_element) !=
-            AutocompleteFlag::CURRENT_PASSWORD) {
-      continue;
-    }
-
-    // Check for a non-unique match.
-    if (found_input) {
-      // For change password form keep only the first password field entry.
-      if (does_password_field_has_ambigous_or_empty_name) {
-        if (!form_util::IsWebElementVisible((*result)[field_name])) {
-          // If a previously chosen field was invisible then take the current
-          // one.
-          (*result)[field_name] = input_element;
-        }
-        continue;
-      }
-
-      found_input = false;
-      break;
-    }
-
-    (*result)[field_name] = input_element;
-    found_input = true;
-  }
-
-  // A required element was not found. This is not the right form.
-  // Make sure no input elements from a partially matched form in this
-  // iteration remain in the result set.
-  // Note: clear will remove a reference from each InputElement.
-  if (!found_input) {
-    result->clear();
-    return false;
-  }
-
-  return true;
-}
-
-// Helper to search through |control_elements| for the specified input elements
-// in |data|, and add results to |result|.
-bool FindFormInputElements(
-    const std::vector<WebFormControlElement>& control_elements,
-    const PasswordFormFillData& data,
-    bool ambiguous_or_empty_names,
-    FormInputElementMap* result) {
-  return FindFormInputElement(control_elements, data.password_field,
-                              ambiguous_or_empty_names, result) &&
-         (!FillDataContainsFillableUsername(data) ||
-          FindFormInputElement(control_elements, data.username_field,
-                               ambiguous_or_empty_names, result));
-}
-
-// Helper to locate form elements identified by |data|.
-void FindFormElements(content::RenderFrame* render_frame,
-                      const PasswordFormFillData& data,
-                      bool ambiguous_or_empty_names,
-                      FormElementsList* results) {
-  DCHECK(results);
-
-  WebDocument doc = render_frame->GetWebFrame()->GetDocument();
-
-  if (GetSignOnRealm(data.origin) !=
-      GetSignOnRealm(form_util::GetCanonicalOriginForDocument(doc)))
-    return;
-
-  WebVector<WebFormElement> forms;
-  doc.Forms(forms);
-
-  for (const WebFormElement& form : forms) {
-    // Action URL must match.
-    if (data.action != form_util::GetCanonicalActionForForm(form))
-      continue;
-
-    std::vector<WebFormControlElement> control_elements =
-        form_util::ExtractAutofillableElementsInForm(form);
-    FormInputElementMap cur_map;
-    if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
-                              &cur_map))
-      results->push_back(cur_map);
-  }
-  // If the element to be filled are not in a <form> element, the "action" and
-  // origin should be the same.
-  if (data.action != data.origin)
-    return;
-
-  std::vector<WebFormControlElement> control_elements =
-      form_util::GetUnownedAutofillableFormFieldElements(doc.All(), nullptr);
-  FormInputElementMap unowned_elements_map;
-  if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
-                            &unowned_elements_map))
-    results->push_back(unowned_elements_map);
-}
-
 bool IsElementEditable(const WebInputElement& element) {
   return element.IsEnabled() && !element.IsReadOnly();
 }
@@ -1083,7 +914,7 @@
   }
 
   provisionally_saved_form_.SetSubmissionIndicatorEvent(event);
-  GetPasswordManagerDriver()->SameDocumentNavigation(password_form);
+  GetPasswordManagerDriver()->SameDocumentNavigation(event);
   provisionally_saved_form_.Reset();
 }
 
@@ -1274,7 +1105,7 @@
     provisionally_saved_form_.SetSubmissionIndicatorEvent(
         SubmissionIndicatorEvent::FRAME_DETACHED);
     GetPasswordManagerDriver()->SameDocumentNavigation(
-        provisionally_saved_form_.password_form());
+        SubmissionIndicatorEvent::FRAME_DETACHED);
   }
   CleanupOnDocumentShutdown();
 }
@@ -1415,76 +1246,6 @@
                           logger.get());
 }
 
-void PasswordAutofillAgent::GetFillableElementFromFormData(
-    const PasswordFormFillData& form_data,
-    RendererSavePasswordProgressLogger* logger,
-    std::vector<WebInputElement>* elements) {
-  DCHECK(elements);
-  bool ambiguous_or_empty_names =
-      DoesFormContainAmbiguousOrEmptyNames(form_data);
-  FormElementsList forms;
-  FindFormElements(render_frame(), form_data, ambiguous_or_empty_names, &forms);
-  if (logger) {
-    logger->LogBoolean(Logger::STRING_AMBIGUOUS_OR_EMPTY_NAMES,
-                       ambiguous_or_empty_names);
-    logger->LogNumber(Logger::STRING_NUMBER_OF_POTENTIAL_FORMS_TO_FILL,
-                      forms.size());
-    logger->LogBoolean(Logger::STRING_FORM_DATA_WAIT,
-                       form_data.wait_for_username);
-  }
-  for (const auto& form : forms) {
-    base::string16 username_field_name;
-    base::string16 password_field_name =
-        FieldName(form_data.password_field, ambiguous_or_empty_names);
-    bool form_contains_fillable_username_field =
-        FillDataContainsFillableUsername(form_data);
-    if (form_contains_fillable_username_field) {
-      username_field_name =
-          FieldName(form_data.username_field, ambiguous_or_empty_names);
-    }
-    if (logger) {
-      logger->LogBoolean(Logger::STRING_CONTAINS_FILLABLE_USERNAME_FIELD,
-                         form_contains_fillable_username_field);
-      logger->LogBoolean(Logger::STRING_USERNAME_FIELD_NAME_EMPTY,
-                         username_field_name.empty());
-      logger->LogBoolean(Logger::STRING_PASSWORD_FIELD_NAME_EMPTY,
-                         password_field_name.empty());
-    }
-
-    // Attach autocomplete listener to enable selecting alternate logins.
-    WebInputElement username_element;
-    WebInputElement password_element;
-
-    // Check whether the password form has a username input field.
-    if (!username_field_name.empty()) {
-      const auto it = form.find(username_field_name);
-      DCHECK(it != form.end());
-      username_element = it->second;
-    }
-
-    // No password field, bail out.
-    if (password_field_name.empty())
-      break;
-
-    // Get pointer to password element. (We currently only support single
-    // password forms).
-    {
-      const auto it = form.find(password_field_name);
-      DCHECK(it != form.end());
-      password_element = it->second;
-    }
-
-    WebInputElement main_element =
-        username_element.IsNull() ? password_element : username_element;
-    if (elements)
-      elements->push_back(main_element);
-    StoreDataForFillOnAccountSelect(form_data, username_element,
-                                    password_element);
-  }
-
-  MaybeStoreFallbackData(form_data);
-}
-
 void PasswordAutofillAgent::FocusedNodeHasChanged(const blink::WebNode& node) {
   DCHECK(!node.IsNull());
   focused_input_element_.Reset();
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index a7ad556..069545e 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -209,15 +209,6 @@
   // JavaScript.
   void UserGestureObserved();
 
-  // Given password form data |form_data| returns a set of WebInputElements in
-  // |elements|, which must be non-null, that the password manager has values
-  // for filling. Also takes an optional logger |logger| for logging password
-  // autofill behavior.
-  void GetFillableElementFromFormData(
-      const PasswordFormFillData& form_data,
-      RendererSavePasswordProgressLogger* logger,
-      std::vector<blink::WebInputElement>* elements);
-
   // Called when the focused node has changed. This is not called if the focus
   // moves outside the frame.
   void FocusedNodeHasChanged(const blink::WebNode& node);
diff --git a/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc b/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
index bdbb7597..1cce757 100644
--- a/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
+++ b/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
@@ -55,8 +55,8 @@
 
   void HideManualFallbackForSaving() override {}
 
-  void SameDocumentNavigation(
-      const autofill::PasswordForm& password_form) override {}
+  void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent
+                                  submission_indication_event) override {}
 
   void ShowPasswordSuggestions(base::i18n::TextDirection text_direction,
                                const base::string16& typed_username,
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc
index 45a42fc..b7d24be3 100644
--- a/components/content_settings/core/browser/cookie_settings.cc
+++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -61,7 +61,9 @@
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
   registry->RegisterIntegerPref(
       prefs::kCookieControlsMode,
-      static_cast<int>(CookieControlsMode::kIncognitoOnly),
+      static_cast<int>(kImprovedCookieControlsDefaultInIncognito.Get()
+                           ? CookieControlsMode::kIncognitoOnly
+                           : CookieControlsMode::kOff),
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
 }
 
diff --git a/components/content_settings/core/common/features.cc b/components/content_settings/core/common/features.cc
index 189ab9f..17dceed1 100644
--- a/components/content_settings/core/common/features.cc
+++ b/components/content_settings/core/common/features.cc
@@ -5,6 +5,7 @@
 #include "components/content_settings/core/common/features.h"
 
 #include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
 
 namespace content_settings {
 
@@ -12,6 +13,10 @@
 const base::Feature kImprovedCookieControls{"ImprovedCookieControls",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Default setting for improved cookie controls.
+const base::FeatureParam<bool> kImprovedCookieControlsDefaultInIncognito{
+    &kImprovedCookieControls, "DefaultInIncognito", true};
+
 // Enables an improved UI for existing third-party cookie blocking users.
 const base::Feature kImprovedCookieControlsForThirdPartyCookieBlocking{
     "ImprovedCookieControlsForThirdPartyCookieBlocking",
diff --git a/components/content_settings/core/common/features.h b/components/content_settings/core/common/features.h
index 78fc7dd..9d6965be 100644
--- a/components/content_settings/core/common/features.h
+++ b/components/content_settings/core/common/features.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_FEATURES_H_
 
 #include "base/component_export.h"
+#include "base/metrics/field_trial_params.h"
 
 namespace base {
 struct Feature;
@@ -17,6 +18,9 @@
 COMPONENT_EXPORT(CONTENT_SETTINGS_FEATURES)
 extern const base::Feature kImprovedCookieControls;
 
+COMPONENT_EXPORT(CONTENT_SETTINGS_FEATURES)
+extern const base::FeatureParam<bool> kImprovedCookieControlsDefaultInIncognito;
+
 // Feature to enable the improved cookie contronls ui for third-party cookie
 // blocking users.
 COMPONENT_EXPORT(CONTENT_SETTINGS_FEATURES)
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index 3be99d4..63344e8 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -732,15 +732,42 @@
   ]
 }
 
+# See crbug.com/1005836 for more info on why repackage_native requires 2 extra
+# targets. These 3 targets exist to ensure the correct version of GEN_JNI
+# (a generated class containing native method definitions) is included.
 repackage_jars("repackage_native") {
   output = "$_package_dir/cronet_impl_native_java.jar"
-  deps = cronet_impl_native_java_deps_to_package + [
-           ":cronet_impl_native_base_java",
-           ":cronet_jni_registration_java",
-         ]
+  deps = [
+    ":cronet_jni_registration_java",
+    ":repackage_native_java",
+  ]
   jar_excluded_patterns = _jar_excluded_patterns
 }
 
+_native_intermediate_jar_path = "$target_out_dir/repackage_native_impl.jar"
+
+# Do not depend on this target directly. Use :repackage_native.
+repackage_jars("repackage_native_impl") {
+  output = _native_intermediate_jar_path
+  deps = cronet_impl_native_java_deps_to_package +
+         [ ":cronet_impl_native_base_java" ]
+  jar_excluded_patterns = _jar_excluded_patterns
+}
+
+# Do not depend on this target directly. Use :repackage_native.
+# This target exists to provide :repackage_native with a suitable target to
+# depend on (since dist_aar only pulls in deps of type "java_library").
+android_java_prebuilt("repackage_native_java") {
+  jar_path = _native_intermediate_jar_path
+
+  # Since only the unprocessed jar is used, no need to complete the bytecode
+  # processing steps.
+  enable_bytecode_rewriter = false
+  deps = [
+    ":repackage_native_impl",
+  ]
+}
+
 repackage_jars("repackage_common") {
   output = "$_package_dir/cronet_impl_common_java.jar"
   deps = cronet_impl_common_java_deps_to_package + [
diff --git a/components/download/internal/common/download_response_handler.cc b/components/download/internal/common/download_response_handler.cc
index d7fb8be..dfbf59ea 100644
--- a/components/download/internal/common/download_response_handler.cc
+++ b/components/download/internal/common/download_response_handler.cc
@@ -215,7 +215,7 @@
   mojom::DownloadStreamHandlePtr stream_handle =
       mojom::DownloadStreamHandle::New();
   stream_handle->stream = std::move(body);
-  stream_handle->client_request = mojo::MakeRequest(&client_ptr_);
+  stream_handle->client_receiver = client_remote_.BindNewPipeAndPassReceiver();
   OnResponseStarted(std::move(stream_handle));
 }
 
@@ -229,8 +229,8 @@
       static_cast<net::Error>(status.error_code), has_strong_validators_,
       cert_status_, is_partial_request_, abort_reason_);
 
-  if (client_ptr_) {
-    client_ptr_->OnStreamCompleted(
+  if (client_remote_) {
+    client_remote_->OnStreamCompleted(
         ConvertInterruptReasonToMojoNetworkRequestStatus(reason));
   }
 
diff --git a/components/download/internal/common/stream_handle_input_stream.cc b/components/download/internal/common/stream_handle_input_stream.cc
index d6a2a823..fc1ddd6 100644
--- a/components/download/internal/common/stream_handle_input_stream.cc
+++ b/components/download/internal/common/stream_handle_input_stream.cc
@@ -27,9 +27,9 @@
 
 void StreamHandleInputStream::Initialize() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  binding_ = std::make_unique<mojo::Binding<mojom::DownloadStreamClient>>(
-      this, std::move(stream_handle_->client_request));
-  binding_->set_connection_error_handler(base::BindOnce(
+  receiver_ = std::make_unique<mojo::Receiver<mojom::DownloadStreamClient>>(
+      this, std::move(stream_handle_->client_receiver));
+  receiver_->set_disconnect_handler(base::BindOnce(
       &StreamHandleInputStream::OnStreamCompleted, base::Unretained(this),
       mojom::NetworkRequestStatus::USER_CANCELED));
   handle_watcher_ = std::make_unique<mojo::SimpleWatcher>(
diff --git a/components/download/public/common/download_response_handler.h b/components/download/public/common/download_response_handler.h
index 08d93025..cf557de 100644
--- a/components/download/public/common/download_response_handler.h
+++ b/components/download/public/common/download_response_handler.h
@@ -15,6 +15,7 @@
 #include "components/download/public/common/download_stream.mojom.h"
 #include "components/download/public/common/download_url_parameters.h"
 #include "components/download/public/common/download_utils.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/cert/cert_status_flags.h"
 #include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
@@ -104,8 +105,8 @@
   // The abort reason if this class decides to block the download.
   DownloadInterruptReason abort_reason_;
 
-  // Mojo interface ptr to send the completion status to the download sink.
-  mojom::DownloadStreamClientPtr client_ptr_;
+  // Mojo interface remote to send the completion status to the download sink.
+  mojo::Remote<mojom::DownloadStreamClient> client_remote_;
 
   // Whether the download is running in background mode.
   bool is_background_mode_;
diff --git a/components/download/public/common/download_stream.mojom b/components/download/public/common/download_stream.mojom
index 5083aaa..d363694 100644
--- a/components/download/public/common/download_stream.mojom
+++ b/components/download/public/common/download_stream.mojom
@@ -24,5 +24,5 @@
 
 struct DownloadStreamHandle {
   handle<data_pipe_consumer> stream;
-  DownloadStreamClient& client_request;
-};
\ No newline at end of file
+  pending_receiver<DownloadStreamClient> client_receiver;
+};
diff --git a/components/download/public/common/stream_handle_input_stream.h b/components/download/public/common/stream_handle_input_stream.h
index a54097e..f490b77 100644
--- a/components/download/public/common/stream_handle_input_stream.h
+++ b/components/download/public/common/stream_handle_input_stream.h
@@ -8,7 +8,7 @@
 #include "components/download/public/common/download_export.h"
 #include "components/download/public/common/download_stream.mojom.h"
 #include "components/download/public/common/input_stream.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 
 namespace download {
@@ -40,7 +40,7 @@
   // Objects for consuming a mojo data pipe.
   mojom::DownloadStreamHandlePtr stream_handle_;
   std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
-  std::unique_ptr<mojo::Binding<mojom::DownloadStreamClient>> binding_;
+  std::unique_ptr<mojo::Receiver<mojom::DownloadStreamClient>> receiver_;
 
   // Whether the producer has completed handling the response.
   bool is_response_completed_;
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc
index 8c17bfa7..e0790c24 100644
--- a/components/exo/shell_surface_base.cc
+++ b/components/exo/shell_surface_base.cc
@@ -556,6 +556,7 @@
   }
 
   bool frame_was_disabled = !frame_enabled();
+  // TODO(b/141151475): Make frame_type a committable property.
   frame_type_ = frame_type;
   switch (frame_type) {
     case SurfaceFrameType::NONE:
@@ -564,9 +565,11 @@
     case SurfaceFrameType::NORMAL:
     case SurfaceFrameType::AUTOHIDE:
     case SurfaceFrameType::OVERLAY:
-      // Initialize the shadow if it didn't exist.  Do not reset if
-      // the frame type just switched from another enabled type.
-      if (!shadow_bounds_ || frame_was_disabled)
+      // Initialize the shadow if it didn't exist. Do not reset if
+      // the frame type just switched from another enabled type or
+      // there is a pending shadow_bounds_ change to avoid overriding
+      // a shadow bounds which have been changed and not yet committed.
+      if (!shadow_bounds_ || (frame_was_disabled && !shadow_bounds_changed_))
         shadow_bounds_ = gfx::Rect();
       break;
     case SurfaceFrameType::SHADOW:
diff --git a/components/paint_preview/common/BUILD.gn b/components/paint_preview/common/BUILD.gn
index 5bc0898..a2f9f77 100644
--- a/components/paint_preview/common/BUILD.gn
+++ b/components/paint_preview/common/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "file_stream.cc",
     "file_stream.h",
+    "glyph_usage.cc",
+    "glyph_usage.h",
   ]
 
   deps = [
@@ -21,6 +23,7 @@
 
   sources = [
     "file_stream_unittest.cc",
+    "glyph_usage_unittest.cc",
   ]
 
   deps = [
diff --git a/components/paint_preview/common/glyph_usage.cc b/components/paint_preview/common/glyph_usage.cc
new file mode 100644
index 0000000..5a20f801
--- /dev/null
+++ b/components/paint_preview/common/glyph_usage.cc
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/paint_preview/common/glyph_usage.h"
+
+#include "base/callback.h"
+
+namespace paint_preview {
+
+GlyphUsage::GlyphUsage() : first_(0), last_(0) {}
+GlyphUsage::GlyphUsage(uint16_t first, uint16_t last)
+    : first_(first), last_(last) {
+  DCHECK_EQ(first, 1U);
+  DCHECK_LE(first, last);
+}
+GlyphUsage::~GlyphUsage() = default;
+
+DenseGlyphUsage::DenseGlyphUsage() : GlyphUsage(), bitset_(0, 0) {}
+DenseGlyphUsage::DenseGlyphUsage(uint16_t num_glyphs)
+    : GlyphUsage(1, num_glyphs), bitset_(num_glyphs + 1, false) {}
+DenseGlyphUsage::~DenseGlyphUsage() = default;
+
+void DenseGlyphUsage::Set(uint16_t glyph_id) {
+  if (!ShouldSubset() ||
+      (glyph_id != 0 && (glyph_id < First() || glyph_id > Last())))
+    return;
+  bitset_[glyph_id] = true;
+}
+
+bool DenseGlyphUsage::IsSet(uint16_t glyph_id) const {
+  if (!ShouldSubset() ||
+      (glyph_id != 0 && (glyph_id < First() || glyph_id > Last())))
+    return false;
+  return bitset_[glyph_id];
+}
+
+void DenseGlyphUsage::ForEach(
+    const base::RepeatingCallback<void(uint16_t)>& callback) const {
+  for (uint16_t i = 0; i < bitset_.size(); ++i) {
+    if (bitset_[i])
+      callback.Run(i);
+  }
+}
+
+SparseGlyphUsage::SparseGlyphUsage() : GlyphUsage() {}
+SparseGlyphUsage::SparseGlyphUsage(uint16_t num_glyphs)
+    : GlyphUsage(1, num_glyphs) {}
+SparseGlyphUsage::~SparseGlyphUsage() = default;
+
+void SparseGlyphUsage::Set(uint16_t glyph_id) {
+  if (!ShouldSubset() ||
+      (glyph_id != 0 && (glyph_id < First() || glyph_id > Last())))
+    return;
+  glyph_ids_.insert(glyph_id);
+}
+
+bool SparseGlyphUsage::IsSet(uint16_t glyph_id) const {
+  return glyph_ids_.count(glyph_id);
+}
+
+void SparseGlyphUsage::ForEach(
+    const base::RepeatingCallback<void(uint16_t)>& callback) const {
+  for (const auto& key : glyph_ids_)
+    callback.Run(key);
+}
+
+}  // namespace paint_preview
diff --git a/components/paint_preview/common/glyph_usage.h b/components/paint_preview/common/glyph_usage.h
new file mode 100644
index 0000000..0bbb0a3
--- /dev/null
+++ b/components/paint_preview/common/glyph_usage.h
@@ -0,0 +1,100 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PAINT_PREVIEW_COMMON_GLYPH_USAGE_H_
+#define COMPONENTS_PAINT_PREVIEW_COMMON_GLYPH_USAGE_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+
+namespace paint_preview {
+
+// Base class for tracking glyph usage.
+class GlyphUsage {
+ public:
+  GlyphUsage();
+  // Range of glyph ids.
+  // Note: at present |first| must be 1 as we don't support offset subset codes.
+  GlyphUsage(uint16_t first, uint16_t last);
+  virtual ~GlyphUsage();
+
+  virtual void Set(uint16_t glyph_id) = 0;
+  virtual bool IsSet(uint16_t glyph_id) const = 0;
+
+  // Executes |callback| with the glyph id of each glyph that is set.
+  virtual void ForEach(
+      const base::RepeatingCallback<void(uint16_t)>& callback) const = 0;
+
+  bool ShouldSubset() const { return first_ < last_; }
+  uint16_t First() const { return first_; }
+  uint16_t Last() const { return last_; }
+
+  GlyphUsage& operator=(GlyphUsage&& other) noexcept;
+  GlyphUsage(GlyphUsage&& other) noexcept;
+
+ private:
+  uint16_t first_;
+  uint16_t last_;
+
+  DISALLOW_COPY_AND_ASSIGN(GlyphUsage);
+};
+
+// An implementation of GlyphUsage that works well for densely set glyphs.
+// Usecases:
+// - Primary language
+// - Pre-subsetted fonts
+class DenseGlyphUsage : public GlyphUsage {
+ public:
+  DenseGlyphUsage();
+  DenseGlyphUsage(uint16_t num_glyphs);
+  ~DenseGlyphUsage() override;
+
+  void Set(uint16_t glyph_id) override;
+  bool IsSet(uint16_t glyph_id) const override;
+  void ForEach(
+      const base::RepeatingCallback<void(uint16_t)>& callback) const override;
+
+  DenseGlyphUsage& operator=(DenseGlyphUsage&& other) noexcept;
+  DenseGlyphUsage(DenseGlyphUsage&& other) noexcept;
+
+ private:
+  std::vector<bool> bitset_;
+
+  DISALLOW_COPY_AND_ASSIGN(DenseGlyphUsage);
+};
+
+// An implementation of GlyphUsage that works well for sparsely set glyphs.
+// Usecases:
+// - Non-subsetted CJK fonts
+// - Emoji
+// - Large glyph counts fonts with low glyph usage
+// - Non-primary language
+class SparseGlyphUsage : public GlyphUsage {
+ public:
+  SparseGlyphUsage();
+  SparseGlyphUsage(uint16_t num_glyphs);
+  ~SparseGlyphUsage() override;
+
+  void Set(uint16_t glyph_id) override;
+  bool IsSet(uint16_t glyph_id) const override;
+  void ForEach(
+      const base::RepeatingCallback<void(uint16_t)>& callback) const override;
+
+  SparseGlyphUsage& operator=(SparseGlyphUsage&& other) noexcept;
+  SparseGlyphUsage(SparseGlyphUsage&& other) noexcept;
+
+ private:
+  base::flat_set<uint16_t> glyph_ids_;
+
+  DISALLOW_COPY_AND_ASSIGN(SparseGlyphUsage);
+};
+
+}  // namespace paint_preview
+
+#endif  // COMPONENTS_PAINT_PREVIEW_COMMON_GLYPH_USAGE_H_
diff --git a/components/paint_preview/common/glyph_usage_unittest.cc b/components/paint_preview/common/glyph_usage_unittest.cc
new file mode 100644
index 0000000..81ac104
--- /dev/null
+++ b/components/paint_preview/common/glyph_usage_unittest.cc
@@ -0,0 +1,106 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/paint_preview/common/glyph_usage.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace paint_preview {
+
+TEST(PaintPreviewGlyphUsageTest, TestEmpty) {
+  DenseGlyphUsage dense;
+  EXPECT_EQ(dense.First(), 0U);
+  EXPECT_EQ(dense.Last(), 0U);
+  EXPECT_FALSE(dense.ShouldSubset());
+  dense.Set(0);
+  EXPECT_FALSE(dense.IsSet(0));
+  dense.Set(5);
+  EXPECT_FALSE(dense.IsSet(5));
+  dense.Set(60);
+  EXPECT_FALSE(dense.IsSet(60));
+  size_t counter = 0;
+  auto cb = base::BindRepeating(
+      [](size_t* counter, uint16_t glyph_id) { ++(*counter); },
+      base::Unretained(&counter));
+  dense.ForEach(cb);
+  EXPECT_EQ(counter, 0U);
+
+  SparseGlyphUsage sparse;
+  EXPECT_EQ(sparse.First(), 0U);
+  EXPECT_EQ(sparse.Last(), 0U);
+  EXPECT_FALSE(sparse.ShouldSubset());
+  sparse.Set(0);
+  EXPECT_FALSE(sparse.IsSet(0));
+  sparse.Set(5);
+  EXPECT_FALSE(sparse.IsSet(5));
+  sparse.Set(60);
+  EXPECT_FALSE(sparse.IsSet(60));
+  counter = 0;
+  sparse.ForEach(cb);
+  EXPECT_EQ(counter, 0U);
+}
+
+TEST(PaintPreviewGlyphUsageTest, TestDense) {
+  const uint16_t kFirst = 1;
+  const uint16_t kNumGlyphs = 70;
+  DenseGlyphUsage dense(kNumGlyphs);
+  EXPECT_EQ(dense.First(), kFirst);
+  EXPECT_EQ(dense.Last(), kNumGlyphs);
+  EXPECT_TRUE(dense.ShouldSubset());
+  // 0 should be valid even though it is before "first".
+  std::vector<uint16_t> test_glyph_ids = {0, 1, 24, 70, 68, 1, 9, 8};
+  for (const auto& gid : test_glyph_ids) {
+    dense.Set(gid);
+    EXPECT_TRUE(dense.IsSet(gid));
+  }
+  dense.Set(kNumGlyphs + 1);
+  EXPECT_FALSE(dense.IsSet(kNumGlyphs + 1));
+  dense.Set(kNumGlyphs * 2);
+  EXPECT_FALSE(dense.IsSet(kNumGlyphs * 2));
+  std::vector<uint16_t> set_gids;
+  auto cb = base::BindRepeating(
+      [](std::vector<uint16_t>* set_gids, uint16_t glyph_id) {
+        set_gids->push_back(glyph_id);
+      },
+      base::Unretained(&set_gids));
+  dense.ForEach(cb);
+  EXPECT_THAT(set_gids,
+              testing::UnorderedElementsAre(0U, 1U, 24U, 70U, 68U, 9U, 8U));
+}
+
+TEST(PaintPreviewGlyphUsageTest, TestSparse) {
+  const uint16_t kFirst = 1;
+  const uint16_t kNumGlyphs = 70;
+  SparseGlyphUsage sparse(kNumGlyphs);
+  EXPECT_EQ(sparse.First(), kFirst);
+  EXPECT_EQ(sparse.Last(), kNumGlyphs);
+  EXPECT_TRUE(sparse.ShouldSubset());
+  // 0 should be valid even though it is before "first".
+  std::vector<uint16_t> test_glyph_ids = {0, 1, 24, 70, 68, 1, 9, 8};
+  for (const auto& gid : test_glyph_ids) {
+    sparse.Set(gid);
+    EXPECT_TRUE(sparse.IsSet(gid));
+  }
+  sparse.Set(kNumGlyphs + 1);
+  EXPECT_FALSE(sparse.IsSet(kNumGlyphs + 1));
+  sparse.Set(kNumGlyphs * 2);
+  EXPECT_FALSE(sparse.IsSet(kNumGlyphs * 2));
+  std::vector<uint16_t> set_gids;
+  auto cb = base::BindRepeating(
+      [](std::vector<uint16_t>* set_gids, uint16_t glyph_id) {
+        set_gids->push_back(glyph_id);
+      },
+      base::Unretained(&set_gids));
+  sparse.ForEach(cb);
+  EXPECT_THAT(set_gids,
+              testing::UnorderedElementsAre(0U, 1U, 24U, 70U, 68U, 9U, 8U));
+}
+
+}  // namespace paint_preview
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc
index 5e2ad8e..7f05cc4 100644
--- a/components/password_manager/content/browser/content_password_manager_driver.cc
+++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -113,14 +113,6 @@
   }
 }
 
-void ContentPasswordManagerDriver::AutofillDataReceived(
-    const autofill::FormsPredictionsMap& predictions) {
-  // TODO(https://crbug.com/949519): Remove this method, MOJO calls and
-  // processing server predictions in the renderer.
-  GetPasswordAutofillAgent()->AutofillUsernameAndPasswordDataReceived(
-      predictions);
-}
-
 void ContentPasswordManagerDriver::GeneratedPasswordAccepted(
     const base::string16& password) {
   GetPasswordGenerationAgent()->GeneratedPasswordAccepted(password);
@@ -152,12 +144,6 @@
   GetAutofillAgent()->PreviewPasswordSuggestion(username, password);
 }
 
-void ContentPasswordManagerDriver::ShowInitialPasswordAccountSuggestions(
-    const autofill::PasswordFormFillData& form_data) {
-  password_autofill_manager_.OnAddPasswordFillData(form_data);
-  GetAutofillAgent()->ShowInitialPasswordAccountSuggestions(form_data);
-}
-
 void ContentPasswordManagerDriver::ClearPreviewedForm() {
   GetAutofillAgent()->ClearPreviewedForm();
 }
@@ -269,13 +255,9 @@
 }
 
 void ContentPasswordManagerDriver::SameDocumentNavigation(
-    const autofill::PasswordForm& password_form) {
-  if (!password_manager::bad_message::CheckChildProcessSecurityPolicy(
-          render_frame_host_, password_form,
-          BadMessageReason::CPMD_BAD_ORIGIN_IN_PAGE_NAVIGATION))
-    return;
-  GetPasswordManager()->OnPasswordFormSubmittedNoChecks(this, password_form);
-
+    autofill::mojom::SubmissionIndicatorEvent submission_indication_event) {
+  GetPasswordManager()->OnPasswordFormSubmittedNoChecks(
+      this, submission_indication_event);
   LogSiteIsolationMetricsForSubmittedForm(render_frame_host_);
 }
 
diff --git a/components/password_manager/content/browser/content_password_manager_driver.h b/components/password_manager/content/browser/content_password_manager_driver.h
index 623ae2e..e9bece9 100644
--- a/components/password_manager/content/browser/content_password_manager_driver.h
+++ b/components/password_manager/content/browser/content_password_manager_driver.h
@@ -59,8 +59,6 @@
       const autofill::PasswordFormFillData& form_data) override;
   void FormEligibleForGenerationFound(
       const autofill::PasswordFormGenerationData& form) override;
-  void AutofillDataReceived(
-      const autofill::FormsPredictionsMap& predictions) override;
   void GeneratedPasswordAccepted(const base::string16& password) override;
   void GeneratedPasswordAccepted(const autofill::FormData& form_data,
                                  uint32_t generation_element_id,
@@ -71,8 +69,6 @@
                             const base::string16& credential) override;
   void PreviewSuggestion(const base::string16& username,
                          const base::string16& password) override;
-  void ShowInitialPasswordAccountSuggestions(
-      const autofill::PasswordFormFillData& form_data) override;
   void ClearPreviewedForm() override;
   PasswordGenerationFrameHelper* GetPasswordGenerationHelper() override;
   PasswordManager* GetPasswordManager() override;
@@ -105,8 +101,8 @@
       const autofill::PasswordForm& password_form) override;
   void ShowManualFallbackForSaving(const autofill::PasswordForm& form) override;
   void HideManualFallbackForSaving() override;
-  void SameDocumentNavigation(
-      const autofill::PasswordForm& password_form) override;
+  void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent
+                                  submission_indication_event) override;
   void RecordSavePasswordProgress(const std::string& log) override;
   void UserModifiedPasswordField() override;
   void UserModifiedNonPasswordField(uint32_t renderer_id,
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
index 9fcabb6..27ee2f2 100644
--- a/components/password_manager/core/browser/browser_save_password_progress_logger.cc
+++ b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -100,26 +100,6 @@
 
 BrowserSavePasswordProgressLogger::~BrowserSavePasswordProgressLogger() {}
 
-void BrowserSavePasswordProgressLogger::LogFormSignatures(
-    SavePasswordProgressLogger::StringID label,
-    const autofill::PasswordForm& form) {
-  FormStructure form_structure(form.form_data);
-  std::string message = GetStringFromID(label) + ": {\n";
-  message += GetStringFromID(STRING_FORM_SIGNATURE) + ": " +
-             FormSignatureToDebugString(form_structure.form_signature()) + "\n";
-  message += GetStringFromID(STRING_SIGNON_REALM) + ": " +
-             ScrubURL(GURL(form.signon_realm)) + "\n";
-  message +=
-      GetStringFromID(STRING_ORIGIN) + ": " + ScrubURL(form.origin) + "\n";
-  message +=
-      GetStringFromID(STRING_ACTION) + ": " + ScrubURL(form.action) + "\n";
-  message += GetStringFromID(STRING_FORM_NAME) + ": " +
-             ScrubElementID(form.form_data.name) + "\n";
-  message += FormStructureToFieldsLogString(form_structure);
-  message += "}";
-  SendLog(message);
-}
-
 void BrowserSavePasswordProgressLogger::LogFormStructure(
     StringID label,
     const FormStructure& form_structure) {
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.h b/components/password_manager/core/browser/browser_save_password_progress_logger.h
index 7a072d5..751d053 100644
--- a/components/password_manager/core/browser/browser_save_password_progress_logger.h
+++ b/components/password_manager/core/browser/browser_save_password_progress_logger.h
@@ -32,10 +32,6 @@
 
   // Browser-specific addition to the base class' Log* methods. The input is
   // sanitized and passed to SendLog for display.
-  void LogFormSignatures(StringID label, const autofill::PasswordForm& form);
-
-  // Browser-specific addition to the base class' Log* methods. The input is
-  // sanitized and passed to SendLog for display.
   void LogFormStructure(StringID label, const autofill::FormStructure& form);
 
   // Browser-specific addition to the base class' Log* methods. The input is
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc b/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
index 764834d..2b042b2b 100644
--- a/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
+++ b/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
@@ -76,41 +76,6 @@
 
 }  // namespace
 
-TEST_F(BrowserSavePasswordProgressLoggerTest, LogFormSignatures) {
-  MockLogManager log_manager;
-  TestLogger logger(&log_manager);
-
-  autofill::FormStructure form_structure(form_);
-
-  // Add a vote, a generation event and a client-side classifier outcome to the
-  // password field.
-  autofill::ServerFieldTypeSet type_set;
-  type_set.insert(autofill::NEW_PASSWORD);
-  form_structure.field(0)->set_possible_types(type_set);
-  form_structure.field(0)->set_generation_type(
-      autofill::AutofillUploadContents::Field::
-          MANUALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM);
-
-  // Add a server prediction for the text field.
-  form_structure.field(1)->set_server_type(autofill::EMAIL_ADDRESS);
-
-  logger.LogFormStructure(Logger::STRING_PASSWORD_FORM_VOTE, form_structure);
-  SCOPED_TRACE(testing::Message() << "Log string = ["
-                                  << logger.accumulated_log() << "]");
-  EXPECT_TRUE(logger.LogsContainSubstring("PasswordForm vote: {"));
-  EXPECT_TRUE(logger.LogsContainSubstring("Signature of form"));
-  EXPECT_TRUE(logger.LogsContainSubstring("Origin: http://myform.com"));
-  EXPECT_TRUE(logger.LogsContainSubstring("Form fields:"));
-  EXPECT_TRUE(logger.LogsContainSubstring(
-      "password: 2051817934, type=password, renderer_id = 10, "
-      "autocomplete=new-password, VOTE: "
-      "NEW_PASSWORD, GENERATION_EVENT: "
-      "Manual generation on sign-up"));
-  EXPECT_TRUE(
-      logger.LogsContainSubstring("email: 420638584, type=text, renderer_id = "
-                                  "42, SERVER_PREDICTION: EMAIL_ADDRESS"));
-}
-
 TEST_F(BrowserSavePasswordProgressLoggerTest, LogFormData) {
   MockLogManager log_manager;
   TestLogger logger(&log_manager);
diff --git a/components/password_manager/core/browser/password_form_filling.cc b/components/password_manager/core/browser/password_form_filling.cc
index 9652bf00..db4371ef 100644
--- a/components/password_manager/core/browser/password_form_filling.cc
+++ b/components/password_manager/core/browser/password_form_filling.cc
@@ -41,7 +41,7 @@
   return PreferredRealmIsFromAndroid(fill_data);
 }
 
-bool ShouldShowInitialPasswordAccountSuggestions() {
+bool IsFillOnAccountSelectFeatureEnabled() {
   return base::FeatureList::IsEnabled(
       password_manager::features::kFillOnAccountSelect);
 }
@@ -77,29 +77,6 @@
                                 &federated_matches);
 }
 
-void ShowInitialPasswordAccountSuggestions(
-    const PasswordManagerClient& client,
-    PasswordManagerDriver* driver,
-    const PasswordForm& form_for_autofill,
-    const std::map<base::string16, const PasswordForm*>& best_matches,
-    const PasswordForm& preferred_match,
-    bool wait_for_username) {
-  DCHECK_EQ(PasswordForm::Scheme::kHtml, preferred_match.scheme);
-
-  std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
-  if (password_manager_util::IsLoggingActive(&client)) {
-    logger.reset(new BrowserSavePasswordProgressLogger(client.GetLogManager()));
-    logger->LogMessage(
-        Logger::
-            STRING_PASSWORDMANAGER_SHOW_INITIAL_PASSWORD_ACCOUNT_SUGGESTIONS);
-  }
-
-  if (logger)
-    logger->LogBoolean(Logger::STRING_WAIT_FOR_USERNAME, wait_for_username);
-  driver->ShowInitialPasswordAccountSuggestions(PasswordFormFillData(
-      form_for_autofill, best_matches, preferred_match, wait_for_username));
-}
-
 }  // namespace
 
 LikelyFormFilling SendFillInformationToRenderer(
@@ -158,6 +135,8 @@
     wait_for_username_reason = WaitForUsernameReason::kFoasOnHTTP;
   } else if (autofill::IsTouchToFillEnabled()) {
     wait_for_username_reason = WaitForUsernameReason::kTouchToFill;
+  } else if (IsFillOnAccountSelectFeatureEnabled()) {
+    wait_for_username_reason = WaitForUsernameReason::kFoasFeature;
   }
 
   // Record no "FirstWaitForUsernameReason" metrics for a form that is not meant
@@ -182,19 +161,9 @@
         PasswordFormMetricsRecorder::kManagerFillEventAutofilled);
     base::RecordAction(base::UserMetricsAction("PasswordManager_Autofilled"));
   }
-  if (ShouldShowInitialPasswordAccountSuggestions()) {
-    // This is for the fill-on-account-select experiment. Instead of autofilling
-    // found usernames and passwords on load, this instructs the renderer to
-    // return with any found password forms so a list of password account
-    // suggestions can be drawn.
-    ShowInitialPasswordAccountSuggestions(*client, driver, observed_form,
-                                          best_matches, *preferred_match,
-                                          wait_for_username);
-    return LikelyFormFilling::kShowInitialAccountSuggestions;
-  }
 
-  // If fill-on-account-select is not enabled, continue with autofilling any
-  // password forms as traditionally has been done.
+  // Continue with autofilling any password forms as traditionally has been
+  // done.
   Autofill(client, driver, observed_form, best_matches, federated_matches,
            *preferred_match, wait_for_username);
   return wait_for_username ? LikelyFormFilling::kFillOnAccountSelect
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 322310d..5c56853c 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -369,6 +369,12 @@
   CreatePendingCredentials();
 }
 
+void PasswordFormManager::UpdateSubmissionIndicatorEvent(
+    autofill::mojom::SubmissionIndicatorEvent event) {
+  parsed_submitted_form_->form_data.submission_event = event;
+  parsed_submitted_form_->submission_event = event;
+}
+
 void PasswordFormManager::OnNopeUpdateClicked() {
   votes_uploader_.UploadPasswordVote(*parsed_submitted_form_,
                                      *parsed_submitted_form_,
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index 668ce74..802b7ca 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -128,6 +128,9 @@
   // Sends fill data to the renderer to fill |observed_form|.
   void FillForm(const autofill::FormData& observed_form);
 
+  void UpdateSubmissionIndicatorEvent(
+      autofill::mojom::SubmissionIndicatorEvent event);
+
   // Sends the request to prefill the generated password or pops up an
   // additional UI in case of possible override.
   void OnGeneratedPasswordAccepted(autofill::FormData form_data,
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.h b/components/password_manager/core/browser/password_form_metrics_recorder.h
index cd083d0..f61927f2 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder.h
+++ b/components/password_manager/core/browser/password_form_metrics_recorder.h
@@ -226,7 +226,9 @@
     kFoasOnHTTP = 4,
     // The Touch To Fill feature is enabled.
     kTouchToFill = 5,
-    kMaxValue = kTouchToFill,
+    // Show suggestion on account selection feature is enabled.
+    kFoasFeature = 6,
+    kMaxValue = kFoasFeature,
   };
 
   // This metric records the user experience with the passwords filling. The
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index dc3c32f3..2c67ee4 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -392,17 +392,23 @@
   ProvisionallySaveForm(password_form.form_data, driver, false);
 }
 
-
 void PasswordManager::OnPasswordFormSubmittedNoChecks(
     password_manager::PasswordManagerDriver* driver,
-    const PasswordForm& password_form) {
+    autofill::mojom::SubmissionIndicatorEvent event) {
   if (password_manager_util::IsLoggingActive(client_)) {
     BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
     logger.LogMessage(Logger::STRING_ON_SAME_DOCUMENT_NAVIGATION);
   }
+  PasswordFormManager* submitted_manager = GetSubmittedManager();
+  // TODO(crbug.com/949519): Add UMA metric for how frequently submitted_manager
+  // is actually null.
+  if (!submitted_manager || !submitted_manager->GetSubmittedForm())
+    return;
 
-  if (gaia::IsGaiaSignonRealm(GURL(password_form.signon_realm)) &&
-      !IsThereVisiblePasswordField(password_form.form_data)) {
+  const PasswordForm* submitted_form = submitted_manager->GetSubmittedForm();
+
+  if (gaia::IsGaiaSignonRealm(GURL(submitted_form->signon_realm)) &&
+      !IsThereVisiblePasswordField(submitted_form->form_data)) {
     // Gaia form without visible password fields is found.
     // It might happen only when Password Manager autofilled a username
     // (visible) and a password (invisible) fields. Then the user typed a new
@@ -411,11 +417,27 @@
     return;
   }
 
+  submitted_manager->UpdateSubmissionIndicatorEvent(event);
+
+  if (IsAutomaticSavePromptAvailable())
+    OnLoginSuccessful();
+}
+
+#if defined(OS_IOS)
+void PasswordManager::OnPasswordFormSubmittedNoChecksForiOS(
+    password_manager::PasswordManagerDriver* driver,
+    const PasswordForm& password_form) {
+  if (password_manager_util::IsLoggingActive(client_)) {
+    BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
+    logger.LogMessage(Logger::STRING_ON_SAME_DOCUMENT_NAVIGATION);
+  }
+
   ProvisionallySaveForm(password_form.form_data, driver, false);
 
   if (IsAutomaticSavePromptAvailable())
     OnLoginSuccessful();
 }
+#endif
 
 void PasswordManager::OnUserModifiedNonPasswordField(
     PasswordManagerDriver* driver,
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h
index a9e5ca0..8137014 100644
--- a/components/password_manager/core/browser/password_manager.h
+++ b/components/password_manager/core/browser/password_manager.h
@@ -104,13 +104,23 @@
                                const autofill::PasswordForm& password_form);
 
   // Handles a password form being submitted, assumes that submission is
-  // successful and does not do any checks on success of submission.
-  // For example, this is called if |password_form| was filled
-  // upon in-page navigation. This often means history.pushState being
-  // called from JavaScript.
+  // successful and does not do any checks on success of submission. For
+  // example, this is called if |password_form| was filled upon in-page
+  // navigation. This often means history.pushState being called from
+  // JavaScript.
+  // TODO(crbug.com/949519): Rename this method together with
+  // SameDocumentNavigation in autofill::mojom::PasswordManagerDriver
   void OnPasswordFormSubmittedNoChecks(
       PasswordManagerDriver* driver,
+      autofill::mojom::SubmissionIndicatorEvent event);
+
+#if defined(OS_IOS)
+  // Similar to OnPasswordFormSubmittedNoChecks() but for iOS which is using a
+  // different signature for now.
+  void OnPasswordFormSubmittedNoChecksForiOS(
+      PasswordManagerDriver* driver,
       const autofill::PasswordForm& password_form);
+#endif
 
   // Called when a user changed a value in a non-password field. The field is in
   // a frame corresponding to |driver| and has a renderer id |renderer_id|.
diff --git a/components/password_manager/core/browser/password_manager_driver.h b/components/password_manager/core/browser/password_manager_driver.h
index 8b6fbd97..8c81c21e 100644
--- a/components/password_manager/core/browser/password_manager_driver.h
+++ b/components/password_manager/core/browser/password_manager_driver.h
@@ -49,11 +49,6 @@
   virtual void FormEligibleForGenerationFound(
       const autofill::PasswordFormGenerationData& form) {}
 
-  // Notifies the driver that username and password predictions from autofill
-  // have been received.
-  virtual void AutofillDataReceived(
-      const autofill::FormsPredictionsMap& predictions) {}
-
   // Notifies the driver that the user has accepted a generated password.
   // TODO(crbug/936011): delete this method. The UI should call the one below.
   virtual void GeneratedPasswordAccepted(const base::string16& password) = 0;
@@ -80,11 +75,6 @@
   virtual void PreviewSuggestion(const base::string16& username,
                                  const base::string16& password) = 0;
 
-  // Tells the driver to show an initial set of accounts to suggest for the
-  // form.
-  virtual void ShowInitialPasswordAccountSuggestions(
-      const autofill::PasswordFormFillData& form_data) = 0;
-
   // Tells the driver to clear previewed password and username fields.
   virtual void ClearPreviewedForm() = 0;
 
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc
index 1725ba6..be4ca14 100644
--- a/components/password_manager/core/browser/password_manager_metrics_util.cc
+++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -28,13 +28,6 @@
 
 namespace metrics_util {
 
-void LogUMAHistogramBoolean(const std::string& name, bool sample) {
-  // Note: This leaks memory, which is expected behavior.
-  base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet(
-      name, base::Histogram::kUmaTargetedHistogramFlag);
-  histogram->AddBoolean(sample);
-}
-
 void LogGeneralUIDismissalReason(UIDismissalReason reason) {
   base::UmaHistogramEnumeration("PasswordManager.UIDismissalReason", reason,
                                 NUM_UI_RESPONSES);
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h
index fc449fe..e72b1aab 100644
--- a/components/password_manager/core/browser/password_manager_metrics_util.h
+++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -445,10 +445,6 @@
   kMaxValue = kConflictWithEmptyUsername
 };
 
-// A version of the UMA_HISTOGRAM_BOOLEAN macro that allows the |name|
-// to vary over the program's runtime.
-void LogUMAHistogramBoolean(const std::string& name, bool sample);
-
 // Log the |reason| a user dismissed the password manager UI except save/update
 // bubbles.
 void LogGeneralUIDismissalReason(UIDismissalReason reason);
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index e9943a9d..29235fe 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -190,8 +190,6 @@
   MOCK_METHOD1(FormEligibleForGenerationFound,
                void(const autofill::PasswordFormGenerationData&));
   MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&));
-  MOCK_METHOD1(AutofillDataReceived,
-               void(const autofill::FormsPredictionsMap&));
   MOCK_METHOD0(GetPasswordManager, PasswordManager*());
   MOCK_METHOD0(GetPasswordAutofillManager, PasswordAutofillManager*());
   MOCK_CONST_METHOD0(GetLastCommittedURL, const GURL&());
@@ -1695,19 +1693,18 @@
   std::vector<PasswordForm> observed;
   PasswordForm form(MakeSimpleForm());
   observed.push_back(form);
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
+      .WillRepeatedly(Return(true));
   EXPECT_CALL(*store_, GetLogins(_, _))
       .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
-  EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
-      .WillRepeatedly(Return(true));
+  manager()->ShowManualFallbackForSaving(&driver_, form);
 
   std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
       .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
-
-  manager()->OnPasswordFormSubmittedNoChecks(&driver_, form);
+  manager()->OnPasswordFormSubmittedNoChecks(&driver_, form.submission_event);
   ASSERT_TRUE(form_manager_to_save);
 
   // Simulate saving the form, as if the info bar was accepted.
@@ -1729,17 +1726,17 @@
   // the old parser is gone.
   EXPECT_CALL(*store_, GetLogins(_, _))
       .WillRepeatedly(WithArg<1>(InvokeConsumer(blacklisted_form)));
-  manager()->OnPasswordFormsParsed(&driver_, observed);
-  manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
   EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
       .WillRepeatedly(Return(true));
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed, true);
+  manager()->ShowManualFallbackForSaving(&driver_, form);
 
   std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
       .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
 
-  manager()->OnPasswordFormSubmittedNoChecks(&driver_, form);
+  manager()->OnPasswordFormSubmittedNoChecks(&driver_, form.submission_event);
   EXPECT_TRUE(form_manager_to_save->IsBlacklisted());
 }
 
@@ -2679,6 +2676,7 @@
   observed.push_back(form);
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
+  manager()->ShowManualFallbackForSaving(&driver_, form);
 
   auto submitted_form = form;
   submitted_form.form_data.fields[0].value = ASCIIToUTF16("username");
@@ -2687,7 +2685,8 @@
   std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
       .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
-  manager()->OnPasswordFormSubmittedNoChecks(&driver_, submitted_form);
+  manager()->OnPasswordFormSubmittedNoChecks(&driver_,
+                                             submitted_form.submission_event);
   EXPECT_TRUE(manager()->form_managers().empty());
 }
 
@@ -2710,7 +2709,7 @@
   form.form_data.fields[1].is_focusable = false;
 
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
-  manager()->OnPasswordFormSubmittedNoChecks(&driver_, form);
+  manager()->OnPasswordFormSubmittedNoChecks(&driver_, form.submission_event);
 }
 
 TEST_F(PasswordManagerTest, MetricForSchemeOfSuccessfulLogins) {
@@ -2797,7 +2796,8 @@
   submitted_form.form_data.fields[1].value = ASCIIToUTF16("strong_password");
 
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
-  manager()->OnPasswordFormSubmittedNoChecks(&driver_, submitted_form);
+  manager()->OnPasswordFormSubmittedNoChecks(&driver_,
+                                             submitted_form.submission_event);
 }
 
 TEST_F(PasswordManagerTest, NoSavePromptForNotPasswordForm) {
@@ -2816,7 +2816,8 @@
   submitted_form.form_data.fields[1].value = ASCIIToUTF16("1234");
 
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
-  manager()->OnPasswordFormSubmittedNoChecks(&driver_, submitted_form);
+  manager()->OnPasswordFormSubmittedNoChecks(&driver_,
+                                             submitted_form.submission_event);
 }
 
 // Check that when autofill predictions are received before a form is found then
diff --git a/components/password_manager/core/browser/stub_password_manager_driver.cc b/components/password_manager/core/browser/stub_password_manager_driver.cc
index b1c289b2..00d63eb 100644
--- a/components/password_manager/core/browser/stub_password_manager_driver.cc
+++ b/components/password_manager/core/browser/stub_password_manager_driver.cc
@@ -29,9 +29,6 @@
     const base::string16& password) {
 }
 
-void StubPasswordManagerDriver::ShowInitialPasswordAccountSuggestions(
-    const autofill::PasswordFormFillData& form_data) {}
-
 void StubPasswordManagerDriver::ClearPreviewedForm() {
 }
 
diff --git a/components/password_manager/core/browser/stub_password_manager_driver.h b/components/password_manager/core/browser/stub_password_manager_driver.h
index a2676b2..76f66efa 100644
--- a/components/password_manager/core/browser/stub_password_manager_driver.h
+++ b/components/password_manager/core/browser/stub_password_manager_driver.h
@@ -26,8 +26,6 @@
                       const base::string16& password) override;
   void PreviewSuggestion(const base::string16& username,
                          const base::string16& password) override;
-  void ShowInitialPasswordAccountSuggestions(
-      const autofill::PasswordFormFillData& form_data) override;
   void ClearPreviewedForm() override;
   PasswordGenerationFrameHelper* GetPasswordGenerationHelper() override;
   PasswordManager* GetPasswordManager() override;
diff --git a/components/password_manager/core/browser/sync/password_syncable_service.cc b/components/password_manager/core/browser/sync/password_syncable_service.cc
index 62a0f67f..331b0038 100644
--- a/components/password_manager/core/browser/sync/password_syncable_service.cc
+++ b/components/password_manager/core/browser/sync/password_syncable_service.cc
@@ -338,12 +338,6 @@
   std::vector<std::unique_ptr<autofill::PasswordForm>> blacklist_entries;
   if (!password_store_->FillAutofillableLogins(&autofillable_entries) ||
       !password_store_->FillBlacklistLogins(&blacklist_entries)) {
-    // Password store often fails to load passwords. Track failures with UMA.
-    // (http://crbug.com/249000)
-    // TODO(wychen): enum uma should be strongly typed. crbug.com/661401
-    UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad",
-                              ModelTypeToHistogramInt(syncer::PASSWORDS),
-                              static_cast<int>(syncer::ModelType::NUM_ENTRIES));
     return false;
   }
   password_entries->resize(autofillable_entries.size() +
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index 73a3a3f..c4cd3423 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -1352,6 +1352,14 @@
   optional string device_login_screen_webusb_allow_devices_for_urls = 1;
 }
 
+// Settings that control if the device is enforced to show (or hide) system
+// information.
+message DeviceLoginScreenSystemInfoEnforcedProto {
+  // Determines whether the system information is always shown (or hidden) on
+  // the login screen.
+  optional bool enabled = 1;
+}
+
 message ChromeDeviceSettingsProto {
   reserved 61, 90;
   optional DevicePolicyRefreshRateProto device_policy_refresh_rate = 1;
@@ -1466,4 +1474,6 @@
   optional DevicePowerwashAllowedProto device_powerwash_allowed = 91;
   optional DeviceLoginScreenWebUsbAllowDevicesForUrlsProto
       device_login_screen_webusb_allow_devices_for_urls = 92;
+  optional DeviceLoginScreenSystemInfoEnforcedProto
+      device_login_screen_system_info_enforced = 93;
 }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 7c73b12..0707af7 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -805,6 +805,7 @@
         'DeviceLoginScreenExtensions',
         'DeviceLoginScreenLocales',
         'DeviceLoginScreenInputMethods',
+        'DeviceLoginScreenSystemInfoEnforced',
         'DeviceSecondFactorAuthentication',
         'DeviceLoginScreenIsolateOrigins',
         'DeviceLoginScreenSitePerProcess',
@@ -13111,6 +13112,29 @@
       If this policy is set to a list of input method identifiers, the given input methods will be available on the sign-in screen. The first given input method will be preselected. While a user pod is focused on the sign-in screen, the user's last used input method will be available in addition to the input methods given by this policy. If this policy is not set, the input methods on the sign-in screen will be derived from the locale in which the sign-in screen is displayed. Values which are not valid input method identifiers will be ignored.''',
     },
     {
+      'name': 'DeviceLoginScreenSystemInfoEnforced',
+      'owners': ['anqing@chromium.org'],
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'supported_on': ['chrome_os:79-'],
+      'supported_chrome_os_management': ['google_cloud'],
+      'device_only': True,
+      'features': {
+        'dynamic_refresh': True,
+      },
+      'example_value': True,
+      'id': 609,
+      'caption': '''Force the sign-in screen to show or hide system information.''',
+      'tags': [],
+      'desc': '''Specify whether the system information (e.g. Chrome OS version, device serial
+      number) is always shown (or hidden) on the login screen.
+
+      If the policy is set to true, the system information will be shown forcedly.
+      If the policy is set to false, the system information will be hidden forcedly.
+      If the policy is unset, default hehavior (being shown for Canary / Dev channel)
+      is effective. Users can toggle the visibility by specific operations (e.g., Alt-V).'''
+    },
+    {
       'name': 'SmsMessagesAllowed',
       'owners': ['jlklein@chromium.org', 'jonmann@chromium.org'],
       'type': 'main',
@@ -18051,6 +18075,7 @@
     'DeviceLoginScreenDomainAutoComplete': 'login_screen_domain_auto_complete.login_screen_domain_auto_complete',
     'DeviceLoginScreenLocales': 'login_screen_locales.login_screen_locales',
     'DeviceLoginScreenInputMethods': 'login_screen_input_methods.login_screen_input_methods',
+    'DeviceLoginScreenSystemInfoEnforced': 'device_login_screen_system_info_enforced.enabled',
     'DeviceSamlLoginAuthenticationType': 'saml_login_authentication_type.saml_login_authentication_type',
     'DeviceDataRoamingEnabled': 'data_roaming_enabled.data_roaming_enabled',
     'AllowKioskAppControlChromeVersion': 'allow_kiosk_app_control_chrome_version.allow_kiosk_app_control_chrome_version',
@@ -18606,6 +18631,6 @@
   ],
   'placeholders': [],
   'deleted_policy_ids': [412, 546, 562, 569],
-  'highest_id_currently_used': 608,
+  'highest_id_currently_used': 609,
   'highest_atomic_group_id_currently_used': 37
 }
diff --git a/components/search_engines/keyword_web_data_service.cc b/components/search_engines/keyword_web_data_service.cc
index 8638763..07de4b1 100644
--- a/components/search_engines/keyword_web_data_service.cc
+++ b/components/search_engines/keyword_web_data_service.cc
@@ -135,9 +135,14 @@
                         base::Bind(&SetBuiltinKeywordVersionImpl, version));
 }
 
+void KeywordWebDataService::ShutdownOnUISequence() {
+  CommitQueuedOperations();
+  WebDataServiceBase::ShutdownOnUISequence();
+}
+
 KeywordWebDataService::~KeywordWebDataService() {
   DCHECK(!batch_mode_level_);
-  CommitQueuedOperations();
+  DCHECK(queued_keyword_operations_.empty());
 }
 
 void KeywordWebDataService::AdjustBatchModeLevel(bool entering_batch_mode) {
diff --git a/components/search_engines/keyword_web_data_service.h b/components/search_engines/keyword_web_data_service.h
index 2b4a16c..f3e23ca 100644
--- a/components/search_engines/keyword_web_data_service.h
+++ b/components/search_engines/keyword_web_data_service.h
@@ -88,6 +88,9 @@
   // Sets the version of the builtin keywords.
   void SetBuiltinKeywordVersion(int version);
 
+  // WebDataServiceBase:
+  void ShutdownOnUISequence() override;
+
  protected:
   ~KeywordWebDataService() override;
 
diff --git a/components/sync/base/model_type.cc b/components/sync/base/model_type.cc
index 50bd0dc..bcbb2e88f 100644
--- a/components/sync/base/model_type.cc
+++ b/components/sync/base/model_type.cc
@@ -47,7 +47,7 @@
   const int specifics_field_number;
   // Model type value from SyncModelTypes enum in enums.xml. Must always be in
   // sync with the enum.
-  const int model_type_histogram_val;
+  const ModelTypeForHistograms model_type_histogram_val;
 };
 
 // Below struct entries are in the same order as their definition in the
@@ -57,113 +57,151 @@
 //  - update the SyncModelType histogram suffix in histograms.xml.
 // Struct field values should be unique across the entire map.
 const ModelTypeInfo kModelTypeInfoMap[] = {
-    {UNSPECIFIED, "", "", "Unspecified", -1, 0},
-    {TOP_LEVEL_FOLDER, "", "", "Top Level Folder", -1, 1},
+    {UNSPECIFIED, "", "", "Unspecified", -1,
+     ModelTypeForHistograms::kUnspecified},
+    {TOP_LEVEL_FOLDER, "", "", "Top Level Folder", -1,
+     ModelTypeForHistograms::kTopLevelFolder},
     {BOOKMARKS, "BOOKMARK", "bookmarks", "Bookmarks",
-     sync_pb::EntitySpecifics::kBookmarkFieldNumber, 2},
+     sync_pb::EntitySpecifics::kBookmarkFieldNumber,
+     ModelTypeForHistograms::kBookmarks},
     {PREFERENCES, "PREFERENCE", "preferences", "Preferences",
-     sync_pb::EntitySpecifics::kPreferenceFieldNumber, 3},
+     sync_pb::EntitySpecifics::kPreferenceFieldNumber,
+     ModelTypeForHistograms::kPreferences},
     {PASSWORDS, "PASSWORD", "passwords", "Passwords",
-     sync_pb::EntitySpecifics::kPasswordFieldNumber, 4},
+     sync_pb::EntitySpecifics::kPasswordFieldNumber,
+     ModelTypeForHistograms::kPasswords},
     {AUTOFILL_PROFILE, "AUTOFILL_PROFILE", "autofill_profiles",
      "Autofill Profiles", sync_pb::EntitySpecifics::kAutofillProfileFieldNumber,
-     5},
+     ModelTypeForHistograms::kAutofillProfile},
     {AUTOFILL, "AUTOFILL", "autofill", "Autofill",
-     sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},
+     sync_pb::EntitySpecifics::kAutofillFieldNumber,
+     ModelTypeForHistograms::kAutofill},
     {AUTOFILL_WALLET_DATA, "AUTOFILL_WALLET", "autofill_wallet",
      "Autofill Wallet", sync_pb::EntitySpecifics::kAutofillWalletFieldNumber,
-     34},
+     ModelTypeForHistograms::kAutofillWalletData},
     {AUTOFILL_WALLET_METADATA, "WALLET_METADATA", "autofill_wallet_metadata",
      "Autofill Wallet Metadata",
-     sync_pb::EntitySpecifics::kWalletMetadataFieldNumber, 35},
+     sync_pb::EntitySpecifics::kWalletMetadataFieldNumber,
+     ModelTypeForHistograms::kAutofillWalletMetadata},
     {THEMES, "THEME", "themes", "Themes",
-     sync_pb::EntitySpecifics::kThemeFieldNumber, 7},
+     sync_pb::EntitySpecifics::kThemeFieldNumber,
+     ModelTypeForHistograms::kThemes},
     {TYPED_URLS, "TYPED_URL", "typed_urls", "Typed URLs",
-     sync_pb::EntitySpecifics::kTypedUrlFieldNumber, 8},
+     sync_pb::EntitySpecifics::kTypedUrlFieldNumber,
+     ModelTypeForHistograms::kTypedUrls},
     {EXTENSIONS, "EXTENSION", "extensions", "Extensions",
-     sync_pb::EntitySpecifics::kExtensionFieldNumber, 9},
+     sync_pb::EntitySpecifics::kExtensionFieldNumber,
+     ModelTypeForHistograms::kExtensions},
     {SEARCH_ENGINES, "SEARCH_ENGINE", "search_engines", "Search Engines",
-     sync_pb::EntitySpecifics::kSearchEngineFieldNumber, 10},
+     sync_pb::EntitySpecifics::kSearchEngineFieldNumber,
+     ModelTypeForHistograms::kSearchEngines},
     {SESSIONS, "SESSION", "sessions", "Sessions",
-     sync_pb::EntitySpecifics::kSessionFieldNumber, 11},
+     sync_pb::EntitySpecifics::kSessionFieldNumber,
+     ModelTypeForHistograms::kSessions},
     {APPS, "APP", "apps", "Apps", sync_pb::EntitySpecifics::kAppFieldNumber,
-     12},
+     ModelTypeForHistograms::kApps},
     {APP_SETTINGS, "APP_SETTING", "app_settings", "App settings",
-     sync_pb::EntitySpecifics::kAppSettingFieldNumber, 13},
+     sync_pb::EntitySpecifics::kAppSettingFieldNumber,
+     ModelTypeForHistograms::kAppSettings},
     {EXTENSION_SETTINGS, "EXTENSION_SETTING", "extension_settings",
      "Extension settings",
-     sync_pb::EntitySpecifics::kExtensionSettingFieldNumber, 14},
+     sync_pb::EntitySpecifics::kExtensionSettingFieldNumber,
+     ModelTypeForHistograms::kExtensionSettings},
     {DEPRECATED_APP_NOTIFICATIONS, "APP_NOTIFICATION", "app_notifications",
      "App Notifications", sync_pb::EntitySpecifics::kAppNotificationFieldNumber,
-     15},
+     ModelTypeForHistograms::kDeprecatedAppNotifications},
     {HISTORY_DELETE_DIRECTIVES, "HISTORY_DELETE_DIRECTIVE",
      "history_delete_directives", "History Delete Directives",
-     sync_pb::EntitySpecifics::kHistoryDeleteDirectiveFieldNumber, 16},
+     sync_pb::EntitySpecifics::kHistoryDeleteDirectiveFieldNumber,
+     ModelTypeForHistograms::kHistoryDeleteDirectices},
     {DEPRECATED_SYNCED_NOTIFICATIONS, "SYNCED_NOTIFICATION",
      "synced_notifications", "Synced Notifications",
-     sync_pb::EntitySpecifics::kSyncedNotificationFieldNumber, 20},
+     sync_pb::EntitySpecifics::kSyncedNotificationFieldNumber,
+     ModelTypeForHistograms::kDeprecatedSyncedNotifications},
     {DEPRECATED_SYNCED_NOTIFICATION_APP_INFO, "SYNCED_NOTIFICATION_APP_INFO",
      "synced_notification_app_info", "Synced Notification App Info",
-     sync_pb::EntitySpecifics::kSyncedNotificationAppInfoFieldNumber, 31},
+     sync_pb::EntitySpecifics::kSyncedNotificationAppInfoFieldNumber,
+     ModelTypeForHistograms::kDeprecatedSyncedNotificationAppInfo},
     {DICTIONARY, "DICTIONARY", "dictionary", "Dictionary",
-     sync_pb::EntitySpecifics::kDictionaryFieldNumber, 22},
+     sync_pb::EntitySpecifics::kDictionaryFieldNumber,
+     ModelTypeForHistograms::kDictionary},
     {FAVICON_IMAGES, "FAVICON_IMAGE", "favicon_images", "Favicon Images",
-     sync_pb::EntitySpecifics::kFaviconImageFieldNumber, 23},
+     sync_pb::EntitySpecifics::kFaviconImageFieldNumber,
+     ModelTypeForHistograms::kFaviconImages},
     {FAVICON_TRACKING, "FAVICON_TRACKING", "favicon_tracking",
      "Favicon Tracking", sync_pb::EntitySpecifics::kFaviconTrackingFieldNumber,
-     24},
+     ModelTypeForHistograms::kFaviconTracking},
     {DEVICE_INFO, "DEVICE_INFO", "device_info", "Device Info",
-     sync_pb::EntitySpecifics::kDeviceInfoFieldNumber, 18},
+     sync_pb::EntitySpecifics::kDeviceInfoFieldNumber,
+     ModelTypeForHistograms::kDeviceInfo},
     {PRIORITY_PREFERENCES, "PRIORITY_PREFERENCE", "priority_preferences",
      "Priority Preferences",
-     sync_pb::EntitySpecifics::kPriorityPreferenceFieldNumber, 21},
+     sync_pb::EntitySpecifics::kPriorityPreferenceFieldNumber,
+     ModelTypeForHistograms::kPriorityPreferences},
     {SUPERVISED_USER_SETTINGS, "MANAGED_USER_SETTING", "managed_user_settings",
      "Managed User Settings",
-     sync_pb::EntitySpecifics::kManagedUserSettingFieldNumber, 26},
+     sync_pb::EntitySpecifics::kManagedUserSettingFieldNumber,
+     ModelTypeForHistograms::kSupervisedUserSettings},
     {DEPRECATED_SUPERVISED_USERS, "MANAGED_USER", "managed_users",
-     "Managed Users", sync_pb::EntitySpecifics::kManagedUserFieldNumber, 27},
+     "Managed Users", sync_pb::EntitySpecifics::kManagedUserFieldNumber,
+     ModelTypeForHistograms::kDeprecatedSupervisedUsers},
     {DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS, "MANAGED_USER_SHARED_SETTING",
      "managed_user_shared_settings", "Managed User Shared Settings",
-     sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber, 30},
+     sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber,
+     ModelTypeForHistograms::kDeprecatedSupervisedUserSharedSettings},
     {DEPRECATED_ARTICLES, "ARTICLE", "articles", "Articles",
-     sync_pb::EntitySpecifics::kArticleFieldNumber, 28},
+     sync_pb::EntitySpecifics::kArticleFieldNumber,
+     ModelTypeForHistograms::kDeprecatedArticles},
     {APP_LIST, "APP_LIST", "app_list", "App List",
-     sync_pb::EntitySpecifics::kAppListFieldNumber, 29},
+     sync_pb::EntitySpecifics::kAppListFieldNumber,
+     ModelTypeForHistograms::kAppList},
     {DEPRECATED_WIFI_CREDENTIALS, "WIFI_CREDENTIAL", "wifi_credentials",
      "WiFi Credentials", sync_pb::EntitySpecifics::kWifiCredentialFieldNumber,
-     32},
+     ModelTypeForHistograms::kDeprecatedWifiCredentials},
     {SUPERVISED_USER_WHITELISTS, "MANAGED_USER_WHITELIST",
      "managed_user_whitelists", "Managed User Whitelists",
-     sync_pb::EntitySpecifics::kManagedUserWhitelistFieldNumber, 33},
+     sync_pb::EntitySpecifics::kManagedUserWhitelistFieldNumber,
+     ModelTypeForHistograms::kSupervisedUserWhitelists},
     {ARC_PACKAGE, "ARC_PACKAGE", "arc_package", "Arc Package",
-     sync_pb::EntitySpecifics::kArcPackageFieldNumber, 36},
+     sync_pb::EntitySpecifics::kArcPackageFieldNumber,
+     ModelTypeForHistograms::kArcPackage},
     {PRINTERS, "PRINTER", "printers", "Printers",
-     sync_pb::EntitySpecifics::kPrinterFieldNumber, 37},
+     sync_pb::EntitySpecifics::kPrinterFieldNumber,
+     ModelTypeForHistograms::kPrinters},
     {READING_LIST, "READING_LIST", "reading_list", "Reading List",
-     sync_pb::EntitySpecifics::kReadingListFieldNumber, 38},
+     sync_pb::EntitySpecifics::kReadingListFieldNumber,
+     ModelTypeForHistograms::kReadingList},
     {USER_EVENTS, "USER_EVENT", "user_events", "User Events",
-     sync_pb::EntitySpecifics::kUserEventFieldNumber, 39},
+     sync_pb::EntitySpecifics::kUserEventFieldNumber,
+     ModelTypeForHistograms::kUserEvents},
     {MOUNTAIN_SHARES, "MOUNTAIN_SHARE", "mountain_shares", "Mountain Shares",
-     sync_pb::EntitySpecifics::kMountainShareFieldNumber, 40},
+     sync_pb::EntitySpecifics::kMountainShareFieldNumber,
+     ModelTypeForHistograms::kMountainShares},
     {USER_CONSENTS, "USER_CONSENT", "user_consent", "User Consents",
-     sync_pb::EntitySpecifics::kUserConsentFieldNumber, 41},
+     sync_pb::EntitySpecifics::kUserConsentFieldNumber,
+     ModelTypeForHistograms::kUserConsents},
     {SEND_TAB_TO_SELF, "SEND_TAB_TO_SELF", "send_tab_to_self",
      "Send Tab To Self", sync_pb::EntitySpecifics::kSendTabToSelfFieldNumber,
-     42},
+     ModelTypeForHistograms::kSendTabToSelf},
     {SECURITY_EVENTS, "SECURITY_EVENT", "security_events", "Security Events",
-     sync_pb::EntitySpecifics::kSecurityEventFieldNumber, 43},
+     sync_pb::EntitySpecifics::kSecurityEventFieldNumber,
+     ModelTypeForHistograms::kSecurityEvents},
     {WIFI_CONFIGURATIONS, "WIFI_CONFIGURATION", "wifi_configurations",
      "Wifi Configurations",
-     sync_pb::EntitySpecifics::kWifiConfigurationFieldNumber, 44},
+     sync_pb::EntitySpecifics::kWifiConfigurationFieldNumber,
+     ModelTypeForHistograms::kWifiConfigurations},
     {WEB_APPS, "WEB_APP", "web_apps", "Web Apps",
-     sync_pb::EntitySpecifics::kWebAppFieldNumber, 45},
+     sync_pb::EntitySpecifics::kWebAppFieldNumber,
+     ModelTypeForHistograms::kWebApps},
     // ---- Proxy types ----
-    {PROXY_TABS, "", "", "Tabs", -1, 25},
+    {PROXY_TABS, "", "", "Tabs", -1, ModelTypeForHistograms::kProxyTabs},
     // ---- Control Types ----
     {NIGORI, "NIGORI", "nigori", "Encryption Keys",
-     sync_pb::EntitySpecifics::kNigoriFieldNumber, 17},
+     sync_pb::EntitySpecifics::kNigoriFieldNumber,
+     ModelTypeForHistograms::kNigori},
     {DEPRECATED_EXPERIMENTS, "EXPERIMENTS", "experiments", "Experiments",
-     sync_pb::EntitySpecifics::kExperimentsFieldNumber, 19},
+     sync_pb::EntitySpecifics::kExperimentsFieldNumber,
+     ModelTypeForHistograms::kDeprecatedExperiments},
 };
 
 static_assert(base::size(kModelTypeInfoMap) == ModelType::NUM_ENTRIES,
@@ -528,6 +566,13 @@
 int ModelTypeToHistogramInt(ModelType model_type) {
   DCHECK_GE(model_type, UNSPECIFIED);
   DCHECK_LT(model_type, ModelType::NUM_ENTRIES);
+  return static_cast<int>(
+      kModelTypeInfoMap[model_type].model_type_histogram_val);
+}
+
+ModelTypeForHistograms ModelTypeHistogramValue(ModelType model_type) {
+  DCHECK_GE(model_type, UNSPECIFIED);
+  DCHECK_LT(model_type, ModelType::NUM_ENTRIES);
   return kModelTypeInfoMap[model_type].model_type_histogram_val;
 }
 
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h
index 489c10e..74de9da 100644
--- a/components/sync/base/model_type.h
+++ b/components/sync/base/model_type.h
@@ -176,6 +176,64 @@
   return static_cast<ModelType>(i);
 }
 
+// A version of the ModelType enum for use in histograms. ModelType does not
+// have stable values (e.g. new ones may be inserted in the middle), so it can't
+// be recorded directly.
+// Instead of using entries from this enum directly, you'll usually want to get
+// them via ModelTypeHistogramValue(model_type).
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused. When you add a new entry, also update
+// SyncModelTypes in enums.xml
+enum class ModelTypeForHistograms {
+  kUnspecified = 0,
+  kTopLevelFolder = 1,
+  kBookmarks = 2,
+  kPreferences = 3,
+  kPasswords = 4,
+  kAutofillProfile = 5,
+  kAutofill = 6,
+  kThemes = 7,
+  kTypedUrls = 8,
+  kExtensions = 9,
+  kSearchEngines = 10,
+  kSessions = 11,
+  kApps = 12,
+  kAppSettings = 13,
+  kExtensionSettings = 14,
+  kDeprecatedAppNotifications = 15,
+  kHistoryDeleteDirectices = 16,
+  kNigori = 17,
+  kDeviceInfo = 18,
+  kDeprecatedExperiments = 19,
+  kDeprecatedSyncedNotifications = 20,
+  kPriorityPreferences = 21,
+  kDictionary = 22,
+  kFaviconImages = 23,
+  kFaviconTracking = 24,
+  kProxyTabs = 25,
+  kSupervisedUserSettings = 26,
+  kDeprecatedSupervisedUsers = 27,
+  kDeprecatedArticles = 28,
+  kAppList = 29,
+  kDeprecatedSupervisedUserSharedSettings = 30,
+  kDeprecatedSyncedNotificationAppInfo = 31,
+  kDeprecatedWifiCredentials = 32,
+  kSupervisedUserWhitelists = 33,
+  kAutofillWalletData = 34,
+  kAutofillWalletMetadata = 35,
+  kArcPackage = 36,
+  kPrinters = 37,
+  kReadingList = 38,
+  kUserEvents = 39,
+  kMountainShares = 40,
+  kUserConsents = 41,
+  kSendTabToSelf = 42,
+  kSecurityEvents = 43,
+  kWifiConfigurations = 44,
+  kWebApps = 45,
+  kMaxValue = kWebApps
+};
+
 // Used to mark the type of EntitySpecifics that has no actual data.
 void AddDefaultFieldValue(ModelType type, sync_pb::EntitySpecifics* specifics);
 
@@ -308,7 +366,10 @@
 // The mapping from ModelType to integer is defined here. It defines a
 // completely different order than the ModelType enum itself. The mapping should
 // match the SyncModelTypes mapping from integer to labels defined in enums.xml.
+// TODO(crbug.com/1007293): Update all histogram recording sites to use
+// ModelTypeHistogramValue() and remove ModelTypeToHistogramInt();
 int ModelTypeToHistogramInt(ModelType model_type);
+ModelTypeForHistograms ModelTypeHistogramValue(ModelType model_type);
 
 // Returns for every model_type a positive unique integer that is stable over
 // time and thus can be used when persisting data.
diff --git a/components/sync/base/model_type_unittest.cc b/components/sync/base/model_type_unittest.cc
index c318006..c55ac38 100644
--- a/components/sync/base/model_type_unittest.cc
+++ b/components/sync/base/model_type_unittest.cc
@@ -73,20 +73,17 @@
 }
 
 TEST_F(ModelTypeTest, ModelTypeHistogramMapping) {
-  std::set<int> histogram_values;
+  std::set<ModelTypeForHistograms> histogram_values;
   ModelTypeSet all_types = ModelTypeSet::All();
   for (ModelType type : all_types) {
     SCOPED_TRACE(ModelTypeToString(type));
-    int histogram_value = ModelTypeToHistogramInt(type);
+    ModelTypeForHistograms histogram_value = ModelTypeHistogramValue(type);
 
     EXPECT_TRUE(histogram_values.insert(histogram_value).second)
         << "Expected histogram values to be unique";
 
-    // This is not necessary for the mapping to be valid, but most instances of
-    // UMA_HISTOGRAM that use this mapping specify ModelType::NUM_ENTRIES as the
-    // maximum possible value.  If you break this assumption, you should update
-    // those histograms.
-    EXPECT_LT(histogram_value, ModelType::NUM_ENTRIES);
+    EXPECT_LE(static_cast<int>(histogram_value),
+              static_cast<int>(ModelTypeForHistograms::kMaxValue));
   }
 }
 
diff --git a/components/sync/engine_impl/model_type_worker.cc b/components/sync/engine_impl/model_type_worker.cc
index 40cbeef0..9d812be2 100644
--- a/components/sync/engine_impl/model_type_worker.cc
+++ b/components/sync/engine_impl/model_type_worker.cc
@@ -263,61 +263,62 @@
   data->name = update_entity.name();
   data->is_folder = update_entity.folder();
   data->parent_id = update_entity.parent_id_string();
-
-  // Handle deprecated positioning fields. Relevant only for bookmarks.
-  bool has_position_scheme = false;
-  SyncPositioningScheme sync_positioning_scheme;
-  if (update_entity.has_unique_position()) {
-    data->unique_position = update_entity.unique_position();
-    has_position_scheme = true;
-    sync_positioning_scheme = SyncPositioningScheme::UNIQUE_POSITION;
-  } else if (update_entity.has_position_in_parent() ||
-             update_entity.has_insert_after_item_id()) {
-    bool missing_originator_fields = false;
-    if (!update_entity.has_originator_cache_guid() ||
-        !update_entity.has_originator_client_item_id()) {
-      DLOG(ERROR) << "Update is missing requirements for bookmark position.";
-      missing_originator_fields = true;
-    }
-
-    std::string suffix =
-        missing_originator_fields
-            ? UniquePosition::RandomSuffix()
-            : GenerateSyncableHash(
-                  syncer::GetModelType(update_entity),
-                  /*client_tag=*/update_entity.originator_cache_guid() +
-                      update_entity.originator_client_item_id());
-
-    if (update_entity.has_position_in_parent()) {
-      data->unique_position =
-          UniquePosition::FromInt64(update_entity.position_in_parent(), suffix)
-              .ToProto();
-      has_position_scheme = true;
-      sync_positioning_scheme = SyncPositioningScheme::POSITION_IN_PARENT;
-    } else {
-      // If update_entity has insert_after_item_id, use 0 index.
-      DCHECK(update_entity.has_insert_after_item_id());
-      data->unique_position = UniquePosition::FromInt64(0, suffix).ToProto();
-      has_position_scheme = true;
-      sync_positioning_scheme = SyncPositioningScheme::INSERT_AFTER_ITEM_ID;
-    }
-  } else if (SyncerProtoUtil::ShouldMaintainPosition(update_entity) &&
-             !update_entity.deleted()) {
-    DLOG(ERROR) << "Missing required position information in update.";
-    has_position_scheme = true;
-    sync_positioning_scheme = SyncPositioningScheme::MISSING;
-  }
-  if (has_position_scheme) {
-    UMA_HISTOGRAM_ENUMERATION("Sync.Entities.PositioningScheme",
-                              sync_positioning_scheme);
-  }
+  data->server_defined_unique_tag = update_entity.server_defined_unique_tag();
 
   // Populate |originator_cache_guid| and |originator_client_item_id|. This is
-  // relevant only for bookmarks.
+  // currently relevant only for bookmarks.
   data->originator_cache_guid = update_entity.originator_cache_guid();
   data->originator_client_item_id = update_entity.originator_client_item_id();
 
-  data->server_defined_unique_tag = update_entity.server_defined_unique_tag();
+  // Handle deprecated positioning fields. Relevant only for bookmarks.
+  if (model_type == syncer::BOOKMARKS) {
+    bool has_position_scheme = false;
+    SyncPositioningScheme sync_positioning_scheme;
+    if (update_entity.has_unique_position()) {
+      data->unique_position = update_entity.unique_position();
+      has_position_scheme = true;
+      sync_positioning_scheme = SyncPositioningScheme::UNIQUE_POSITION;
+    } else if (update_entity.has_position_in_parent() ||
+               update_entity.has_insert_after_item_id()) {
+      bool missing_originator_fields = false;
+      if (!update_entity.has_originator_cache_guid() ||
+          !update_entity.has_originator_client_item_id()) {
+        DLOG(ERROR) << "Update is missing requirements for bookmark position.";
+        missing_originator_fields = true;
+      }
+
+      std::string suffix =
+          missing_originator_fields
+              ? UniquePosition::RandomSuffix()
+              : GenerateSyncableHash(
+                    syncer::GetModelType(update_entity),
+                    /*client_tag=*/update_entity.originator_cache_guid() +
+                        update_entity.originator_client_item_id());
+
+      if (update_entity.has_position_in_parent()) {
+        data->unique_position = UniquePosition::FromInt64(
+                                    update_entity.position_in_parent(), suffix)
+                                    .ToProto();
+        has_position_scheme = true;
+        sync_positioning_scheme = SyncPositioningScheme::POSITION_IN_PARENT;
+      } else {
+        // If update_entity has insert_after_item_id, use 0 index.
+        DCHECK(update_entity.has_insert_after_item_id());
+        data->unique_position = UniquePosition::FromInt64(0, suffix).ToProto();
+        has_position_scheme = true;
+        sync_positioning_scheme = SyncPositioningScheme::INSERT_AFTER_ITEM_ID;
+      }
+    } else if (SyncerProtoUtil::ShouldMaintainPosition(update_entity) &&
+               !update_entity.deleted()) {
+      DLOG(ERROR) << "Missing required position information in update.";
+      has_position_scheme = true;
+      sync_positioning_scheme = SyncPositioningScheme::MISSING;
+    }
+    if (has_position_scheme) {
+      UMA_HISTOGRAM_ENUMERATION("Sync.Entities.PositioningScheme",
+                                sync_positioning_scheme);
+    }
+  }
 
   // Deleted entities must use the default instance of EntitySpecifics in
   // order for EntityData to correctly reflect that they are deleted.
diff --git a/components/sync/engine_impl/model_type_worker_unittest.cc b/components/sync/engine_impl/model_type_worker_unittest.cc
index 654d59e..a685543 100644
--- a/components/sync/engine_impl/model_type_worker_unittest.cc
+++ b/components/sync/engine_impl/model_type_worker_unittest.cc
@@ -1327,14 +1327,12 @@
 }
 
 TEST_F(ModelTypeWorkerTest, PopulateUpdateResponseData) {
-  InitializeCommitOnly();
+  NormalInitialize();
   sync_pb::SyncEntity entity;
 
   entity.set_id_string("SomeID");
   entity.set_parent_id_string("ParentID");
   entity.set_folder(false);
-  *entity.mutable_unique_position() =
-      UniquePosition::InitialPosition(UniquePosition::RandomSuffix()).ToProto();
   entity.set_version(1);
   entity.set_client_defined_unique_tag("CLIENT_TAG");
   entity.set_server_defined_unique_tag("SERVER_TAG");
@@ -1352,19 +1350,11 @@
   EXPECT_FALSE(data.id.empty());
   EXPECT_FALSE(data.parent_id.empty());
   EXPECT_FALSE(data.is_folder);
-  EXPECT_TRUE(
-      syncer::UniquePosition::FromProto(data.unique_position).IsValid());
   EXPECT_EQ("CLIENT_TAG", data.client_tag_hash);
   EXPECT_EQ("SERVER_TAG", data.server_defined_unique_tag);
   EXPECT_FALSE(data.is_deleted());
   EXPECT_EQ(kTag1, data.specifics.preference().name());
   EXPECT_EQ(kValue1, data.specifics.preference().value());
-
-  histogram_tester.ExpectUniqueSample(
-      "Sync.Entities.PositioningScheme",
-      /*sample=*/
-      ExpectedSyncPositioningScheme::UNIQUE_POSITION,
-      /*count=*/1);
 }
 
 TEST_F(ModelTypeWorkerTest, PopulateUpdateResponseDataForBookmarkTombstone) {
@@ -1395,8 +1385,38 @@
   EXPECT_TRUE(data.is_deleted());
 }
 
-TEST_F(ModelTypeWorkerTest, PopulateUpdateResponseDataWithPositionInParent) {
-  InitializeCommitOnly();
+TEST_F(ModelTypeWorkerTest,
+       PopulateUpdateResponseDataForBookmarkWithUniquePosition) {
+  NormalInitialize();
+  sync_pb::SyncEntity entity;
+
+  *entity.mutable_unique_position() =
+      UniquePosition::InitialPosition(UniquePosition::RandomSuffix()).ToProto();
+  entity.set_client_defined_unique_tag("CLIENT_TAG");
+  entity.set_server_defined_unique_tag("SERVER_TAG");
+  *entity.mutable_specifics() = GenerateSpecifics(kTag1, kValue1);
+
+  UpdateResponseData response_data;
+  DirectoryCryptographer cryptographer;
+  base::HistogramTester histogram_tester;
+
+  EXPECT_EQ(ModelTypeWorker::SUCCESS,
+            ModelTypeWorker::PopulateUpdateResponseData(
+                &cryptographer, BOOKMARKS, entity, &response_data));
+  const EntityData& data = *response_data.entity;
+  EXPECT_TRUE(
+      syncer::UniquePosition::FromProto(data.unique_position).IsValid());
+
+  histogram_tester.ExpectUniqueSample(
+      "Sync.Entities.PositioningScheme",
+      /*sample=*/
+      ExpectedSyncPositioningScheme::UNIQUE_POSITION,
+      /*count=*/1);
+}
+
+TEST_F(ModelTypeWorkerTest,
+       PopulateUpdateResponseDataForBookmarkWithPositionInParent) {
+  NormalInitialize();
   sync_pb::SyncEntity entity;
 
   entity.set_position_in_parent(5);
@@ -1410,7 +1430,7 @@
 
   EXPECT_EQ(ModelTypeWorker::SUCCESS,
             ModelTypeWorker::PopulateUpdateResponseData(
-                &cryptographer, PREFERENCES, entity, &response_data));
+                &cryptographer, BOOKMARKS, entity, &response_data));
   const EntityData& data = *response_data.entity;
   EXPECT_TRUE(
       syncer::UniquePosition::FromProto(data.unique_position).IsValid());
@@ -1422,8 +1442,9 @@
       /*count=*/1);
 }
 
-TEST_F(ModelTypeWorkerTest, PopulateUpdateResponseDataWithInsertAfterItemId) {
-  InitializeCommitOnly();
+TEST_F(ModelTypeWorkerTest,
+       PopulateUpdateResponseDataForBookmarkWithInsertAfterItemId) {
+  NormalInitialize();
   sync_pb::SyncEntity entity;
 
   entity.set_insert_after_item_id("ITEM_ID");
@@ -1437,7 +1458,7 @@
 
   EXPECT_EQ(ModelTypeWorker::SUCCESS,
             ModelTypeWorker::PopulateUpdateResponseData(
-                &cryptographer, PREFERENCES, entity, &response_data));
+                &cryptographer, BOOKMARKS, entity, &response_data));
   const EntityData& data = *response_data.entity;
   EXPECT_TRUE(
       syncer::UniquePosition::FromProto(data.unique_position).IsValid());
@@ -1449,8 +1470,8 @@
 }
 
 TEST_F(ModelTypeWorkerTest,
-       PopulateUpdateResponseDataWithBookmarkMissingPosition) {
-  InitializeCommitOnly();
+       PopulateUpdateResponseDataForBookmarkWithMissingPosition) {
+  NormalInitialize();
   sync_pb::SyncEntity entity;
 
   entity.set_client_defined_unique_tag("CLIENT_TAG");
@@ -1466,7 +1487,7 @@
 
   EXPECT_EQ(ModelTypeWorker::SUCCESS,
             ModelTypeWorker::PopulateUpdateResponseData(
-                &cryptographer, PREFERENCES, entity, &response_data));
+                &cryptographer, BOOKMARKS, entity, &response_data));
   const EntityData& data = *response_data.entity;
   EXPECT_FALSE(
       syncer::UniquePosition::FromProto(data.unique_position).IsValid());
@@ -1477,8 +1498,8 @@
 }
 
 TEST_F(ModelTypeWorkerTest,
-       PopulateUpdateResponseDataWithNonBookmarkHasNoPosition) {
-  InitializeCommitOnly();
+       PopulateUpdateResponseDataForNonBookmarkWithNoPosition) {
+  NormalInitialize();
   sync_pb::SyncEntity entity;
 
   EntitySpecifics specifics;
@@ -1498,7 +1519,7 @@
                                     /*count=*/0);
 }
 
-TEST_F(ModelTypeWorkerTest, PopulateUpdateResponseDataWithBookmarkGUID) {
+TEST_F(ModelTypeWorkerTest, PopulateUpdateResponseDataForBookmarkWithGUID) {
   const std::string kGuid1 = base::GenerateGUID();
   const std::string kGuid2 = base::GenerateGUID();
 
@@ -1524,7 +1545,8 @@
   EXPECT_EQ(kGuid2, data.originator_client_item_id);
 }
 
-TEST_F(ModelTypeWorkerTest, PopulateUpdateResponseDataWithMissingBookmarkGUID) {
+TEST_F(ModelTypeWorkerTest,
+       PopulateUpdateResponseDataForBookmarkWithMissingGUID) {
   const std::string kGuid1 = base::GenerateGUID();
 
   NormalInitialize();
@@ -1549,7 +1571,7 @@
 }
 
 TEST_F(ModelTypeWorkerTest,
-       PopulateUpdateResponseDataWithMissingBookmarkGUIDAndInvalidOCII) {
+       PopulateUpdateResponseDataForBookmarkWithMissingGUIDAndInvalidOCII) {
   const std::string kInvalidOCII = "INVALID OCII";
 
   NormalInitialize();
diff --git a/components/sync/engine_impl/syncer_proto_util.cc b/components/sync/engine_impl/syncer_proto_util.cc
index 791e269..956f28d 100644
--- a/components/sync/engine_impl/syncer_proto_util.cc
+++ b/components/sync/engine_impl/syncer_proto_util.cc
@@ -420,7 +420,6 @@
   DCHECK(msg.has_api_key());
   DCHECK(msg.has_client_status());
   DCHECK(msg.has_invalidator_client_id());
-  DCHECK(!msg.get_updates().has_from_timestamp());  // Deprecated.
 
   LogClientToServerMessage(msg);
   if (!PostAndProcessHeaders(cycle->context()->connection_manager(), cycle, msg,
@@ -613,12 +612,12 @@
       "d (%s), "
       "ctime: %" PRId64
       "d (%s), "
-      "name: %s, sync_timestamp: %" PRId64
+      "name: %s, "
       "d, "
       "%s ",
       entry.id_string().c_str(), entry.parent_id_string().c_str(),
       entry.version(), entry.mtime(), mtime_str.c_str(), entry.ctime(),
-      ctime_str.c_str(), entry.name().c_str(), entry.sync_timestamp(),
+      ctime_str.c_str(), entry.name().c_str(),
       entry.deleted() ? "deleted, " : "");
 }
 
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index 1dfb64f..b83e9de9 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -851,7 +851,6 @@
   VISIT(ctime);
   VISIT(name);
   VISIT(non_unique_name);
-  VISIT(sync_timestamp);
   VISIT(server_defined_unique_tag);
   VISIT(position_in_parent);
   VISIT(unique_position);
diff --git a/components/sync/protocol/sync.proto b/components/sync/protocol/sync.proto
index 807cc5e7..e213548 100644
--- a/components/sync/protocol/sync.proto
+++ b/components/sync/protocol/sync.proto
@@ -225,11 +225,8 @@
   // Present in both GetUpdatesResponse and CommitMessage.
   optional string non_unique_name = 8;
 
-  // A value from a monotonically increasing sequence that indicates when
-  // this item was last updated on the server. This is now equivalent
-  // to version. This is now deprecated in favor of version.
-  // Present only in GetUpdatesResponse.
-  optional int64 sync_timestamp = 9;
+  reserved 9;
+  reserved "sync_timestamp";
 
   // If present, this tag identifies this item as being a uniquely
   // instanced item.  The server ensures that there is never more
@@ -249,26 +246,14 @@
   // Present only in GetUpdatesResponse.
   optional string server_defined_unique_tag = 10;
 
-  // If this group is present, it implies that this SyncEntity corresponds to
-  // a bookmark or a bookmark folder.
-  //
-  // This group is deprecated; clients should use the bookmark EntitySpecifics
-  // protocol buffer extension instead.
-  optional group BookmarkData = 11 [deprecated = true] {
-    // We use a required field to differentiate between a bookmark and a
-    // bookmark folder.
-    // Present in both GetUpdatesMessage and CommitMessage.
-    required bool bookmark_folder = 12;
-
-    // For bookmark objects, contains the bookmark's URL.
-    // Present in both GetUpdatesResponse and CommitMessage.
-    optional string bookmark_url = 13;
-
-    // For bookmark objects, contains the bookmark's favicon. The favicon is
-    // represented as a 16X16 PNG image.
-    // Present in both GetUpdatesResponse and CommitMessage.
-    optional bytes bookmark_favicon = 14;
-  }
+  reserved 11;
+  reserved "BookmarkData";
+  reserved 12;
+  reserved "bookmark_folder";
+  reserved 13;
+  reserved "bookmark_url";
+  reserved 14;
+  reserved "bookmark_favicon";
 
   // Supplies a numeric position for this item, relative to other items with the
   // same parent.  Deprecated in M26, though clients are still required to set
@@ -296,7 +281,7 @@
   // Conversion from UniquePosition to int64 reverses this process: the first 8
   // bytes of the position are to be interpreted as a big endian int64 value
   // with its sign bit flipped.
-  optional int64 position_in_parent = 15;
+  optional int64 position_in_parent = 15 [deprecated = true];
 
   // Contains the ID of the element (under the same parent) after which this
   // element resides. An empty string indicates that the element is the first
@@ -309,7 +294,7 @@
   //
   // This is deprecated.  Clients are allowed to omit this as long as they
   // include |position_in_parent| instead.
-  optional string insert_after_item_id = 16;
+  optional string insert_after_item_id = 16 [deprecated = true];
 
   reserved 17;
   reserved "extended_attributes";
@@ -380,7 +365,7 @@
   // attempt to support it.  In fact, no client ever read or set this field.
   //
   // Deprecated in M26.
-  optional bytes ordinal_in_parent = 24;
+  optional bytes ordinal_in_parent = 24 [deprecated = true];
 
   // This is the fourth attempt at positioning.
   //
@@ -603,7 +588,7 @@
   // token mechanism can set this field in a GetUpdatesMessage.  The server
   // will perform a get updates operation as normal from the indicated
   // timestamp, and return only an opaque progress token.
-  optional int64 timestamp_token_for_migration = 3;
+  optional int64 timestamp_token_for_migration = 3 [deprecated = true];
 
   // An opaque-to-the-client string of bytes, received through a notification,
   // that the server may interpret as a hint about the location of the latest
@@ -611,7 +596,7 @@
   //
   // Deprecated in M29.  We should use the repeated field version in the
   // PerClientTypeState instead.
-  optional string notification_hint = 4;
+  optional string notification_hint = 4 [deprecated = true];
 
   // This field will be included only in GetUpdates with origin GU_TRIGGER.
   optional GetUpdateTriggers get_update_triggers = 5;
@@ -624,14 +609,8 @@
 }
 
 message GetUpdatesMessage {
-  // Indicates the client's current progress in downloading updates.  A
-  // from_timestamp value of zero means that the client is requesting a first-
-  // time sync.  After that point, clients should fill in this value with the
-  // value returned in the last-seen GetUpdatesResponse.new_timestamp.
-  //
-  // from_timestamp has been deprecated; clients should use
-  // |from_progress_marker| instead, which allows more flexibility.
-  optional int64 from_timestamp = 1;
+  reserved 1;
+  reserved "from_timestamp";
 
   // Indicates the reason for the GetUpdatesMessage.
   // This was *mostly* deprecated in M29.  GetUpdatesOrigin is the new way to
@@ -690,8 +669,6 @@
   // Set of optional per-client datatype contexts.
   repeated DataTypeContext client_contexts = 11;
 
-  // requested_types is a deprecated predecessor to using progress markers.
-  // See https://crbug.com/687426.
   reserved 4;
   reserved "requested_types";
 };
@@ -881,15 +858,8 @@
   // New sync entries that the client should apply.
   repeated SyncEntity entries = 1;
 
-  // If there are more changes on the server that weren't processed during this
-  // GetUpdates request, the client should send another GetUpdates request and
-  // use new_timestamp as the from_timestamp value within GetUpdatesMessage.
-  //
-  // This field has been deprecated and will be returned only to clients
-  // that set the also-deprecated |from_timestamp| field in the update request.
-  // Clients should use |from_progress_marker| and |new_progress_marker|
-  // instead.
-  optional int64 new_timestamp = 2;
+  reserved 2;
+  reserved "new_timestamp";
 
   reserved 3;
   reserved "newest_timestamp";
@@ -899,11 +869,9 @@
   // after the current batch.
   optional int64 changes_remaining = 4;
 
-  // Opaque, per-datatype timestamp-like tokens.  A client should use this
-  // field in lieu of new_timestamp, which is deprecated in newer versions
-  // of the protocol.  Clients should retain and persist the values returned
-  // in this field, and present them back to the server to indicate the
-  // starting point for future update requests.
+  // Opaque, per-datatype timestamp-like tokens.  Clients should retain and
+  // persist the values returned in this field, and present them back to the
+  // server to indicate the starting point for future update requests.
   //
   // This will be sent only if the client provided |from_progress_marker|
   // in the update request.
@@ -930,29 +898,6 @@
   repeated DataTypeContext context_mutations = 7;
 };
 
-// The metadata response for GetUpdatesMessage.  This response is sent when
-// streaming is set to true in the request.  It is prefixed with a length
-// delimiter, which is encoded in varint.
-message GetUpdatesMetadataResponse {
-  // Approximate count of changes remaining.  Detailed comment is available in
-  // GetUpdatesResponse.
-  optional int64 changes_remaining = 1;
-
-  // Opaque, per-datatype timestamp-like tokens.  Detailed comment is available
-  // in GetUpdatesResponse.
-  repeated DataTypeProgressMarker new_progress_marker = 2;
-};
-
-// The streaming response message for GetUpdatesMessage.  This message is sent
-// when streaming is set to true in the request.  There may be multiple
-// GetUpdatesStreamingResponse messages in a response.  This type of messages
-// is preceded by GetUpdatesMetadataResponse.  It is prefixed with a length
-// delimiter, which is encoded in varint.
-message GetUpdatesStreamingResponse {
-  // New sync entries that the client should apply.
-  repeated SyncEntity entries = 1;
-};
-
 message ClientToServerResponse {
   optional CommitResponse commit = 1;
   optional GetUpdatesResponse get_updates = 2;
@@ -978,10 +923,10 @@
   optional ClientCommand client_command = 7;
   optional ProfilingData profiling_data = 8;
   reserved 9;
-  optional GetUpdatesMetadataResponse stream_metadata = 10;
-  // If GetUpdatesStreamingResponse is contained in the ClientToServerResponse,
-  // none of the other fields (error_code and etc) will be set.
-  optional GetUpdatesStreamingResponse stream_data = 11;
+  reserved 10;
+  reserved "stream_metadata";
+  reserved 11;
+  reserved "stream_data";
 
   // The data types whose storage has been migrated.  Present when the value of
   // error_code is MIGRATION_DONE.
diff --git a/components/sync/test/engine/mock_connection_manager.cc b/components/sync/test/engine/mock_connection_manager.cc
index fc954be..b1eaeba 100644
--- a/components/sync/test/engine/mock_connection_manager.cc
+++ b/components/sync/test/engine/mock_connection_manager.cc
@@ -313,7 +313,6 @@
   ent->set_name("Nigori");
   ent->set_non_unique_name("Nigori");
   ent->set_version(version);
-  ent->set_sync_timestamp(sync_ts);
   ent->set_mtime(sync_ts);
   ent->set_ctime(1);
   ent->set_position_in_parent(0);
@@ -365,7 +364,6 @@
   ent->set_non_unique_name(name);
   ent->set_name(name);
   ent->set_version(version);
-  ent->set_sync_timestamp(sync_ts);
   ent->set_mtime(sync_ts);
   ent->set_ctime(1);
   ent->set_position_in_parent(GeneratePositionInParent());
@@ -523,7 +521,6 @@
   }
   const GetUpdatesMessage& gu = csm->get_updates();
   num_get_updates_requests_++;
-  EXPECT_FALSE(gu.has_from_timestamp());
 
   if (fail_non_periodic_get_updates_) {
     EXPECT_EQ(sync_pb::SyncEnums::PERIODIC, gu.get_updates_origin());
diff --git a/components/sync_bookmarks/bookmark_model_associator.cc b/components/sync_bookmarks/bookmark_model_associator.cc
index 1a5fefc8..b5aad348 100644
--- a/components/sync_bookmarks/bookmark_model_associator.cc
+++ b/components/sync_bookmarks/bookmark_model_associator.cc
@@ -957,12 +957,6 @@
     if (native_version == sync_version) {
       context->set_native_model_sync_state(IN_SYNC);
     } else {
-      // TODO(wychen): enum uma should be strongly typed. crbug.com/661401
-      UMA_HISTOGRAM_ENUMERATION(
-          "Sync.LocalModelOutOfSync",
-          ModelTypeToHistogramInt(syncer::BOOKMARKS),
-          static_cast<int>(syncer::ModelType::NUM_ENTRIES));
-
       // Clear version on bookmark model so that we only report error once.
       bookmark_model_->SetNodeSyncTransactionVersion(
           bookmark_model_->root_node(),
diff --git a/components/visitedlink/browser/visitedlink_event_listener.cc b/components/visitedlink/browser/visitedlink_event_listener.cc
index 10b3aac..1f86eea 100644
--- a/components/visitedlink/browser/visitedlink_event_listener.cc
+++ b/components/visitedlink/browser/visitedlink_event_listener.cc
@@ -11,6 +11,7 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 
 using base::Time;
@@ -45,7 +46,7 @@
         invalidate_hashes_(false),
         render_process_id_(render_process_id) {
     BindInterface(content::RenderProcessHost::FromID(render_process_id),
-                  &sink_);
+                  sink_.BindNewPipeAndPassReceiver());
   }
 
   // Informs the renderer about a new visited link table.
@@ -112,7 +113,7 @@
   bool reset_needed_;
   bool invalidate_hashes_;
   int render_process_id_;
-  mojom::VisitedLinkNotificationSinkPtr sink_;
+  mojo::Remote<mojom::VisitedLinkNotificationSink> sink_;
   VisitedLinkCommon::Fingerprints pending_;
 };
 
diff --git a/components/visitedlink/renderer/visitedlink_slave.cc b/components/visitedlink/renderer/visitedlink_slave.cc
index a8c05ae..702d9f0 100644
--- a/components/visitedlink/renderer/visitedlink_slave.cc
+++ b/components/visitedlink/renderer/visitedlink_slave.cc
@@ -15,13 +15,13 @@
 
 namespace visitedlink {
 
-VisitedLinkSlave::VisitedLinkSlave() : binding_(this) {}
+VisitedLinkSlave::VisitedLinkSlave() = default;
 
 VisitedLinkSlave::~VisitedLinkSlave() {
   FreeTable();
 }
 
-base::Callback<void(mojom::VisitedLinkNotificationSinkRequest)>
+base::Callback<void(mojo::PendingReceiver<mojom::VisitedLinkNotificationSink>)>
 VisitedLinkSlave::GetBindCallback() {
   return base::Bind(&VisitedLinkSlave::Bind, weak_factory_.GetWeakPtr());
 }
@@ -80,8 +80,9 @@
   table_length_ = 0;
 }
 
-void VisitedLinkSlave::Bind(mojom::VisitedLinkNotificationSinkRequest request) {
-  binding_.Bind(std::move(request));
+void VisitedLinkSlave::Bind(
+    mojo::PendingReceiver<mojom::VisitedLinkNotificationSink> receiver) {
+  receiver_.Bind(std::move(receiver));
 }
 
 }  // namespace visitedlink
diff --git a/components/visitedlink/renderer/visitedlink_slave.h b/components/visitedlink/renderer/visitedlink_slave.h
index f2c3f14..7f8e636 100644
--- a/components/visitedlink/renderer/visitedlink_slave.h
+++ b/components/visitedlink/renderer/visitedlink_slave.h
@@ -12,7 +12,8 @@
 #include "base/memory/weak_ptr.h"
 #include "components/visitedlink/common/visitedlink.mojom.h"
 #include "components/visitedlink/common/visitedlink_common.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace visitedlink {
 
@@ -24,7 +25,8 @@
   VisitedLinkSlave();
   ~VisitedLinkSlave() override;
 
-  base::Callback<void(mojom::VisitedLinkNotificationSinkRequest)>
+  base::Callback<
+      void(mojo::PendingReceiver<mojom::VisitedLinkNotificationSink>)>
   GetBindCallback();
 
   // mojom::VisitedLinkNotificationSink overrides.
@@ -37,11 +39,11 @@
  private:
   void FreeTable();
 
-  void Bind(mojom::VisitedLinkNotificationSinkRequest request);
+  void Bind(mojo::PendingReceiver<mojom::VisitedLinkNotificationSink> receiver);
 
   base::ReadOnlySharedMemoryMapping table_mapping_;
 
-  mojo::Binding<mojom::VisitedLinkNotificationSink> binding_;
+  mojo::Receiver<mojom::VisitedLinkNotificationSink> receiver_{this};
 
   base::WeakPtrFactory<VisitedLinkSlave> weak_factory_{this};
 
diff --git a/components/visitedlink/test/visitedlink_unittest.cc b/components/visitedlink/test/visitedlink_unittest.cc
index 0705baf4..9a51eff 100644
--- a/components/visitedlink/test/visitedlink_unittest.cc
+++ b/components/visitedlink/test/visitedlink_unittest.cc
@@ -34,7 +34,8 @@
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_utils.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -531,8 +532,9 @@
         new_table_count_(0) {}
 
   void Bind(mojo::ScopedMessagePipeHandle handle) {
-    binding_.AddBinding(
-        this, mojom::VisitedLinkNotificationSinkRequest(std::move(handle)));
+    receiver_.Add(this,
+                  mojo::PendingReceiver<mojom::VisitedLinkNotificationSink>(
+                      std::move(handle)));
   }
 
   void WaitForUpdate() {
@@ -541,10 +543,10 @@
     run_loop.Run();
   }
 
-  void WaitForNoUpdate() { binding_.FlushForTesting(); }
+  void WaitForNoUpdate() { receiver_.FlushForTesting(); }
 
-  mojo::BindingSet<mojom::VisitedLinkNotificationSink>& binding() {
-    return binding_;
+  mojo::ReceiverSet<mojom::VisitedLinkNotificationSink>& binding() {
+    return receiver_;
   }
 
   void NotifyUpdate() {
@@ -588,7 +590,7 @@
   int new_table_count_;
 
   base::Closure quit_closure_;
-  mojo::BindingSet<mojom::VisitedLinkNotificationSink> binding_;
+  mojo::ReceiverSet<mojom::VisitedLinkNotificationSink> receiver_;
 
   DISALLOW_COPY_AND_ASSIGN(VisitCountingContext);
 };
diff --git a/components/viz/service/display/dc_layer_overlay.cc b/components/viz/service/display/dc_layer_overlay.cc
index 69a85d1..e65bf4f 100644
--- a/components/viz/service/display/dc_layer_overlay.cc
+++ b/components/viz/service/display/dc_layer_overlay.cc
@@ -42,7 +42,8 @@
   DC_LAYER_FAILED_NON_ROOT,
   DC_LAYER_FAILED_TOO_MANY_OVERLAYS,
   DC_LAYER_FAILED_NO_HW_OVERLAY_SUPPORT,  // deprecated
-  kMaxValue = DC_LAYER_FAILED_NO_HW_OVERLAY_SUPPORT,
+  DC_LAYER_FAILED_ROUNDED_CORNERS,
+  kMaxValue = DC_LAYER_FAILED_ROUNDED_CORNERS,
 };
 
 enum : size_t {
@@ -89,6 +90,10 @@
 
     if (current_frame_processed_overlay_count > 0)
       return DC_LAYER_FAILED_TOO_MANY_OVERLAYS;
+
+    // Rounded corner on overlays are not supported.
+    if (!quad->shared_quad_state->rounded_corner_bounds.IsEmpty())
+      return DC_LAYER_FAILED_ROUNDED_CORNERS;
   }
 
   // Direct composition path only supports single NV12 buffer, or two buffers
@@ -135,6 +140,7 @@
     if (!resource_provider->IsOverlayCandidate(resource))
       return DC_LAYER_FAILED_TEXTURE_NOT_CANDIDATE;
   }
+
   if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver)
     return DC_LAYER_FAILED_QUAD_BLEND_MODE;
 
@@ -145,6 +151,10 @@
     return DC_LAYER_FAILED_COMPLEX_TRANSFORM;
   }
 
+  // Rounded corner on overlays are not supported.
+  if (!quad->shared_quad_state->rounded_corner_bounds.IsEmpty())
+    return DC_LAYER_FAILED_ROUNDED_CORNERS;
+
   dc_layer->resources[kTextureResourceIndex] = quad->resource_id();
   dc_layer->z_order = 1;
   dc_layer->content_rect = gfx::Rect(quad->resource_size_in_pixels());
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 9480735..7034456 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -2418,6 +2418,11 @@
       current_program_->tex_matrix_location(), false, gl_matrix);
 
   SetShaderOpacity(quad->shared_quad_state->opacity);
+  if (current_program_->rounded_corner_rect_location() != -1) {
+    SetShaderRoundedCorner(
+        quad->shared_quad_state->rounded_corner_bounds,
+        current_frame()->window_matrix * current_frame()->projection_matrix);
+  }
   gfx::Size texture_size = lock.size();
   gfx::RectF uv_visible_rect(quad->uv_top_left.x(), quad->uv_top_left.y(),
                              quad->uv_bottom_right.x() - quad->uv_top_left.x(),
diff --git a/components/webdata_services/BUILD.gn b/components/webdata_services/BUILD.gn
index fbe9230..7c7e85b 100644
--- a/components/webdata_services/BUILD.gn
+++ b/components/webdata_services/BUILD.gn
@@ -27,3 +27,19 @@
     deps += [ "//components/payments/content:utils" ]
   }
 }
+
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [
+    "web_data_service_wrapper_unittest.cc",
+  ]
+
+  deps = [
+    ":webdata_services",
+    "//base",
+    "//base/test:test_support",
+    "//components/search_engines",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/webdata_services/DEPS b/components/webdata_services/DEPS
index 2d67e6c3..b83a086 100644
--- a/components/webdata_services/DEPS
+++ b/components/webdata_services/DEPS
@@ -3,10 +3,10 @@
   "+components/keyed_service/core",
   "+components/password_manager/core/browser/webdata",
   "+components/payments/content",
-  "+components/search_engines/keyword_table.h",
-  "+components/search_engines/keyword_web_data_service.h",
+  "+components/search_engines",
   "+components/signin/public/webdata",
   "+components/sync",
   "+components/webdata/common",
   "+sql",
+  "+testing/gtest",
 ]
diff --git a/components/webdata_services/web_data_service_wrapper_unittest.cc b/components/webdata_services/web_data_service_wrapper_unittest.cc
new file mode 100644
index 0000000..77a6422
--- /dev/null
+++ b/components/webdata_services/web_data_service_wrapper_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/webdata_services/web_data_service_wrapper.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind_helpers.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/task_environment.h"
+#include "components/search_engines/keyword_table.h"
+#include "components/search_engines/keyword_web_data_service.h"
+#include "components/search_engines/template_url_data.h"
+#include "components/webdata/common/web_data_results.h"
+#include "components/webdata/common/web_data_service_consumer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Helper class that stores request result.
+class KeywordsConsumer : public WebDataServiceConsumer {
+ public:
+  ~KeywordsConsumer() override = default;
+
+  void OnWebDataServiceRequestDone(
+      WebDataServiceBase::Handle h,
+      std::unique_ptr<WDTypedResult> result) override {
+    keywords_ = std::move(result);
+  }
+
+  std::unique_ptr<WDTypedResult> keywords_;
+};
+
+class WebDataServiceWrapperTest : public testing::Test {
+ protected:
+  void SetUp() override { ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); }
+
+  // Creates WebDataServiceWrapper under test.
+  std::unique_ptr<WebDataServiceWrapper> CreateWebDataServiceWrapper() {
+    return std::make_unique<WebDataServiceWrapper>(
+        scoped_temp_dir_.GetPath(), "en_US",
+        task_environment_.GetMainThreadTaskRunner(), base::DoNothing());
+  }
+
+  base::test::TaskEnvironment task_environment_{
+      base::test::TaskEnvironment::MainThreadType::UI};
+  base::ScopedTempDir scoped_temp_dir_;
+};
+
+}  // namespace
+
+// This test ensures that KeywordWebDataService writes all pending operations
+// on shutdown. This requires wrapped services to be closed in a proper order
+// but also that asynchronous tasks are posted to DB sequence in a proper order
+// (the task that closes database should be the last one).
+TEST_F(WebDataServiceWrapperTest, ShutdownKeywordWebDataService) {
+  TemplateURLData test_keyword;
+  test_keyword.SetShortName(base::ASCIIToUTF16("Foo Bar"));
+  test_keyword.SetKeyword(base::ASCIIToUTF16("foo"));
+  test_keyword.SetURL("http://foo.bar");
+  test_keyword.id = 1234;
+
+  // Create WebDataServiceWrapper. Add a test keyword and perform shutdown.
+  auto web_data_service_wrapper = CreateWebDataServiceWrapper();
+  web_data_service_wrapper->GetKeywordWebData()->AddKeyword(test_keyword);
+  web_data_service_wrapper->Shutdown();
+  task_environment_.RunUntilIdle();
+  web_data_service_wrapper.reset();
+
+  // Create WebDataServiceWrapper again. Verify that the test keyword is present
+  // in the database.
+  web_data_service_wrapper = CreateWebDataServiceWrapper();
+  KeywordsConsumer keywords_consumer;
+  web_data_service_wrapper->GetKeywordWebData()->GetKeywords(
+      &keywords_consumer);
+  task_environment_.RunUntilIdle();
+  ASSERT_TRUE(keywords_consumer.keywords_);
+  ASSERT_EQ(KEYWORDS_RESULT, keywords_consumer.keywords_->GetType());
+  WDKeywordsResult keyword_result =
+      reinterpret_cast<const WDResult<WDKeywordsResult>*>(
+          keywords_consumer.keywords_.get())
+          ->GetValue();
+  ASSERT_EQ(1u, keyword_result.keywords.size());
+  EXPECT_EQ(test_keyword.short_name(), keyword_result.keywords[0].short_name());
+  web_data_service_wrapper->Shutdown();
+}
diff --git a/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc b/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc
index 1f20133..fa4ca55 100644
--- a/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc
+++ b/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc
@@ -41,13 +41,6 @@
 
   void TearDownOnMainThread() override {}
 
-  void CreateCacheEntry(const std::set<GURL>& urls) {
-    for (auto& url : urls) {
-      ASSERT_EQ(net::OK, LoadBasicRequest(
-                             storage_partition()->GetNetworkContext(), url));
-    }
-  }
-
   bool TestCacheEntry(const GURL& url) {
     return LoadBasicRequest(storage_partition()->GetNetworkContext(), url,
                             0 /* process_id */, 0 /* render_frame_id */,
@@ -55,6 +48,38 @@
                                 net::LOAD_SKIP_CACHE_VALIDATION) == net::OK;
   }
 
+  void CreateCacheEntries(const std::set<GURL>& urls) {
+    for (auto& url : urls) {
+      ASSERT_EQ(net::OK, LoadBasicRequest(
+                             storage_partition()->GetNetworkContext(), url));
+    }
+
+    // Wait for the entries to be written. There is no callback for this action
+    // being completed, only scheduled. Therefore, we need to continuously poll
+    // every |tiny_timeout|. However, wait at most |action_timeout| for this
+    // action to be performed.
+    base::Time start = base::Time::Now();
+    bool all_entries_written = false;
+
+    while (base::Time::Now() - start < TestTimeouts::action_timeout()) {
+      all_entries_written = true;
+      for (auto& url : urls) {
+        if (!TestCacheEntry(url)) {
+          all_entries_written = false;
+          break;
+        }
+      }
+
+      if (all_entries_written)
+        break;
+
+      base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
+    }
+
+    ASSERT_TRUE(all_entries_written)
+        << "Unable to write cache entries. The deletion test can't proceed.";
+  }
+
   void CompareRemainingKeys(const std::set<GURL>& expected_urls,
                             const std::set<GURL>& erase_urls) {
     for (auto& url : expected_urls)
@@ -89,21 +114,14 @@
 
 // Tests that ConditionalCacheDeletionHelper only deletes those cache entries
 // that match the condition.
-// Disabled on Android due to flakiness. See https://crbug.com/978891.
-#if defined(OS_ANDROID)
-#define MAYBE_Condition DISABLED_Condition
-#else
-#define MAYBE_Condition Condition
-#endif
-IN_PROC_BROWSER_TEST_F(ConditionalCacheDeletionHelperBrowserTest,
-                       MAYBE_Condition) {
+IN_PROC_BROWSER_TEST_F(ConditionalCacheDeletionHelperBrowserTest, Condition) {
   std::set<GURL> urls = {
       embedded_test_server()->GetURL("foo.com", "/title1.html"),
       embedded_test_server()->GetURL("bar.com", "/title1.html"),
       embedded_test_server()->GetURL("baz.com", "/title1.html"),
       embedded_test_server()->GetURL("qux.com", "/title1.html")};
 
-  CreateCacheEntry(urls);
+  CreateCacheEntries(urls);
 
   std::set<GURL> erase_urls = {
       embedded_test_server()->GetURL("bar.com", "/title1.html"),
@@ -130,31 +148,15 @@
 
 // Tests that ConditionalCacheDeletionHelper correctly constructs a condition
 // for time and URL.
-//
-// Note: This test depends on the timing in cache backends and can be flaky
-// if those backends are slow.
-//
-// It previously flaked on Mac 10.11 (crbug.com/646119) and on Linux/ChromeOS
-// (crbug.com/624836) but it seems to be stable now.
-
-// Disabled on Android due to flakiness. See https://crbug.com/978891.
-#if defined(OS_ANDROID)
-#define MAYBE_TimeAndURL DISABLED_TimeAndURL
-#else
-// https://crbug.com/911171: this test depends on the timing of the cache,
-// which changes if it's running out-of-process.
-#define MAYBE_TimeAndURL DISABLED_TimeAndURL
-#endif
-IN_PROC_BROWSER_TEST_F(ConditionalCacheDeletionHelperBrowserTest,
-                       MAYBE_TimeAndURL) {
+IN_PROC_BROWSER_TEST_F(ConditionalCacheDeletionHelperBrowserTest, TimeAndURL) {
   // Create some entries.
   std::set<GURL> urls = {
       embedded_test_server()->GetURL("foo.com", "/title1.html"),
       embedded_test_server()->GetURL("example.com", "/title1.html"),
       embedded_test_server()->GetURL("bar.com", "/title1.html")};
-  CreateCacheEntry(urls);
+  CreateCacheEntries(urls);
 
-  // Wait some milliseconds for the cache to write the entries.
+  // Wait a short time after writing the entries.
   // This assures that future entries will have timestamps strictly greater than
   // the ones we just added.
   base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
@@ -166,7 +168,7 @@
       embedded_test_server()->GetURL("example.com", "/title2.html"),
       embedded_test_server()->GetURL("example.com", "/title3.html"),
       embedded_test_server()->GetURL("example2.com", "/simple_page.html")};
-  CreateCacheEntry(newer_urls);
+  CreateCacheEntries(newer_urls);
 
   // Create a condition for entries with the "http://example.com" origin
   // created after waiting.
diff --git a/content/browser/frame_host/back_forward_cache_impl.cc b/content/browser/frame_host/back_forward_cache_impl.cc
index 3c72b7e..1fbcceb 100644
--- a/content/browser/frame_host/back_forward_cache_impl.cc
+++ b/content/browser/frame_host/back_forward_cache_impl.cc
@@ -119,19 +119,9 @@
 
 }  // namespace
 
-enum class BackForwardCacheImpl::CanStoreDocumentResult::Reason : uint8_t {
-  kNotMainFrame,
-  kBackForwardCacheDisabled,
-  kRelatedActiveContentsExist,
-  kHTTPStatusNotOK,
-  kSchemeNotHTTPOrHTTPS,
-  kLoading,
-  kWasGrantedMediaAccess,
-  kBlocklistedFeatures,
-  kDisableForRenderFrameHostCalled
-};
-
 std::string BackForwardCacheImpl::CanStoreDocumentResult::ToString() {
+  using Reason = BackForwardCacheMetrics::CanNotStoreDocumentReason;
+
   if (can_store)
     return "Yes";
 
@@ -169,20 +159,23 @@
 }
 
 BackForwardCacheImpl::CanStoreDocumentResult
-BackForwardCacheImpl::CanStoreDocumentResult::No(Reason reason) {
+BackForwardCacheImpl::CanStoreDocumentResult::No(
+    BackForwardCacheMetrics::CanNotStoreDocumentReason reason) {
   return CanStoreDocumentResult(false, reason, 0);
 }
 
 BackForwardCacheImpl::CanStoreDocumentResult
 BackForwardCacheImpl::CanStoreDocumentResult::NoDueToFeatures(
     uint64_t blocklisted_features) {
-  return CanStoreDocumentResult(false, Reason::kBlocklistedFeatures,
-                                blocklisted_features);
+  return CanStoreDocumentResult(
+      false,
+      BackForwardCacheMetrics::CanNotStoreDocumentReason::kBlocklistedFeatures,
+      blocklisted_features);
 }
 
 BackForwardCacheImpl::CanStoreDocumentResult::CanStoreDocumentResult(
     bool can_store,
-    base::Optional<Reason> reason,
+    base::Optional<BackForwardCacheMetrics::CanNotStoreDocumentReason> reason,
     uint64_t blocklisted_features)
     : can_store(can_store),
       reason(reason),
@@ -202,17 +195,19 @@
   // Use the BackForwardCache only for the main frame.
   if (rfh->GetParent()) {
     return CanStoreDocumentResult::No(
-        CanStoreDocumentResult::Reason::kNotMainFrame);
+        BackForwardCacheMetrics::CanNotStoreDocumentReason::kNotMainFrame);
   }
 
   if (!IsBackForwardCacheEnabled() || is_disabled_for_testing_) {
     return CanStoreDocumentResult::No(
-        CanStoreDocumentResult::Reason::kBackForwardCacheDisabled);
+        BackForwardCacheMetrics::CanNotStoreDocumentReason::
+            kBackForwardCacheDisabled);
   }
 
   if (rfh->is_back_forward_cache_disallowed()) {
     return CanStoreDocumentResult::No(
-        CanStoreDocumentResult::Reason::kDisableForRenderFrameHostCalled);
+        BackForwardCacheMetrics::CanNotStoreDocumentReason::
+            kDisableForRenderFrameHostCalled);
   }
 
   // Two pages in the same BrowsingInstance can script each other. When a page
@@ -226,21 +221,23 @@
   // BrowsingInstance.
   if (rfh->GetSiteInstance()->GetRelatedActiveContentsCount() != 0) {
     return CanStoreDocumentResult::No(
-        CanStoreDocumentResult::Reason::kRelatedActiveContentsExist);
+        BackForwardCacheMetrics::CanNotStoreDocumentReason::
+            kRelatedActiveContentsExist);
   }
 
   // Only store documents that have successful http status code.
   // Note that for error pages, |last_http_status_code| is equal to 0.
   if (rfh->last_http_status_code() != net::HTTP_OK) {
     return CanStoreDocumentResult::No(
-        CanStoreDocumentResult::Reason::kHTTPStatusNotOK);
+        BackForwardCacheMetrics::CanNotStoreDocumentReason::kHTTPStatusNotOK);
   }
 
   // Do store main document with non HTTP/HTTPS URL scheme. In particular, this
   // excludes the new tab page.
   if (!rfh->GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) {
     return CanStoreDocumentResult::No(
-        CanStoreDocumentResult::Reason::kSchemeNotHTTPOrHTTPS);
+        BackForwardCacheMetrics::CanNotStoreDocumentReason::
+            kSchemeNotHTTPOrHTTPS);
   }
 
   return CanStoreRenderFrameHost(rfh, GetDisallowedFeatures());
@@ -257,15 +254,18 @@
   bool is_loading = rfh->frame_tree_node()->IsMainFrame()
                         ? rfh->is_loading()
                         : rfh->frame_tree_node()->IsLoading();
-  if (is_loading)
-    return CanStoreDocumentResult::No(CanStoreDocumentResult::Reason::kLoading);
+  if (is_loading) {
+    return CanStoreDocumentResult::No(
+        BackForwardCacheMetrics::CanNotStoreDocumentReason::kLoading);
+  }
 
   // If the rfh has ever granted media access, prevent it from entering cache.
   // TODO(crbug.com/989379): Consider only blocking when there's an active
   //                         media stream.
   if (rfh->was_granted_media_access()) {
     return CanStoreDocumentResult::No(
-        CanStoreDocumentResult::Reason::kWasGrantedMediaAccess);
+        BackForwardCacheMetrics::CanNotStoreDocumentReason::
+            kWasGrantedMediaAccess);
   }
 
   // Don't cache the page if it uses any disallowed features.
diff --git a/content/browser/frame_host/back_forward_cache_impl.h b/content/browser/frame_host/back_forward_cache_impl.h
index 959a35f..2fd1dad31 100644
--- a/content/browser/frame_host/back_forward_cache_impl.h
+++ b/content/browser/frame_host/back_forward_cache_impl.h
@@ -15,6 +15,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "content/browser/frame_host/back_forward_cache_metrics.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/back_forward_cache.h"
 #include "content/public/browser/global_routing_id.h"
@@ -35,17 +36,16 @@
   ~BackForwardCacheImpl();
 
   struct CanStoreDocumentResult {
-    enum class Reason : uint8_t;
-
     CanStoreDocumentResult(const CanStoreDocumentResult&);
     ~CanStoreDocumentResult();
 
     bool can_store;
-    base::Optional<Reason> reason;
+    base::Optional<BackForwardCacheMetrics::CanNotStoreDocumentReason> reason;
     uint64_t blocklisted_features;
 
     static CanStoreDocumentResult Yes();
-    static CanStoreDocumentResult No(Reason reason);
+    static CanStoreDocumentResult No(
+        BackForwardCacheMetrics::CanNotStoreDocumentReason reason);
     static CanStoreDocumentResult NoDueToFeatures(uint64_t features);
 
     std::string ToString();
@@ -53,9 +53,11 @@
     operator bool() const { return can_store; }
 
    private:
-    CanStoreDocumentResult(bool can_store,
-                           base::Optional<Reason> reason,
-                           uint64_t blocklisted_features);
+    CanStoreDocumentResult(
+        bool can_store,
+        base::Optional<BackForwardCacheMetrics::CanNotStoreDocumentReason>
+            reason,
+        uint64_t blocklisted_features);
   };
 
   // Returns whether a RenderFrameHost can be stored into the
diff --git a/content/browser/frame_host/back_forward_cache_metrics.h b/content/browser/frame_host/back_forward_cache_metrics.h
index fe1567b..e789c4f 100644
--- a/content/browser/frame_host/back_forward_cache_metrics.h
+++ b/content/browser/frame_host/back_forward_cache_metrics.h
@@ -30,6 +30,18 @@
 class BackForwardCacheMetrics
     : public base::RefCounted<BackForwardCacheMetrics> {
  public:
+  enum class CanNotStoreDocumentReason : uint8_t {
+    kNotMainFrame,
+    kBackForwardCacheDisabled,
+    kRelatedActiveContentsExist,
+    kHTTPStatusNotOK,
+    kSchemeNotHTTPOrHTTPS,
+    kLoading,
+    kWasGrantedMediaAccess,
+    kBlocklistedFeatures,
+    kDisableForRenderFrameHostCalled
+  };
+
   // Creates a potential new metrics object for the navigation.
   // Note that this object will not be used if the entry we are navigating to
   // already has the BackForwardCacheMetrics object (which happens for history
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 886aeed5..f48296a 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -3541,11 +3541,35 @@
   TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
   const GURL url1_sub("http://foo/subframe");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1_sub, subframe);
+
+  auto subframe_navigation =
+      NavigationSimulator::CreateRendererInitiated(url1_sub, subframe);
+  subframe_navigation->Start();
+
+  // Creating the subframe navigation should have no effect on the pending
+  // navigation entry and on the visible URL.
+  EXPECT_EQ(url1, controller.GetLastCommittedEntry()->GetURL());
+  EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
+
+  auto nav_entry_id = [](NavigationSimulator* simulator) {
+    return NavigationRequest::From(simulator->GetNavigationHandle())
+        ->nav_entry_id();
+  };
+
+  // The main frame navigation is still associated with the pending entry, the
+  // subframe one isn't.
+  EXPECT_EQ(controller.GetPendingEntry()->GetUniqueID(),
+            nav_entry_id(main_frame_navigation.get()));
+  EXPECT_EQ(0, nav_entry_id(subframe_navigation.get()));
+
+  subframe_navigation->Commit();
 
   // The subframe navigation should have no effect on the displayed url.
   EXPECT_EQ(url1, controller.GetLastCommittedEntry()->GetURL());
   EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
+
+  EXPECT_EQ(controller.GetPendingEntry()->GetUniqueID(),
+            nav_entry_id(main_frame_navigation.get()));
 }
 
 // Test CopyStateFrom with 2 urls, the first selected and nothing in the target.
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 8a700e29a..b8ff600c 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -657,22 +657,9 @@
     return;
   }
 
-  // In all other cases the current navigation, if any, is canceled and a new
-  // NavigationRequest is created for the node.
-  if (frame_tree_node->IsMainFrame()) {
-    // Renderer-initiated main-frame navigations that need to swap processes
-    // will go to the browser via a OpenURL call, and then be handled by the
-    // same code path as browser-initiated navigations. For renderer-initiated
-    // main frame navigation that start via a BeginNavigation IPC, the
-    // RenderFrameHost will not be swapped. Therefore it is safe to call
-    // DidStartMainFrameNavigation with the SiteInstance from the current
-    // RenderFrameHost.
-    DidStartMainFrameNavigation(
-        *common_params,
-        frame_tree_node->current_frame_host()->GetSiteInstance(), nullptr);
-    navigation_data_.reset();
-  }
-  NavigationEntryImpl* pending_entry = controller_->GetPendingEntry();
+  NavigationEntryImpl* navigation_entry =
+      GetNavigationEntryForRendererInitiatedNavigation(*common_params,
+                                                       frame_tree_node);
   NavigationEntryImpl* current_entry = controller_->GetLastCommittedEntry();
   if (current_entry && common_params->url == current_entry->GetReferrer().url) {
     // Looks like a potential client redirect loop. Turn off any preview
@@ -691,7 +678,7 @@
           : delegate_ && delegate_->ShouldOverrideUserAgentInNewTabs();
   frame_tree_node->CreatedNavigationRequest(
       NavigationRequest::CreateRendererInitiated(
-          frame_tree_node, pending_entry, std::move(common_params),
+          frame_tree_node, navigation_entry, std::move(common_params),
           std::move(begin_params), controller_->GetLastCommittedEntryIndex(),
           controller_->GetEntryCount(), override_user_agent,
           std::move(blob_url_loader_factory), std::move(navigation_client),
@@ -881,10 +868,13 @@
   navigation_data_.reset();
 }
 
-void NavigatorImpl::DidStartMainFrameNavigation(
+NavigationEntryImpl*
+NavigatorImpl::GetNavigationEntryForRendererInitiatedNavigation(
     const mojom::CommonNavigationParams& common_params,
-    SiteInstanceImpl* site_instance,
-    NavigationHandleImpl* navigation_handle) {
+    FrameTreeNode* frame_tree_node) {
+  if (!frame_tree_node->IsMainFrame())
+    return nullptr;
+
   // If there is no browser-initiated pending entry for this navigation and it
   // is not for the error URL, create a pending entry and ensure the address bar
   // updates accordingly.  We don't know the referrer or extra headers at this
@@ -894,6 +884,8 @@
   NavigationEntryImpl* pending_entry = controller_->GetPendingEntry();
   bool has_browser_initiated_pending_entry =
       pending_entry && !pending_entry->is_renderer_initiated();
+  if (has_browser_initiated_pending_entry)
+    return nullptr;
 
   // A pending navigation entry is created in OnBeginNavigation(). The renderer
   // sends a provisional load notification after that. We don't want to create
@@ -901,33 +893,29 @@
   bool renderer_provisional_load_to_pending_url =
       pending_entry && pending_entry->is_renderer_initiated() &&
       (pending_entry->GetURL() == common_params.url);
+  if (renderer_provisional_load_to_pending_url)
+    return nullptr;
 
   // If there is a transient entry, creating a new pending entry will result
   // in deleting it, which leads to inconsistent state.
   bool has_transient_entry = !!controller_->GetTransientEntry();
+  if (has_transient_entry)
+    return nullptr;
 
-  if (!has_browser_initiated_pending_entry && !has_transient_entry &&
-      !renderer_provisional_load_to_pending_url) {
-    std::unique_ptr<NavigationEntryImpl> entry =
-        NavigationEntryImpl::FromNavigationEntry(
-            NavigationController::CreateNavigationEntry(
-                common_params.url, content::Referrer(),
-                common_params.initiator_origin, ui::PAGE_TRANSITION_LINK,
-                true /* is_renderer_initiated */, std::string(),
-                controller_->GetBrowserContext(),
-                nullptr /* blob_url_loader_factory */));
-    // TODO(creis): If there's a pending entry already, find a safe way to
-    // update it instead of replacing it and copying over things like this.
-    // That will allow us to skip the NavigationHandle update below as well.
-    if (pending_entry) {
-      entry->set_should_replace_entry(pending_entry->should_replace_entry());
-      entry->SetRedirectChain(pending_entry->GetRedirectChain());
-    }
+  std::unique_ptr<NavigationEntryImpl> entry =
+      NavigationEntryImpl::FromNavigationEntry(
+          NavigationController::CreateNavigationEntry(
+              common_params.url, content::Referrer(),
+              common_params.initiator_origin, ui::PAGE_TRANSITION_LINK,
+              true /* is_renderer_initiated */, std::string(),
+              controller_->GetBrowserContext(),
+              nullptr /* blob_url_loader_factory */));
 
-    controller_->SetPendingEntry(std::move(entry));
-    if (delegate_)
-      delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL);
-  }
+  controller_->SetPendingEntry(std::move(entry));
+  if (delegate_)
+    delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL);
+
+  return controller_->GetPendingEntry();
 }
 
 }  // namespace content
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h
index fce48a9..d95b4af 100644
--- a/content/browser/frame_host/navigator_impl.h
+++ b/content/browser/frame_host/navigator_impl.h
@@ -127,13 +127,12 @@
       const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
       SiteInstance* site_instance);
 
-  // Called when a navigation has started in a main frame, to update the pending
-  // NavigationEntry if the controller does not currently have a
-  // browser-initiated one.
-  void DidStartMainFrameNavigation(
+  // Called when a renderer initiated navigation has started. Returns the
+  // pending NavigationEntry to be used. Either null or a new one owned
+  // NavigationController.
+  NavigationEntryImpl* GetNavigationEntryForRendererInitiatedNavigation(
       const mojom::CommonNavigationParams& common_params,
-      SiteInstanceImpl* site_instance,
-      NavigationHandleImpl* navigation_handle);
+      FrameTreeNode* frame_tree_node);
 
   // The NavigationController that will keep track of session history for all
   // RenderFrameHost objects using this NavigatorImpl.
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index e0d2be5f..7d87da2 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -347,7 +347,7 @@
   void SendTouch(RenderWidgetHostViewAura* view,
                  ui::EventType type,
                  gfx::Point point) {
-    DCHECK(type >= ui::ET_TOUCH_RELEASED && type << ui::ET_TOUCH_CANCELLED);
+    DCHECK(type >= ui::ET_TOUCH_RELEASED && type <= ui::ET_TOUCH_CANCELLED);
     // If we want the GestureRecognizer to create the gestures for us, we must
     // register the outgoing touch event with it by sending it through the
     // window's event dispatching system.
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc
index 52a96c4..9ed33ec 100644
--- a/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -234,6 +234,9 @@
     Navigate(shell());
 
     TracingControllerImpl* controller = TracingControllerImpl::GetInstance();
+    tracing::TraceEventAgent::GetInstance()->AddMetadataGeneratorFunction(
+        base::Bind(&TracingControllerTest::GenerateMetadataDict,
+                   base::Unretained(this)));
 
     {
       base::RunLoop run_loop;
@@ -263,9 +266,6 @@
 
       metadata_ = std::make_unique<base::DictionaryValue>();
       metadata_->SetString("not-whitelisted", "this_not_found");
-      tracing::TraceEventAgent::GetInstance()->AddMetadataGeneratorFunction(
-          base::Bind(&TracingControllerTest::GenerateMetadataDict,
-                     base::Unretained(this)));
 
       bool result = controller->StopTracing(trace_data_endpoint);
       ASSERT_TRUE(result);
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index f77550f..a40e8af 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -334,10 +334,6 @@
       base::FeatureList::IsEnabled(features::kWebAuth));
 #endif
 
-  WebRuntimeFeatures::EnableClientPlaceholdersForServerLoFi(
-      base::GetFieldTrialParamValue("PreviewsClientLoFi",
-                                    "replace_server_placeholders") != "false");
-
   WebRuntimeFeatures::EnableResourceLoadScheduler(
       base::FeatureList::IsEnabled(features::kResourceLoadScheduler));
 
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index 45e93ab..3505d05 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -91,7 +91,9 @@
       browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
       delegate_(delegate),
       task_runner_(
-          render_frame->GetTaskRunner(blink::TaskType::kInternalDefault)) {
+          // Make sure BrowserPlugin::UpdateInternalInstanceId runs in FIFO
+          // order with respect to other loading tasks.
+          render_frame->GetTaskRunner(blink::TaskType::kInternalLoading)) {
   browser_plugin_instance_id_ =
       BrowserPluginManager::Get()->GetNextInstanceID();
 
diff --git a/content/test/data/gpu/pixel_video_mp4_rounded_corner.html b/content/test/data/gpu/pixel_video_mp4_rounded_corner.html
new file mode 100644
index 0000000..07d2a7c0
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_mp4_rounded_corner.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+
+<!-- READ BEFORE UPDATING:
+If this test is updated make sure to increment the "revision" value of the
+associated test in content/test/gpu/page_sets/pixel_tests.py. This will ensure
+that the baseline images are regenerated on the next run.
+-->
+
+<html>
+  <head>
+    <meta name="viewport" content="initial-scale=1">
+    <title>MP4 Video test</title>
+    <style type="text/css">
+      .nomargin {
+        margin: 0px auto;
+      }
+      .rounded-corner {
+        border-radius: 20px;
+      }
+    </style>
+    <script src="pixel_video_test.js"></script>
+  </head>
+  <body onload="main()">
+    <div id="container" style="position:absolute; top:0px; left:0px">
+      <video class="nomargin rounded-corner" id="video" width="240"
+          height="135">
+        <source src="/media/test/data/four-colors.mp4" type="video/mp4">
+      </video>
+    </div>
+  </body>
+</html>
+
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py
index ecda631..56f453c1 100644
--- a/content/test/gpu/gpu_tests/gpu_helper.py
+++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -134,6 +134,16 @@
 
 
 # Used to parse additional options sent to the browser instance via
+# '--extra-browser-args', looking for '--use-gl='.
+def GetGL(extra_browser_args):
+  if extra_browser_args:
+    for o in extra_browser_args:
+      if "--use-gl=" in o:
+        return 'use-gl'
+  return 'no-use-gl'
+
+
+# Used to parse additional options sent to the browser instance via
 # '--extra-browser-args', looking for '--use-vulkan='.
 def GetVulkan(extra_browser_args):
   if extra_browser_args:
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test.py b/content/test/gpu/gpu_tests/gpu_integration_test.py
index 2b54779..fe8d50b 100644
--- a/content/test/gpu/gpu_tests/gpu_integration_test.py
+++ b/content/test/gpu/gpu_tests/gpu_integration_test.py
@@ -315,6 +315,9 @@
       skia_renderer = gpu_helper.GetSkiaRenderer(\
           browser._browser_backend.browser_options.extra_browser_args)
       tags.extend([skia_renderer])
+      use_gl = gpu_helper.GetGL(\
+          browser._browser_backend.browser_options.extra_browser_args)
+      tags.extend([use_gl])
       use_vulkan = gpu_helper.GetVulkan(\
           browser._browser_backend.browser_options.extra_browser_args)
       tags.extend([use_vulkan])
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index 01f9e82..bc18e470 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -425,6 +425,13 @@
         ]),
 
       PixelTestPage(
+        'pixel_video_mp4_rounded_corner.html',
+        base_name + '_Video_MP4_Rounded_Corner',
+        test_rect=[0, 0, 240, 135],
+        revision=0,
+        tolerance=tolerance),
+
+      PixelTestPage(
         'pixel_video_vp9.html',
         base_name + '_Video_VP9',
         test_rect=[0, 0, 240, 135],
@@ -1750,4 +1757,12 @@
             'size': [65, 30],
             'color': [44, 255, 16],
           }]),
+
+      PixelTestPage(
+        'pixel_video_mp4_rounded_corner.html',
+        base_name + '_DirectComposition_Video_MP4_Rounded_Corner',
+        test_rect=[0, 0, 240, 135],
+        revision=0,
+        browser_args=browser_args,
+        tolerance=tolerance_dc),
       ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index a68ab95..39c5dd2 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -1,6 +1,7 @@
 # tags: [ android chromeos highsierra linux mac mojave win ]
 # tags: [ android-chromium android-webview-instrumentation debug ]
 # tags: [ skia-renderer no-skia-renderer ]
+# tags: [ use-gl no-use-gl ]
 # tags: [ use-vulkan no-use-vulkan ]
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 intel intel-0xa2e intel-0x5912
 #         intel-0xd26 nvidia qualcomm-adreno-(tm)-330 qualcomm-adreno-(tm)-418
@@ -132,11 +133,11 @@
 
 # Fails on Nexus 5, 6 and 6P
 crbug.com/883500 [ android no-skia-renderer qualcomm-adreno-(tm)-330 ] Pixel_BackgroundImage [ Skip ]
-crbug.com/883500 [ android no-use-vulkan qualcomm-adreno-(tm)-420 ] Pixel_BackgroundImage [ Skip ]
-crbug.com/883500 [ android no-use-vulkan qualcomm-adreno-(tm)-430 ] Pixel_BackgroundImage [ Skip ]
+crbug.com/883500 [ android no-use-gl no-use-vulkan qualcomm-adreno-(tm)-420 ] Pixel_BackgroundImage [ Skip ]
+crbug.com/883500 [ android no-use-gl no-use-vulkan qualcomm-adreno-(tm)-430 ] Pixel_BackgroundImage [ Skip ]
 
 # Flakes on Nexus 5X.
-crbug.com/883500 [ android-chromium no-use-vulkan qualcomm-adreno-(tm)-418 ] Pixel_BackgroundImage [ RetryOnFailure ]
+crbug.com/883500 [ android-chromium no-use-gl no-use-vulkan qualcomm-adreno-(tm)-418 ] Pixel_BackgroundImage [ RetryOnFailure ]
 
 # We do not have software H.264 decoding on Android, so it can't survive a
 # context loss which results in hardware decoder loss.
@@ -222,6 +223,19 @@
 crbug.com/991291 [ android skia-renderer use-vulkan ] Pixel_Video_MP4_FourColors_Rot_90 [ Skip ]
 crbug.com/991291 [ android skia-renderer use-vulkan ] Pixel_Video_VP9 [ Skip ]
 
+# Fails when the browser features SkiaRenderer & GL are enabled on Android.
+# The more specific matching criteria is to prevent collisions with other expectations.
+crbug.com/969864 [ android skia-renderer use-gl no-use-vulkan ] Pixel_BackgroundImage [ Skip ]
+crbug.com/969864 [ android skia-renderer use-gl no-use-vulkan ] Pixel_CanvasDisplayLinearRGBAccelerated2D [ Skip ]
+crbug.com/969864 [ android android-chromium skia-renderer use-gl no-use-vulkan ] Pixel_OffscreenCanvasTransferAfterStyleResize [ Skip ]
+crbug.com/969864 [ android android-chromium skia-renderer use-gl no-use-vulkan ] Pixel_OffscreenCanvasTransferBeforeStyleResize [ Skip ]
+crbug.com/969864 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4 [ Skip ]
+crbug.com/969864 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4_FourColors_Aspect_4x3 [ Skip ]
+crbug.com/969864 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4_FourColors_Rot_180 [ Skip ]
+crbug.com/969864 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4_FourColors_Rot_270 [ Skip ]
+crbug.com/969864 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4_FourColors_Rot_90 [ Skip ]
+crbug.com/969864 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_VP9 [ Skip ]
+
 # Produces blank images on Intel HD 630 w/ Mesa 19.0.2
 crbug.com/976861 [ linux intel-0x5912 ] Pixel_OffscreenCanvasTransferToImageBitmap [ Skip ]
 
@@ -244,3 +258,6 @@
 
 # Producing incorrect image on Win10 Intel HD 630 w/ 26.20.100.6912 drivers.
 crbug.com/997313 [ win intel-0x5912 ] Pixel_WebGL_PremultipliedAlpha_False [ Failure ]
+
+# Rounded corner pixel test fails on Android vulkan.
+crbug.com/1007019 [ android skia-renderer use-vulkan ] Pixel_Video_MP4_Rounded_Corner [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index 0d56f55e..3260186 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -40,3 +40,8 @@
 crbug.com/960007 [ win10 nvidia ] OverlayModeTraceTest_DirectComposition_Nonroot [ RetryOnFailure ]
 crbug.com/969117 [ win10 intel ] OverlayModeTraceTest_DirectComposition_Video_MP4_FourColors_Aspect_4x3 [ RetryOnFailure ]
 crbug.com/978181 [ win10 nvidia ] OverlayModeTraceTest_DirectComposition_Underlay [ RetryOnFailure ]
+
+# These tests check if overlay is being used for the test, but they shouldn't.
+# TODO(sunnyps) - Remove when this inherent check is removed.
+crbug.com/1007411 [ win10 ] OverlayModeTraceTest_DirectComposition_Video_MP4_Rounded_Corner [ Failure ]
+crbug.com/1007411 [ win10 ] VideoPathTraceTest_DirectComposition_Video_MP4_Rounded_Corner [ Failure ]
diff --git a/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc
index 292b9e2..d84b5af 100644
--- a/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc
@@ -12,8 +12,8 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/task_environment.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_advertisement.h"
@@ -166,7 +166,8 @@
 
   BluetoothAdvertisement::ErrorCode last_error_code_;
 
-  base::MessageLoopForIO message_loop_;
+  base::test::SingleThreadTaskEnvironment task_environment_{
+      base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
 
   std::unique_ptr<TestBluetoothAdvertisementObserver> observer_;
   scoped_refptr<BluetoothAdapter> adapter_;
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index 4ff8c30..4ee6dad 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -31,6 +31,7 @@
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/install_flag.h"
 #include "extensions/browser/pref_names.h"
+#include "extensions/common/constants.h"
 #include "extensions/common/manifest.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_info.h"
@@ -804,12 +805,20 @@
       disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT |
       disable_reason::DISABLE_CORRUPTED;
 
+  // Allow the camera app to be disabled by extension policy. This is a
+  // temporary solution until there's a dedicated policy to disable the
+  // camera, at which point this should be removed.
+  // TODO(http://crbug.com/1002935)
+  int allowed_disable_reasons = kAllowDisableReasons;
+  if (component_extension_id == extension_misc::kCameraAppId)
+    allowed_disable_reasons |= disable_reason::DISABLE_BLOCKED_BY_POLICY;
+
   // Some disable reasons incorrectly cause component extensions to never
   // activate on load. See https://crbug.com/946839 for more details on why we
   // do this.
   ModifyDisableReasons(
       component_extension_id,
-      kAllowDisableReasons & GetDisableReasons(component_extension_id),
+      allowed_disable_reasons & GetDisableReasons(component_extension_id),
       DISABLE_REASON_REPLACE);
 }
 
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 7fc9e0fe7..f9602ccf 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -554,6 +554,9 @@
     {"ios-breadcrumbs", flag_descriptions::kLogBreadcrumbsName,
      flag_descriptions::kLogBreadcrumbsDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kLogBreadcrumbs)},
+    {"password-leak-detection", flag_descriptions::kPasswordLeakDetectionName,
+     flag_descriptions::kPasswordLeakDetectionDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(password_manager::features::kLeakDetection)},
 };
 
 // Add all switches from experimental flags to |command_line|.
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 5ff7caa6..09a3020 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -287,6 +287,10 @@
     "Make thumbnails of NTP articles optional due to European copyright "
     "directive(EUCD). Also change the layout of article cells";
 
+const char kPasswordLeakDetectionName[] = "Password Leak Detection";
+const char kPasswordLeakDetectionDescription[] =
+    "Enables the detection of leaked passwords.";
+
 const char kSearchIconToggleName[] = "Change the icon for the search button";
 const char kSearchIconToggleDescription[] =
     "Different icons for the search button.";
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 1616ad7..8a8b85e 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -240,6 +240,11 @@
 extern const char kOptionalArticleThumbnailName[];
 extern const char kOptionalArticleThumbnailDescription[];
 
+// Title and description for the flag to enable leak detection for entered
+// credentials.
+extern const char kPasswordLeakDetectionName[];
+extern const char kPasswordLeakDetectionDescription[];
+
 // Title and description for the flag to toggle the flag of the search button.
 extern const char kSearchIconToggleName[];
 extern const char kSearchIconToggleDescription[];
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h
index c04645e..3ac1638 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h
@@ -64,8 +64,6 @@
                       const base::string16& password) override;
   void PreviewSuggestion(const base::string16& username,
                          const base::string16& password) override;
-  void ShowInitialPasswordAccountSuggestions(
-      const autofill::PasswordFormFillData& form_data) override;
   void ClearPreviewedForm() override;
   password_manager::PasswordGenerationFrameHelper* GetPasswordGenerationHelper()
       override;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
index ae40530..90381aaf 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
@@ -58,12 +58,6 @@
   NOTIMPLEMENTED();
 }
 
-// TODO(crbug.com/568713): This method should be given a non-trivial
-// implementation before launch of the fill-on-account password manager
-// experiment.
-void IOSChromePasswordManagerDriver::ShowInitialPasswordAccountSuggestions(
-    const autofill::PasswordFormFillData& form_data) {}
-
 void IOSChromePasswordManagerDriver::ClearPreviewedForm() {
   NOTIMPLEMENTED();
 }
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 51a1112..22cc55d1 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -591,7 +591,7 @@
   } else {
     // Show a save prompt immediately because for iframes it is very hard to
     // figure out correctness of password forms submission.
-    self.passwordManager->OnPasswordFormSubmittedNoChecks(
+    self.passwordManager->OnPasswordFormSubmittedNoChecksForiOS(
         self.passwordManagerDriver, password_form);
   }
 }
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 0c5403d..b776187 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -125,7 +125,8 @@
 @property(nonatomic, weak) UIBarButtonItem* closeAllButton;
 @property(nonatomic, assign) BOOL undoCloseAllAvailable;
 @property(nonatomic, assign) TabGridConfiguration configuration;
-// Setting the current page will adjust the scroll view to the correct position.
+// Setting the current page doesn't scroll the scroll view; use
+// -scrollToPage:animated: for that.
 @property(nonatomic, assign) TabGridPage currentPage;
 // The UIViewController corresponding with |currentPage|.
 @property(nonatomic, readonly) UIViewController* currentPageViewController;
@@ -170,6 +171,14 @@
   // Hide the toolbars and the floating button, so they can fade in the first
   // time there's a transition into this view controller.
   [self hideToolbars];
+
+  // Mark the non-current page view controllers' contents as hidden for
+  // VoiceOver.
+  for (UIViewController* pageViewController in self.pageViewControllers) {
+    if (pageViewController != self.currentPageViewController) {
+      pageViewController.view.accessibilityElementsHidden = YES;
+    }
+  }
 }
 
 - (void)viewWillAppear:(BOOL)animated {
@@ -223,9 +232,10 @@
            (id<UIViewControllerTransitionCoordinator>)coordinator {
   [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
   auto animate = ^(id<UIViewControllerTransitionCoordinatorContext> context) {
-    // Call the current page setter to sync the scroll view offset to the
-    // current page value.
-    self.currentPage = _currentPage;
+    // Sync the scroll view offset to the  current page value. SInce this is
+    // already inside an animation block, the scrolling doesn't need to be
+    // animated.
+    [self scrollToPage:_currentPage animated:NO];
     [self configureViewControllerForCurrentSizeClassesAndPage];
     [self setInsetForRemoteTabs];
   };
@@ -255,8 +265,8 @@
     self.topToolbar.pageControl.sliderPosition = offset;
 
     TabGridPage page = GetPageFromScrollView(scrollView);
-    if (page != _currentPage) {
-      _currentPage = page;
+    if (page != self.currentPage) {
+      self.currentPage = page;
       [self broadcastIncognitoContentVisibility];
       [self configureButtonsForActiveAndCurrentPage];
       // Records when the user drags the scrollView to switch pages.
@@ -284,24 +294,19 @@
   // cause other interactions to be mislabeled.
   self.pageChangeInteraction = PageChangeInteractionNone;
 
-  // Update _currentPage if scroll view has moved to a new page. Especially
+  // Update currentPage if scroll view has moved to a new page. Especially
   // important here for 3-finger accessibility swipes since it's not registered
   // as dragging in scrollViewDidScroll:
   TabGridPage page = GetPageFromScrollView(scrollView);
-  if (page != _currentPage) {
-    // Original current page is about to not be visible. Disable it from being
-    // focused by VoiceOver.
-    self.currentPageViewController.view.accessibilityElementsHidden = YES;
-    _currentPage = page;
-    // Allow VoiceOver to focus on the new current page's elements.
-    self.currentPageViewController.view.accessibilityElementsHidden = NO;
+  if (page != self.currentPage) {
+    self.currentPage = page;
     [self broadcastIncognitoContentVisibility];
     [self configureButtonsForActiveAndCurrentPage];
   }
 }
 
 - (void)scrollViewDidEndScrollingAnimation:(UIScrollView*)scrollView {
-  _currentPage = GetPageFromScrollView(scrollView);
+  self.currentPage = GetPageFromScrollView(scrollView);
   self.scrollViewAnimatingContentOffset = NO;
   [self broadcastIncognitoContentVisibility];
   [self configureButtonsForActiveAndCurrentPage];
@@ -408,7 +413,7 @@
 #pragma mark - TabGridPaging
 
 - (void)setActivePage:(TabGridPage)activePage {
-  [self setCurrentPage:activePage animated:YES];
+  [self scrollToPage:activePage animated:YES];
   _activePage = activePage;
 }
 
@@ -417,10 +422,10 @@
 // Sets the proper insets for the Remote Tabs ViewController to accomodate for
 // the safe area, toolbar, and status bar.
 - (void)setInsetForRemoteTabs {
-  // Call the current page setter to sync the scroll view offset to the current
-  // page value, if the scroll view isn't scrolling. Don't animate this.
+  // Sync the scroll view offset to the current page value if the scroll view
+  // isn't scrolling. Don't animate this.
   if (!self.scrollView.dragging && !self.scrollView.decelerating) {
-    self.currentPage = _currentPage;
+    [self scrollToPage:self.currentPage animated:NO];
   }
   // The content inset of the tab grids must be modified so that the toolbars
   // do not obscure the tabs. This may change depending on orientation.
@@ -452,10 +457,10 @@
 // Sets the proper insets for the Grid ViewControllers to accomodate for the
 // safe area and toolbar.
 - (void)setInsetForGridViews {
-  // Call the current page setter to sync the scroll view offset to the current
-  // page value, if the scroll view isn't scrolling. Don't animate this.
+  // Sync the scroll view offset to the current page value if the scroll view
+  // isn't scrolling. Don't animate this.
   if (!self.scrollView.dragging && !self.scrollView.decelerating) {
-    self.currentPage = _currentPage;
+    [self scrollToPage:self.currentPage animated:NO];
   }
   // The content inset of the tab grids must be modified so that the toolbars
   // do not obscure the tabs. This may change depending on orientation.
@@ -486,38 +491,34 @@
 }
 
 - (void)setCurrentPage:(TabGridPage)currentPage {
-  // Setting the current page will adjust the scroll view to the correct
-  // position.
-  [self setCurrentPage:currentPage animated:NO];
+  // Original current page is about to not be visible. Disable it from being
+  // focused by VoiceOver.
+  self.currentPageViewController.view.accessibilityElementsHidden = YES;
+  _currentPage = currentPage;
+  self.currentPageViewController.view.accessibilityElementsHidden = NO;
 }
 
 // Sets the value of |currentPage|, adjusting the position of the scroll view
 // to match. If |animated| is YES, the scroll view change may animate; if it is
 // NO, it will never animate.
-- (void)setCurrentPage:(TabGridPage)currentPage animated:(BOOL)animated {
+- (void)scrollToPage:(TabGridPage)targetPage animated:(BOOL)animated {
   // This method should never early return if |currentPage| == |_currentPage|;
   // the ivar may have been set before the scroll view could be updated. Calling
   // this method should always update the scroll view's offset if possible.
 
-  // Original current page is about to not be visible. Disable it from being
-  // focused by VoiceOver.
-  self.currentPageViewController.view.accessibilityElementsHidden = YES;
-
-  // If the view isn't loaded yet, just do bookkeeping on _currentPage.
+  // If the view isn't loaded yet, just do bookkeeping on |currentPage|.
   if (!self.viewLoaded) {
-    _currentPage = currentPage;
-    // Allow VoiceOver to focus on the new current page's elements.
-    self.currentPageViewController.view.accessibilityElementsHidden = NO;
+    self.currentPage = targetPage;
     return;
   }
   CGFloat pageWidth = self.scrollView.frame.size.width;
-  NSUInteger pageIndex = GetPageIndexFromPage(currentPage);
+  NSUInteger pageIndex = GetPageIndexFromPage(targetPage);
   CGPoint offset = CGPointMake(pageIndex * pageWidth, 0);
   // If the view is visible and |animated| is YES, animate the change.
   // Otherwise don't.
   if (self.view.window == nil || !animated) {
     [self.scrollView setContentOffset:offset animated:NO];
-    _currentPage = currentPage;
+    self.currentPage = targetPage;
   } else {
     // Only set |scrollViewAnimatingContentOffset| to YES if there's an actual
     // change in the contentOffset, as |-scrollViewDidEndScrollingAnimation:| is
@@ -525,19 +526,17 @@
     if (!CGPointEqualToPoint(self.scrollView.contentOffset, offset)) {
       self.scrollViewAnimatingContentOffset = YES;
       [self.scrollView setContentOffset:offset animated:YES];
-      // _currentPage is set in scrollViewDidEndScrollingAnimation:
+      // |self.currentPage| is set in scrollViewDidEndScrollingAnimation:
     } else {
-      _currentPage = currentPage;
+      self.currentPage = targetPage;
     }
   }
-  // Allow VoiceOver to focus on the new current page's elements.
-  self.currentPageViewController.view.accessibilityElementsHidden = NO;
 
   // TODO(crbug.com/872303) : This is a workaround because TabRestoreService
   // does not notify observers when entries are removed. When close all tabs
   // removes entries, the remote tabs page in the tab grid are not updated. This
   // ensures that the table is updated whenever scrolling to it.
-  if (currentPage == TabGridPageRemoteTabs) {
+  if (targetPage == TabGridPageRemoteTabs) {
     [self.remoteTabsViewController loadModel];
     [self.remoteTabsViewController.tableView reloadData];
   }
@@ -1054,7 +1053,7 @@
   if (self.topToolbar.pageControl.selectedPage != page)
     [self.topToolbar.pageControl setSelectedPage:page animated:animated];
   if (self.currentPage != page)
-    [self setCurrentPage:page animated:animated];
+    [self scrollToPage:page animated:animated];
 }
 
 #pragma mark - GridViewControllerDelegate
@@ -1238,7 +1237,7 @@
     self.pageChangeInteraction = PageChangeInteractionPageControlTap;
 
   TabGridPage currentPage = self.currentPage;
-  [self setCurrentPage:newPage animated:YES];
+  [self scrollToPage:newPage animated:YES];
   // Records when the user uses the pageControl to switch pages.
   if (currentPage != newPage)
     [self recordActionSwitchingToPage:newPage];
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index 71f14423..c0dfe84 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -1636,6 +1636,22 @@
 
   web::NavigationContextImpl* navigationContext =
       [self.navigationStates contextForNavigation:navigation];
+
+  if (@available(iOS 13, *)) {
+  } else {
+    if (provisionalLoad && !navigationContext &&
+        web::RequiresProvisionalNavigationFailureWorkaround()) {
+      // It is likely that |navigationContext| is null because
+      // didStartProvisionalNavigation: was not called with this WKNavigation
+      // object. Log UMA to know when this workaround can be removed and
+      // do not call OnNavigationFinished() to avoid crash on null pointer
+      // dereferencing. See crbug.com/973653 and crbug.com/1004634 for details.
+      UMA_HISTOGRAM_BOOLEAN(
+          "Navigation.IOSNullContextInDidFailProvisionalNavigation", true);
+      return;
+    }
+  }
+
   navigationContext->SetError(error);
   navigationContext->SetIsPost([self isCurrentNavigationItemPOST]);
   // TODO(crbug.com/803631) DCHECK that self.currentNavItem is the navigation
diff --git a/ios/web/public/test/error_test_util.mm b/ios/web/public/test/error_test_util.mm
index 26139c9..57a13b4a 100644
--- a/ios/web/public/test/error_test_util.mm
+++ b/ios/web/public/test/error_test_util.mm
@@ -7,7 +7,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#import "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
 #import "ios/web/web_view/error_translation_util.h"
 #include "url/gurl.h"
 
diff --git a/ios/web/public/web_state/web_state.h b/ios/web/public/web_state/web_state.h
deleted file mode 100644
index f19a68b..0000000
--- a/ios/web/public/web_state/web_state.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_H_
-#define IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_H_
-
-// TODO(crbug.com/942244): Remove this header after downstream code
-// stopped including ios/web/public/web_state/web_state.h
-
-#import "ios/web/public/web_state.h"
-
-#endif  // IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_H_
diff --git a/ios/web/public/web_state/web_state_observer.h b/ios/web/public/web_state/web_state_observer.h
deleted file mode 100644
index 7e200da..0000000
--- a/ios/web/public/web_state/web_state_observer.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_OBSERVER_H_
-#define IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_OBSERVER_H_
-
-// TODO(crbug.com/942244): Remove this header after downstream code
-// stopped including ios/web/public/web_state/web_state.h
-
-#include "ios/web/public/web_state_observer.h"
-
-#endif  // IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_OBSERVER_H_
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn
index 8c519a6..28a3bcf 100644
--- a/ios/web_view/BUILD.gn
+++ b/ios/web_view/BUILD.gn
@@ -440,6 +440,7 @@
     "//components/autofill/ios/browser:test_support",
     "//components/autofill/ios/form_util:test_support",
     "//components/browser_sync:test_support",
+    "//components/password_manager/core/browser:test_support",
     "//components/prefs:test_support",
     "//components/signin/public/base:test_support",
     "//components/signin/public/identity_manager:test_support",
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller.mm b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
index fc0ef481..6348d528 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_controller.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
@@ -645,30 +645,28 @@
 #pragma mark - CWVPasswordControllerDelegate
 
 - (void)passwordController:(CWVPasswordController*)passwordController
-    decidePasswordSavingPolicyForUsername:(NSString*)username
-                          decisionHandler:
-                              (void (^)(CWVPasswordUserDecision decision))
-                                  decisionHandler {
+    decideSavePolicyForPassword:(CWVPassword*)password
+                decisionHandler:(void (^)(CWVPasswordUserDecision decision))
+                                    decisionHandler {
   if ([self.delegate respondsToSelector:@selector
-                     (autofillController:decidePasswordSavingPolicyForUsername
-                                           :decisionHandler:)]) {
+                     (autofillController:
+                         decideSavePolicyForPassword:decisionHandler:)]) {
     [self.delegate autofillController:self
-        decidePasswordSavingPolicyForUsername:username
-                              decisionHandler:decisionHandler];
+          decideSavePolicyForPassword:password
+                      decisionHandler:decisionHandler];
   }
 }
 
 - (void)passwordController:(CWVPasswordController*)passwordController
-    decidePasswordUpdatingPolicyForUsername:(NSString*)username
-                            decisionHandler:
-                                (void (^)(CWVPasswordUserDecision decision))
-                                    decisionHandler {
+    decideUpdatePolicyForPassword:(CWVPassword*)password
+                  decisionHandler:(void (^)(CWVPasswordUserDecision decision))
+                                      decisionHandler {
   if ([self.delegate respondsToSelector:@selector
-                     (autofillController:decidePasswordUpdatingPolicyForUsername
-                                           :decisionHandler:)]) {
+                     (autofillController:
+                         decideUpdatePolicyForPassword:decisionHandler:)]) {
     [self.delegate autofillController:self
-        decidePasswordUpdatingPolicyForUsername:username
-                                decisionHandler:decisionHandler];
+        decideUpdatePolicyForPassword:password
+                      decisionHandler:decisionHandler];
   }
 }
 
diff --git a/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm b/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
index 383e528..36540d5 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
@@ -10,24 +10,34 @@
 #include "base/task/post_task.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
+#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/password_store_default.h"
 #include "ios/web/public/thread/web_task_traits.h"
 #include "ios/web/public/thread/web_thread.h"
 #import "ios/web_view/internal/autofill/cwv_autofill_profile_internal.h"
 #import "ios/web_view/internal/autofill/cwv_credit_card_internal.h"
+#import "ios/web_view/internal/passwords/cwv_password_internal.h"
 #import "ios/web_view/public/cwv_autofill_data_manager_observer.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-// Typedefs of |completionHandler| in |fetchProfilesWithCompletionHandler:|
-// and |fetchCreditCardsWithCompletionHandler:|.
+// Typedefs of |completionHandler| in |fetchProfilesWithCompletionHandler:|,
+// |fetchCreditCardsWithCompletionHandler:|, and
+// |fetchPasswordsWithCompletionHandler|.
 typedef void (^CWVFetchProfilesCompletionHandler)(
     NSArray<CWVAutofillProfile*>* profiles);
 typedef void (^CWVFetchCreditCardsCompletionHandler)(
     NSArray<CWVCreditCard*>* creditCards);
+typedef void (^CWVFetchPasswordsCompletionHandler)(
+    NSArray<CWVPassword*>* passwords);
 
 @interface CWVAutofillDataManager ()
+
+// Called when WebViewPasswordStoreConsumer's |OnGetPasswordStoreResults| is
+// invoked.
+- (void)handlePasswordStoreResults:(NSArray<CWVPassword*>*)passwords;
 // Called when WebViewPersonalDataManagerObserverBridge's
 // |OnPersonalDataChanged| is invoked.
 - (void)personalDataDidChange;
@@ -37,6 +47,7 @@
 // Collects and converts autofill::CreditCards stored internally in
 // |_personalDataManager| to CWVCreditCards.
 - (NSArray<CWVCreditCard*>*)creditCards;
+
 @end
 
 namespace ios_web_view {
@@ -61,6 +72,27 @@
  private:
   __weak CWVAutofillDataManager* data_manager_;
 };
+
+// C++ to ObjC bridge for PasswordStoreConsumer.
+class WebViewPasswordStoreConsumer
+    : public password_manager::PasswordStoreConsumer {
+ public:
+  explicit WebViewPasswordStoreConsumer(CWVAutofillDataManager* data_manager)
+      : data_manager_(data_manager) {}
+  void OnGetPasswordStoreResults(
+      std::vector<std::unique_ptr<autofill::PasswordForm>> results) override {
+    NSMutableArray<CWVPassword*>* passwords = [NSMutableArray array];
+    for (auto& form : results) {
+      CWVPassword* password = [[CWVPassword alloc] initWithPasswordForm:*form];
+      [passwords addObject:password];
+    }
+    [data_manager_ handlePasswordStoreResults:passwords];
+  }
+
+ private:
+  __weak CWVAutofillDataManager* data_manager_;
+};
+
 }  // namespace ios_web_view
 
 @implementation CWVAutofillDataManager {
@@ -73,20 +105,30 @@
       _fetchProfilesCompletionHandlers;
   NSMutableArray<CWVFetchCreditCardsCompletionHandler>*
       _fetchCreditCardsCompletionHandlers;
+  NSMutableArray<CWVFetchPasswordsCompletionHandler>*
+      _fetchPasswordsCompletionHandlers;
   // Holds weak observers.
   NSHashTable<id<CWVAutofillDataManagerObserver>>* _observers;
+
+  password_manager::PasswordStore* _passwordStore;
+  std::unique_ptr<ios_web_view::WebViewPasswordStoreConsumer>
+      _passwordStoreConsumer;
 }
 
 - (instancetype)initWithPersonalDataManager:
-    (autofill::PersonalDataManager*)personalDataManager {
+                    (autofill::PersonalDataManager*)personalDataManager
+                              passwordStore:(password_manager::PasswordStore*)
+                                                passwordStore {
   self = [super init];
   if (self) {
     _personalDataManager = personalDataManager;
+    _passwordStore = passwordStore;
     _personalDataManagerObserverBridge = std::make_unique<
         ios_web_view::WebViewPersonalDataManagerObserverBridge>(self);
     _personalDataManager->AddObserver(_personalDataManagerObserverBridge.get());
     _fetchProfilesCompletionHandlers = [NSMutableArray array];
     _fetchCreditCardsCompletionHandlers = [NSMutableArray array];
+    _fetchPasswordsCompletionHandlers = [NSMutableArray array];
     _observers = [NSHashTable weakObjectsHashTable];
   }
   return self;
@@ -155,12 +197,39 @@
   _personalDataManager->RemoveByGUID(creditCard.internalCard->guid());
 }
 
+- (void)fetchPasswordsWithCompletionHandler:
+    (void (^)(NSArray<CWVPassword*>* passwords))completionHandler {
+  [_fetchPasswordsCompletionHandlers addObject:completionHandler];
+
+  // Fetch is already pending.
+  if (_passwordStoreConsumer) {
+    return;
+  }
+
+  _passwordStoreConsumer.reset(
+      new ios_web_view::WebViewPasswordStoreConsumer(self));
+  _passwordStore->GetAllLogins(_passwordStoreConsumer.get());
+}
+
+- (void)deletePassword:(CWVPassword*)password {
+  _passwordStore->RemoveLogin(*[password internalPasswordForm]);
+}
+
 - (void)clearAllLocalData {
   _personalDataManager->ClearAllLocalData();
 }
 
 #pragma mark - Private Methods
 
+- (void)handlePasswordStoreResults:(NSArray<CWVPassword*>*)passwords {
+  for (CWVFetchPasswordsCompletionHandler completionHandler in
+           _fetchPasswordsCompletionHandlers) {
+    completionHandler(passwords);
+  }
+  [_fetchPasswordsCompletionHandlers removeAllObjects];
+  _passwordStoreConsumer.reset();
+}
+
 - (void)personalDataDidChange {
   // Invoke completionHandlers if they are still outstanding.
   if (_personalDataManager->IsDataLoaded()) {
diff --git a/ios/web_view/internal/autofill/cwv_autofill_data_manager_internal.h b/ios/web_view/internal/autofill/cwv_autofill_data_manager_internal.h
index 6a59bd75..a0a51bb 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_data_manager_internal.h
+++ b/ios/web_view/internal/autofill/cwv_autofill_data_manager_internal.h
@@ -11,14 +11,21 @@
 class PersonalDataManager;
 }  // namespace autofill;
 
+namespace password_manager {
+class PasswordStore;
+}  // password_manager
+
 NS_ASSUME_NONNULL_BEGIN
 
 @interface CWVAutofillDataManager ()
 
 // |personalDataManager| The underlying personal data manager being wrapped.
+// |passwordStore| The underlying password store being wrapped.
 // It should outlive this instance.
 - (instancetype)initWithPersonalDataManager:
-    (autofill::PersonalDataManager*)personalDataManager
+                    (autofill::PersonalDataManager*)personalDataManager
+                              passwordStore:(password_manager::PasswordStore*)
+                                                passwordStore
     NS_DESIGNATED_INITIALIZER;
 
 @end
diff --git a/ios/web_view/internal/autofill/cwv_autofill_data_manager_unittest.mm b/ios/web_view/internal/autofill/cwv_autofill_data_manager_unittest.mm
index de12d923..502ec1c 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_data_manager_unittest.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_data_manager_unittest.mm
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
@@ -13,9 +14,12 @@
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/test_password_store.h"
 #include "ios/web/public/test/web_task_environment.h"
 #import "ios/web_view/internal/autofill/cwv_autofill_profile_internal.h"
 #import "ios/web_view/internal/autofill/cwv_credit_card_internal.h"
+#import "ios/web_view/internal/passwords/cwv_password_internal.h"
 #import "ios/web_view/public/cwv_autofill_data_manager_observer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
@@ -54,8 +58,13 @@
     personal_data_manager_->SetAutofillCreditCardEnabled(true);
     personal_data_manager_->SetAutofillWalletImportEnabled(true);
 
+    password_store_ = new password_manager::TestPasswordStore();
+    password_store_->Init(base::RepeatingCallback<void(syncer::ModelType)>(),
+                          nullptr);
+
     autofill_data_manager_ = [[CWVAutofillDataManager alloc]
-        initWithPersonalDataManager:personal_data_manager_.get()];
+        initWithPersonalDataManager:personal_data_manager_.get()
+                      passwordStore:password_store_.get()];
   }
 
   // Fetches profiles from |autofill_data_manager_| and returns them in
@@ -90,12 +99,45 @@
     });
   }
 
+  // Create a test password form for testing.
+  autofill::PasswordForm GetTestPassword() {
+    autofill::PasswordForm password_form;
+    password_form.origin = GURL("http://www.example.com/accounts/LoginAuth");
+    password_form.action = GURL("http://www.example.com/accounts/Login");
+    password_form.username_element = base::SysNSStringToUTF16(@"Email");
+    password_form.username_value = base::SysNSStringToUTF16(@"test@egmail.com");
+    password_form.password_element = base::SysNSStringToUTF16(@"Passwd");
+    password_form.password_value = base::SysNSStringToUTF16(@"test");
+    password_form.submit_element = base::SysNSStringToUTF16(@"signIn");
+    password_form.signon_realm = "http://www.example.com/";
+    password_form.preferred = false;
+    password_form.scheme = autofill::PasswordForm::Scheme::kHtml;
+    password_form.blacklisted_by_user = false;
+    return password_form;
+  }
+
+  // Fetches passwords from |autofill_data_manager_| and returns them.
+  NSArray<CWVPassword*>* FetchPasswords() WARN_UNUSED_RESULT {
+    __block NSArray<CWVPassword*>* fetched_passwords = nil;
+    [autofill_data_manager_ fetchPasswordsWithCompletionHandler:^(
+                                NSArray<CWVPassword*>* passwords) {
+      fetched_passwords = passwords;
+    }];
+    EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^bool {
+      base::RunLoop().RunUntilIdle();
+      return fetched_passwords != nil;
+    }));
+    return fetched_passwords;
+  }
+
   ~CWVAutofillDataManagerTest() override {
+    password_store_->ShutdownOnUIThread();
     ui::ResourceBundle::CleanupSharedInstance();
   }
 
   web::WebTaskEnvironment task_environment_;
   std::unique_ptr<autofill::TestPersonalDataManager> personal_data_manager_;
+  scoped_refptr<password_manager::TestPasswordStore> password_store_;
   CWVAutofillDataManager* autofill_data_manager_;
 };
 
@@ -202,6 +244,25 @@
   }));
 }
 
+// Tests CWVAutofillDataManager properly returns passwords.
+TEST_F(CWVAutofillDataManagerTest, ReturnPassword) {
+  autofill::PasswordForm test_password = GetTestPassword();
+  password_store_->AddLogin(test_password);
+  NSArray<CWVPassword*>* fetched_passwords = FetchPasswords();
+  EXPECT_EQ(1ul, fetched_passwords.count);
+  EXPECT_EQ(test_password, *[fetched_passwords[0] internalPasswordForm]);
+}
+
+// Tests CWVAutofillDataManager properly deletes passwords.
+TEST_F(CWVAutofillDataManagerTest, DeletePassword) {
+  password_store_->AddLogin(GetTestPassword());
+  NSArray<CWVPassword*>* passwords = FetchPasswords();
+  ASSERT_EQ(1ul, passwords.count);
+  [autofill_data_manager_ deletePassword:passwords[0]];
+  passwords = FetchPasswords();
+  EXPECT_EQ(0ul, passwords.count);
+}
+
 // Tests CWVAutofillDataManager properly deletes all local data.
 TEST_F(CWVAutofillDataManagerTest, ClearAllLocalData) {
   personal_data_manager_->AddCreditCard(autofill::test::GetCreditCard());
diff --git a/ios/web_view/internal/cwv_web_view_configuration.mm b/ios/web_view/internal/cwv_web_view_configuration.mm
index 8c39426..57969ad 100644
--- a/ios/web_view/internal/cwv_web_view_configuration.mm
+++ b/ios/web_view/internal/cwv_web_view_configuration.mm
@@ -8,6 +8,8 @@
 
 #include "base/logging.h"
 #include "base/threading/thread_restrictions.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/password_store_default.h"
 #include "components/sync/driver/sync_service.h"
 #include "ios/web_view/cwv_web_view_buildflags.h"
 #include "ios/web_view/internal/app/application_context.h"
@@ -16,6 +18,7 @@
 #import "ios/web_view/internal/cwv_preferences_internal.h"
 #import "ios/web_view/internal/cwv_user_content_controller_internal.h"
 #import "ios/web_view/internal/cwv_web_view_internal.h"
+#include "ios/web_view/internal/passwords/web_view_password_store_factory.h"
 #include "ios/web_view/internal/signin/ios_web_view_signin_client.h"
 #include "ios/web_view/internal/signin/web_view_identity_manager_factory.h"
 #include "ios/web_view/internal/signin/web_view_signin_client_factory.h"
@@ -135,8 +138,12 @@
     autofill::PersonalDataManager* personalDataManager =
         ios_web_view::WebViewPersonalDataManagerFactory::GetForBrowserState(
             self.browserState);
+    scoped_refptr<password_manager::PasswordStore> passwordStore =
+        ios_web_view::WebViewPasswordStoreFactory::GetForBrowserState(
+            self.browserState, ServiceAccessType::EXPLICIT_ACCESS);
     _autofillDataManager = [[CWVAutofillDataManager alloc]
-        initWithPersonalDataManager:personalDataManager];
+        initWithPersonalDataManager:personalDataManager
+                      passwordStore:passwordStore.get()];
   }
   return _autofillDataManager;
 }
diff --git a/ios/web_view/internal/passwords/cwv_password_controller.h b/ios/web_view/internal/passwords/cwv_password_controller.h
index dd5f829..81d0dc3 100644
--- a/ios/web_view/internal/passwords/cwv_password_controller.h
+++ b/ios/web_view/internal/passwords/cwv_password_controller.h
@@ -12,6 +12,7 @@
 typedef NS_ENUM(NSInteger, CWVPasswordUserDecision);
 @class CWVAutofillSuggestion;
 @class CWVPasswordController;
+@class CWVPassword;
 
 namespace web {
 class WebState;
@@ -20,29 +21,25 @@
 // Internal protocol to receive callbacks related to password autofilling.
 @protocol CWVPasswordControllerDelegate
 
-// Called when user needs to decide on whether or not to save the
-// password for |username|.
+// Called when user needs to decide on whether or not to save the |password|.
 // This can happen when user is successfully logging into a web site with a new
 // username.
 // Pass user decision to |decisionHandler|. This block should be called only
 // once if user made the decision, or not get called if user ignores the prompt.
 - (void)passwordController:(CWVPasswordController*)passwordController
-    decidePasswordSavingPolicyForUsername:(NSString*)username
-                          decisionHandler:
-                              (void (^)(CWVPasswordUserDecision decision))
-                                  decisionHandler;
+    decideSavePolicyForPassword:(CWVPassword*)password
+                decisionHandler:
+                    (void (^)(CWVPasswordUserDecision decision))decisionHandler;
 
-// Called when user needs to decide on whether or not to update the
-// password for |username|.
+// Called when user needs to decide on whether or not to update the |password|.
 // This can happen when user is successfully logging into a web site with a new
 // password and an existing username.
 // Pass user decision to |decisionHandler|. This block should be called only
 // once if user made the decision, or not get called if user ignores the prompt.
 - (void)passwordController:(CWVPasswordController*)passwordController
-    decidePasswordUpdatingPolicyForUsername:(NSString*)username
-                            decisionHandler:
-                                (void (^)(CWVPasswordUserDecision decision))
-                                    decisionHandler;
+    decideUpdatePolicyForPassword:(CWVPassword*)password
+                  decisionHandler:(void (^)(CWVPasswordUserDecision decision))
+                                      decisionHandler;
 
 @end
 
diff --git a/ios/web_view/internal/passwords/cwv_password_controller.mm b/ios/web_view/internal/passwords/cwv_password_controller.mm
index 263ec23..dbf4ff8 100644
--- a/ios/web_view/internal/passwords/cwv_password_controller.mm
+++ b/ios/web_view/internal/passwords/cwv_password_controller.mm
@@ -23,6 +23,7 @@
 #import "ios/web/public/web_state.h"
 #import "ios/web/public/web_state_observer_bridge.h"
 #import "ios/web_view/internal/autofill/cwv_autofill_suggestion_internal.h"
+#import "ios/web_view/internal/passwords/cwv_password_internal.h"
 #import "ios/web_view/internal/passwords/web_view_password_manager_client.h"
 #import "ios/web_view/internal/passwords/web_view_password_manager_driver.h"
 #include "ios/web_view/internal/web_view_browser_state.h"
@@ -207,25 +208,25 @@
   __block std::unique_ptr<PasswordFormManagerForUI> formPtr(
       std::move(formToSave));
 
-  NSString* userName =
-      base::SysUTF16ToNSString(formPtr->GetPendingCredentials().username_value);
+  const PasswordForm& credentials = formPtr->GetPendingCredentials();
+  CWVPassword* password =
+      [[CWVPassword alloc] initWithPasswordForm:credentials];
 
   [self.delegate passwordController:self
-      decidePasswordSavingPolicyForUsername:userName
-                            decisionHandler:^(
-                                CWVPasswordUserDecision decision) {
-                              switch (decision) {
-                                case CWVPasswordUserDecisionYes:
-                                  formPtr->Save();
-                                  break;
-                                case CWVPasswordUserDecisionNever:
-                                  formPtr->PermanentlyBlacklist();
-                                  break;
-                                default:
-                                  // Do nothing.
-                                  break;
-                              }
-                            }];
+        decideSavePolicyForPassword:password
+                    decisionHandler:^(CWVPasswordUserDecision decision) {
+                      switch (decision) {
+                        case CWVPasswordUserDecisionYes:
+                          formPtr->Save();
+                          break;
+                        case CWVPasswordUserDecisionNever:
+                          formPtr->PermanentlyBlacklist();
+                          break;
+                        default:
+                          // Do nothing.
+                          break;
+                      }
+                    }];
 }
 
 - (void)showUpdatePasswordInfoBar:
@@ -240,18 +241,17 @@
       std::move(formToUpdate));
 
   const PasswordForm& credentials = formPtr->GetPendingCredentials();
-  NSString* userName = base::SysUTF16ToNSString(credentials.username_value);
+  CWVPassword* password =
+      [[CWVPassword alloc] initWithPasswordForm:credentials];
 
   [self.delegate passwordController:self
-      decidePasswordUpdatingPolicyForUsername:userName
-                              decisionHandler:^(
-                                  CWVPasswordUserDecision decision) {
-                                DCHECK_NE(decision,
-                                          CWVPasswordUserDecisionNever);
-                                if (decision == CWVPasswordUserDecisionYes) {
-                                  formPtr->Update(credentials);
-                                }
-                              }];
+      decideUpdatePolicyForPassword:password
+                    decisionHandler:^(CWVPasswordUserDecision decision) {
+                      DCHECK_NE(decision, CWVPasswordUserDecisionNever);
+                      if (decision == CWVPasswordUserDecisionYes) {
+                        formPtr->Update(credentials);
+                      }
+                    }];
 }
 
 - (void)showAutosigninNotification:(std::unique_ptr<PasswordForm>)formSignedIn {
@@ -285,7 +285,7 @@
   } else {
     // Show a save prompt immediately because for iframes it is very hard to
     // figure out correctness of password forms submission.
-    self.passwordManager->OnPasswordFormSubmittedNoChecks(
+    self.passwordManager->OnPasswordFormSubmittedNoChecksForiOS(
         self.passwordManagerDriver, password_form);
   }
 }
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_driver.h b/ios/web_view/internal/passwords/web_view_password_manager_driver.h
index 6b526732..2d56ed04 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_driver.h
+++ b/ios/web_view/internal/passwords/web_view_password_manager_driver.h
@@ -53,8 +53,6 @@
                       const base::string16& password) override;
   void PreviewSuggestion(const base::string16& username,
                          const base::string16& password) override;
-  void ShowInitialPasswordAccountSuggestions(
-      const autofill::PasswordFormFillData& form_data) override;
   void ClearPreviewedForm() override;
   password_manager::PasswordGenerationFrameHelper* GetPasswordGenerationHelper()
       override;
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_driver.mm b/ios/web_view/internal/passwords/web_view_password_manager_driver.mm
index 90eea3c..9eccbe3 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_driver.mm
+++ b/ios/web_view/internal/passwords/web_view_password_manager_driver.mm
@@ -49,9 +49,6 @@
   NOTIMPLEMENTED();
 }
 
-void WebViewPasswordManagerDriver::ShowInitialPasswordAccountSuggestions(
-    const autofill::PasswordFormFillData& form_data) {}
-
 void WebViewPasswordManagerDriver::ClearPreviewedForm() {
   NOTIMPLEMENTED();
 }
diff --git a/ios/web_view/public/cwv_autofill_controller_delegate.h b/ios/web_view/public/cwv_autofill_controller_delegate.h
index 5b41efa6..ed79af1 100644
--- a/ios/web_view/public/cwv_autofill_controller_delegate.h
+++ b/ios/web_view/public/cwv_autofill_controller_delegate.h
@@ -15,6 +15,7 @@
 @class CWVCreditCard;
 @class CWVCreditCardSaver;
 @class CWVCreditCardVerifier;
+@class CWVPassword;
 
 // User decision for saving / updating password.
 // Note: CWVPasswordUserDecisionNever is only used in saving scenarios.
@@ -97,31 +98,27 @@
 - (void)autofillController:(CWVAutofillController*)autofillController
     verifyCreditCardWithVerifier:(CWVCreditCardVerifier*)verifier;
 
-// Called when user needs to decide on whether or not to save the
-// password for |username|.
+// Called when user needs to decide on whether or not to save the |password|.
 // This can happen when user successfully logs into a web site with a new
 // username.
 // Pass user decision to |decisionHandler|. This block should be called only
 // once if user made the decision, or not get called if user ignores the prompt.
 // Not implementing it is equivalent of not calling |decisionHandler|.
 - (void)autofillController:(CWVAutofillController*)autofillController
-    decidePasswordSavingPolicyForUsername:(NSString*)username
-                          decisionHandler:
-                              (void (^)(CWVPasswordUserDecision decision))
-                                  decisionHandler;
+    decideSavePolicyForPassword:(CWVPassword*)password
+                decisionHandler:
+                    (void (^)(CWVPasswordUserDecision decision))decisionHandler;
 
-// Called when user needs to decide on whether or not to update the
-// password for |username|.
+// Called when user needs to decide on whether or not to update the |password|.
 // This can happen when user successfully logs into a web site with a new
 // password and an existing username.
 // Pass user decision to |decisionHandler|. This block should be called only
 // once if user made the decision, or not get called if user ignores the prompt.
 // Not implementing it is equivalent of not calling |decisionHandler|.
 - (void)autofillController:(CWVAutofillController*)autofillController
-    decidePasswordUpdatingPolicyForUsername:(NSString*)username
-                            decisionHandler:
-                                (void (^)(CWVPasswordUserDecision decision))
-                                    decisionHandler;
+    decideUpdatePolicyForPassword:(CWVPassword*)password
+                  decisionHandler:(void (^)(CWVPasswordUserDecision decision))
+                                      decisionHandler;
 
 @end
 
diff --git a/ios/web_view/public/cwv_autofill_data_manager.h b/ios/web_view/public/cwv_autofill_data_manager.h
index 60f3782..17117fb 100644
--- a/ios/web_view/public/cwv_autofill_data_manager.h
+++ b/ios/web_view/public/cwv_autofill_data_manager.h
@@ -13,6 +13,7 @@
 
 @class CWVAutofillProfile;
 @class CWVCreditCard;
+@class CWVPassword;
 @protocol CWVAutofillDataManagerObserver;
 
 // Exposes saved autofill data such as address profiles and credit cards.
@@ -47,6 +48,13 @@
 // Deletes the card.
 - (void)deleteCreditCard:(CWVCreditCard*)creditCard;
 
+// Returns all saved passwords for password autofill in |completionHandler|.
+- (void)fetchPasswordsWithCompletionHandler:
+    (void (^)(NSArray<CWVPassword*>* passwords))completionHandler;
+
+// Deletes the password.
+- (void)deletePassword:(CWVPassword*)password;
+
 // Deletes all locally saved data.
 - (void)clearAllLocalData;
 
diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc
index 8cfe044..6e34266 100644
--- a/ipc/ipc_channel_mojo.cc
+++ b/ipc/ipc_channel_mojo.cc
@@ -26,7 +26,8 @@
 #include "ipc/ipc_mojo_bootstrap.h"
 #include "ipc/ipc_mojo_handle_attachment.h"
 #include "ipc/native_handle_type_converters.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
 namespace IPC {
@@ -150,8 +151,8 @@
 
   WillConnect();
 
-  mojom::ChannelAssociatedPtr sender;
-  mojom::ChannelAssociatedRequest receiver;
+  mojo::AssociatedRemote<mojom::Channel> sender;
+  mojo::PendingAssociatedReceiver<mojom::Channel> receiver;
   bootstrap_->Connect(&sender, &receiver);
 
   DCHECK(!message_reader_);
diff --git a/ipc/ipc_message_pipe_reader.cc b/ipc/ipc_message_pipe_reader.cc
index b055d41..a78972c 100644
--- a/ipc/ipc_message_pipe_reader.cc
+++ b/ipc/ipc_message_pipe_reader.cc
@@ -23,18 +23,18 @@
 
 MessagePipeReader::MessagePipeReader(
     mojo::MessagePipeHandle pipe,
-    mojom::ChannelAssociatedPtr sender,
-    mojo::AssociatedInterfaceRequest<mojom::Channel> receiver,
+    mojo::AssociatedRemote<mojom::Channel> sender,
+    mojo::PendingAssociatedReceiver<mojom::Channel> receiver,
     MessagePipeReader::Delegate* delegate)
     : delegate_(delegate),
       sender_(std::move(sender)),
-      binding_(this, std::move(receiver)) {
-  sender_.set_connection_error_handler(
-      base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this),
-                 MOJO_RESULT_FAILED_PRECONDITION));
-  binding_.set_connection_error_handler(
-      base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this),
-                 MOJO_RESULT_FAILED_PRECONDITION));
+      receiver_(this, std::move(receiver)) {
+  sender_.set_disconnect_handler(base::Bind(&MessagePipeReader::OnPipeError,
+                                            base::Unretained(this),
+                                            MOJO_RESULT_FAILED_PRECONDITION));
+  receiver_.set_disconnect_handler(base::Bind(&MessagePipeReader::OnPipeError,
+                                              base::Unretained(this),
+                                              MOJO_RESULT_FAILED_PRECONDITION));
 }
 
 MessagePipeReader::~MessagePipeReader() {
@@ -45,8 +45,8 @@
 void MessagePipeReader::Close() {
   DCHECK(thread_checker_.CalledOnValidThread());
   sender_.reset();
-  if (binding_.is_bound())
-    binding_.Close();
+  if (receiver_.is_bound())
+    receiver_.reset();
 }
 
 bool MessagePipeReader::Send(std::unique_ptr<Message> message) {
diff --git a/ipc/ipc_message_pipe_reader.h b/ipc/ipc_message_pipe_reader.h
index e1c3fd4..8b09cf7 100644
--- a/ipc/ipc_message_pipe_reader.h
+++ b/ipc/ipc_message_pipe_reader.h
@@ -18,7 +18,9 @@
 #include "base/threading/thread_checker.h"
 #include "ipc/ipc.mojom.h"
 #include "ipc/ipc_message.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "mojo/public/cpp/system/core.h"
 #include "mojo/public/cpp/system/message_pipe.h"
@@ -66,8 +68,8 @@
   //
   // Note that MessagePipeReader doesn't delete |delegate|.
   MessagePipeReader(mojo::MessagePipeHandle pipe,
-                    mojom::ChannelAssociatedPtr sender,
-                    mojo::AssociatedInterfaceRequest<mojom::Channel> receiver,
+                    mojo::AssociatedRemote<mojom::Channel> sender,
+                    mojo::PendingAssociatedReceiver<mojom::Channel> receiver,
                     Delegate* delegate);
   ~MessagePipeReader() override;
 
@@ -85,7 +87,7 @@
   void GetRemoteInterface(const std::string& name,
                           mojo::ScopedInterfaceEndpointHandle handle);
 
-  mojom::ChannelAssociatedPtr& sender() { return sender_; }
+  mojo::AssociatedRemote<mojom::Channel>& sender() { return sender_; }
 
  protected:
   void OnPipeClosed();
@@ -101,8 +103,8 @@
 
   // |delegate_| is null once the message pipe is closed.
   Delegate* delegate_;
-  mojom::ChannelAssociatedPtr sender_;
-  mojo::AssociatedBinding<mojom::Channel> binding_;
+  mojo::AssociatedRemote<mojom::Channel> sender_;
+  mojo::AssociatedReceiver<mojom::Channel> receiver_;
   base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(MessagePipeReader);
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
index f038a95..8817d8e 100644
--- a/ipc/ipc_mojo_bootstrap.cc
+++ b/ipc/ipc_mojo_bootstrap.cc
@@ -202,8 +202,9 @@
       SendMessage(&message);
   }
 
-  void CreateChannelEndpoints(mojom::ChannelAssociatedPtr* sender,
-                              mojom::ChannelAssociatedRequest* receiver) {
+  void CreateChannelEndpoints(
+      mojo::AssociatedRemote<mojom::Channel>* sender,
+      mojo::PendingAssociatedReceiver<mojom::Channel>* receiver) {
     mojo::InterfaceId sender_id, receiver_id;
     if (set_interface_id_namespace_bit_) {
       sender_id = 1 | mojo::kInterfaceIdNamespaceMask;
@@ -228,8 +229,10 @@
     mojo::ScopedInterfaceEndpointHandle receiver_handle =
         CreateScopedInterfaceEndpointHandle(receiver_id);
 
-    sender->Bind(mojom::ChannelAssociatedPtrInfo(std::move(sender_handle), 0));
-    *receiver = mojom::ChannelAssociatedRequest(std::move(receiver_handle));
+    sender->Bind(mojo::PendingAssociatedRemote<mojom::Channel>(
+        std::move(sender_handle), 0));
+    *receiver = mojo::PendingAssociatedReceiver<mojom::Channel>(
+        std::move(receiver_handle));
   }
 
   void ShutDown() {
@@ -1059,8 +1062,9 @@
   }
 
  private:
-  void Connect(mojom::ChannelAssociatedPtr* sender,
-               mojom::ChannelAssociatedRequest* receiver) override {
+  void Connect(
+      mojo::AssociatedRemote<mojom::Channel>* sender,
+      mojo::PendingAssociatedReceiver<mojom::Channel>* receiver) override {
     controller_->Bind(std::move(handle_));
     controller_->CreateChannelEndpoints(sender, receiver);
   }
diff --git a/ipc/ipc_mojo_bootstrap.h b/ipc/ipc_mojo_bootstrap.h
index c2778b6..89262846 100644
--- a/ipc/ipc_mojo_bootstrap.h
+++ b/ipc/ipc_mojo_bootstrap.h
@@ -18,6 +18,8 @@
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_listener.h"
 #include "mojo/public/cpp/bindings/associated_group.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 
 namespace IPC {
@@ -43,8 +45,9 @@
       const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner);
 
   // Start the handshake over the underlying message pipe.
-  virtual void Connect(mojom::ChannelAssociatedPtr* sender,
-                       mojom::ChannelAssociatedRequest* receiver) = 0;
+  virtual void Connect(
+      mojo::AssociatedRemote<mojom::Channel>* sender,
+      mojo::PendingAssociatedReceiver<mojom::Channel>* receiver) = 0;
 
   // Stop transmitting messages and start queueing them instead.
   virtual void Pause() = 0;
diff --git a/ipc/ipc_mojo_bootstrap_unittest.cc b/ipc/ipc_mojo_bootstrap_unittest.cc
index 4508369..2b6dd97 100644
--- a/ipc/ipc_mojo_bootstrap_unittest.cc
+++ b/ipc/ipc_mojo_bootstrap_unittest.cc
@@ -14,7 +14,7 @@
 #include "ipc/ipc.mojom.h"
 #include "ipc/ipc_test_base.h"
 #include "mojo/core/test/multiprocess_test_helper.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
 
 namespace {
 
@@ -30,15 +30,16 @@
     sender_->SetPeerPid(sender_id);
   }
 
-  void TakeReceiver(IPC::mojom::ChannelAssociatedRequest* receiver) {
+  void TakeReceiver(
+      mojo::PendingAssociatedReceiver<IPC::mojom::Channel>* receiver) {
     *receiver = std::move(receiver_);
   }
 
-  IPC::mojom::ChannelAssociatedPtr& GetSender() { return sender_; }
+  mojo::AssociatedRemote<IPC::mojom::Channel>& GetSender() { return sender_; }
 
  private:
-  IPC::mojom::ChannelAssociatedPtr sender_;
-  IPC::mojom::ChannelAssociatedRequest receiver_;
+  mojo::AssociatedRemote<IPC::mojom::Channel> sender_;
+  mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver_;
   std::unique_ptr<IPC::MojoBootstrap> bootstrap_;
 };
 
@@ -51,13 +52,13 @@
   };
 
   PeerPidReceiver(
-      IPC::mojom::ChannelAssociatedRequest request,
+      mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver,
       const base::Closure& on_peer_pid_set,
       MessageExpectation message_expectation = MessageExpectation::kNotExpected)
-      : binding_(this, std::move(request)),
+      : receiver_(this, std::move(receiver)),
         on_peer_pid_set_(on_peer_pid_set),
         message_expectation_(message_expectation) {
-    binding_.set_connection_error_handler(disconnect_run_loop_.QuitClosure());
+    receiver_.set_disconnect_handler(disconnect_run_loop_.QuitClosure());
   }
 
   ~PeerPidReceiver() override {
@@ -91,7 +92,7 @@
   void RunUntilDisconnect() { disconnect_run_loop_.Run(); }
 
  private:
-  mojo::AssociatedBinding<IPC::mojom::Channel> binding_;
+  mojo::AssociatedReceiver<IPC::mojom::Channel> receiver_;
   const base::Closure on_peer_pid_set_;
   MessageExpectation message_expectation_;
   int32_t peer_pid_ = -1;
@@ -115,7 +116,7 @@
           base::ThreadTaskRunnerHandle::Get()),
       kTestServerPid);
 
-  IPC::mojom::ChannelAssociatedRequest receiver;
+  mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver;
   connection.TakeReceiver(&receiver);
 
   base::RunLoop run_loop;
@@ -140,7 +141,7 @@
           base::ThreadTaskRunnerHandle::Get()),
       kTestClientPid);
 
-  IPC::mojom::ChannelAssociatedRequest receiver;
+  mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver;
   connection.TakeReceiver(&receiver);
 
   base::RunLoop run_loop;
@@ -161,7 +162,7 @@
           base::ThreadTaskRunnerHandle::Get()),
       kTestServerPid);
 
-  IPC::mojom::ChannelAssociatedRequest receiver;
+  mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver;
   connection.TakeReceiver(&receiver);
 
   base::RunLoop run_loop;
@@ -188,7 +189,7 @@
           base::ThreadTaskRunnerHandle::Get()),
       kTestClientPid);
 
-  IPC::mojom::ChannelAssociatedRequest receiver;
+  mojo::PendingAssociatedReceiver<IPC::mojom::Channel> receiver;
   connection.TakeReceiver(&receiver);
   auto& sender = connection.GetSender();
 
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 7ca9a46..5b4cf31 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -485,11 +485,6 @@
 const base::Feature kUseAudioLatencyFromHAL{"UseAudioLatencyFromHAL",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Enable pooling of SharedImageVideo objects for use by MCVD, to save a hop to
-// the GPU main thread during VideoFrame construction.
-const base::Feature kUsePooledSharedImageVideoProvider{
-    "UsePooledSharedImageVideoProvider", base::FEATURE_DISABLED_BY_DEFAULT};
-
 #endif  // defined(OS_ANDROID)
 
 #if defined(OS_WIN)
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 8df20f29..965c584 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -166,7 +166,6 @@
 MEDIA_EXPORT extern const base::Feature kPictureInPictureAPI;
 MEDIA_EXPORT extern const base::Feature kHlsPlayer;
 MEDIA_EXPORT extern const base::Feature kUseAudioLatencyFromHAL;
-MEDIA_EXPORT extern const base::Feature kUsePooledSharedImageVideoProvider;
 #endif  // defined(OS_ANDROID)
 
 #if defined(OS_WIN)
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 041f6054..c290ec2 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -123,8 +123,6 @@
       "android/maybe_render_early_manager.h",
       "android/media_codec_video_decoder.cc",
       "android/media_codec_video_decoder.h",
-      "android/pooled_shared_image_video_provider.cc",
-      "android/pooled_shared_image_video_provider.h",
       "android/promotion_hint_aggregator.h",
       "android/promotion_hint_aggregator_impl.cc",
       "android/promotion_hint_aggregator_impl.h",
@@ -482,9 +480,6 @@
       "android/mock_device_info.h",
       "android/mock_promotion_hint_aggregator.cc",
       "android/mock_promotion_hint_aggregator.h",
-      "android/mock_shared_image_video_provider.cc",
-      "android/mock_shared_image_video_provider.h",
-      "android/pooled_shared_image_video_provider_unittest.cc",
       "android/promotion_hint_aggregator_impl_unittest.cc",
       "android/surface_chooser_helper_unittest.cc",
       "android/video_frame_factory_impl_unittest.cc",
diff --git a/media/gpu/android/codec_image.cc b/media/gpu/android/codec_image.cc
index eaf4173..8c4dd49 100644
--- a/media/gpu/android/codec_image.cc
+++ b/media/gpu/android/codec_image.cc
@@ -44,7 +44,8 @@
 CodecImage::CodecImage() = default;
 
 CodecImage::~CodecImage() {
-  NotifyUnused();
+  for (auto& cb : unused_cbs_)
+    std::move(cb).Run(this);
 }
 
 void CodecImage::Initialize(
@@ -62,19 +63,6 @@
   unused_cbs_.push_back(std::move(unused_cb));
 }
 
-void CodecImage::NotifyUnused() {
-  // If we haven't done so yet, release the codec output buffer.  Also drop
-  // our reference to the TextureOwner (if any).  In other words, undo anything
-  // that we did in Initialize.
-  ReleaseCodecBuffer();
-  codec_buffer_wait_coordinator_.reset();
-  promotion_hint_cb_ = PromotionHintAggregator::NotifyPromotionHintCB();
-
-  for (auto& cb : unused_cbs_)
-    std::move(cb).Run(this);
-  unused_cbs_.clear();
-}
-
 gfx::Size CodecImage::GetSize() {
   // Return a nonzero size, to avoid GL errors, even if we dropped the codec
   // buffer already.  Note that if we dropped it, there's no data in the
@@ -341,10 +329,6 @@
   return codec_buffer_wait_coordinator_->texture_owner()->GetAHardwareBuffer();
 }
 
-bool CodecImage::HasMutableState() const {
-  return false;
-}
-
 CodecImageHolder::CodecImageHolder(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     scoped_refptr<CodecImage> codec_image)
diff --git a/media/gpu/android/codec_image.h b/media/gpu/android/codec_image.h
index 0b13cb36..fb8426c 100644
--- a/media/gpu/android/codec_image.h
+++ b/media/gpu/android/codec_image.h
@@ -98,15 +98,6 @@
                            int display_y,
                            int display_width,
                            int display_height) override;
-  // If we re-use one CodecImage with different output buffers, then we must
-  // not claim to have mutable state.  Otherwise, CopyTexImage is only called
-  // once.  For pooled shared images, this must return false.  For single-use
-  // images, it works either way.
-  bool HasMutableState() const override;
-
-  // Notify us that we're no longer in-use for display, and may be pointed at
-  // another output buffer via a call to Initialize.
-  void NotifyUnused();
 
   // gpu::StreamTextureSharedImageInterface implementation.
   void ReleaseResources() override;
diff --git a/media/gpu/android/codec_image_unittest.cc b/media/gpu/android/codec_image_unittest.cc
index e545235f..bbf8bf6 100644
--- a/media/gpu/android/codec_image_unittest.cc
+++ b/media/gpu/android/codec_image_unittest.cc
@@ -82,7 +82,7 @@
   enum ImageKind { kOverlay, kTextureOwner };
   scoped_refptr<CodecImage> NewImage(
       ImageKind kind,
-      CodecImage::UnusedCB unused_cb = base::DoNothing()) {
+      CodecImage::UnusedCB now_unused_cb = base::DoNothing()) {
     std::unique_ptr<CodecOutputBuffer> buffer;
     wrapper_->DequeueOutputBuffer(nullptr, nullptr, &buffer);
     scoped_refptr<CodecImage> image = new CodecImage();
@@ -92,7 +92,7 @@
         base::BindRepeating(&PromotionHintReceiver::OnPromotionHint,
                             base::Unretained(&promotion_hint_receiver_)));
 
-    image->AddUnusedCB(std::move(unused_cb));
+    image->AddUnusedCB(std::move(now_unused_cb));
     return image;
   }
 
@@ -133,26 +133,6 @@
   i = nullptr;
 }
 
-TEST_F(CodecImageTest, UnusedCBRunsOnNotifyUnused) {
-  base::MockCallback<CodecImage::UnusedCB> cb_1;
-  base::MockCallback<CodecImage::UnusedCB> cb_2;
-  auto i = NewImage(kTextureOwner);
-  ASSERT_TRUE(i->get_codec_output_buffer_for_testing());
-  ASSERT_TRUE(i->is_texture_owner_backed());
-  i->AddUnusedCB(cb_1.Get());
-  i->AddUnusedCB(cb_2.Get());
-  EXPECT_CALL(cb_1, Run(i.get()));
-  EXPECT_CALL(cb_2, Run(i.get()));
-
-  // Also verify that the output buffer and texture owner are released.
-  i->NotifyUnused();
-  EXPECT_FALSE(i->get_codec_output_buffer_for_testing());
-  EXPECT_FALSE(i->is_texture_owner_backed());
-
-  // Verify that an additional call doesn't crash.  It should do nothing.
-  i->NotifyUnused();
-}
-
 TEST_F(CodecImageTest, ImageStartsUnrendered) {
   auto i = NewImage(kTextureOwner);
   ASSERT_FALSE(i->was_rendered_to_front_buffer());
diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc
index 6408aa5..3b43fad 100644
--- a/media/gpu/android/media_codec_video_decoder.cc
+++ b/media/gpu/android/media_codec_video_decoder.cc
@@ -942,7 +942,7 @@
       CreatePromotionHintCB(),
       base::BindOnce(&MediaCodecVideoDecoder::ForwardVideoFrame,
                      weak_factory_.GetWeakPtr(), reset_generation_,
-                     std::move(async_trace), base::TimeTicks::Now()));
+                     std::move(async_trace)));
   return true;
 }
 
@@ -959,17 +959,10 @@
 void MediaCodecVideoDecoder::ForwardVideoFrame(
     int reset_generation,
     std::unique_ptr<ScopedAsyncTrace> async_trace,
-    base::TimeTicks started_at,
     scoped_refptr<VideoFrame> frame) {
   DVLOG(3) << __func__ << " : "
            << (frame ? frame->AsHumanReadableString() : "null");
 
-  // Record how long this frame was pending.
-  const base::TimeDelta duration = base::TimeTicks::Now() - started_at;
-  UMA_HISTOGRAM_CUSTOM_TIMES("Media.MCVD.ForwardVideoFrameTiming", duration,
-                             base::TimeDelta::FromMilliseconds(1),
-                             base::TimeDelta::FromMilliseconds(100), 25);
-
   // No |frame| indicates an error creating it.
   if (!frame) {
     DLOG(ERROR) << __func__ << " |frame| is null";
diff --git a/media/gpu/android/media_codec_video_decoder.h b/media/gpu/android/media_codec_video_decoder.h
index 59055e4..81a5a63 100644
--- a/media/gpu/android/media_codec_video_decoder.h
+++ b/media/gpu/android/media_codec_video_decoder.h
@@ -181,11 +181,9 @@
 
   // Forwards |frame| via |output_cb_| if |reset_generation| matches
   // |reset_generation_|.  |async_trace| is the (optional) scoped trace that
-  // started when we dequeued the corresponding output buffer.  |started_at| is
-  // the wall clock time at which we dequeued the output buffer.
+  // started when we dequeued the corresponding output buffer.
   void ForwardVideoFrame(int reset_generation,
                          std::unique_ptr<ScopedAsyncTrace> async_trace,
-                         base::TimeTicks started_at,
                          scoped_refptr<VideoFrame> frame);
 
   // Starts draining the codec by queuing an EOS if required. It skips the drain
diff --git a/media/gpu/android/mock_shared_image_video_provider.cc b/media/gpu/android/mock_shared_image_video_provider.cc
deleted file mode 100644
index 65122e3..0000000
--- a/media/gpu/android/mock_shared_image_video_provider.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/gpu/android/mock_shared_image_video_provider.h"
-
-namespace media {
-
-MockSharedImageVideoProvider::RequestImageArgs::RequestImageArgs(
-    ImageReadyCB cb,
-    ImageSpec spec,
-    scoped_refptr<gpu::TextureOwner> texture_owner)
-    : cb_(std::move(cb)),
-      spec_(std::move(spec)),
-      texture_owner_(std::move(texture_owner)) {}
-
-MockSharedImageVideoProvider::RequestImageArgs::~RequestImageArgs() = default;
-
-MockSharedImageVideoProvider::MockSharedImageVideoProvider() = default;
-MockSharedImageVideoProvider::~MockSharedImageVideoProvider() = default;
-
-}  // namespace media
diff --git a/media/gpu/android/mock_shared_image_video_provider.h b/media/gpu/android/mock_shared_image_video_provider.h
deleted file mode 100644
index 7d19831..0000000
--- a/media/gpu/android/mock_shared_image_video_provider.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_GPU_ANDROID_MOCK_SHARED_IMAGE_VIDEO_PROVIDER_H_
-#define MEDIA_GPU_ANDROID_MOCK_SHARED_IMAGE_VIDEO_PROVIDER_H_
-
-#include "media/gpu/android/pooled_shared_image_video_provider.h"
-#include "mojo/public/cpp/bindings/callback_helpers.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace media {
-
-class MockSharedImageVideoProvider : public SharedImageVideoProvider {
- public:
-  MockSharedImageVideoProvider();
-  ~MockSharedImageVideoProvider();
-
-  void Initialize(GpuInitCB gpu_init_cb) {
-    Initialize_(gpu_init_cb);
-    gpu_init_cb_ = std::move(gpu_init_cb);
-  }
-
-  MOCK_METHOD1(Initialize_, void(GpuInitCB& gpu_init_cb));
-
-  void RequestImage(ImageReadyCB cb,
-                    const ImageSpec& spec,
-                    scoped_refptr<gpu::TextureOwner> texture_owner) override {
-    requests_.emplace_back(std::move(cb), spec, std::move(texture_owner));
-
-    MockRequestImage();
-  }
-
-  MOCK_METHOD0(MockRequestImage, void());
-
-  // Provide an image for the least recent request.  If |record| is provided,
-  // then we'll use it.  Otherwise, we'll make one up.
-  void ProvideOneRequestedImage(ImageRecord* record = nullptr) {
-    ImageRecord tmp_record;
-    if (!record) {
-      record = &tmp_record;
-      record->release_cb = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
-          base::BindOnce(
-              [](int* count, const gpu::SyncToken& sync_token) { (*count)++; },
-              base::Unretained(&num_release_callbacks_)),
-          gpu::SyncToken());
-    }
-
-    auto& req = requests_.front();
-    std::move(req.cb_).Run(std::move(*record));
-    requests_.pop_front();
-  }
-
-  // Most recent arguments to Initialize.
-  GpuInitCB gpu_init_cb_;
-
-  // Most recent arguments to RequestImage.
-  struct RequestImageArgs {
-    RequestImageArgs(ImageReadyCB cb,
-                     ImageSpec spec,
-                     scoped_refptr<gpu::TextureOwner> texture_owner);
-    ~RequestImageArgs();
-    ImageReadyCB cb_;
-    ImageSpec spec_;
-    scoped_refptr<gpu::TextureOwner> texture_owner_;
-  };
-
-  std::list<RequestImageArgs> requests_;
-
-  // Number of times a release callback has been called.
-  int num_release_callbacks_ = 0;
-};
-
-}  // namespace media
-
-#endif  // MEDIA_GPU_ANDROID_MOCK_SHARED_IMAGE_VIDEO_PROVIDER_H_
diff --git a/media/gpu/android/pooled_shared_image_video_provider.cc b/media/gpu/android/pooled_shared_image_video_provider.cc
deleted file mode 100644
index 0415a15..0000000
--- a/media/gpu/android/pooled_shared_image_video_provider.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/gpu/android/pooled_shared_image_video_provider.h"
-
-#include "gpu/command_buffer/common/sync_token.h"
-#include "media/base/bind_to_current_loop.h"
-#include "mojo/public/cpp/bindings/callback_helpers.h"
-
-namespace media {
-
-// static
-std::unique_ptr<PooledSharedImageVideoProvider>
-PooledSharedImageVideoProvider::Create(
-    scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-    GetStubCB get_stub_cb,
-    std::unique_ptr<SharedImageVideoProvider> provider) {
-  return base::WrapUnique(new PooledSharedImageVideoProvider(
-      base::SequenceBound<GpuHelperImpl>(std::move(gpu_task_runner),
-                                         std::move(get_stub_cb)),
-      std::move(provider)));
-}
-
-PooledSharedImageVideoProvider::PooledImage::PooledImage(const ImageSpec& spec,
-                                                         ImageRecord record)
-    : spec(spec), record(std::move(record)) {}
-
-PooledSharedImageVideoProvider::PooledImage::~PooledImage() = default;
-
-PooledSharedImageVideoProvider::PendingRequest::PendingRequest(
-    const ImageSpec& spec,
-    ImageReadyCB cb)
-    : spec(spec), cb(std::move(cb)) {}
-
-PooledSharedImageVideoProvider::PendingRequest::~PendingRequest() = default;
-
-PooledSharedImageVideoProvider::PooledSharedImageVideoProvider(
-    base::SequenceBound<GpuHelper> gpu_helper,
-    std::unique_ptr<SharedImageVideoProvider> provider)
-    : provider_(std::move(provider)),
-      gpu_helper_(std::move(gpu_helper)),
-      weak_factory_(this) {}
-
-// Note that this will drop everything in |pool_|, which will call all the
-// release callbacks for the underlying byffer.
-PooledSharedImageVideoProvider::~PooledSharedImageVideoProvider() = default;
-
-// SharedImageVideoProvider
-void PooledSharedImageVideoProvider::Initialize(GpuInitCB gpu_init_cb) {
-  provider_->Initialize(std::move(gpu_init_cb));
-}
-
-void PooledSharedImageVideoProvider::RequestImage(
-    ImageReadyCB cb,
-    const ImageSpec& spec,
-    scoped_refptr<gpu::TextureOwner> texture_owner) {
-  // See if the pool matches the requested spec.
-  if (pool_spec_ != spec) {
-    // Nope -- mark any outstanding images for destruction and start a new pool.
-    // Note that this calls all the release callbacks.
-    pool_.clear();
-
-    // Any images added to the pool should match |spec|.
-    pool_spec_ = spec;
-  }
-
-  // Push this onto the pending requests.
-  // IMPORTANT BUT SUBTLE NOTE: |spec| doesn't mention the TextureOwner, but it
-  // is sent to the provider so it must also match the one that was used with
-  // |spec|.  We assume that the generation id will be updated by our caller
-  // whenever the TextureOwner changes.  While this is fragile, it's also just
-  // a temporary thing.  Keeping a strong ref to |texture_owner| would probably
-  // work, but it's not good to keep refs to those around longer than needed.
-  // It might be okay to do that directly, since the request (if any) that's
-  // pending for it would have the strong ref, so maybe we could just add it
-  // here too.
-  pending_requests_.emplace_back(spec, std::move(cb));
-
-  // Are there any free images in the pool?  If so, then pop one and use it to
-  // process the request we just pushed, assuming that it's the most recent.  We
-  // could optimize this call out if |pending_requensts_| wasn't empty before,
-  // since we know it doesn't match the pool spec if the pool's not empty.  As
-  // it is, it will just pop and re-push the pooled buffer in the (rare) case
-  // that the pool doesn't match.
-  if (!pool_.empty()) {
-    auto front = std::move(pool_.front());
-    pool_.pop_front();
-    ProcessFreePooledImage(front);
-    // TODO(liberato): See if skipping the return if |pool_| is now empty is
-    // helpful, especially during start-up.  Alternatively, just request some
-    // constant number of images (~5) when the pool spec changes, then add them
-    // one at a time if needed.
-    return;
-  }
-
-  // Request a new image, since we don't have enough.  There might be some
-  // outstanding that will be returned, but we'd like to have enough not to wait
-  // on them.  This has the nice property that everything in |pending_requests_|
-  // will have an image delivered in order for it.  Note that we might not
-  // exactly match up returned (new) images to the requests; there might be
-  // intervening returns of existing images from the client that happen to match
-  // if we switch from spec A => spec B => spec A, but that's okay.  We can be
-  // sure that there are at least as many that will arrive as we need.
-  auto ready_cb =
-      base::BindOnce(&PooledSharedImageVideoProvider::OnImageCreated,
-                     weak_factory_.GetWeakPtr(), spec);
-  provider_->RequestImage(std::move(ready_cb), spec, std::move(texture_owner));
-}
-
-void PooledSharedImageVideoProvider::OnImageCreated(ImageSpec spec,
-                                                    ImageRecord record) {
-  // Wrap |record| up for the pool, and process it.
-  scoped_refptr<PooledImage> pooled_image =
-      base::MakeRefCounted<PooledImage>(std::move(spec), std::move(record));
-  ProcessFreePooledImage(pooled_image);
-}
-
-void PooledSharedImageVideoProvider::OnImageReturned(
-    scoped_refptr<PooledImage> pooled_image,
-    const gpu::SyncToken& sync_token) {
-  // An image has been returned to us.  Wait for |sync_token| and then send it
-  // to ProcessFreePooledImage to re-use / pool / delete.
-  gpu_helper_.Post(FROM_HERE, &GpuHelper::OnImageReturned, sync_token,
-                   pooled_image->record.codec_image_holder,
-                   BindToCurrentLoop(base::BindOnce(
-                       &PooledSharedImageVideoProvider::ProcessFreePooledImage,
-                       weak_factory_.GetWeakPtr(), pooled_image)));
-}
-
-void PooledSharedImageVideoProvider::ProcessFreePooledImage(
-    scoped_refptr<PooledImage> pooled_image) {
-  // Are there any requests pending?
-  if (pending_requests_.size()) {
-    // See if |record| matches the top request.  If so, fulfill it, else drop
-    // |record| since we don't need it.  Note that it's possible to have pending
-    // requests that don't match the pool spec; the pool spec is the most recent
-    // request.  There might be other ones that were made before that which we
-    // didn't fulfill yet.
-    auto& front = pending_requests_.front();
-    if (pooled_image->spec == front.spec) {
-      // Construct a record that notifies us when the image is released.
-      // TODO(liberato): Don't copy fields this way.
-      ImageRecord record;
-      record.mailbox = pooled_image->record.mailbox;
-      record.is_vulkan = pooled_image->record.is_vulkan;
-      record.codec_image_holder = pooled_image->record.codec_image_holder;
-      // The release CB notifies us instead of |provider_|.
-      record.release_cb = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
-          base::BindOnce(&PooledSharedImageVideoProvider::OnImageReturned,
-                         weak_factory_.GetWeakPtr(), std::move(pooled_image)),
-          gpu::SyncToken());
-
-      // Save the callback and remove the request, in case |cb| calls us back.
-      auto cb = std::move(front.cb);
-      pending_requests_.pop_front();
-
-      std::move(cb).Run(std::move(record));
-      return;
-    }
-
-    // Can't fulfill the topmost request.  Discard |pooled_image|, even if it
-    // matches the pool.  The reason is that any pending requests will have
-    // images created for them, which we'll use when they arrive.  It would be
-    // okay to store |pooled_image| in the pool if it matches, but then we'd
-    // have more pooled images than we expect.
-    return;
-  }
-
-  // There are no outstanding image requests, or the top one doesn't match
-  // |pooled_image|.  If this image is compatible with the pool, then pool it.
-  // Otherwise, discard it.
-
-  // See if |record| matches |pool_spec_|.  If not, then drop it.  Otherwise,
-  // pool it for later.  Note that we don't explicitly call the release cb,
-  // since dropping the image is sufficient to notify |provider_|.  Note that
-  // we've already waited for any sync token at this point, so it's okay if we
-  // don't provide one to the underlying release cb.
-  if (pool_spec_ != pooled_image->spec)
-    return;
-
-  // Add it to the pool.
-  pool_.push_front(std::move(pooled_image));
-}
-
-PooledSharedImageVideoProvider::GpuHelperImpl::GpuHelperImpl(
-    GetStubCB get_stub_cb)
-    : weak_factory_(this) {
-  gpu::CommandBufferStub* stub = get_stub_cb.Run();
-  if (stub) {
-    stub->AddDestructionObserver(this);
-    command_buffer_helper_ = CommandBufferHelper::Create(stub);
-  }
-}
-
-PooledSharedImageVideoProvider::GpuHelperImpl::~GpuHelperImpl() = default;
-
-void PooledSharedImageVideoProvider::GpuHelperImpl::OnImageReturned(
-    const gpu::SyncToken& sync_token,
-    scoped_refptr<CodecImageHolder> codec_image_holder,
-    base::OnceClosure cb) {
-  auto on_sync_token_cleared_cb = base::BindOnce(
-      &GpuHelperImpl::OnSyncTokenCleared, weak_factory_.GetWeakPtr(),
-      std::move(codec_image_holder), std::move(cb));
-  command_buffer_helper_->WaitForSyncToken(sync_token,
-                                           std::move(on_sync_token_cleared_cb));
-}
-
-void PooledSharedImageVideoProvider::GpuHelperImpl::OnSyncTokenCleared(
-    scoped_refptr<CodecImageHolder> codec_image_holder,
-    base::OnceClosure cb) {
-  codec_image_holder->codec_image_raw()->NotifyUnused();
-  // Do this last, since |cb| might post to some other thread.
-  std::move(cb).Run();
-}
-
-void PooledSharedImageVideoProvider::GpuHelperImpl::OnWillDestroyStub(
-    bool have_context) {
-  command_buffer_helper_ = nullptr;
-}
-
-}  // namespace media
diff --git a/media/gpu/android/pooled_shared_image_video_provider.h b/media/gpu/android/pooled_shared_image_video_provider.h
deleted file mode 100644
index c0ec44a..0000000
--- a/media/gpu/android/pooled_shared_image_video_provider.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_GPU_ANDROID_POOLED_SHARED_IMAGE_VIDEO_PROVIDER_H_
-#define MEDIA_GPU_ANDROID_POOLED_SHARED_IMAGE_VIDEO_PROVIDER_H_
-
-#include "base/memory/weak_ptr.h"
-#include "base/threading/sequence_bound.h"
-#include "gpu/ipc/service/command_buffer_stub.h"
-#include "media/gpu/android/shared_image_video_provider.h"
-#include "media/gpu/command_buffer_helper.h"
-
-namespace media {
-
-class PooledSharedImageVideoProviderTest;
-
-// Provider class for shared images.
-class MEDIA_GPU_EXPORT PooledSharedImageVideoProvider
-    : public SharedImageVideoProvider {
- public:
-  // Helper class that processes image returns on the gpu thread.
-  class GpuHelper {
-   public:
-    GpuHelper() = default;
-    virtual ~GpuHelper() = default;
-
-    // Called (on the gpu thread) to handle image return.
-    virtual void OnImageReturned(
-        const gpu::SyncToken& sync_token,
-        scoped_refptr<CodecImageHolder> codec_image_holder,
-        base::OnceClosure cb) = 0;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(GpuHelper);
-  };
-
-  // Create a default implementation.  |provider| is the underlying provider to
-  // create shared images.
-  static std::unique_ptr<PooledSharedImageVideoProvider> Create(
-      scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-      GetStubCB get_stub_cb,
-      std::unique_ptr<SharedImageVideoProvider> provider);
-
-  ~PooledSharedImageVideoProvider() override;
-
-  // SharedImageVideoProvider
-  void Initialize(GpuInitCB gpu_init_cb) override;
-  void RequestImage(ImageReadyCB cb,
-                    const ImageSpec& spec,
-                    scoped_refptr<gpu::TextureOwner> texture_owner) override;
-
- private:
-  friend class PooledSharedImageVideoProviderTest;
-
-  PooledSharedImageVideoProvider(
-      base::SequenceBound<GpuHelper> gpu_helper,
-      std::unique_ptr<SharedImageVideoProvider> provider);
-
-  class GpuHelperImpl : public GpuHelper,
-                        public gpu::CommandBufferStub::DestructionObserver {
-   public:
-    GpuHelperImpl(GetStubCB get_stub_cb);
-    ~GpuHelperImpl() override;
-
-    // GpuHelper
-    void OnImageReturned(const gpu::SyncToken& sync_token,
-                         scoped_refptr<CodecImageHolder> codec_image_holder,
-                         base::OnceClosure cb) override;
-
-    // gpu::CommandBufferStub::DestructionObserver
-    void OnWillDestroyStub(bool have_context) override;
-
-   private:
-    void OnSyncTokenCleared(scoped_refptr<CodecImageHolder> codec_image_holder,
-                            base::OnceClosure cb);
-
-    scoped_refptr<CommandBufferHelper> command_buffer_helper_;
-    base::WeakPtrFactory<GpuHelperImpl> weak_factory_;
-  };
-
-  // Record of on image from |provider|.
-  class PooledImage : public base::RefCounted<PooledImage> {
-   public:
-    PooledImage(const ImageSpec& spec, ImageRecord record);
-
-    ImageSpec spec;
-    // The original record, including the original reuse callback.
-    ImageRecord record;
-
-   private:
-    virtual ~PooledImage();
-
-    friend class base::RefCounted<PooledImage>;
-  };
-
-  // One request from the client that's pending an image.
-  class PendingRequest {
-   public:
-    PendingRequest(const ImageSpec& spec, ImageReadyCB cb);
-    ~PendingRequest();
-    ImageSpec spec;
-    ImageReadyCB cb;
-    std::unique_ptr<CodecOutputBuffer> output_buffer;
-    scoped_refptr<gpu::TextureOwner> texture_owner;
-    PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb;
-  };
-
-  // Called by |provider_| when a new image is created.
-  void OnImageCreated(ImageSpec spec, ImageRecord record);
-
-  // Called by our client when it runs the release cb, to notify us that the
-  // image is no longer in use.
-  void OnImageReturned(scoped_refptr<PooledImage> pooled_image,
-                       const gpu::SyncToken& sync_token);
-
-  // Given a free image |pooled_image| that is not in our pool, use it to either
-  // fulfill a pending request, add it to the pool, or discard it.
-  void ProcessFreePooledImage(scoped_refptr<PooledImage> pooled_image);
-
-  // Underlying provider that we use to construct images.
-  std::unique_ptr<SharedImageVideoProvider> provider_;
-
-  // All currently unused images.
-  std::list<scoped_refptr<PooledImage>> pool_;
-
-  // Spec for all images in |pool_|.
-  ImageSpec pool_spec_;
-
-  std::list<PendingRequest> pending_requests_;
-
-  base::SequenceBound<GpuHelper> gpu_helper_;
-
-  base::WeakPtrFactory<PooledSharedImageVideoProvider> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(PooledSharedImageVideoProvider);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_GPU_ANDROID_POOLED_SHARED_IMAGE_VIDEO_PROVIDER_H_
diff --git a/media/gpu/android/pooled_shared_image_video_provider_unittest.cc b/media/gpu/android/pooled_shared_image_video_provider_unittest.cc
deleted file mode 100644
index c561eed..0000000
--- a/media/gpu/android/pooled_shared_image_video_provider_unittest.cc
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/gpu/android/pooled_shared_image_video_provider.h"
-
-#include <list>
-
-#include "base/test/mock_callback.h"
-#include "base/test/task_environment.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "gpu/command_buffer/service/abstract_texture_impl_shared_context_state.h"
-#include "gpu/ipc/common/command_buffer_id.h"
-#include "media/gpu/android/mock_shared_image_video_provider.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::Mock;
-
-namespace media {
-
-class PooledSharedImageVideoProviderTest : public testing::Test {
- public:
-  class MockGpuHelper : public PooledSharedImageVideoProvider::GpuHelper {
-   public:
-    MockGpuHelper(gpu::SyncToken* sync_token_out)
-        : sync_token_out_(sync_token_out) {}
-
-    // PooledSharedImageVideoProvider::GpuHelper
-    void OnImageReturned(const gpu::SyncToken& sync_token,
-                         scoped_refptr<CodecImageHolder> codec_image_holder,
-                         base::OnceClosure cb) override {
-      *sync_token_out_ = sync_token;
-
-      // Run the output cb.
-      std::move(cb).Run();
-    }
-
-   private:
-    gpu::SyncToken* sync_token_out_ = nullptr;
-  };
-
-  PooledSharedImageVideoProviderTest() = default;
-
-  void SetUp() override {
-    task_runner_ = base::SequencedTaskRunnerHandle::Get();
-    base::SequenceBound<MockGpuHelper> mock_gpu_helper(task_runner_,
-                                                       &sync_token_);
-
-    std::unique_ptr<MockSharedImageVideoProvider> mock_provider =
-        std::make_unique<MockSharedImageVideoProvider>();
-    mock_provider_raw_ = mock_provider.get();
-
-    provider_ = base::WrapUnique(new PooledSharedImageVideoProvider(
-        std::move(mock_gpu_helper), std::move(mock_provider)));
-  }
-
-  // Return an ImageReadyCB that saves the ImageRecord in |image_records_|.
-  SharedImageVideoProvider::ImageReadyCB SaveImageRecordCB() {
-    return base::BindOnce(
-        [](std::list<SharedImageVideoProvider::ImageRecord>* output_list,
-           SharedImageVideoProvider::ImageRecord record) {
-          output_list->push_back(std::move(record));
-        },
-        &image_records_);
-  }
-
-  // Request an image from |provier_|, which we expect will call through to
-  // |mock_provider_raw_|.  Have |mock_provider_raw_| return an image, too.
-  void RequestAndProvideImage(const SharedImageVideoProvider::ImageSpec& spec) {
-    EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(1);
-    provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_);
-    base::RunLoop().RunUntilIdle();
-    Mock::VerifyAndClearExpectations(mock_provider_raw_);
-    mock_provider_raw_->ProvideOneRequestedImage();
-  }
-
-  base::test::TaskEnvironment task_environment_;
-
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
-  // Provider under test.
-  std::unique_ptr<PooledSharedImageVideoProvider> provider_;
-
-  MockSharedImageVideoProvider* mock_provider_raw_ = nullptr;
-  gpu::SyncToken sync_token_;
-
-  scoped_refptr<gpu::TextureOwner> texture_owner_;
-
-  // Image records that we've received from |provider|, via SaveImageRecordCB().
-  std::list<SharedImageVideoProvider::ImageRecord> image_records_;
-};
-
-TEST_F(PooledSharedImageVideoProviderTest, InitializeForwardsGpuCallback) {
-  bool was_called = false;
-  auto gpu_init_cb = base::BindOnce(
-      [](bool* flag, scoped_refptr<gpu::SharedContextState>) { *flag = true; },
-      &was_called);
-  provider_->Initialize(std::move(gpu_init_cb));
-  std::move(mock_provider_raw_->gpu_init_cb_).Run(nullptr);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(was_called);
-}
-
-TEST_F(PooledSharedImageVideoProviderTest, RequestImageRequestsMultipleImages) {
-  // Test the RequestImage will keep requesting images from the underlying
-  // provider as long as we don't return any.
-  SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u);
-  RequestAndProvideImage(spec);
-  RequestAndProvideImage(spec);
-  RequestAndProvideImage(spec);
-  EXPECT_EQ(image_records_.size(), 3u);
-}
-
-TEST_F(PooledSharedImageVideoProviderTest, ReleasingAnImageForwardsSyncToken) {
-  // Calling the release callback on an image should forward the sync token to
-  // our gpu helper.
-  SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u);
-  RequestAndProvideImage(spec);
-
-  gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
-                            gpu::CommandBufferIdFromChannelAndRoute(2, 3), 4);
-  std::move(image_records_.back().release_cb).Run(sync_token);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(sync_token, sync_token_);
-}
-
-TEST_F(PooledSharedImageVideoProviderTest,
-       ReleasingAnImageDoesntRunUnderlyingReleaseCallback) {
-  // Verify that releasing an image doesn't call the underlying release callback
-  // on it.  Presumably, it should be sent back to the pool instead.
-  SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u);
-  RequestAndProvideImage(spec);
-
-  // Release the image.
-  image_records_.pop_back();
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0);
-}
-
-TEST_F(PooledSharedImageVideoProviderTest, RequestImageReusesReturnedImages) {
-  // Test the RequestImage will return images without requesting new ones, if
-  // some have been returned to the pool.
-  SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u);
-  // Request two images.
-  RequestAndProvideImage(spec);
-  RequestAndProvideImage(spec);
-  EXPECT_EQ(image_records_.size(), 2u);
-  // Now return one, and request another.
-  image_records_.pop_back();
-  // Let the release CB run.
-  base::RunLoop().RunUntilIdle();
-
-  // Shouldn't call MockRequestImage a third time.
-  EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(0);
-  provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(image_records_.size(), 2u);
-}
-
-TEST_F(PooledSharedImageVideoProviderTest,
-       DeletingProviderWithOutstandingImagesDoesntCrash) {
-  // Destroying |provider_| with outstanding images shouldn't break anything.
-  SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u);
-  provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_);
-  base::RunLoop().RunUntilIdle();
-  provider_.reset();
-  base::RunLoop().RunUntilIdle();
-  // Shouldn't crash.
-}
-
-TEST_F(PooledSharedImageVideoProviderTest,
-       ReturnedImagesAreReleasedAfterSpecChange) {
-  // When we change the ImageSpec, old images should be released on the
-  // underlying provider as they are returned.
-  SharedImageVideoProvider::ImageSpec spec_1(gfx::Size(1, 1), 0u);
-  SharedImageVideoProvider::ImageSpec spec_2(gfx::Size(1, 2), 0u);
-  RequestAndProvideImage(spec_1);
-  RequestAndProvideImage(spec_2);
-
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0);
-
-  // Return image 1, and it should run the underlying release callback since it
-  // doesn't match the pool spec.
-  image_records_.pop_front();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1);
-
-  // Returning image 2 should not, since it should be put into the pool.
-  image_records_.pop_front();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1);
-}
-
-TEST_F(PooledSharedImageVideoProviderTest, SizeChangeEmptiesPool) {
-  // Verify that a size change in the ImageSpec causes the pool to be emptied.
-  SharedImageVideoProvider::ImageSpec spec_1(gfx::Size(1, 1), 0u);
-  SharedImageVideoProvider::ImageSpec spec_2(gfx::Size(1, 2), 0u);
-
-  // Request an image with |spec_1| and release it, to send it to the pool.
-  RequestAndProvideImage(spec_1);
-  image_records_.pop_front();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0);
-
-  // Request an image with |spec_2|, which should release the first one.
-  RequestAndProvideImage(spec_2);
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1);
-}
-
-TEST_F(PooledSharedImageVideoProviderTest, GenerationIdChangeEmptiesPool) {
-  // Verify that a change in the generation id causes the pool to be emptied.
-  SharedImageVideoProvider::ImageSpec spec_1(gfx::Size(1, 1), 0u);
-  SharedImageVideoProvider::ImageSpec spec_2(gfx::Size(1, 1), 1u);
-  RequestAndProvideImage(spec_1);
-  image_records_.pop_front();
-  base::RunLoop().RunUntilIdle();
-  RequestAndProvideImage(spec_2);
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1);
-}
-
-TEST_F(PooledSharedImageVideoProviderTest, InFlightSpecChangeProvidesImage) {
-  // If we change the ImageSpec between requesting and receiving an image from
-  // the provider, it should still provide the image to the requestor.
-  SharedImageVideoProvider::ImageSpec spec_1(gfx::Size(1, 1), 0u);
-  SharedImageVideoProvider::ImageSpec spec_2(gfx::Size(1, 1), 1u);
-
-  // Request both images before providing either.
-  EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(2);
-  provider_->RequestImage(SaveImageRecordCB(), spec_1, texture_owner_);
-  provider_->RequestImage(SaveImageRecordCB(), spec_2, texture_owner_);
-  base::RunLoop().RunUntilIdle();
-
-  // Provide the |spec_1| image.  Nothing should be released since it should
-  // fulfill the first request.
-  mock_provider_raw_->ProvideOneRequestedImage();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0);
-  EXPECT_EQ(image_records_.size(), 1u);
-
-  // Provide the |spec_2| image, which should also be provided to us.
-  mock_provider_raw_->ProvideOneRequestedImage();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0);
-  EXPECT_EQ(image_records_.size(), 2u);
-
-  // Drop the |spec_1| image, which should be released rather than added back to
-  // the pool.
-  image_records_.pop_front();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1);
-
-  // Drop the |spec_2| image, which should be pooled rather than released.
-  image_records_.pop_front();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1);
-}
-
-}  // namespace media
diff --git a/media/gpu/android/shared_image_video_provider.cc b/media/gpu/android/shared_image_video_provider.cc
index c543495f..445acd0 100644
--- a/media/gpu/android/shared_image_video_provider.cc
+++ b/media/gpu/android/shared_image_video_provider.cc
@@ -6,23 +6,11 @@
 
 namespace media {
 
-SharedImageVideoProvider::ImageSpec::ImageSpec() = default;
-SharedImageVideoProvider::ImageSpec::ImageSpec(const gfx::Size& our_size,
-                                               uint64_t our_generation_id)
-    : size(our_size), generation_id(our_generation_id) {}
+SharedImageVideoProvider::ImageSpec::ImageSpec(const gfx::Size& our_size)
+    : size(our_size) {}
 SharedImageVideoProvider::ImageSpec::ImageSpec(const ImageSpec&) = default;
 SharedImageVideoProvider::ImageSpec::~ImageSpec() = default;
 
-bool SharedImageVideoProvider::ImageSpec::operator==(
-    const ImageSpec& rhs) const {
-  return size == rhs.size && generation_id == rhs.generation_id;
-}
-
-bool SharedImageVideoProvider::ImageSpec::operator!=(
-    const ImageSpec& rhs) const {
-  return !(*this == rhs);
-}
-
 SharedImageVideoProvider::ImageRecord::ImageRecord() = default;
 SharedImageVideoProvider::ImageRecord::ImageRecord(ImageRecord&&) = default;
 SharedImageVideoProvider::ImageRecord::~ImageRecord() = default;
diff --git a/media/gpu/android/shared_image_video_provider.h b/media/gpu/android/shared_image_video_provider.h
index 83332f5..4e1ea50db 100644
--- a/media/gpu/android/shared_image_video_provider.h
+++ b/media/gpu/android/shared_image_video_provider.h
@@ -30,28 +30,16 @@
 
   // Description of the underlying properties of the shared image.
   struct ImageSpec {
-    ImageSpec();
-    ImageSpec(const gfx::Size& size, uint64_t generation_id);
+    ImageSpec(const gfx::Size& size);
     ImageSpec(const ImageSpec&);
     ~ImageSpec();
 
     // Size of the underlying texture.
     gfx::Size size;
 
-    // This is a hack to allow us to discard pooled images if the TextureOwner
-    // changes.  We don't want to keep a ref to the TextureOwner here, so we
-    // just use a generation counter.  Note that this is temporary anyway; we
-    // only need it for legacy mailbox support to construct a per-video-frame
-    // texture with the TextureOwner's service id (unowned texture hack).  Once
-    // legacy mailboxes aren't needed, SharedImageVideo::BeginAccess can just
-    // ask the CodecImage for whatever TextureOwner it is using currently, which
-    // is set by the client via CodecImage::Initialize.
-    uint64_t generation_id = 0;
-
     // TODO: Include other properties, if they matter, like texture format.
 
-    bool operator==(const ImageSpec&) const;
-    bool operator!=(const ImageSpec&) const;
+    bool operator==(const ImageSpec&);
   };
 
   using ReleaseCB = base::OnceCallback<void(const gpu::SyncToken&)>;
@@ -69,8 +57,7 @@
     // considered to be unused.
     ReleaseCB release_cb;
 
-    // CodecImage that one can use for MaybeRenderEarly, and to attach a codec
-    // output buffer.
+    // CodecImage that one can use for MaybeRenderEarly.
     scoped_refptr<CodecImageHolder> codec_image_holder;
 
     // Is the underlying context Vulkan?  If so, then one must provide YCbCrInfo
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc
index ce422d0..cced87f 100644
--- a/media/gpu/android/video_frame_factory_impl.cc
+++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -109,11 +109,6 @@
 void VideoFrameFactoryImpl::SetSurfaceBundle(
     scoped_refptr<CodecSurfaceBundle> surface_bundle) {
   scoped_refptr<CodecImageGroup> image_group;
-
-  // Increase the generation ID used by the shared image provider, since we're
-  // changing the TextureOwner.  This is temporary.  See ImageSpec.
-  image_spec_.generation_id++;
-
   if (!surface_bundle) {
     // Clear everything, just so we're not holding a reference.
     codec_buffer_wait_coordinator_ = nullptr;
@@ -159,8 +154,7 @@
     return;
   }
 
-  // Update the current spec to match the size.
-  image_spec_.size = coded_size;
+  SharedImageVideoProvider::ImageSpec spec(coded_size);
 
   auto image_ready_cb = base::BindOnce(
       &VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady,
@@ -170,7 +164,7 @@
       enable_threaded_texture_mailboxes_, gpu_task_runner_);
 
   image_provider_->RequestImage(
-      std::move(image_ready_cb), image_spec_,
+      std::move(image_ready_cb), spec,
       codec_buffer_wait_coordinator_
           ? codec_buffer_wait_coordinator_->texture_owner()
           : nullptr);
@@ -200,9 +194,6 @@
   // on the gpu main thread here, but it's okay since CodecImage is not being
   // used at this point.  Alternatively, we could post it, or hand it off to the
   // MaybeRenderEarlyManager to save a post.
-  //
-  // When we remove the output buffer management from CodecImage, then that's
-  // what we'd have a reference to here rather than CodecImage.
   record.codec_image_holder->codec_image_raw()->Initialize(
       std::move(output_buffer), codec_buffer_wait_coordinator,
       std::move(promotion_hint_cb));
@@ -270,6 +261,18 @@
   mailbox_holders[0] = gpu::MailboxHolder(record.mailbox, gpu::SyncToken(),
                                           GL_TEXTURE_EXTERNAL_OES);
 
+  // TODO(liberato): We should set the promotion hint cb here on the image.  We
+  // should also set the output buffer params; we shouldn't send the output
+  // buffer to the gpu thread, since the codec image isn't in use anyway.  We
+  // can access it on any thread.  We'll also need to get new images when we
+  // switch texture owners.  That's left for future work.
+
+  // TODO(liberato): When we switch to a pool, we need to provide some way to
+  // call MaybeRenderEarly that doesn't depend on |release_cb|.  I suppose we
+  // could get a RepeatingCallback that's a "reuse cb", that we'd attach to the
+  // VideoFrame's release cb, since we have to wait for the sync token anyway.
+  // That would run on the gpu thread, and could MaybeRenderEarly.
+
   gfx::Rect visible_rect(coded_size);
 
   auto frame = VideoFrame::WrapNativeTextures(
@@ -331,24 +334,12 @@
 void VideoFrameFactoryImpl::RunAfterPendingVideoFrames(
     base::OnceClosure closure) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  // Run |closure| after we receive an image from |image_provider_|.  We don't
-  // need the image, but it guarantees that it's ordered after all previous
-  // requests have been fulfilled.
-
-  auto image_ready_cb = base::BindOnce(
-      [](base::OnceClosure closure,
-         SharedImageVideoProvider::ImageRecord record) {
-        // Ignore |record| since we don't actually need an image.
-        std::move(closure).Run();
-      },
-      std::move(closure));
-
-  image_provider_->RequestImage(
-      std::move(image_ready_cb), image_spec_,
-      codec_buffer_wait_coordinator_
-          ? codec_buffer_wait_coordinator_->texture_owner()
-          : nullptr);
+  // Hop through |gpu_task_runner_| to ensure it comes after pending frames.
+  // TODO(liberato): If we're using a pool for SharedImageVideo, then this
+  // doesn't really make much sense.  SharedImageVideoProvider should do this
+  // for us instead.
+  gpu_task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(),
+                                     std::move(closure));
 }
 
 }  // namespace media
diff --git a/media/gpu/android/video_frame_factory_impl.h b/media/gpu/android/video_frame_factory_impl.h
index 02ccf9e..8352166 100644
--- a/media/gpu/android/video_frame_factory_impl.h
+++ b/media/gpu/android/video_frame_factory_impl.h
@@ -137,9 +137,6 @@
   // Optional helper to get the Vulkan YCbCrInfo.
   base::SequenceBound<YCbCrHelper> ycbcr_helper_;
 
-  // The current image spec that we'll use to request images.
-  SharedImageVideoProvider::ImageSpec image_spec_;
-
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<VideoFrameFactoryImpl> weak_factory_{this};
diff --git a/media/gpu/android/video_frame_factory_impl_unittest.cc b/media/gpu/android/video_frame_factory_impl_unittest.cc
index 0e7d94d0..f33c6ab 100644
--- a/media/gpu/android/video_frame_factory_impl_unittest.cc
+++ b/media/gpu/android/video_frame_factory_impl_unittest.cc
@@ -18,7 +18,6 @@
 #include "media/gpu/android/codec_buffer_wait_coordinator.h"
 #include "media/gpu/android/maybe_render_early_manager.h"
 #include "media/gpu/android/mock_codec_image.h"
-#include "media/gpu/android/mock_shared_image_video_provider.h"
 #include "media/gpu/android/shared_image_video_provider.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -40,6 +39,32 @@
   MOCK_METHOD0(MaybeRenderEarly, void());
 };
 
+class MockSharedImageVideoProvider : public SharedImageVideoProvider {
+ public:
+  MockSharedImageVideoProvider() : spec_(gfx::Size(0, 0)) {}
+
+  void Initialize(GpuInitCB gpu_init_cb) { Initialize_(gpu_init_cb); }
+
+  MOCK_METHOD1(Initialize_, void(GpuInitCB& gpu_init_cb));
+
+  void RequestImage(ImageReadyCB cb,
+                    const ImageSpec& spec,
+                    scoped_refptr<gpu::TextureOwner> texture_owner) override {
+    cb_ = std::move(cb);
+    spec_ = spec;
+    texture_owner_ = std::move(texture_owner);
+
+    MockRequestImage();
+  }
+
+  MOCK_METHOD0(MockRequestImage, void());
+
+  // Most recent arguments to RequestImage.
+  ImageReadyCB cb_;
+  ImageSpec spec_;
+  scoped_refptr<gpu::TextureOwner> texture_owner_;
+};
+
 class MockYCbCrHelper : public YCbCrHelper, public DestructionObservable {
  public:
   MockYCbCrHelper(MockYCbCrHelper** thiz) { *thiz = this; }
@@ -98,9 +123,6 @@
         VideoFrame::IsValidConfig(PIXEL_FORMAT_ARGB, VideoFrame::STORAGE_OPAQUE,
                                   coded_size, visible_rect, natural_size));
 
-    // Save a copy in case the test wants it.
-    output_buffer_raw_ = output_buffer.get();
-
     // We should get a call to the output callback, but no calls to the
     // provider.
     // TODO(liberato): Verify that it's sending the proper TextureOwner.
@@ -219,7 +241,7 @@
   auto record = MakeImageRecord(&release_cb_called_flag);
   scoped_refptr<CodecImage> codec_image(
       record.codec_image_holder->codec_image_raw());
-  image_provider_raw_->ProvideOneRequestedImage(&record);
+  std::move(image_provider_raw_->cb_).Run(std::move(record));
   base::RunLoop().RunUntilIdle();
   EXPECT_NE(frame, nullptr);
 
@@ -249,7 +271,7 @@
   RequestVideoFrame();
   auto image_record = MakeImageRecord();
   image_record.is_vulkan = false;
-  image_provider_raw_->ProvideOneRequestedImage(&image_record);
+  std::move(image_provider_raw_->cb_).Run(std::move(image_record));
   base::RunLoop().RunUntilIdle();
 }
 
@@ -261,7 +283,7 @@
               MockGetYCbCrInfo(image_record.codec_image_holder))
       .Times(1);
   image_record.is_vulkan = true;
-  image_provider_raw_->ProvideOneRequestedImage(&image_record);
+  std::move(image_provider_raw_->cb_).Run(std::move(image_record));
   base::RunLoop().RunUntilIdle();
 
   // Provide YCbCrInfo.  It should provide the VideoFrame too.
@@ -285,7 +307,7 @@
   if (ycbcr_helper_raw_)
     EXPECT_CALL(*ycbcr_helper_raw_, MockGetYCbCrInfo(_)).Times(0);
   EXPECT_CALL(output_cb_, Run(_)).Times(1);
-  image_provider_raw_->ProvideOneRequestedImage(&other_image_record);
+  std::move(image_provider_raw_->cb_).Run(std::move(other_image_record));
   base::RunLoop().RunUntilIdle();
 }
 
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc
index 428b30184..2820bde 100644
--- a/media/mojo/services/gpu_mojo_media_client.cc
+++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -33,7 +33,6 @@
 #include "media/gpu/android/direct_shared_image_video_provider.h"
 #include "media/gpu/android/maybe_render_early_manager.h"
 #include "media/gpu/android/media_codec_video_decoder.h"
-#include "media/gpu/android/pooled_shared_image_video_provider.h"
 #include "media/gpu/android/video_frame_factory_impl.h"
 #include "media/mojo/mojom/media_drm_storage.mojom.h"
 #include "media/mojo/mojom/provision_fetcher.mojom.h"
@@ -209,14 +208,8 @@
       auto get_stub_cb = base::Bind(
           &GetCommandBufferStub, gpu_task_runner_, media_gpu_channel_manager_,
           command_buffer_id->channel_token, command_buffer_id->route_id);
-      std::unique_ptr<SharedImageVideoProvider> image_provider;
-      image_provider = std::make_unique<DirectSharedImageVideoProvider>(
+      auto image_provider = std::make_unique<DirectSharedImageVideoProvider>(
           gpu_task_runner_, get_stub_cb);
-      if (base::FeatureList::IsEnabled(kUsePooledSharedImageVideoProvider)) {
-        // Wrap |image_provider| in a pool.
-        image_provider = PooledSharedImageVideoProvider::Create(
-            gpu_task_runner_, get_stub_cb, std::move(image_provider));
-      }
       // TODO(liberato): Create this only if we're using Vulkan, else it's
       // ignored.  If we can tell that here, then VideoFrameFactory can use it
       // as a signal about whether it's supposed to get YCbCrInfo rather than
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 1a3cf32..e25ca80 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -2779,7 +2779,8 @@
   if (verify_proc_type() == CERT_VERIFY_PROC_WIN) {
     // CertVerifyProcWin has a flaky result of ERR_CERT_AUTHORITY_INVALID or
     // ERR_CERT_INVALID (https://crbug.com/859387) - accept either.
-    EXPECT_TRUE(error == ERR_CERT_AUTHORITY_INVALID || ERR_CERT_INVALID)
+    EXPECT_TRUE(error == ERR_CERT_AUTHORITY_INVALID ||
+                error == ERR_CERT_INVALID)
         << "Unexpected error: " << error;
   } else {
     EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
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 1f80780..b456e4d 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -8,7 +8,6 @@
 #include <map>
 #include <memory>
 #include <utility>
-#include <vector>
 
 #include "base/base64.h"
 #include "base/bind.h"
@@ -23,11 +22,9 @@
 #include "base/pickle.h"
 #include "base/sequence_checker.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/synchronization/lock.h"
 #include "base/task/common/scoped_defer_task_posting.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
-#include "base/trace_event/trace_config.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_log.h"
 #include "build/build_config.h"
@@ -55,7 +52,6 @@
 using TraceLog = base::trace_event::TraceLog;
 using TraceEvent = base::trace_event::TraceEvent;
 using TraceConfig = base::trace_event::TraceConfig;
-using TraceRecordMode = base::trace_event::TraceRecordMode;
 using perfetto::protos::pbzero::ChromeMetadataPacket;
 
 namespace tracing {
@@ -80,8 +76,8 @@
 
 }  // namespace
 
-using perfetto::protos::pbzero::ChromeEventBundle;
-using ChromeEventBundleHandle = protozero::MessageHandle<ChromeEventBundle>;
+using ChromeEventBundleHandle =
+    protozero::MessageHandle<perfetto::protos::pbzero::ChromeEventBundle>;
 
 // static
 TraceEventMetadataSource* TraceEventMetadataSource::GetInstance() {
@@ -106,15 +102,12 @@
     JsonMetadataGeneratorFunction generator) {
   DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
   json_generator_functions_.push_back(generator);
-  // An EventBundle is created when nullptr is passed.
-  GenerateJsonMetadataFromGenerator(generator, nullptr);
 }
 
 void TraceEventMetadataSource::AddGeneratorFunction(
     MetadataGeneratorFunction generator) {
   DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
   generator_functions_.push_back(generator);
-  GenerateMetadataFromGenerator(generator);
 }
 
 std::unique_ptr<base::DictionaryValue>
@@ -123,12 +116,14 @@
     return nullptr;
   }
 
+  base::trace_event::TraceConfig parsed_chrome_config(chrome_config_);
+
   auto metadata_dict = std::make_unique<base::DictionaryValue>();
   // If argument filtering is enabled, we need to check if the trace config is
   // whitelisted before emitting it.
   // TODO(eseckler): Figure out a way to solve this without calling directly
   // into IsMetadataWhitelisted().
-  if (!parsed_chrome_config_->IsArgumentFilterEnabled() ||
+  if (!parsed_chrome_config.IsArgumentFilterEnabled() ||
       IsMetadataWhitelisted("trace-config")) {
     metadata_dict->SetString("trace-config", chrome_config_);
   } else {
@@ -139,177 +134,81 @@
   return metadata_dict;
 }
 
-void TraceEventMetadataSource::GenerateMetadataFromGenerator(
-    const TraceEventMetadataSource::MetadataGeneratorFunction& generator) {
-  DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
-  perfetto::TraceWriter::TracePacketHandle trace_packet;
-  {
-    base::AutoLock lock(lock_);
-    if (!emit_metadata_at_start_ || !trace_writer_) {
-      return;
-    }
-    trace_packet = trace_writer_->NewTracePacket();
-  }
-  trace_packet->set_timestamp(
-      TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds());
-  auto* chrome_metadata = trace_packet->set_chrome_metadata();
-  generator.Run(chrome_metadata, privacy_filtering_enabled_);
-}
-
-void TraceEventMetadataSource::GenerateJsonMetadataFromGenerator(
-    const TraceEventMetadataSource::JsonMetadataGeneratorFunction& generator,
-    ChromeEventBundle* event_bundle) {
-  DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
-  perfetto::TraceWriter::TracePacketHandle trace_packet;
-  if (!event_bundle) {
-    {
-      base::AutoLock lock(lock_);
-      if (!emit_metadata_at_start_ || !trace_writer_) {
-        return;
-      }
-      trace_packet = trace_writer_->NewTracePacket();
-    }
-    trace_packet->set_timestamp(
-        TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds());
-    event_bundle = trace_packet->set_chrome_events();
-  }
-
-  std::unique_ptr<base::DictionaryValue> metadata_dict = generator.Run();
-  if (!metadata_dict) {
-    return;
-  }
-
-  for (const auto& it : metadata_dict->DictItems()) {
-    auto* new_metadata = event_bundle->add_metadata();
-    new_metadata->set_name(it.first.c_str());
-
-    if (it.second.is_int()) {
-      new_metadata->set_int_value(it.second.GetInt());
-    } else if (it.second.is_bool()) {
-      new_metadata->set_bool_value(it.second.GetBool());
-    } else if (it.second.is_string()) {
-      new_metadata->set_string_value(it.second.GetString().c_str());
-    } else {
-      std::string json_value;
-      base::JSONWriter::Write(it.second, &json_value);
-      new_metadata->set_json_value(json_value.c_str());
-    }
-  }
-}
-
 void TraceEventMetadataSource::GenerateMetadata(
-    std::unique_ptr<
-        std::vector<TraceEventMetadataSource::JsonMetadataGeneratorFunction>>
-        json_generators,
-    std::unique_ptr<
-        std::vector<TraceEventMetadataSource::MetadataGeneratorFunction>>
-        proto_generators) {
+    std::unique_ptr<perfetto::TraceWriter> trace_writer) {
   DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
-  perfetto::TraceWriter::TracePacketHandle trace_packet;
-  bool privacy_filtering_enabled;
-  {
-    base::AutoLock lock(lock_);
-    trace_packet = trace_writer_->NewTracePacket();
-    privacy_filtering_enabled = privacy_filtering_enabled_;
-  }
-
-  trace_packet->set_timestamp(
-      TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds());
+  auto trace_packet = trace_writer->NewTracePacket();
   auto* chrome_metadata = trace_packet->set_chrome_metadata();
-  for (auto& generator : *proto_generators) {
+  for (auto& generator : generator_functions_) {
     generator.Run(chrome_metadata, privacy_filtering_enabled_);
   }
+  trace_packet = perfetto::TraceWriter::TracePacketHandle();
 
-  if (privacy_filtering_enabled) {
+  // We already have the |trace_writer| and |trace_packet|, so regardless of if
+  // we need to return due to privacy we need to null out the |producer_| to
+  // inform the system that we are done tracing with this |producer_|
+  producer_ = nullptr;
+  if (privacy_filtering_enabled_) {
     return;
   }
 
-  trace_packet->set_timestamp(
-      TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds());
-  ChromeEventBundle* event_bundle = trace_packet->set_chrome_events();
+  auto legacy_trace_packet = trace_writer->NewTracePacket();
+  ChromeEventBundleHandle event_bundle(
+      legacy_trace_packet->set_chrome_events());
 
-  for (auto& generator : *json_generators) {
-    GenerateJsonMetadataFromGenerator(generator, event_bundle);
+  for (auto& generator : json_generator_functions_) {
+    std::unique_ptr<base::DictionaryValue> metadata_dict = generator.Run();
+    if (!metadata_dict) {
+      continue;
+    }
+
+    for (const auto& it : metadata_dict->DictItems()) {
+      auto* new_metadata = event_bundle->add_metadata();
+      new_metadata->set_name(it.first.c_str());
+
+      if (it.second.is_int()) {
+        new_metadata->set_int_value(it.second.GetInt());
+      } else if (it.second.is_bool()) {
+        new_metadata->set_bool_value(it.second.GetBool());
+      } else if (it.second.is_string()) {
+        new_metadata->set_string_value(it.second.GetString().c_str());
+      } else {
+        std::string json_value;
+        base::JSONWriter::Write(it.second, &json_value);
+        new_metadata->set_json_value(json_value.c_str());
+      }
+    }
   }
 }
 
 void TraceEventMetadataSource::StartTracing(
     PerfettoProducer* producer,
     const perfetto::DataSourceConfig& data_source_config) {
-  auto json_generators =
-      std::make_unique<std::vector<JsonMetadataGeneratorFunction>>();
-  auto proto_generators =
-      std::make_unique<std::vector<MetadataGeneratorFunction>>();
-  {
-    base::AutoLock lock(lock_);
-    privacy_filtering_enabled_ =
-        data_source_config.chrome_config().privacy_filtering_enabled();
-    chrome_config_ = data_source_config.chrome_config().trace_config();
-    parsed_chrome_config_ = std::make_unique<TraceConfig>(chrome_config_);
-    trace_writer_ =
-        producer->CreateTraceWriter(data_source_config.target_buffer());
-    switch (parsed_chrome_config_->GetTraceRecordMode()) {
-      case TraceRecordMode::RECORD_UNTIL_FULL:
-      case TraceRecordMode::RECORD_AS_MUCH_AS_POSSIBLE: {
-        emit_metadata_at_start_ = true;
-        *json_generators = json_generator_functions_;
-        *proto_generators = generator_functions_;
-        break;
-      }
-      case TraceRecordMode::RECORD_CONTINUOUSLY:
-      case TraceRecordMode::ECHO_TO_CONSOLE:
-        emit_metadata_at_start_ = false;
-        return;
-    }
-  }
-  // |emit_metadata_at_start_| is true if we are in discard packets mode, write
-  // metadata at the beginning of the trace to make it less likely to be
-  // dropped.
-  origin_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&TraceEventMetadataSource::GenerateMetadata,
-                     base::Unretained(this), std::move(json_generators),
-                     std::move(proto_generators)));
+  // TODO(eseckler): Once we support streaming of trace data, it would make
+  // sense to emit the metadata on startup, so the UI can display it right away.
+  privacy_filtering_enabled_ =
+      data_source_config.chrome_config().privacy_filtering_enabled();
+  chrome_config_ = data_source_config.chrome_config().trace_config();
+  trace_writer_ =
+      producer->CreateTraceWriter(data_source_config.target_buffer());
 }
 
 void TraceEventMetadataSource::StopTracing(
     base::OnceClosure stop_complete_callback) {
-  base::OnceClosure maybe_generate_task = base::DoNothing();
-  {
-    base::AutoLock lock(lock_);
-    if (!emit_metadata_at_start_ && trace_writer_) {
-      // Write metadata at the end of tracing if not emitted at start (in ring
-      // buffer mode), to make it less likely that it is overwritten by other
-      // trace data in perfetto's ring buffer.
-      auto json_generators =
-          std::make_unique<std::vector<JsonMetadataGeneratorFunction>>();
-      *json_generators = json_generator_functions_;
-      auto proto_generators =
-          std::make_unique<std::vector<MetadataGeneratorFunction>>();
-      *proto_generators = generator_functions_;
-      maybe_generate_task = base::BindOnce(
-          &TraceEventMetadataSource::GenerateMetadata, base::Unretained(this),
-          std::move(json_generators), std::move(proto_generators));
-    }
+  if (trace_writer_) {
+    // Write metadata at the end of tracing to make it less likely that it is
+    // overwritten by other trace data in perfetto's ring buffer.
+    origin_task_runner_->PostTaskAndReply(
+        FROM_HERE,
+        base::BindOnce(&TraceEventMetadataSource::GenerateMetadata,
+                       base::Unretained(this), std::move(trace_writer_)),
+        std::move(stop_complete_callback));
+  } else {
+    producer_ = nullptr;
+    trace_writer_.reset();
+    chrome_config_ = std::string();
+    std::move(stop_complete_callback).Run();
   }
-  // Even when not generating metadata, make sure the metadata generate task
-  // posted at the start is finished, by posting task on origin task runner.
-  origin_task_runner_->PostTaskAndReply(
-      FROM_HERE, std::move(maybe_generate_task),
-      base::BindOnce(
-          [](TraceEventMetadataSource* ds,
-             base::OnceClosure stop_complete_callback) {
-            {
-              base::AutoLock lock(ds->lock_);
-              ds->producer_ = nullptr;
-              ds->trace_writer_.reset();
-              ds->chrome_config_ = std::string();
-              ds->parsed_chrome_config_.reset();
-              ds->emit_metadata_at_start_ = false;
-            }
-            std::move(stop_complete_callback).Run();
-          },
-          base::Unretained(this), std::move(stop_complete_callback)));
 }
 
 void TraceEventMetadataSource::Flush(
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.h b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
index 428b1c3..e082ce23 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.h
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
@@ -20,7 +20,6 @@
 #include "base/trace_event/trace_config.h"
 #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
 #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h"
-#include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h"
 
 namespace perfetto {
 class StartupTraceWriter;
@@ -61,9 +60,7 @@
       perfetto::protos::pbzero::ChromeMetadataPacket*,
       bool /* privacy_filtering_enabled */)>;
 
-  // Any callbacks passed here will be called when tracing. Note that if tracing
-  // is enabled while calling this method, the callback may be invoked
-  // directly.
+  // Any callbacks passed here will be called when tracing starts.
   void AddGeneratorFunction(JsonMetadataGeneratorFunction generator);
   // Same as above, but for filling in proto format.
   void AddGeneratorFunction(MetadataGeneratorFunction generator);
@@ -84,29 +81,15 @@
   TraceEventMetadataSource();
   ~TraceEventMetadataSource() override;
 
-  void GenerateMetadata(
-      std::unique_ptr<std::vector<JsonMetadataGeneratorFunction>>
-          json_generators,
-      std::unique_ptr<std::vector<MetadataGeneratorFunction>> proto_generators);
-  void GenerateMetadataFromGenerator(
-      const MetadataGeneratorFunction& generator);
-  void GenerateJsonMetadataFromGenerator(
-      const JsonMetadataGeneratorFunction& generator,
-      perfetto::protos::pbzero::ChromeEventBundle* event_bundle);
+  void GenerateMetadata(std::unique_ptr<perfetto::TraceWriter> trace_writer);
   std::unique_ptr<base::DictionaryValue> GenerateTraceConfigMetadataDict();
 
-  // All members are protected by |lock_|.
-  base::Lock lock_;
   std::vector<JsonMetadataGeneratorFunction> json_generator_functions_;
   std::vector<MetadataGeneratorFunction> generator_functions_;
-
-  const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_;
-
+  scoped_refptr<base::SequencedTaskRunner> origin_task_runner_;
   std::unique_ptr<perfetto::TraceWriter> trace_writer_;
   bool privacy_filtering_enabled_ = false;
   std::string chrome_config_;
-  std::unique_ptr<base::trace_event::TraceConfig> parsed_chrome_config_;
-  bool emit_metadata_at_start_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(TraceEventMetadataSource);
 };
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
index 4e773b40..2fe1f1f 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -486,76 +486,24 @@
   NOTREACHED();
 }
 
-std::unique_ptr<base::DictionaryValue> AddJsonMetadataGenerator() {
-  auto metadata = std::make_unique<base::DictionaryValue>();
-  metadata->SetInteger("foo_int", 42);
-  metadata->SetString("foo_str", "bar");
-  metadata->SetBoolean("foo_bool", true);
-
-  auto child_dict = std::make_unique<base::DictionaryValue>();
-  child_dict->SetString("child_str", "child_val");
-  metadata->Set("child_dict", std::move(child_dict));
-  return metadata;
-}
-
-TEST_F(TraceEventDataSourceTest, MetadataGeneratorBeforeTracing) {
-  auto* metadata_source = TraceEventMetadataSource::GetInstance();
-  metadata_source->AddGeneratorFunction(
-      base::BindRepeating(&AddJsonMetadataGenerator));
-
-  metadata_source->StartTracing(producer_client(),
-                                perfetto::DataSourceConfig());
-
-  base::RunLoop wait_for_stop;
-  metadata_source->StopTracing(wait_for_stop.QuitClosure());
-  wait_for_stop.Run();
-
-  auto metadata = producer_client()->GetChromeMetadata();
-  EXPECT_EQ(4, metadata.size());
-  MetadataHasNamedValue(metadata, "foo_int", 42);
-  MetadataHasNamedValue(metadata, "foo_str", "bar");
-  MetadataHasNamedValue(metadata, "foo_bool", true);
-
-  auto child_dict = std::make_unique<base::DictionaryValue>();
-  child_dict->SetString("child_str", "child_val");
-  MetadataHasNamedValue(metadata, "child_dict", *child_dict);
-}
-
-TEST_F(TraceEventDataSourceTest, MetadataGeneratorWhileTracing) {
-  auto* metadata_source = TraceEventMetadataSource::GetInstance();
-
-  metadata_source->StartTracing(producer_client(),
-                                perfetto::DataSourceConfig());
-  metadata_source->AddGeneratorFunction(
-      base::BindRepeating(&AddJsonMetadataGenerator));
-
-  base::RunLoop wait_for_stop;
-  metadata_source->StopTracing(wait_for_stop.QuitClosure());
-  wait_for_stop.Run();
-
-  auto metadata = producer_client()->GetChromeMetadata();
-  EXPECT_EQ(4, metadata.size());
-  MetadataHasNamedValue(metadata, "foo_int", 42);
-  MetadataHasNamedValue(metadata, "foo_str", "bar");
-  MetadataHasNamedValue(metadata, "foo_bool", true);
-
-  auto child_dict = std::make_unique<base::DictionaryValue>();
-  child_dict->SetString("child_str", "child_val");
-  MetadataHasNamedValue(metadata, "child_dict", *child_dict);
-}
-
-TEST_F(TraceEventDataSourceTest, MultipleMetadataGenerators) {
+TEST_F(TraceEventDataSourceTest, MetadataSourceBasicTypes) {
   auto* metadata_source = TraceEventMetadataSource::GetInstance();
   metadata_source->AddGeneratorFunction(base::BindRepeating([]() {
     auto metadata = std::make_unique<base::DictionaryValue>();
-    metadata->SetInteger("before_int", 42);
+    metadata->SetInteger("foo_int", 42);
+    metadata->SetString("foo_str", "bar");
+    metadata->SetBoolean("foo_bool", true);
+
+    auto child_dict = std::make_unique<base::DictionaryValue>();
+    child_dict->SetString("child_str", "child_val");
+    metadata->Set("child_dict", std::move(child_dict));
     return metadata;
   }));
 
+  CreateTraceEventDataSource();
+
   metadata_source->StartTracing(producer_client(),
                                 perfetto::DataSourceConfig());
-  metadata_source->AddGeneratorFunction(
-      base::BindRepeating(&AddJsonMetadataGenerator));
 
   base::RunLoop wait_for_stop;
   metadata_source->StopTracing(wait_for_stop.QuitClosure());
@@ -570,10 +518,6 @@
   auto child_dict = std::make_unique<base::DictionaryValue>();
   child_dict->SetString("child_str", "child_val");
   MetadataHasNamedValue(metadata, "child_dict", *child_dict);
-
-  metadata = producer_client()->GetChromeMetadata(1);
-  EXPECT_EQ(1, metadata.size());
-  MetadataHasNamedValue(metadata, "before_int", 42);
 }
 
 TEST_F(TraceEventDataSourceTest, BasicTraceEvent) {
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index d9a0c64..e8b51cb 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -6797,200 +6797,12 @@
     "isolated_scripts": [
       {
         "args": [
-          "context_lost",
-          "--show-stdout",
-          "--browser=android-chromium",
-          "--passthrough",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "context_lost_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "idempotent": false
-        }
-      },
-      {
-        "args": [
-          "depth_capture",
-          "--show-stdout",
-          "--browser=android-chromium",
-          "--passthrough",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "depth_capture_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "idempotent": false
-        }
-      },
-      {
-        "args": [
-          "gpu_process",
-          "--show-stdout",
-          "--browser=android-chromium",
-          "--passthrough",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "gpu_process_launch_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "idempotent": false
-        }
-      },
-      {
-        "args": [
-          "hardware_accelerated_feature",
-          "--show-stdout",
-          "--browser=android-chromium",
-          "--passthrough",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "hardware_accelerated_feature_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "idempotent": false
-        }
-      },
-      {
-        "args": [
-          "maps",
-          "--show-stdout",
-          "--browser=android-chromium",
-          "--passthrough",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer",
-          "--dont-restore-color-profile-after-test",
-          "--os-type",
-          "android",
-          "--build-revision",
-          "${got_revision}",
-          "--test-machine-name",
-          "${buildername}"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "maps_pixel_test",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "idempotent": false
-        }
-      },
-      {
-        "args": [
-          "screenshot_sync",
-          "--show-stdout",
-          "--browser=android-chromium",
-          "--passthrough",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer",
-          "--dont-restore-color-profile-after-test"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "screenshot_sync_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "idempotent": false
-        }
-      },
-      {
-        "args": [
           "pixel",
           "--show-stdout",
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=VizDisplayCompositor,UseSkiaRenderer,UseSkiaForGLReadback --use-gl=egl --enable-gpu-rasterization --force-gpu-rasterization --enable-oop-rasterization --disable-software-compositing-fallback --disable-headless-mode",
           "--dont-restore-color-profile-after-test",
           "--os-type",
           "android",
@@ -6999,13 +6811,12 @@
           "--test-machine-name",
           "${buildername}"
         ],
-        "experiment_percentage": 100,
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "skia_renderer_pixel_skia_gold_test",
+        "name": "egl_pixel_skia_gold_test",
         "precommit_args": [
           "--review-patch-issue",
           "${patch_issue}",
diff --git a/testing/buildbot/filters/bfcache.browser_tests.filter b/testing/buildbot/filters/bfcache.browser_tests.filter
index 7578195..5955cec 100644
--- a/testing/buildbot/filters/bfcache.browser_tests.filter
+++ b/testing/buildbot/filters/bfcache.browser_tests.filter
@@ -1,8 +1,5 @@
 # These tests currently fail when run with --enable-features=BackForwardCache
 
-# Rely on an unload handler to run. It doesn't run.
--IsolatedAppTest.IsolatedAppProcessModel
-
 # No focused view.
 -PaymentRequestShippingAddressEditorTest.FocusFirstInvalidField_NotName
 
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 32e457bf..4185fa0b 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3713,6 +3713,37 @@
       }
     },
 
+    'gpu_skia_renderer_egl_telemetry_tests': {
+      'egl_pixel_skia': {
+        'name': 'egl_pixel_skia_gold_test',
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--os-type',
+          '${os_type}',
+          '--build-revision',
+          '${got_revision}',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--enable-features=VizDisplayCompositor,UseSkiaRenderer,UseSkiaForGLReadback --use-gl=egl --enable-gpu-rasterization --force-gpu-rasterization --enable-oop-rasterization --disable-software-compositing-fallback --disable-headless-mode',
+        ],
+        'precommit_args': [
+          # Gerrit issue ID
+          '--review-patch-issue',
+          '${patch_issue}',
+          # Patch set number
+          '--review-patch-set',
+          '${patch_set}',
+          # Buildbucket ID
+          '--buildbucket-build-id',
+          '${buildbucket_build_id}',
+        ],
+        'swarming': {
+          'service_account': 'chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com'
+        },
+        'telemetry_test_name': 'pixel',
+      },
+    },
+
     'gpu_skia_renderer_non_vulkan_telemetry_tests': {
       'skia_renderer_pixel_skia_gold_test': {
         'name': 'skia_renderer_pixel_skia_gold_test',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 1ef1d41..3b1351e0 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2592,7 +2592,7 @@
           'bullhead',
        ],
        'test_suites': {
-         'gpu_telemetry_tests': 'gpu_skia_renderer_non_vulkan_telemetry_tests',
+         'gpu_telemetry_tests': 'gpu_skia_renderer_egl_telemetry_tests',
        }
       },
       'Android FYI SkiaRenderer Vulkan (Pixel 2)': {
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index f7c993b..1ea5aad 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -212,7 +212,6 @@
   BLINK_PLATFORM_EXPORT static void EnableMediaControlsOverlayPlayButton(bool);
   BLINK_PLATFORM_EXPORT static void EnableRemotePlaybackBackend(bool);
   BLINK_PLATFORM_EXPORT static void EnableMediaCastOverlayButton(bool);
-  BLINK_PLATFORM_EXPORT static void EnableClientPlaceholdersForServerLoFi(bool);
   BLINK_PLATFORM_EXPORT static void EnableLazyInitializeMediaControls(bool);
   BLINK_PLATFORM_EXPORT static void EnableMediaEngagementBypassAutoplayPolicies(
       bool);
diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_readable_stream_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_readable_stream_custom.cc
index d0e9fe4..e1baf4a 100644
--- a/third_party/blink/renderer/bindings/core/v8/custom/v8_readable_stream_custom.cc
+++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_readable_stream_custom.cc
@@ -27,17 +27,15 @@
       ScriptState::From(info.NewTarget().As<v8::Object>()->CreationContext());
 
   ScriptValue underlying_source =
-      ScriptValue(ScriptState::Current(info.GetIsolate()),
-                  v8::Undefined(info.GetIsolate()));
-  ScriptValue strategy = ScriptValue(ScriptState::Current(info.GetIsolate()),
-                                     v8::Undefined(info.GetIsolate()));
+      ScriptValue(info.GetIsolate(), v8::Undefined(info.GetIsolate()));
+  ScriptValue strategy =
+      ScriptValue(info.GetIsolate(), v8::Undefined(info.GetIsolate()));
   int num_args = info.Length();
   if (num_args >= 1) {
-    underlying_source =
-        ScriptValue(ScriptState::Current(info.GetIsolate()), info[0]);
+    underlying_source = ScriptValue(info.GetIsolate(), info[0]);
   }
   if (num_args >= 2)
-    strategy = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
+    strategy = ScriptValue(info.GetIsolate(), info[1]);
 
   v8::Local<v8::Object> wrapper = info.Holder();
   if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_writable_stream_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_writable_stream_custom.cc
index 2f67ed5..d9c253d1 100644
--- a/third_party/blink/renderer/bindings/core/v8/custom/v8_writable_stream_custom.cc
+++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_writable_stream_custom.cc
@@ -27,17 +27,15 @@
       ScriptState::From(info.NewTarget().As<v8::Object>()->CreationContext());
 
   ScriptValue underlying_sink =
-      ScriptValue(ScriptState::Current(info.GetIsolate()),
-                  v8::Undefined(info.GetIsolate()));
-  ScriptValue strategy = ScriptValue(ScriptState::Current(info.GetIsolate()),
-                                     v8::Undefined(info.GetIsolate()));
+      ScriptValue(info.GetIsolate(), v8::Undefined(info.GetIsolate()));
+  ScriptValue strategy =
+      ScriptValue(info.GetIsolate(), v8::Undefined(info.GetIsolate()));
   int num_args = info.Length();
   if (num_args >= 1) {
-    underlying_sink =
-        ScriptValue(ScriptState::Current(info.GetIsolate()), info[0]);
+    underlying_sink = ScriptValue(info.GetIsolate(), info[0]);
   }
   if (num_args >= 2)
-    strategy = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
+    strategy = ScriptValue(info.GetIsolate(), info[1]);
   v8::Local<v8::Object> wrapper = info.Holder();
 
   if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
diff --git a/third_party/blink/renderer/bindings/core/v8/iterable.h b/third_party/blink/renderer/bindings/core/v8/iterable.h
index 18db609..8cf18c1 100644
--- a/third_party/blink/renderer/bindings/core/v8/iterable.h
+++ b/third_party/blink/renderer/bindings/core/v8/iterable.h
@@ -79,8 +79,9 @@
 
       if (callback
               ->Invoke(v8_callback_this_value,
-                       ScriptValue(script_state, v8_value),
-                       ScriptValue(script_state, v8_key), this_value)
+                       ScriptValue(script_state->GetIsolate(), v8_value),
+                       ScriptValue(script_state->GetIsolate(), v8_key),
+                       this_value)
               .IsNothing()) {
         exception_state.RethrowV8Exception(try_catch.Exception());
         return;
@@ -129,9 +130,9 @@
 
       HeapVector<ScriptValue, 2> entry;
       entry.push_back(
-          ScriptValue(script_state, ToV8(key, creation_context, isolate)));
+          ScriptValue(isolate, ToV8(key, creation_context, isolate)));
       entry.push_back(
-          ScriptValue(script_state, ToV8(value, creation_context, isolate)));
+          ScriptValue(isolate, ToV8(value, creation_context, isolate)));
       return entry;
     }
   };
diff --git a/third_party/blink/renderer/bindings/core/v8/maplike.h b/third_party/blink/renderer/bindings/core/v8/maplike.h
index a7ca7bfb..f22fa75 100644
--- a/third_party/blink/renderer/bindings/core/v8/maplike.h
+++ b/third_party/blink/renderer/bindings/core/v8/maplike.h
@@ -26,10 +26,11 @@
                             ExceptionState& exception_state) {
     ValueType value;
     if (GetMapEntry(script_state, key, value, exception_state))
-      return ScriptValue(script_state,
+      return ScriptValue(script_state->GetIsolate(),
                          ToV8(value, script_state->GetContext()->Global(),
                               script_state->GetIsolate()));
-    return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
+    return ScriptValue(script_state->GetIsolate(),
+                       v8::Undefined(script_state->GetIsolate()));
   }
 
  private:
diff --git a/third_party/blink/renderer/bindings/core/v8/module_record.cc b/third_party/blink/renderer/bindings/core/v8/module_record.cc
index b127895..31f2081 100644
--- a/third_party/blink/renderer/bindings/core/v8/module_record.cc
+++ b/third_party/blink/renderer/bindings/core/v8/module_record.cc
@@ -107,7 +107,7 @@
            .To(&success) ||
       !success) {
     DCHECK(try_catch.HasCaught());
-    return ScriptValue(script_state, try_catch.Exception());
+    return ScriptValue(isolate, try_catch.Exception());
   }
   DCHECK(!try_catch.HasCaught());
   return ScriptValue();
@@ -133,7 +133,7 @@
                                       script_state->GetContext())
            .ToLocal(&result)) {
     DCHECK(try_catch.HasCaught());
-    return ScriptValue(script_state, try_catch.Exception());
+    return ScriptValue(isolate, try_catch.Exception());
   }
 
   return ScriptValue();
diff --git a/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc b/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc
index cb6ba97..9f459d22 100644
--- a/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc
+++ b/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc
@@ -75,7 +75,7 @@
         sanitize_script_errors_ == SanitizeScriptErrors::kDoNotSanitize) {
       PromiseRejectionEventInit* init = PromiseRejectionEventInit::Create();
       init->setPromise(ScriptPromise(script_state_, value));
-      init->setReason(ScriptValue(script_state_, reason));
+      init->setReason(ScriptValue(script_state_->GetIsolate(), reason));
       init->setCancelable(true);
       PromiseRejectionEvent* event = PromiseRejectionEvent::Create(
           script_state_, event_type_names::kUnhandledrejection, init);
@@ -115,7 +115,7 @@
         sanitize_script_errors_ == SanitizeScriptErrors::kDoNotSanitize) {
       PromiseRejectionEventInit* init = PromiseRejectionEventInit::Create();
       init->setPromise(ScriptPromise(script_state_, value));
-      init->setReason(ScriptValue(script_state_, reason));
+      init->setReason(ScriptValue(script_state_->GetIsolate(), reason));
       PromiseRejectionEvent* event = PromiseRejectionEvent::Create(
           script_state_, event_type_names::kRejectionhandled, init);
       target->DispatchEvent(*event);
diff --git a/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc b/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
index dfbfed1..aae5dbe 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
@@ -262,7 +262,7 @@
 
 // CustomElementDefinition
 ScriptValue ScriptCustomElementDefinition::GetConstructorForScript() {
-  return ScriptValue(script_state_, Constructor());
+  return ScriptValue(script_state_->GetIsolate(), Constructor());
 }
 
 bool ScriptCustomElementDefinition::HasConnectedCallback() const {
diff --git a/third_party/blink/renderer/bindings/core/v8/script_function.cc b/third_party/blink/renderer/bindings/core/v8/script_function.cc
index 3657116f..849ba64 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_function.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_function.cc
@@ -34,7 +34,8 @@
 }
 
 void ScriptFunction::CallRaw(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  ScriptValue result = Call(ScriptValue(GetScriptState(), args[0]));
+  ScriptValue result =
+      Call(ScriptValue(GetScriptState()->GetIsolate(), args[0]));
   V8SetReturnValue(args, result.V8Value());
 }
 
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise.cc b/third_party/blink/renderer/bindings/core/v8/script_promise.cc
index 54ba036..25ec59b 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise.cc
@@ -224,7 +224,7 @@
                                      "the given value is not a Promise");
     return;
   }
-  promise_ = ScriptValue(script_state, value);
+  promise_ = ScriptValue(script_state->GetIsolate(), value);
 }
 
 ScriptPromise::ScriptPromise(const ScriptPromise& other) {
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
index 5ab7eba..a64d5000 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
@@ -154,7 +154,7 @@
         ScriptState::From(ToV8Context(&GetDocument(), world));
     ScriptState::Scope scope(script_state);
     return ScriptValue(
-        script_state,
+        GetIsolate(),
         ToV8(value, script_state->GetContext()->Global(), GetIsolate()));
   }
 
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
index 288848e..0e4aa41 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
@@ -283,8 +283,8 @@
   V8TestingScope scope;
   ScriptValue on_fulfilled1, on_fulfilled2, on_rejected1, on_rejected2;
 
-  ScriptValue value = ScriptValue(scope.GetScriptState(),
-                                  V8String(scope.GetIsolate(), "hello"));
+  ScriptValue value =
+      ScriptValue(scope.GetIsolate(), V8String(scope.GetIsolate(), "hello"));
   ScriptPromise promise1 =
       ScriptPromise::Cast(scope.GetScriptState(), ScriptValue(value));
   ScriptPromise promise2 =
@@ -322,8 +322,8 @@
   V8TestingScope scope;
   ScriptValue on_fulfilled, on_rejected;
 
-  ScriptValue value = ScriptValue(scope.GetScriptState(),
-                                  V8String(scope.GetIsolate(), "hello"));
+  ScriptValue value =
+      ScriptValue(scope.GetIsolate(), V8String(scope.GetIsolate(), "hello"));
   ScriptPromise promise =
       ScriptPromise::Reject(scope.GetScriptState(), ScriptValue(value));
   promise.Then(FunctionForScriptPromiseTest::CreateFunction(
diff --git a/third_party/blink/renderer/bindings/core/v8/script_value.h b/third_party/blink/renderer/bindings/core/v8/script_value.h
index 134d872e..32983aa3 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_value.h
+++ b/third_party/blink/renderer/bindings/core/v8/script_value.h
@@ -74,18 +74,6 @@
   // TODO(rikaf): Forbid passing empty v8::Local<v8::Value> to ScriptValue's
   // ctor.
 
-  // TODO(crbug.com/998994): Remove ScriptValue(ScriptState*,
-  // v8::Local<v8::Value>) once we finish replacing with ScriptValue(Isolate*,
-  // v8::Local<v8::Value>)
-  ScriptValue(ScriptState* script_state, v8::Local<v8::Value> value)
-      : isolate_(script_state->GetIsolate()),
-        value_(value.IsEmpty()
-                   ? WorldSafeV8Reference<v8::Value>()
-                   : WorldSafeV8Reference<v8::Value>(script_state->GetIsolate(),
-                                                     value)) {
-    DCHECK(isolate_);
-  }
-
   ScriptValue(v8::Isolate* isolate, v8::Local<v8::Value> value)
       : isolate_(isolate),
         value_(value.IsEmpty()
@@ -201,7 +189,7 @@
   static inline ScriptValue NativeValue(v8::Isolate* isolate,
                                         v8::Local<v8::Value> value,
                                         ExceptionState& exception_state) {
-    return ScriptValue(ScriptState::Current(isolate), value);
+    return ScriptValue(isolate, value);
   }
 };
 
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
index a6518b84..c53a9f9 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
@@ -1850,8 +1850,7 @@
 
   auto* rs = ReadableStream::Create(script_state, ASSERT_NO_EXCEPTION);
   v8::Local<v8::Value> wrapper = ToV8(rs, script_state);
-  HeapVector<ScriptValue> transferable_array = {
-      ScriptValue(script_state, wrapper)};
+  HeapVector<ScriptValue> transferable_array = {ScriptValue(isolate, wrapper)};
   Transferables transferables;
   ASSERT_TRUE(SerializedScriptValue::ExtractTransferables(
       isolate, transferable_array, transferables, ASSERT_NO_EXCEPTION));
diff --git a/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h b/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h
index 86e865d7..5087a684 100644
--- a/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h
+++ b/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h
@@ -68,7 +68,8 @@
 // and ScriptValue
 template <typename T>
 inline ScriptValue ScriptValue::From(ScriptState* script_state, T&& value) {
-  return ScriptValue(script_state, ToV8(std::forward<T>(value), script_state));
+  return ScriptValue(script_state->GetIsolate(),
+                     ToV8(std::forward<T>(value), script_state));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc b/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc
index b71fa3f..ed09cf5 100644
--- a/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc
@@ -152,7 +152,7 @@
 
 TEST(ToV8Test, scriptValue) {
   V8TestingScope scope;
-  ScriptValue value(scope.GetScriptState(),
+  ScriptValue value(scope.GetIsolate(),
                     v8::Number::New(scope.GetIsolate(), 1234));
 
   TEST_TOV8("1234", value);
@@ -300,7 +300,7 @@
 
 TEST(ToV8Test, withScriptState) {
   V8TestingScope scope;
-  ScriptValue value(scope.GetScriptState(),
+  ScriptValue value(scope.GetIsolate(),
                     v8::Number::New(scope.GetIsolate(), 1234.0));
 
   v8::Local<v8::Value> actual = ToV8(value, scope.GetScriptState());
diff --git a/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc b/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
index e07a189..b8f95c9 100644
--- a/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
@@ -318,7 +318,7 @@
 }
 
 ScriptValue V0CustomElementConstructorBuilder::BindingsReturnValue() const {
-  return ScriptValue(script_state_, constructor_);
+  return ScriptValue(script_state_->GetIsolate(), constructor_);
 }
 
 bool V0CustomElementConstructorBuilder::HasValidPrototypeChainFor(
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h b/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h
index 6d376489..0af30777 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h
+++ b/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h
@@ -27,7 +27,7 @@
 template <typename T>
 inline ScriptValue V8IteratorResult(ScriptState* script_state, const T& value) {
   return ScriptValue(
-      script_state,
+      script_state->GetIsolate(),
       V8IteratorResultValue(script_state, false,
                             ToV8(value, script_state->GetContext()->Global(),
                                  script_state->GetIsolate())));
@@ -35,7 +35,7 @@
 
 inline ScriptValue V8IteratorResultDone(ScriptState* script_state) {
   return ScriptValue(
-      script_state,
+      script_state->GetIsolate(),
       V8IteratorResultValue(script_state, true,
                             v8::Undefined(script_state->GetIsolate())));
 }
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc b/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
index c448406..6abb611 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
@@ -53,7 +53,7 @@
 }
 
 ScriptValue V8ObjectBuilder::GetScriptValue() const {
-  return ScriptValue(script_state_, object_);
+  return ScriptValue(script_state_->GetIsolate(), object_);
 }
 
 void V8ObjectBuilder::AddInternal(const StringView& name,
diff --git a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
index 22f8ae2..7382cbd 100644
--- a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
@@ -373,7 +373,8 @@
     execution_state_->error_message = ToCoreString(message->Get());
     execution_state_->location_ = SourceLocation::FromMessage(
         isolate_, message, ExecutionContext::From(script_state_));
-    execution_state_->exception = ScriptValue(script_state_, block.Exception());
+    execution_state_->exception =
+        ScriptValue(script_state_->GetIsolate(), block.Exception());
     block.Reset();
   } else {
     execution_state_->had_exception = false;
@@ -383,7 +384,7 @@
   if (!maybe_result.ToLocal(&result) || result->IsUndefined())
     return ScriptValue();
 
-  return ScriptValue(script_state_, result);
+  return ScriptValue(script_state_->GetIsolate(), result);
 }
 
 bool WorkerOrWorkletScriptController::Evaluate(
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
index 8e1db2c..c6eb591f 100644
--- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
@@ -729,8 +729,7 @@
   SerializedScriptValue::DeserializeOptions options;
   options.blob_info = blob_info;
   options.read_wasm_from_stream = read_wasm_from_stream;
-  return ScriptValue(script_state,
-                     serialized_value->Deserialize(isolate, options));
+  return ScriptValue(isolate, serialized_value->Deserialize(isolate, options));
 }
 
 SQLValue NativeValueTraits<SQLValue>::NativeValue(
@@ -792,8 +791,7 @@
   ScriptState::Scope scope(script_state);
   v8::Isolate* isolate = script_state->GetIsolate();
   ScriptValue key_value = ScriptValue::From(script_state, value->PrimaryKey());
-  ScriptValue script_value(script_state,
-                           DeserializeIDBValueData(isolate, value));
+  ScriptValue script_value(isolate, DeserializeIDBValueData(isolate, value));
 
   DummyExceptionStateForTesting exception_state;
   std::unique_ptr<IDBKey> expected_key = CreateIDBKeyFromValueAndKeyPath(
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
index f7125da..df48fafd 100644
--- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
@@ -255,7 +255,7 @@
   {
     // Value is an array with a getter that throws.
     ScriptValue script_value(
-        scope.GetScriptState(),
+        scope.GetIsolate(),
         EvaluateScriptAsObject(
             scope,
             "(()=>{"
@@ -273,7 +273,7 @@
   {
     // Value is an array containing an array with a getter that throws.
     ScriptValue script_value(
-        scope.GetScriptState(),
+        scope.GetIsolate(),
         EvaluateScriptAsObject(
             scope,
             "(()=>{"
@@ -293,7 +293,7 @@
 TEST(IDBKeyFromValueAndKeyPathTest, Exceptions) {
   V8TestingScope scope;
   ScriptValue script_value(
-      scope.GetScriptState(),
+      scope.GetIsolate(),
       EvaluateScriptAsObject(scope,
                              "({id:1, get throws() { throw Error(); }})"));
   {
@@ -380,14 +380,14 @@
   v8::Isolate* isolate = scope.GetIsolate();
   {
     v8::Local<v8::String> string = V8String(isolate, "string");
-    ScriptValue value = ScriptValue(scope.GetScriptState(), string);
+    ScriptValue value = ScriptValue(scope.GetIsolate(), string);
     std::unique_ptr<IDBKey> idb_key = IDBKey::CreateNumber(123);
     CheckInjectionIgnored(scope.GetScriptState(), idb_key.get(), value,
                           "length");
   }
   {
     v8::Local<v8::Array> array = v8::Array::New(isolate);
-    ScriptValue value = ScriptValue(scope.GetScriptState(), array);
+    ScriptValue value = ScriptValue(scope.GetIsolate(), array);
     std::unique_ptr<IDBKey> idb_key = IDBKey::CreateNumber(456);
     CheckInjectionIgnored(scope.GetScriptState(), idb_key.get(), value,
                           "length");
diff --git a/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc b/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc
index 2933abb..271f0f5 100644
--- a/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc
@@ -12,7 +12,7 @@
 namespace blink {
 
 ScriptValue WebGLAny(ScriptState* script_state, bool value) {
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      v8::Boolean::New(script_state->GetIsolate(), value));
 }
 
@@ -20,69 +20,73 @@
                      const bool* value,
                      uint32_t size) {
   auto span = base::make_span(value, size);
-  return ScriptValue(script_state, ToV8(span, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(span, script_state));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, const Vector<bool>& value) {
-  return ScriptValue(script_state, ToV8(value, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, const Vector<unsigned>& value) {
-  return ScriptValue(script_state, ToV8(value, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, const Vector<int>& value) {
-  return ScriptValue(script_state, ToV8(value, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, int value) {
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      v8::Integer::New(script_state->GetIsolate(), value));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, unsigned value) {
   return ScriptValue(
-      script_state, v8::Integer::NewFromUnsigned(script_state->GetIsolate(),
-                                                 static_cast<unsigned>(value)));
+      script_state->GetIsolate(),
+      v8::Integer::NewFromUnsigned(script_state->GetIsolate(),
+                                   static_cast<unsigned>(value)));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, int64_t value) {
-  return ScriptValue(script_state, v8::Number::New(script_state->GetIsolate(),
-                                                   static_cast<double>(value)));
+  return ScriptValue(
+      script_state->GetIsolate(),
+      v8::Number::New(script_state->GetIsolate(), static_cast<double>(value)));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, uint64_t value) {
-  return ScriptValue(script_state, v8::Number::New(script_state->GetIsolate(),
-                                                   static_cast<double>(value)));
+  return ScriptValue(
+      script_state->GetIsolate(),
+      v8::Number::New(script_state->GetIsolate(), static_cast<double>(value)));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, float value) {
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      v8::Number::New(script_state->GetIsolate(), value));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, String value) {
-  return ScriptValue(script_state, V8String(script_state->GetIsolate(), value));
+  return ScriptValue(script_state->GetIsolate(),
+                     V8String(script_state->GetIsolate(), value));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, WebGLObject* value) {
-  return ScriptValue(script_state, ToV8(value, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, DOMFloat32Array* value) {
-  return ScriptValue(script_state, ToV8(value, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, DOMInt32Array* value) {
-  return ScriptValue(script_state, ToV8(value, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, DOMUint8Array* value) {
-  return ScriptValue(script_state, ToV8(value, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
 }
 
 ScriptValue WebGLAny(ScriptState* script_state, DOMUint32Array* value) {
-  return ScriptValue(script_state, ToV8(value, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/scripts/idl_definitions.py b/third_party/blink/renderer/bindings/scripts/idl_definitions.py
index 58d091b..27c6b03 100644
--- a/third_party/blink/renderer/bindings/scripts/idl_definitions.py
+++ b/third_party/blink/renderer/bindings/scripts/idl_definitions.py
@@ -509,6 +509,8 @@
             return '%g' % self.value
         if self.idl_type == 'boolean':
             return 'true' if self.value else 'false'
+        if self.idl_type == 'dictionary':
+            return self.value
         raise ValueError('Unsupported literal type: %s' % self.idl_type)
 
 
@@ -537,6 +539,8 @@
         return IdlLiteral(idl_type, value)
     if idl_type == 'NULL':
         return IdlLiteralNull()
+    if idl_type == 'dictionary':
+        return IdlLiteral(idl_type, value)
     raise ValueError('Unrecognized default value type: %s' % idl_type)
 
 
diff --git a/third_party/blink/renderer/bindings/scripts/v8_methods.py b/third_party/blink/renderer/bindings/scripts/v8_methods.py
index c170e7e..07fcc8d 100644
--- a/third_party/blink/renderer/bindings/scripts/v8_methods.py
+++ b/third_party/blink/renderer/bindings/scripts/v8_methods.py
@@ -474,9 +474,11 @@
     if not default_value:
         return None
     if idl_type.is_dictionary:
-        if not argument.default_value.is_null:
-            raise Exception('invalid default value for dictionary type')
-        return None
+        if argument.default_value.is_null:
+            return None
+        if argument.default_value.value == '{}':
+            return None
+        raise Exception('invalid default value for dictionary type')
     if idl_type.is_array_or_sequence_type:
         if default_value.value != '[]':
             raise Exception('invalid default value for sequence type: %s' % default_value.value)
diff --git a/third_party/blink/renderer/bindings/scripts/v8_types.py b/third_party/blink/renderer/bindings/scripts/v8_types.py
index cd9eef5..b9ed49b 100644
--- a/third_party/blink/renderer/bindings/scripts/v8_types.py
+++ b/third_party/blink/renderer/bindings/scripts/v8_types.py
@@ -570,7 +570,7 @@
     # Interface types
     'FlexibleArrayBufferView': 'ToFlexibleArrayBufferView({isolate}, {v8_value}, {variable_name}, allocateFlexibleArrayBufferViewStorage({v8_value}))',
     'Promise': 'ScriptPromise::Cast(ScriptState::Current({isolate}), {v8_value})',
-    'ScriptValue': 'ScriptValue(ScriptState::Current({isolate}), {v8_value})',
+    'ScriptValue': 'ScriptValue({isolate}, {v8_value})',
     'Window': 'ToDOMWindow({isolate}, {v8_value})',
     'XPathNSResolver': 'ToXPathNSResolver(ScriptState::Current({isolate}), {v8_value})',
 }
@@ -1055,6 +1055,8 @@
     literal_value = str(idl_literal)
     if idl_type.base_type in ('octet', 'unsigned short', 'unsigned long'):
         return literal_value + 'u'
+    if idl_type.is_dictionary and literal_value == '{}':
+        return 'MakeGarbageCollected<{}>()'.format(idl_type.base_type)
     return literal_value
 
 
diff --git a/third_party/blink/renderer/bindings/scripts/v8_utilities.py b/third_party/blink/renderer/bindings/scripts/v8_utilities.py
index bbadf62..ec31d27 100644
--- a/third_party/blink/renderer/bindings/scripts/v8_utilities.py
+++ b/third_party/blink/renderer/bindings/scripts/v8_utilities.py
@@ -210,7 +210,7 @@
     'ScriptState': 'script_state',
     'ExecutionContext': 'execution_context',
     'Document': 'document',
-    'ThisValue': 'ScriptValue(script_state, info.Holder())',
+    'ThisValue': 'ScriptValue(info.GetIsolate(), info.Holder())',
 }
 # List because key order matters, as we want arguments in deterministic order
 CALL_WITH_VALUES = [
diff --git a/third_party/blink/renderer/bindings/templates/methods.cc.tmpl b/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
index 15cd677..9c3b4f4 100644
--- a/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
+++ b/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
@@ -206,10 +206,10 @@
   {{v8_value_to_local_cpp_value(argument)}}
 {% if argument.is_nullable %}
 } else if (info[{{argument.index}}]->IsNullOrUndefined()) {
-  {{argument.local_cpp_variable}} = ScriptValue(ScriptState::Current(info.GetIsolate()), v8::Null(info.GetIsolate()));
+  {{argument.local_cpp_variable}} = ScriptValue(info.GetIsolate(), v8::Null(info.GetIsolate()));
 {% elif argument.is_optional %}
 } else if (info[{{argument.index}}]->IsUndefined()) {
-  {{argument.local_cpp_variable}} = ScriptValue(ScriptState::Current(info.GetIsolate()), v8::Undefined(info.GetIsolate()));
+  {{argument.local_cpp_variable}} = ScriptValue(info.GetIsolate(), v8::Undefined(info.GetIsolate()));
 {% endif %}
 } else {
   {{throw_argument_error(method, argument, "parameter %(index)d ('%(name)s') is not an object.")}}
diff --git a/third_party/blink/renderer/bindings/tests/idls/core/test_interface.idl b/third_party/blink/renderer/bindings/tests/idls/core/test_interface.idl
index f3b35e4..b723790c 100644
--- a/third_party/blink/renderer/bindings/tests/idls/core/test_interface.idl
+++ b/third_party/blink/renderer/bindings/tests/idls/core/test_interface.idl
@@ -74,6 +74,7 @@
     void voidMethodNullableAndOptionalObjectArgs(object objectArg, object? nullableObjectArg, optional object optionalObjectArg);
     void voidMethodUnrestrictedDoubleArgUnrestrictedFloatArg(unrestricted double unrestrictedDoubleArg, unrestricted float unrestrictedFloatArg);
     void voidMethodTestEnumArg(TestEnum testEnumArg);
+    void voidOptionalDictArgWithEmptyDefault(optional TestDictionary testDict={});
     [PerWorldBindings] void voidMethod();
 
     // Anonymous indexed property operations
diff --git a/third_party/blink/renderer/bindings/tests/idls/modules/test_dictionary_2.idl b/third_party/blink/renderer/bindings/tests/idls/modules/test_dictionary_2.idl
new file mode 100644
index 0000000..ec0afcc
--- /dev/null
+++ b/third_party/blink/renderer/bindings/tests/idls/modules/test_dictionary_2.idl
@@ -0,0 +1,7 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+dictionary TestDictionary2 {
+  TestDictionary defaultEmptyDictionary = {};
+};
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc
index ae1a93b1..ed9df40 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc
@@ -143,7 +143,7 @@
   if (any_member_value.IsEmpty() || any_member_value->IsUndefined()) {
     // Do nothing.
   } else {
-    ScriptValue any_member_cpp_value = ScriptValue(ScriptState::Current(isolate), any_member_value);
+    ScriptValue any_member_cpp_value = ScriptValue(isolate, any_member_value);
     impl->setAnyMember(any_member_cpp_value);
   }
 
@@ -547,7 +547,7 @@
   if (object_member_value.IsEmpty() || object_member_value->IsUndefined()) {
     // Do nothing.
   } else {
-    ScriptValue object_member_cpp_value = ScriptValue(ScriptState::Current(isolate), object_member_value);
+    ScriptValue object_member_cpp_value = ScriptValue(isolate, object_member_value);
     if (!object_member_cpp_value.IsObject()) {
       exception_state.ThrowTypeError("member objectMember is not an object.");
       return;
@@ -565,7 +565,7 @@
   } else if (object_or_null_member_value->IsNull()) {
     impl->setObjectOrNullMemberToNull();
   } else {
-    ScriptValue object_or_null_member_cpp_value = ScriptValue(ScriptState::Current(isolate), object_or_null_member_value);
+    ScriptValue object_or_null_member_cpp_value = ScriptValue(isolate, object_or_null_member_value);
     if (!object_or_null_member_cpp_value.IsObject()) {
       exception_state.ThrowTypeError("member objectOrNullMember is not an object.");
       return;
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed.cc
index 4e5170b..db95dac 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed.cc
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed.cc
@@ -167,9 +167,9 @@
     return;
   }
 
-  this_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
+  this_arg = ScriptValue(info.GetIsolate(), info[1]);
 
-  impl->forEachForBinding(script_state, ScriptValue(script_state, info.Holder()), callback, this_arg, exception_state);
+  impl->forEachForBinding(script_state, ScriptValue(info.GetIsolate(), info.Holder()), callback, this_arg, exception_state);
   if (exception_state.HadException()) {
     return;
   }
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc
index 349c696..def5fee 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc
@@ -23,6 +23,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_for_each_iterator_callback.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_iterator.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_node.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_test_dictionary.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_test_interface.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_test_interface_2.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_test_interface_empty.h"
@@ -688,7 +689,7 @@
   TestInterfaceImplementation* impl = V8TestInterface::ToImpl(holder);
 
   // Prepare the value to be set.
-  ScriptValue cpp_value = ScriptValue(ScriptState::Current(info.GetIsolate()), v8_value);
+  ScriptValue cpp_value = ScriptValue(info.GetIsolate(), v8_value);
 
   impl->setLenientThisAttribute(cpp_value);
 }
@@ -1553,16 +1554,16 @@
     --num_args_passed;
   }
   if (info[0]->IsObject()) {
-    object_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[0]);
+    object_arg = ScriptValue(info.GetIsolate(), info[0]);
   } else {
     V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::FailedToExecute("voidMethodNullableAndOptionalObjectArgs", "TestInterface", "parameter 1 ('objectArg') is not an object."));
     return;
   }
 
   if (info[1]->IsObject()) {
-    nullable_object_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
+    nullable_object_arg = ScriptValue(info.GetIsolate(), info[1]);
   } else if (info[1]->IsNullOrUndefined()) {
-    nullable_object_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), v8::Null(info.GetIsolate()));
+    nullable_object_arg = ScriptValue(info.GetIsolate(), v8::Null(info.GetIsolate()));
   } else {
     V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::FailedToExecute("voidMethodNullableAndOptionalObjectArgs", "TestInterface", "parameter 2 ('nullableObjectArg') is not an object."));
     return;
@@ -1573,9 +1574,9 @@
     return;
   }
   if (info[2]->IsObject()) {
-    optional_object_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[2]);
+    optional_object_arg = ScriptValue(info.GetIsolate(), info[2]);
   } else if (info[2]->IsUndefined()) {
-    optional_object_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), v8::Undefined(info.GetIsolate()));
+    optional_object_arg = ScriptValue(info.GetIsolate(), v8::Undefined(info.GetIsolate()));
   } else {
     V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::FailedToExecute("voidMethodNullableAndOptionalObjectArgs", "TestInterface", "parameter 3 ('optionalObjectArg') is not an object."));
     return;
@@ -1634,6 +1635,23 @@
   impl->voidMethodTestEnumArg(test_enum_arg);
 }
 
+static void VoidOptionalDictArgWithEmptyDefaultMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kExecutionContext, "TestInterface", "voidOptionalDictArgWithEmptyDefault");
+
+  TestInterfaceImplementation* impl = V8TestInterface::ToImpl(info.Holder());
+
+  TestDictionary* test_dict;
+  if (!info[0]->IsNullOrUndefined() && !info[0]->IsObject()) {
+    exception_state.ThrowTypeError("parameter 1 ('testDict') is not an object.");
+    return;
+  }
+  test_dict = NativeValueTraits<TestDictionary>::NativeValue(info.GetIsolate(), info[0], exception_state);
+  if (exception_state.HadException())
+    return;
+
+  impl->voidOptionalDictArgWithEmptyDefault(test_dict);
+}
+
 static void VoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
   TestInterfaceImplementation* impl = V8TestInterface::ToImpl(info.Holder());
 
@@ -2119,7 +2137,7 @@
 
   ScriptValue partial_callback_type_arg;
   if (info[0]->IsFunction()) {
-    partial_callback_type_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[0]);
+    partial_callback_type_arg = ScriptValue(info.GetIsolate(), info[0]);
   } else {
     V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::FailedToExecute("partialVoidMethodPartialCallbackTypeArg", "TestInterface", "The callback provided as parameter 1 is not a function."));
     return;
@@ -2349,9 +2367,9 @@
     return;
   }
 
-  this_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
+  this_arg = ScriptValue(info.GetIsolate(), info[1]);
 
-  impl->forEachForBinding(script_state, ScriptValue(script_state, info.Holder()), callback, this_arg, exception_state);
+  impl->forEachForBinding(script_state, ScriptValue(info.GetIsolate(), info.Holder()), callback, this_arg, exception_state);
   if (exception_state.HadException()) {
     return;
   }
@@ -3307,6 +3325,12 @@
   test_interface_implementation_v8_internal::VoidMethodTestEnumArgMethod(info);
 }
 
+void V8TestInterface::VoidOptionalDictArgWithEmptyDefaultMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestInterfaceImplementation_voidOptionalDictArgWithEmptyDefault");
+
+  test_interface_implementation_v8_internal::VoidOptionalDictArgWithEmptyDefaultMethod(info);
+}
+
 void V8TestInterface::VoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestInterfaceImplementation_voidMethod");
 
@@ -3726,6 +3750,7 @@
     {"voidMethodNullableAndOptionalObjectArgs", V8TestInterface::VoidMethodNullableAndOptionalObjectArgsMethodCallback, 2, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
     {"voidMethodUnrestrictedDoubleArgUnrestrictedFloatArg", V8TestInterface::VoidMethodUnrestrictedDoubleArgUnrestrictedFloatArgMethodCallback, 2, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
     {"voidMethodTestEnumArg", V8TestInterface::VoidMethodTestEnumArgMethodCallback, 1, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
+    {"voidOptionalDictArgWithEmptyDefault", V8TestInterface::VoidOptionalDictArgWithEmptyDefaultMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
     {"voidMethod", V8TestInterface::VoidMethodMethodCallbackForMainWorld, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kMainWorld},
     {"voidMethod", V8TestInterface::VoidMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kNonMainWorlds},
     {"alwaysExposedMethod", V8TestInterface::AlwaysExposedMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds},
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.h b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.h
index b31ac38..2079730 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.h
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.h
@@ -185,6 +185,7 @@
   CORE_EXPORT static void VoidMethodNullableAndOptionalObjectArgsMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
   CORE_EXPORT static void VoidMethodUnrestrictedDoubleArgUnrestrictedFloatArgMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
   CORE_EXPORT static void VoidMethodTestEnumArgMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+  CORE_EXPORT static void VoidOptionalDictArgWithEmptyDefaultMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
   CORE_EXPORT static void VoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
   CORE_EXPORT static void VoidMethodMethodCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>&);
   CORE_EXPORT static void AlwaysExposedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_2.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_2.cc
index ef76e62..80ffde4c 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_2.cc
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_2.cc
@@ -282,9 +282,9 @@
     return;
   }
 
-  this_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
+  this_arg = ScriptValue(info.GetIsolate(), info[1]);
 
-  impl->forEachForBinding(script_state, ScriptValue(script_state, info.Holder()), callback, this_arg, exception_state);
+  impl->forEachForBinding(script_state, ScriptValue(info.GetIsolate(), info.Holder()), callback, this_arg, exception_state);
   if (exception_state.HadException()) {
     return;
   }
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
index 4e4c7ac..f7b6ae5 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
@@ -916,7 +916,7 @@
   TestObject* impl = V8TestObject::ToImpl(holder);
 
   // Prepare the value to be set.
-  ScriptValue cpp_value = ScriptValue(ScriptState::Current(info.GetIsolate()), v8_value);
+  ScriptValue cpp_value = ScriptValue(info.GetIsolate(), v8_value);
 
   impl->setAnyAttribute(cpp_value);
 }
@@ -2030,7 +2030,7 @@
   TestObject* impl = V8TestObject::ToImpl(holder);
 
   // Prepare the value to be set.
-  ScriptValue cpp_value = ScriptValue(ScriptState::Current(info.GetIsolate()), v8_value);
+  ScriptValue cpp_value = ScriptValue(info.GetIsolate(), v8_value);
 
   impl->setCachedAttributeAnyAttribute(cpp_value);
 
@@ -2164,7 +2164,7 @@
   TestObject* impl = V8TestObject::ToImpl(holder);
 
   // Prepare the value to be set.
-  ScriptValue cpp_value = ScriptValue(ScriptState::Current(info.GetIsolate()), v8_value);
+  ScriptValue cpp_value = ScriptValue(info.GetIsolate(), v8_value);
 
   ExecutionContext* execution_context = ExecutionContext::ForRelevantRealm(info);
 
@@ -2192,7 +2192,7 @@
   TestObject* impl = V8TestObject::ToImpl(holder);
 
   // Prepare the value to be set.
-  ScriptValue cpp_value = ScriptValue(ScriptState::Current(info.GetIsolate()), v8_value);
+  ScriptValue cpp_value = ScriptValue(info.GetIsolate(), v8_value);
 
   ScriptState* script_state = ScriptState::ForRelevantRealm(info);
 
@@ -2222,7 +2222,7 @@
   TestObject* impl = V8TestObject::ToImpl(holder);
 
   // Prepare the value to be set.
-  ScriptValue cpp_value = ScriptValue(ScriptState::Current(info.GetIsolate()), v8_value);
+  ScriptValue cpp_value = ScriptValue(info.GetIsolate(), v8_value);
 
   ExecutionContext* execution_context = ExecutionContext::ForRelevantRealm(info);
 
@@ -3147,7 +3147,7 @@
   ExceptionState exception_state(isolate, ExceptionState::kSetterContext, "TestObject", "cachedAttributeRaisesExceptionGetterAnyAttribute");
 
   // Prepare the value to be set.
-  ScriptValue cpp_value = ScriptValue(ScriptState::Current(info.GetIsolate()), v8_value);
+  ScriptValue cpp_value = ScriptValue(info.GetIsolate(), v8_value);
 
   impl->setCachedAttributeRaisesExceptionGetterAnyAttribute(cpp_value, exception_state);
 
@@ -4817,7 +4817,7 @@
   }
 
   ScriptValue any_arg;
-  any_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[0]);
+  any_arg = ScriptValue(info.GetIsolate(), info[0]);
 
   impl->voidMethodAnyArg(any_arg);
 }
@@ -7807,9 +7807,7 @@
 static void CallWithThisValueMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
   TestObject* impl = V8TestObject::ToImpl(info.Holder());
 
-  ScriptState* script_state = ScriptState::ForRelevantRealm(info);
-
-  impl->callWithThisValue(ScriptValue(script_state, info.Holder()));
+  impl->callWithThisValue(ScriptValue(info.GetIsolate(), info.Holder()));
 }
 
 static void CheckSecurityForNodeVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -8988,9 +8986,9 @@
     return;
   }
 
-  this_arg = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
+  this_arg = ScriptValue(info.GetIsolate(), info[1]);
 
-  impl->forEachForBinding(script_state, ScriptValue(script_state, info.Holder()), callback, this_arg, exception_state);
+  impl->forEachForBinding(script_state, ScriptValue(info.GetIsolate(), info.Holder()), callback, this_arg, exception_state);
   if (exception_state.HadException()) {
     return;
   }
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/test_dictionary_2.cc b/third_party/blink/renderer/bindings/tests/results/modules/test_dictionary_2.cc
new file mode 100644
index 0000000..5285f64
--- /dev/null
+++ b/third_party/blink/renderer/bindings/tests/results/modules/test_dictionary_2.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file has been auto-generated from the Jinja2 template
+// third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl
+// by the script code_generator_v8.py.
+// DO NOT MODIFY!
+
+// clang-format off
+#include "third_party/blink/renderer/bindings/tests/results/modules/test_dictionary_2.h"
+
+namespace blink {
+
+TestDictionary2::TestDictionary2() {
+  setDefaultEmptyDictionary(MakeGarbageCollected<TestDictionary>());
+}
+
+TestDictionary2::~TestDictionary2() = default;
+
+void TestDictionary2::setDefaultEmptyDictionary(TestDictionary* value) {
+  default_empty_dictionary_ = value;
+}
+
+void TestDictionary2::Trace(blink::Visitor* visitor) {
+  visitor->Trace(default_empty_dictionary_);
+  IDLDictionaryBase::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/test_dictionary_2.h b/third_party/blink/renderer/bindings/tests/results/modules/test_dictionary_2.h
new file mode 100644
index 0000000..a98fe22
--- /dev/null
+++ b/third_party/blink/renderer/bindings/tests/results/modules/test_dictionary_2.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file has been auto-generated from the Jinja2 template
+// third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl
+// by the script code_generator_v8.py.
+// DO NOT MODIFY!
+
+// clang-format off
+#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_TEST_DICTIONARY_2_H_
+#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_TEST_DICTIONARY_2_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/idl_dictionary_base.h"
+#include "third_party/blink/renderer/bindings/tests/idls/core/test_dictionary.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class MODULES_EXPORT TestDictionary2 : public IDLDictionaryBase {
+ public:
+  static TestDictionary2* Create() { return MakeGarbageCollected<TestDictionary2>(); }
+
+  TestDictionary2();
+  virtual ~TestDictionary2();
+
+  bool hasDefaultEmptyDictionary() const { return default_empty_dictionary_; }
+  TestDictionary* defaultEmptyDictionary() const {
+    return default_empty_dictionary_;
+  }
+  void setDefaultEmptyDictionary(TestDictionary*);
+
+  v8::Local<v8::Value> ToV8Impl(v8::Local<v8::Object>, v8::Isolate*) const override;
+  void Trace(blink::Visitor*) override;
+
+ private:
+
+  Member<TestDictionary> default_empty_dictionary_;
+
+  friend class V8TestDictionary2;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_TEST_DICTIONARY_2_H_
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_dictionary_2.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_dictionary_2.cc
new file mode 100644
index 0000000..1b5cb7fe
--- /dev/null
+++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_dictionary_2.cc
@@ -0,0 +1,101 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file has been auto-generated from the Jinja2 template
+// third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl
+// by the script code_generator_v8.py.
+// DO NOT MODIFY!
+
+// clang-format off
+#include "third_party/blink/renderer/bindings/tests/results/modules/v8_test_dictionary_2.h"
+
+#include "base/stl_util.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_test_dictionary.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
+namespace blink {
+
+static const v8::Eternal<v8::Name>* eternalV8TestDictionary2Keys(v8::Isolate* isolate) {
+  static const char* const kKeys[] = {
+    "defaultEmptyDictionary",
+  };
+  return V8PerIsolateData::From(isolate)->FindOrCreateEternalNameCache(
+      kKeys, kKeys, base::size(kKeys));
+}
+
+void V8TestDictionary2::ToImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8_value, TestDictionary2* impl, ExceptionState& exception_state) {
+  if (IsUndefinedOrNull(v8_value)) {
+    return;
+  }
+  if (!v8_value->IsObject()) {
+    exception_state.ThrowTypeError("cannot convert to dictionary.");
+    return;
+  }
+  v8::Local<v8::Object> v8Object = v8_value.As<v8::Object>();
+  ALLOW_UNUSED_LOCAL(v8Object);
+
+  const v8::Eternal<v8::Name>* keys = eternalV8TestDictionary2Keys(isolate);
+  v8::TryCatch block(isolate);
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Value> default_empty_dictionary_value;
+  if (!v8Object->Get(context, keys[0].Get(isolate)).ToLocal(&default_empty_dictionary_value)) {
+    exception_state.RethrowV8Exception(block.Exception());
+    return;
+  }
+  if (default_empty_dictionary_value.IsEmpty() || default_empty_dictionary_value->IsUndefined()) {
+    // Do nothing.
+  } else {
+    TestDictionary* default_empty_dictionary_cpp_value = NativeValueTraits<TestDictionary>::NativeValue(isolate, default_empty_dictionary_value, exception_state);
+    if (exception_state.HadException())
+      return;
+    impl->setDefaultEmptyDictionary(default_empty_dictionary_cpp_value);
+  }
+}
+
+v8::Local<v8::Value> TestDictionary2::ToV8Impl(v8::Local<v8::Object> creationContext, v8::Isolate* isolate) const {
+  v8::Local<v8::Object> v8Object = v8::Object::New(isolate);
+  if (!toV8TestDictionary2(this, v8Object, creationContext, isolate))
+    return v8::Undefined(isolate);
+  return v8Object;
+}
+
+bool toV8TestDictionary2(const TestDictionary2* impl, v8::Local<v8::Object> dictionary, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) {
+  const v8::Eternal<v8::Name>* keys = eternalV8TestDictionary2Keys(isolate);
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+
+  auto create_property = [dictionary, context, keys, isolate](
+                             size_t key_index, v8::Local<v8::Value> value) {
+    bool added_property;
+    v8::Local<v8::Name> key = keys[key_index].Get(isolate);
+    if (!dictionary->CreateDataProperty(context, key, value)
+             .To(&added_property)) {
+      return false;
+    }
+    return added_property;
+  };
+
+  v8::Local<v8::Value> default_empty_dictionary_value;
+  bool default_empty_dictionary_has_value_or_default = false;
+  if (impl->hasDefaultEmptyDictionary()) {
+    default_empty_dictionary_value = ToV8(impl->defaultEmptyDictionary(), creationContext, isolate);
+    default_empty_dictionary_has_value_or_default = true;
+  } else {
+    default_empty_dictionary_value = ToV8(MakeGarbageCollected<TestDictionary>(), creationContext, isolate);
+    default_empty_dictionary_has_value_or_default = true;
+  }
+  if (default_empty_dictionary_has_value_or_default &&
+      !create_property(0, default_empty_dictionary_value)) {
+    return false;
+  }
+
+  return true;
+}
+
+TestDictionary2* NativeValueTraits<TestDictionary2>::NativeValue(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) {
+  TestDictionary2* impl = TestDictionary2::Create();
+  V8TestDictionary2::ToImpl(isolate, value, impl, exception_state);
+  return impl;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_dictionary_2.h b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_dictionary_2.h
new file mode 100644
index 0000000..9d6a4d6
--- /dev/null
+++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_dictionary_2.h
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file has been auto-generated from the Jinja2 template
+// third_party/blink/renderer/bindings/templates/dictionary_v8.h.tmpl
+// by the script code_generator_v8.py.
+// DO NOT MODIFY!
+
+// clang-format off
+#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_V8_TEST_DICTIONARY_2_H_
+#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_V8_TEST_DICTIONARY_2_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/tests/idls/modules/test_dictionary_2.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ExceptionState;
+
+class V8TestDictionary2 {
+ public:
+  MODULES_EXPORT static void ToImpl(v8::Isolate*, v8::Local<v8::Value>, TestDictionary2* impl, ExceptionState&);
+};
+
+MODULES_EXPORT bool toV8TestDictionary2(const TestDictionary2*, v8::Local<v8::Object> dictionary, v8::Local<v8::Object> creationContext, v8::Isolate*);
+
+template <class CallbackInfo>
+inline void V8SetReturnValue(const CallbackInfo& callbackInfo, TestDictionary2* impl) {
+  V8SetReturnValue(callbackInfo, ToV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
+}
+
+template <class CallbackInfo>
+inline void V8SetReturnValue(const CallbackInfo& callbackInfo, TestDictionary2* impl, v8::Local<v8::Object> creationContext) {
+  V8SetReturnValue(callbackInfo, ToV8(impl, creationContext, callbackInfo.GetIsolate()));
+}
+
+template <>
+struct NativeValueTraits<TestDictionary2> : public NativeValueTraitsBase<TestDictionary2> {
+  MODULES_EXPORT static TestDictionary2* NativeValue(v8::Isolate*, v8::Local<v8::Value>, ExceptionState&);
+};
+
+template <>
+struct V8TypeOf<TestDictionary2> {
+  typedef V8TestDictionary2 Type;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_BINDINGS_TESTS_RESULTS_MODULES_V8_TEST_DICTIONARY_2_H_
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 0bc8af2..a4e75e36 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1106,6 +1106,7 @@
     "css/css_test_helpers.h",
     "css/css_uri_value_test.cc",
     "css/css_value_test_helper.h",
+    "css/mock_css_paint_image_generator.h",
     "display_lock/display_lock_budget_test.cc",
     "display_lock/display_lock_context_test.cc",
     "display_lock/display_lock_utilities_test.cc",
diff --git a/third_party/blink/renderer/core/animation/animatable.cc b/third_party/blink/renderer/core/animation/animatable.cc
index 6c772ba..88fc2ef 100644
--- a/third_party/blink/renderer/core/animation/animatable.cc
+++ b/third_party/blink/renderer/core/animation/animatable.cc
@@ -100,10 +100,12 @@
        element->GetDocument().Timeline().getAnimations()) {
     DCHECK(animation->effect());
     Element* target = ToKeyframeEffect(animation->effect())->target();
-
     if (element == target || (use_subtree && element->contains(target))) {
-      if (animation->effect()->IsCurrent() || animation->effect()->IsInEffect())
-        animations.push_back(animation);
+      // DocumentTimeline::getAnimations should only give us animations that are
+      // either current or in effect.
+      DCHECK(animation->effect()->IsCurrent() ||
+             animation->effect()->IsInEffect());
+      animations.push_back(animation);
     }
   }
   return animations;
diff --git a/third_party/blink/renderer/core/animation/animation_effect.cc b/third_party/blink/renderer/core/animation/animation_effect.cc
index 8d185980..1f753625 100644
--- a/third_party/blink/renderer/core/animation/animation_effect.cc
+++ b/third_party/blink/renderer/core/animation/animation_effect.cc
@@ -76,8 +76,11 @@
 
 void AnimationEffect::UpdateInheritedTime(double inherited_time,
                                           TimingUpdateReason reason) const {
+  base::Optional<double> playback_rate = base::nullopt;
+  if (GetAnimation())
+    playback_rate = GetAnimation()->playbackRate();
   const Timing::AnimationDirection direction =
-      (GetAnimation() && GetAnimation()->playbackRate() < 0)
+      (playback_rate && playback_rate.value() < 0)
           ? Timing::AnimationDirection::kBackwards
           : Timing::AnimationDirection::kForwards;
   bool needs_update =
@@ -91,7 +94,7 @@
   const double local_time = inherited_time;
   if (needs_update) {
     Timing::CalculatedTiming calculated = SpecifiedTiming().CalculateTimings(
-        local_time, direction, IsKeyframeEffect());
+        local_time, direction, IsKeyframeEffect(), playback_rate);
 
     const bool was_canceled = calculated.phase != calculated_.phase &&
                               calculated.phase == Timing::kPhaseNone;
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.cc b/third_party/blink/renderer/core/animation/compositor_animations.cc
index a3f55f1..1f809da 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -267,6 +267,11 @@
           if (keyframe_value) {
             DCHECK(RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled());
             DCHECK(keyframe_value->IsDouble() || keyframe_value->IsColor());
+            // If a custom property is not used by CSS Paint, then we should not
+            // support that on the compositor thread.
+            if (!layout_object->Style()->HasCSSPaintImagesUsingCustomProperty(
+                    property.CustomPropertyName()))
+              reasons |= kUnsupportedCSSProperty;
             // TODO: Add support for keyframes containing different types
             if (keyframes.front()->GetCompositorKeyframeValue()->GetType() !=
                 keyframe_value->GetType()) {
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 7491687..af5cd93 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -47,7 +47,11 @@
 #include "third_party/blink/renderer/core/animation/element_animations.h"
 #include "third_party/blink/renderer/core/animation/keyframe_effect.h"
 #include "third_party/blink/renderer/core/animation/pending_animations.h"
+#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
+#include "third_party/blink/renderer/core/css/css_paint_value.h"
+#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
 #include "third_party/blink/renderer/core/css/css_test_helpers.h"
+#include "third_party/blink/renderer/core/css/mock_css_paint_image_generator.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
@@ -58,6 +62,7 @@
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/style/filter_operations.h"
+#include "third_party/blink/renderer/core/style/style_generated_image.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h"
@@ -77,8 +82,27 @@
 #include "third_party/blink/renderer/platform/wtf/hash_functions.h"
 #include "third_party/skia/include/core/SkColor.h"
 
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+using testing::ReturnRef;
+using testing::Values;
+
 namespace blink {
 
+namespace {
+// CSSPaintImageGenerator requires that CSSPaintImageGeneratorCreateFunction be
+// a static method. As such, it cannot access a class member and so instead we
+// store a pointer to the overriding generator globally.
+MockCSSPaintImageGenerator* g_override_generator = nullptr;
+CSSPaintImageGenerator* ProvideOverrideGenerator(
+    const String&,
+    const Document&,
+    CSSPaintImageGenerator::Observer*) {
+  return g_override_generator;
+}
+}  // namespace
+
 using namespace css_test_helpers;
 
 class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
@@ -588,9 +612,11 @@
   RegisterProperty(GetDocument(), "--foo", "<number>", "0", false);
   RegisterProperty(GetDocument(), "--bar", "<length>", "10px", false);
   RegisterProperty(GetDocument(), "--loo", "<color>", "rgb(0, 0, 0)", false);
+  RegisterProperty(GetDocument(), "--x", "<number>", "0", false);
   SetCustomProperty("--foo", "10");
   SetCustomProperty("--bar", "10px");
   SetCustomProperty("--loo", "rgb(0, 255, 0)");
+  SetCustomProperty("--x", "5");
 
   auto style = GetDocument().EnsureStyleResolver().StyleForElement(element_);
   EXPECT_TRUE(style->NonInheritedVariables());
@@ -603,7 +629,41 @@
   EXPECT_TRUE(style->NonInheritedVariables()
                   ->GetData(AtomicString("--loo"))
                   .value_or(nullptr));
+  EXPECT_TRUE(style->NonInheritedVariables()
+                  ->GetData(AtomicString("--x"))
+                  .value_or(nullptr));
 
+  NiceMock<MockCSSPaintImageGenerator>* mock_generator =
+      MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
+  base::AutoReset<MockCSSPaintImageGenerator*> scoped_override_generator(
+      &g_override_generator, mock_generator);
+  base::AutoReset<CSSPaintImageGenerator::CSSPaintImageGeneratorCreateFunction>
+      scoped_create_function(
+          CSSPaintImageGenerator::GetCreateFunctionForTesting(),
+          ProvideOverrideGenerator);
+
+  mock_generator->AddCustomProperty("--foo");
+  mock_generator->AddCustomProperty("--bar");
+  mock_generator->AddCustomProperty("--loo");
+  auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("foopainter");
+  CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
+  paint_value->CreateGeneratorForTesting(GetDocument());
+  StyleGeneratedImage* style_image =
+      MakeGarbageCollected<StyleGeneratedImage>(*paint_value);
+  style->AddPaintImage(style_image);
+  element_->GetLayoutObject()->SetStyle(style);
+  // The image is added for testing off-thread paint worklet supporting
+  // custom property animation case. The style doesn't have a real
+  // PaintImage, so we cannot call UpdateAllLifecyclePhasesForTest. But the
+  // PaintArtifactCompositor requires NeedsUpdate to be false.
+  // In the real world when a PaintImage does exist in the style, the life
+  // cycle will be updated automatically and we don't have to worry about
+  // this.
+  auto* paint_artifact_compositor =
+      GetDocument().View()->GetPaintArtifactCompositor();
+  paint_artifact_compositor->ClearNeedsUpdateForTesting();
+
+  ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true));
   StringKeyframe* keyframe = CreateReplaceOpKeyframe("--foo", "10");
   EXPECT_EQ(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe),
             CompositorAnimations::kNoFailure);
@@ -625,6 +685,12 @@
   SetCustomProperty("opacity", "var(--foo)");
   EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe) &
               CompositorAnimations::kUnsupportedCSSProperty);
+
+  // Cannot composite because "--x" is not used by the paint worklet.
+  StringKeyframe* non_used_keyframe = CreateReplaceOpKeyframe("--x", "5");
+  EXPECT_EQ(
+      DuplicateSingleKeyframeAndTestIsCandidateOnResult(non_used_keyframe),
+      CompositorAnimations::kUnsupportedCSSProperty);
 }
 
 TEST_P(AnimationCompositorAnimationsTest,
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc
index 3b156fd8..4ee0fa6 100644
--- a/third_party/blink/renderer/core/animation/css/css_animations.cc
+++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -1230,17 +1230,18 @@
       // Per the css-transitions-2 spec, transitioncancel is fired with the
       // "active time of the animation at the moment it was cancelled,
       // calculated using a fill mode of both".
-      base::Optional<double> cancel_active_time = CalculateActiveTime(
-          animation_node.SpecifiedTiming().ActiveDuration(),
-          Timing::FillMode::BOTH, animation_node.LocalTime(), previous_phase_,
-          animation_node.SpecifiedTiming());
+      base::Optional<AnimationTimeDelta> cancel_active_time =
+          CalculateActiveTime(animation_node.SpecifiedTiming().ActiveDuration(),
+                              Timing::FillMode::BOTH,
+                              animation_node.LocalTime(), previous_phase_,
+                              animation_node.SpecifiedTiming());
       // Being the FillMode::BOTH the only possibility to get a null
       // cancel_active_time is that previous_phase_ is kPhaseNone. This cannot
       // happen because we know that current_phase == kPhaseNone and
       // current_phase != previous_phase_ (see early return at the beginning).
       DCHECK(cancel_active_time);
       EnqueueEvent(event_type_names::kTransitioncancel,
-                   cancel_active_time.value());
+                   cancel_active_time->InSecondsF());
     }
   }
 
diff --git a/third_party/blink/renderer/core/animation/effect_input_test.cc b/third_party/blink/renderer/core/animation/effect_input_test.cc
index bdfac8f9..88ebc7815 100644
--- a/third_party/blink/renderer/core/animation/effect_input_test.cc
+++ b/third_party/blink/renderer/core/animation/effect_input_test.cc
@@ -38,7 +38,7 @@
                                                  .GetScriptValue()};
 
   ScriptValue js_keyframes(
-      script_state,
+      scope.GetIsolate(),
       ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
 
   Element* element = AppendElement(scope.GetDocument());
@@ -63,7 +63,7 @@
                                                  .GetScriptValue()};
 
   ScriptValue js_keyframes(
-      script_state,
+      scope.GetIsolate(),
       ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
 
   Element* element = AppendElement(scope.GetDocument());
@@ -91,7 +91,7 @@
                                                  .GetScriptValue()};
 
   ScriptValue js_keyframes(
-      script_state,
+      scope.GetIsolate(),
       ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
 
   Element* element = AppendElement(scope.GetDocument());
@@ -123,7 +123,7 @@
                                                  .GetScriptValue()};
 
   ScriptValue js_keyframes(
-      script_state,
+      scope.GetIsolate(),
       ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
 
   Element* element = AppendElement(scope.GetDocument());
@@ -150,7 +150,7 @@
                                                  .GetScriptValue()};
 
   ScriptValue js_keyframes(
-      script_state,
+      scope.GetIsolate(),
       ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
 
   Element* element = AppendElement(scope.GetDocument());
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect_test.cc b/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
index 50440af..2223f15 100644
--- a/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
+++ b/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
@@ -123,7 +123,7 @@
           .GetScriptValue()};
 
   ScriptValue js_keyframes(
-      script_state,
+      scope.GetIsolate(),
       ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
 
   KeyframeEffect* animation =
@@ -202,7 +202,7 @@
       V8ObjectBuilder(script_state).AddString("width", "0px").GetScriptValue()};
 
   ScriptValue js_keyframes(
-      script_state,
+      scope.GetIsolate(),
       ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
 
   KeyframeEffect* effect = CreateAnimationFromOption(
@@ -351,7 +351,7 @@
       V8ObjectBuilder(script_state).AddString("width", "10px").GetScriptValue(),
       V8ObjectBuilder(script_state).AddString("width", "0px").GetScriptValue()};
   ScriptValue new_js_keyframes(
-      script_state,
+      scope.GetIsolate(),
       ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
   effect->setKeyframes(script_state, new_js_keyframes, exception_state);
   ASSERT_FALSE(exception_state.HadException());
diff --git a/third_party/blink/renderer/core/animation/timing.cc b/third_party/blink/renderer/core/animation/timing.cc
index 6f6032a..63c25d4a 100644
--- a/third_party/blink/renderer/core/animation/timing.cc
+++ b/third_party/blink/renderer/core/animation/timing.cc
@@ -155,12 +155,13 @@
 Timing::CalculatedTiming Timing::CalculateTimings(
     double local_time,
     AnimationDirection animation_direction,
-    bool is_keyframe_effect) const {
+    bool is_keyframe_effect,
+    base::Optional<double> playback_rate) const {
   const double active_duration = ActiveDuration();
 
   const Timing::Phase current_phase =
       CalculatePhase(active_duration, local_time, animation_direction, *this);
-  const base::Optional<double> active_time =
+  const base::Optional<AnimationTimeDelta> active_time =
       CalculateActiveTime(active_duration, ResolvedFillMode(is_keyframe_effect),
                           local_time, current_phase, *this);
 
@@ -204,7 +205,7 @@
       DCHECK(active_time);
       time_to_next_iteration =
           iteration_duration - iteration_time->InSecondsF();
-      if (active_duration - active_time.value() < time_to_next_iteration)
+      if (active_duration - active_time->InSecondsF() < time_to_next_iteration)
         time_to_next_iteration = std::numeric_limits<double>::infinity();
     }
   }
@@ -219,8 +220,10 @@
   DCHECK(!calculated.is_in_effect ||
          (current_iteration.has_value() && progress.has_value()));
   calculated.is_in_play = calculated.phase == Timing::kPhaseActive;
-  calculated.is_current =
-      calculated.phase == Timing::kPhaseBefore || calculated.is_in_play;
+  // https://drafts.csswg.org/web-animations-1/#current
+  calculated.is_current = calculated.is_in_play ||
+                          (playback_rate.has_value() && playback_rate > 0 &&
+                           calculated.phase == Timing::kPhaseBefore);
   calculated.local_time = local_time;
   calculated.time_to_next_iteration = time_to_next_iteration;
 
diff --git a/third_party/blink/renderer/core/animation/timing.h b/third_party/blink/renderer/core/animation/timing.h
index 6b693eb..0dafc87 100644
--- a/third_party/blink/renderer/core/animation/timing.h
+++ b/third_party/blink/renderer/core/animation/timing.h
@@ -150,7 +150,8 @@
 
   CalculatedTiming CalculateTimings(double local_time,
                                     AnimationDirection animation_direction,
-                                    bool is_keyframe_effect) const;
+                                    bool is_keyframe_effect,
+                                    base::Optional<double> playback_rate) const;
   ComputedEffectTiming* getComputedTiming(const CalculatedTiming& calculated,
                                           bool is_keyframe_effect) const;
 };
diff --git a/third_party/blink/renderer/core/animation/timing_calculations.h b/third_party/blink/renderer/core/animation/timing_calculations.h
index 6e94f52b..d43104d 100644
--- a/third_party/blink/renderer/core/animation/timing_calculations.h
+++ b/third_party/blink/renderer/core/animation/timing_calculations.h
@@ -94,7 +94,7 @@
 }
 
 // https://drafts.csswg.org/web-animations/#calculating-the-active-time
-static inline base::Optional<double> CalculateActiveTime(
+static inline base::Optional<AnimationTimeDelta> CalculateActiveTime(
     double active_duration,
     Timing::FillMode fill_mode,
     double local_time,
@@ -105,16 +105,20 @@
   switch (phase) {
     case Timing::kPhaseBefore:
       if (fill_mode == Timing::FillMode::BACKWARDS ||
-          fill_mode == Timing::FillMode::BOTH)
-        return std::max(local_time - specified.start_delay, 0.0);
+          fill_mode == Timing::FillMode::BOTH) {
+        return AnimationTimeDelta::FromSecondsD(
+            std::max(local_time - specified.start_delay, 0.0));
+      }
       return base::nullopt;
     case Timing::kPhaseActive:
-      return local_time - specified.start_delay;
+      return AnimationTimeDelta::FromSecondsD(local_time -
+                                              specified.start_delay);
     case Timing::kPhaseAfter:
       if (fill_mode == Timing::FillMode::FORWARDS ||
           fill_mode == Timing::FillMode::BOTH) {
-        return std::max(
-            0.0, std::min(active_duration, local_time - specified.start_delay));
+        return AnimationTimeDelta::FromSecondsD(std::max(
+            0.0,
+            std::min(active_duration, local_time - specified.start_delay)));
       }
       return base::nullopt;
     case Timing::kPhaseNone:
@@ -131,7 +135,7 @@
 // https://drafts.csswg.org/web-animations/#calculating-the-overall-progress
 static inline base::Optional<double> CalculateOverallProgress(
     Timing::Phase phase,
-    base::Optional<double> active_time,
+    base::Optional<AnimationTimeDelta> active_time,
     double iteration_duration,
     double iteration_count,
     double iteration_start) {
@@ -145,7 +149,7 @@
     if (phase != Timing::kPhaseBefore)
       overall_progress = iteration_count;
   } else {
-    overall_progress = active_time.value() / iteration_duration;
+    overall_progress = active_time->InSecondsF() / iteration_duration;
   }
 
   return overall_progress + iteration_start;
@@ -161,7 +165,7 @@
     Timing::Phase phase,
     base::Optional<double> overall_progress,
     double iteration_start,
-    base::Optional<double> active_time,
+    base::Optional<AnimationTimeDelta> active_time,
     double active_duration,
     double iteration_count) {
   // 1. If the overall progress is unresolved, return unresolved.
@@ -187,7 +191,7 @@
   // let the simple iteration progress be 1.0.
   if (IsWithinEpsilon(simple_iteration_progress, 0.0) &&
       (phase == Timing::kPhaseActive || phase == Timing::kPhaseAfter) &&
-      IsWithinEpsilon(active_time.value(), active_duration) &&
+      IsWithinEpsilon(active_time->InSecondsF(), active_duration) &&
       !IsWithinEpsilon(iteration_count, 0.0)) {
     simple_iteration_progress = 1.0;
   }
@@ -199,7 +203,7 @@
 // https://drafts.csswg.org/web-animations/#calculating-the-current-iteration
 static inline base::Optional<double> CalculateCurrentIteration(
     Timing::Phase phase,
-    base::Optional<double> active_time,
+    base::Optional<AnimationTimeDelta> active_time,
     double iteration_count,
     base::Optional<double> overall_progress,
     base::Optional<double> simple_iteration_progress) {
@@ -316,7 +320,7 @@
 // iteration to optimize scheduling.
 static inline base::Optional<AnimationTimeDelta> CalculateOffsetActiveTime(
     double active_duration,
-    base::Optional<double> active_time,
+    base::Optional<AnimationTimeDelta> active_time,
     double start_offset) {
   DCHECK_GE(active_duration, 0);
   DCHECK_GE(start_offset, 0);
@@ -324,13 +328,14 @@
   if (!active_time)
     return base::nullopt;
 
-  DCHECK(active_time.value() >= 0 &&
-         LessThanOrEqualToWithinEpsilon(active_time.value(), active_duration));
+  DCHECK(active_time.value() >= AnimationTimeDelta() &&
+         LessThanOrEqualToWithinEpsilon(active_time->InSecondsF(),
+                                        active_duration));
 
-  if (!std::isfinite(active_time.value()))
+  if (active_time->is_max())
     return AnimationTimeDelta::Max();
 
-  return AnimationTimeDelta::FromSecondsD(active_time.value() + start_offset);
+  return active_time.value() + AnimationTimeDelta::FromSecondsD(start_offset);
 }
 
 // Maps the offset active time into 'iteration time space'[0], aka the offset
diff --git a/third_party/blink/renderer/core/animation/timing_calculations_test.cc b/third_party/blink/renderer/core/animation/timing_calculations_test.cc
index 32f7a91..71657a06 100644
--- a/third_party/blink/renderer/core/animation/timing_calculations_test.cc
+++ b/third_party/blink/renderer/core/animation/timing_calculations_test.cc
@@ -47,25 +47,31 @@
                                    Timing::kPhaseBefore, timing));
   EXPECT_FALSE(CalculateActiveTime(20, Timing::FillMode::NONE, 0,
                                    Timing::kPhaseBefore, timing));
-  EXPECT_EQ(0, CalculateActiveTime(20, Timing::FillMode::BACKWARDS, 0,
-                                   Timing::kPhaseBefore, timing));
-  EXPECT_EQ(0, CalculateActiveTime(20, Timing::FillMode::BOTH, 0,
-                                   Timing::kPhaseBefore, timing));
+  EXPECT_EQ(AnimationTimeDelta(),
+            CalculateActiveTime(20, Timing::FillMode::BACKWARDS, 0,
+                                Timing::kPhaseBefore, timing));
+  EXPECT_EQ(AnimationTimeDelta(),
+            CalculateActiveTime(20, Timing::FillMode::BOTH, 0,
+                                Timing::kPhaseBefore, timing));
   timing.start_delay = -10;
-  EXPECT_EQ(5, CalculateActiveTime(20, Timing::FillMode::BACKWARDS, -5,
-                                   Timing::kPhaseBefore, timing));
+  EXPECT_EQ(AnimationTimeDelta::FromSecondsD(5),
+            CalculateActiveTime(20, Timing::FillMode::BACKWARDS, -5,
+                                Timing::kPhaseBefore, timing));
 
   // Active Phase
   timing.start_delay = 10;
-  EXPECT_EQ(5, CalculateActiveTime(20, Timing::FillMode::FORWARDS, 15,
-                                   Timing::kPhaseActive, timing));
+  EXPECT_EQ(AnimationTimeDelta::FromSecondsD(5),
+            CalculateActiveTime(20, Timing::FillMode::FORWARDS, 15,
+                                Timing::kPhaseActive, timing));
 
   // After Phase
   timing.start_delay = 10;
-  EXPECT_EQ(21, CalculateActiveTime(21, Timing::FillMode::FORWARDS, 45,
-                                    Timing::kPhaseAfter, timing));
-  EXPECT_EQ(21, CalculateActiveTime(21, Timing::FillMode::BOTH, 45,
-                                    Timing::kPhaseAfter, timing));
+  EXPECT_EQ(AnimationTimeDelta::FromSecondsD(21),
+            CalculateActiveTime(21, Timing::FillMode::FORWARDS, 45,
+                                Timing::kPhaseAfter, timing));
+  EXPECT_EQ(AnimationTimeDelta::FromSecondsD(21),
+            CalculateActiveTime(21, Timing::FillMode::BOTH, 45,
+                                Timing::kPhaseAfter, timing));
   EXPECT_FALSE(CalculateActiveTime(21, Timing::FillMode::BACKWARDS, 45,
                                    Timing::kPhaseAfter, timing));
   EXPECT_FALSE(CalculateActiveTime(21, Timing::FillMode::NONE, 45,
@@ -81,20 +87,20 @@
   EXPECT_FALSE(CalculateOffsetActiveTime(4, base::nullopt, 5));
 
   // normal case
-  EXPECT_EQ(AnimationTimeDelta::FromSecondsD(15),
-            CalculateOffsetActiveTime(40, 10, 5));
+  EXPECT_EQ(
+      AnimationTimeDelta::FromSecondsD(15),
+      CalculateOffsetActiveTime(40, AnimationTimeDelta::FromSecondsD(10), 5));
 
-  // infinte activeTime
+  // infinite activeTime
   EXPECT_TRUE(CalculateOffsetActiveTime(std::numeric_limits<double>::infinity(),
-                                        std::numeric_limits<double>::infinity(),
-                                        0)
+                                        AnimationTimeDelta::Max(), 0)
                   ->is_max());
 
   // Edge case for active_time being within epsilon of active_duration.
   // https://crbug.com/962138
-  const double active_time = 1.3435713716800004;
+  auto active_time = AnimationTimeDelta::FromSecondsD(1.3435713716800004);
   const double active_duration = 1.3435713716800002;
-  EXPECT_EQ(AnimationTimeDelta::FromSecondsD(active_time),
+  EXPECT_EQ(active_time,
             CalculateOffsetActiveTime(active_duration, active_time, 0));
 }
 
@@ -154,31 +160,35 @@
                                         /*iteration_start=*/1.0));
 
   // If iteration duration is zero, calculate progress based on iteration count.
-  EXPECT_EQ(3, CalculateOverallProgress(Timing::kPhaseActive,
-                                        /*active_time=*/3.0,
-                                        /*iteration_duration=*/0.0,
-                                        /*iteration_count=*/3.0,
-                                        /*iteration_start=*/0.0));
+  EXPECT_EQ(3, CalculateOverallProgress(
+                   Timing::kPhaseActive,
+                   /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+                   /*iteration_duration=*/0.0,
+                   /*iteration_count=*/3.0,
+                   /*iteration_start=*/0.0));
   // ...unless in before phase, in which case progress is zero.
-  EXPECT_EQ(0, CalculateOverallProgress(Timing::kPhaseBefore,
-                                        /*active_time=*/3.0,
-                                        /*iteration_duration=*/0.0,
-                                        /*iteration_count=*/3.0,
-                                        /*iteration_start=*/0.0));
+  EXPECT_EQ(0, CalculateOverallProgress(
+                   Timing::kPhaseBefore,
+                   /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+                   /*iteration_duration=*/0.0,
+                   /*iteration_count=*/3.0,
+                   /*iteration_start=*/0.0));
   // Edge case for duration being within Epsilon of zero.
   // crbug.com/954558
-  EXPECT_EQ(1, CalculateOverallProgress(Timing::kPhaseActive,
-                                        /*active_time=*/3.0,
-                                        /*iteration_duration=*/1e-18,
-                                        /*iteration_count=*/1.0,
-                                        /*iteration_start=*/0.0));
+  EXPECT_EQ(1, CalculateOverallProgress(
+                   Timing::kPhaseActive,
+                   /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+                   /*iteration_duration=*/1e-18,
+                   /*iteration_count=*/1.0,
+                   /*iteration_start=*/0.0));
 
   // Otherwise.
-  EXPECT_EQ(3.0, CalculateOverallProgress(Timing::kPhaseAfter,
-                                          /*active_time=*/2.5,
-                                          /*iteration_duration=*/1.0,
-                                          /*iteration_count=*/0.0,
-                                          /*iteration_start=*/0.5));
+  EXPECT_EQ(3.0, CalculateOverallProgress(
+                     Timing::kPhaseAfter,
+                     /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5),
+                     /*iteration_duration=*/1.0,
+                     /*iteration_count=*/0.0,
+                     /*iteration_start=*/0.5));
 }
 
 TEST(AnimationTimingCalculationsTest, CalculateSimpleIterationProgress) {
@@ -193,28 +203,31 @@
 
   // If the overall progress is infinite.
   const double inf = std::numeric_limits<double>::infinity();
-  EXPECT_EQ(0.5, CalculateSimpleIterationProgress(Timing::kPhaseAfter,
-                                                  /*overall_progress=*/inf,
-                                                  /*iteration_start=*/1.5,
-                                                  /*active_time=*/0.0,
-                                                  /*active_duration=*/0.0,
-                                                  /*iteration_count=*/inf));
+  EXPECT_EQ(0.5, CalculateSimpleIterationProgress(
+                     Timing::kPhaseAfter,
+                     /*overall_progress=*/inf,
+                     /*iteration_start=*/1.5,
+                     /*active_time=*/AnimationTimeDelta(),
+                     /*active_duration=*/0.0,
+                     /*iteration_count=*/inf));
 
   // Precisely on an iteration boundary.
-  EXPECT_EQ(1.0, CalculateSimpleIterationProgress(Timing::kPhaseAfter,
-                                                  /*overall_progress=*/3.0,
-                                                  /*iteration_start=*/0.0,
-                                                  /*active_time=*/3.0,
-                                                  /*active_duration=*/3.0,
-                                                  /*iteration_count=*/3.0));
+  EXPECT_EQ(1.0, CalculateSimpleIterationProgress(
+                     Timing::kPhaseAfter,
+                     /*overall_progress=*/3.0,
+                     /*iteration_start=*/0.0,
+                     /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+                     /*active_duration=*/3.0,
+                     /*iteration_count=*/3.0));
 
   // Otherwise.
-  EXPECT_EQ(0.5, CalculateSimpleIterationProgress(Timing::kPhaseAfter,
-                                                  /*overall_progress=*/2.5,
-                                                  /*iteration_start=*/0.0,
-                                                  /*active_time=*/2.5,
-                                                  /*active_duration=*/0.0,
-                                                  /*iteration_count=*/0.0));
+  EXPECT_EQ(0.5, CalculateSimpleIterationProgress(
+                     Timing::kPhaseAfter,
+                     /*overall_progress=*/2.5,
+                     /*iteration_start=*/0.0,
+                     /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5),
+                     /*active_duration=*/0.0,
+                     /*iteration_count=*/0.0));
 }
 
 TEST(AnimationTimingCalculationsTest, CurrentIteration) {
@@ -227,34 +240,37 @@
 
   // If the iteration count is infinite.
   const double inf = std::numeric_limits<double>::infinity();
-  EXPECT_EQ(inf, CalculateCurrentIteration(Timing::kPhaseAfter,
-                                           /*active_time=*/1.0,
-                                           /*iteration_count=*/inf,
-                                           /*overall_progress=*/inf,
-                                           /*simple_iteration_progress=*/0.0));
+  EXPECT_EQ(inf, CalculateCurrentIteration(
+                     Timing::kPhaseAfter,
+                     /*active_time=*/AnimationTimeDelta::FromSecondsD(1.0),
+                     /*iteration_count=*/inf,
+                     /*overall_progress=*/inf,
+                     /*simple_iteration_progress=*/0.0));
 
   // Hold the endpoint of the final iteration of ending precisely on an
   // iteration boundary.
-  EXPECT_EQ(2, CalculateCurrentIteration(Timing::kPhaseAfter,
-                                         /*active_time=*/3.0,
-                                         /*iteration_count=*/3.0,
-                                         /*overall_progress=*/3.0,
-                                         /*simple_iteration_progress=*/1.0));
+  EXPECT_EQ(2, CalculateCurrentIteration(
+                   Timing::kPhaseAfter,
+                   /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+                   /*iteration_count=*/3.0,
+                   /*overall_progress=*/3.0,
+                   /*simple_iteration_progress=*/1.0));
 
   // Edge case for zero-duration animation.
   // crbug.com/954558
   EXPECT_EQ(0, CalculateCurrentIteration(Timing::kPhaseAfter,
-                                         /*active_time=*/0.0,
+                                         /*active_time=*/AnimationTimeDelta(),
                                          /*iteration_count=*/1.0,
                                          /*overall_progress=*/0.0,
                                          /*simple_iteration_progress=*/1.0));
 
   // Otherwise.
-  EXPECT_EQ(2, CalculateCurrentIteration(Timing::kPhaseAfter,
-                                         /*active_time=*/2.5,
-                                         /*iteration_count=*/0.0,
-                                         /*overall_progress=*/2.5,
-                                         /*simple_iteration_progress=*/0.5));
+  EXPECT_EQ(2, CalculateCurrentIteration(
+                   Timing::kPhaseAfter,
+                   /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5),
+                   /*iteration_count=*/0.0,
+                   /*overall_progress=*/2.5,
+                   /*simple_iteration_progress=*/0.5));
 }
 
 TEST(AnimationTimingCalculationsTest, IsCurrentDirectionForwards) {
diff --git a/third_party/blink/renderer/core/css/css_image_generator_value.cc b/third_party/blink/renderer/core/css/css_image_generator_value.cc
index f876460..bee88075 100644
--- a/third_party/blink/renderer/core/css/css_image_generator_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_generator_value.cc
@@ -159,6 +159,13 @@
   return nullptr;
 }
 
+bool CSSImageGeneratorValue::IsUsingCustomProperty(
+    const AtomicString& custom_property_name) const {
+  if (GetClassType() == kPaintClass)
+    return To<CSSPaintValue>(this)->IsUsingCustomProperty(custom_property_name);
+  return false;
+}
+
 bool CSSImageGeneratorValue::IsFixedSize() const {
   switch (GetClassType()) {
     case kCrossfadeClass:
diff --git a/third_party/blink/renderer/core/css/css_image_generator_value.h b/third_party/blink/renderer/core/css/css_image_generator_value.h
index ca7d805b..5d00608a 100644
--- a/third_party/blink/renderer/core/css/css_image_generator_value.h
+++ b/third_party/blink/renderer/core/css/css_image_generator_value.h
@@ -105,6 +105,8 @@
   CSSImageGeneratorValue* ComputedCSSValue(const ComputedStyle&,
                                            bool allow_visited_style);
 
+  bool IsUsingCustomProperty(const AtomicString& custom_property_name) const;
+
   void TraceAfterDispatch(blink::Visitor* visitor) {
     CSSValue::TraceAfterDispatch(visitor);
   }
diff --git a/third_party/blink/renderer/core/css/css_image_set_value.cc b/third_party/blink/renderer/core/css/css_image_set_value.cc
index bbb39a7f..5e1fd09 100644
--- a/third_party/blink/renderer/core/css/css_image_set_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_set_value.cc
@@ -127,12 +127,6 @@
                                          cross_origin);
     }
 
-    if (document.GetFrame() &&
-        image_request_optimization == FetchParameters::kAllowPlaceholder &&
-        document.GetFrame()->IsClientLoFiAllowed(params.GetResourceRequest())) {
-      params.SetClientLoFiPlaceholder();
-    }
-
     cached_image_ = MakeGarbageCollected<StyleFetchedImageSet>(
         ImageResourceContent::Fetch(params, document.Fetcher()),
         image.scale_factor, this, params.Url());
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc
index f623e1f4..06f072c9 100644
--- a/third_party/blink/renderer/core/css/css_image_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_value.cc
@@ -80,11 +80,6 @@
                                          cross_origin);
     }
 
-    if (document.GetFrame() &&
-        image_request_optimization == FetchParameters::kAllowPlaceholder &&
-        document.GetFrame()->IsClientLoFiAllowed(params.GetResourceRequest())) {
-      params.SetClientLoFiPlaceholder();
-    }
     bool is_lazily_loaded =
         image_request_optimization == FetchParameters::kDeferImageLoad &&
         // Only http/https images are eligible to be lazily loaded.
diff --git a/third_party/blink/renderer/core/css/css_paint_value.cc b/third_party/blink/renderer/core/css/css_paint_value.cc
index d00c3af..9fbd44f 100644
--- a/third_party/blink/renderer/core/css/css_paint_value.cc
+++ b/third_party/blink/renderer/core/css/css_paint_value.cc
@@ -55,6 +55,21 @@
   return name_->Value();
 }
 
+bool CSSPaintValue::IsUsingCustomProperty(
+    const AtomicString& custom_property_name) const {
+  if (!generator_ || !generator_->IsImageGeneratorReady())
+    return false;
+  return generator_->CustomInvalidationProperties().Contains(
+      custom_property_name);
+}
+
+void CSSPaintValue::CreateGeneratorForTesting(const Document& document) {
+  if (!generator_) {
+    generator_ = CSSPaintImageGenerator::Create(
+        GetName(), document, paint_image_generator_observer_);
+  }
+}
+
 scoped_refptr<Image> CSSPaintValue::GetImage(
     const ImageResourceObserver& client,
     const Document& document,
diff --git a/third_party/blink/renderer/core/css/css_paint_value.h b/third_party/blink/renderer/core/css/css_paint_value.h
index 8c4ce29..36275b0c 100644
--- a/third_party/blink/renderer/core/css/css_paint_value.h
+++ b/third_party/blink/renderer/core/css/css_paint_value.h
@@ -64,6 +64,10 @@
     return this;
   }
 
+  bool IsUsingCustomProperty(const AtomicString& custom_property_name) const;
+
+  void CreateGeneratorForTesting(const Document& document);
+
   void TraceAfterDispatch(blink::Visitor*);
 
  private:
diff --git a/third_party/blink/renderer/core/css/css_paint_value_test.cc b/third_party/blink/renderer/core/css/css_paint_value_test.cc
index b5f3102..108255b 100644
--- a/third_party/blink/renderer/core/css/css_paint_value_test.cc
+++ b/third_party/blink/renderer/core/css/css_paint_value_test.cc
@@ -10,6 +10,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
 #include "third_party/blink/renderer/core/css/css_syntax_definition.h"
+#include "third_party/blink/renderer/core/css/mock_css_paint_image_generator.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
@@ -55,41 +56,6 @@
                                 kCSSPaintAPIArguments |
                                     kOffMainThreadCSSPaint));
 
-class MockCSSPaintImageGenerator : public CSSPaintImageGenerator {
- public:
-  MockCSSPaintImageGenerator() {
-    // These methods return references, so setup a default ON_CALL to make them
-    // easier to use. They can be overridden by a specific test if desired.
-    ON_CALL(*this, NativeInvalidationProperties())
-        .WillByDefault(ReturnRef(native_properties_));
-    ON_CALL(*this, CustomInvalidationProperties())
-        .WillByDefault(ReturnRef(custom_properties_));
-    ON_CALL(*this, InputArgumentTypes())
-        .WillByDefault(ReturnRef(input_argument_types_));
-  }
-
-  MOCK_METHOD4(Paint,
-               scoped_refptr<Image>(const ImageResourceObserver&,
-                                    const FloatSize& container_size,
-                                    const CSSStyleValueVector*,
-                                    float device_scale_factor));
-  MOCK_CONST_METHOD0(NativeInvalidationProperties, Vector<CSSPropertyID>&());
-  MOCK_CONST_METHOD0(CustomInvalidationProperties, Vector<AtomicString>&());
-  MOCK_CONST_METHOD0(HasAlpha, bool());
-  MOCK_CONST_METHOD0(InputArgumentTypes, Vector<CSSSyntaxDefinition>&());
-  MOCK_CONST_METHOD0(IsImageGeneratorReady, bool());
-  MOCK_CONST_METHOD0(WorkletId, int());
-
-  void AddNativeProperty() {
-    native_properties_.push_back(CSSPropertyID::kBorderImageSource);
-  }
-
- private:
-  Vector<CSSPropertyID> native_properties_;
-  Vector<AtomicString> custom_properties_;
-  Vector<CSSSyntaxDefinition> input_argument_types_;
-};
-
 // CSSPaintImageGenerator requires that CSSPaintImageGeneratorCreateFunction be
 // a static method. As such, it cannot access a class member and so instead we
 // store a pointer to the overriding generator globally.
diff --git a/third_party/blink/renderer/core/css/mock_css_paint_image_generator.h b/third_party/blink/renderer/core/css/mock_css_paint_image_generator.h
new file mode 100644
index 0000000..c0c16ad
--- /dev/null
+++ b/third_party/blink/renderer/core/css/mock_css_paint_image_generator.h
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MOCK_CSS_PAINT_IMAGE_GENERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MOCK_CSS_PAINT_IMAGE_GENERATOR_H_
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/css_paint_image_generator.h"
+
+using testing::ReturnRef;
+
+namespace blink {
+
+class MockCSSPaintImageGenerator : public CSSPaintImageGenerator {
+ public:
+  MockCSSPaintImageGenerator() {
+    // These methods return references, so setup a default ON_CALL to make them
+    // easier to use. They can be overridden by a specific test if desired.
+    ON_CALL(*this, NativeInvalidationProperties())
+        .WillByDefault(ReturnRef(native_properties_));
+    ON_CALL(*this, CustomInvalidationProperties())
+        .WillByDefault(ReturnRef(custom_properties_));
+    ON_CALL(*this, InputArgumentTypes())
+        .WillByDefault(ReturnRef(input_argument_types_));
+  }
+
+  MOCK_METHOD4(Paint,
+               scoped_refptr<Image>(const ImageResourceObserver&,
+                                    const FloatSize& container_size,
+                                    const CSSStyleValueVector*,
+                                    float device_scale_factor));
+  MOCK_CONST_METHOD0(NativeInvalidationProperties, Vector<CSSPropertyID>&());
+  MOCK_CONST_METHOD0(CustomInvalidationProperties, Vector<AtomicString>&());
+  MOCK_CONST_METHOD0(HasAlpha, bool());
+  MOCK_CONST_METHOD0(InputArgumentTypes, Vector<CSSSyntaxDefinition>&());
+  MOCK_CONST_METHOD0(IsImageGeneratorReady, bool());
+  MOCK_CONST_METHOD0(WorkletId, int());
+
+  void AddCustomProperty(const AtomicString& custom_property) {
+    custom_properties_.push_back(custom_property);
+  }
+  void AddNativeProperty() {
+    native_properties_.push_back(CSSPropertyID::kBorderImageSource);
+  }
+
+ private:
+  Vector<CSSPropertyID> native_properties_;
+  Vector<AtomicString> custom_properties_;
+  Vector<CSSSyntaxDefinition> input_argument_types_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MOCK_CSS_PAINT_IMAGE_GENERATOR_H_
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
index 2b9319f..322d2b4 100644
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -39,10 +39,11 @@
 #include "third_party/blink/renderer/core/layout/layout_block.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/layout/layout_grid.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
 #include "third_party/blink/renderer/core/style/style_svg_resource.h"
 #include "third_party/blink/renderer/core/style_property_shorthand.h"
-#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/core/svg_element_type_helpers.h"
 
 namespace blink {
 
@@ -1697,7 +1698,7 @@
     const LayoutObject& layout_object,
     UsePixelSnappedBox pixel_snap_box) {
   if (layout_object.IsSVGChild())
-    return ComputeSVGTransformReferenceBox(layout_object);
+    return TransformHelper::ComputeReferenceBox(layout_object);
   if (layout_object.IsBox()) {
     const auto& layout_box = ToLayoutBox(layout_object);
     if (pixel_snap_box == kUsePixelSnappedBox)
diff --git a/third_party/blink/renderer/core/dom/events/custom_event.cc b/third_party/blink/renderer/core/dom/events/custom_event.cc
index be37dfd3..447a53e 100644
--- a/third_party/blink/renderer/core/dom/events/custom_event.cc
+++ b/third_party/blink/renderer/core/dom/events/custom_event.cc
@@ -56,8 +56,8 @@
 ScriptValue CustomEvent::detail(ScriptState* script_state) const {
   v8::Isolate* isolate = script_state->GetIsolate();
   if (detail_.IsEmpty())
-    return ScriptValue(script_state, v8::Null(isolate));
-  return ScriptValue(script_state, detail_.GetAcrossWorld(script_state));
+    return ScriptValue(isolate, v8::Null(isolate));
+  return ScriptValue(isolate, detail_.GetAcrossWorld(script_state));
 }
 
 const AtomicString& CustomEvent::InterfaceName() const {
diff --git a/third_party/blink/renderer/core/dom/events/event.cc b/third_party/blink/renderer/core/dom/events/event.cc
index 543ae51..89fa303 100644
--- a/third_party/blink/renderer/core/dom/events/event.cc
+++ b/third_party/blink/renderer/core/dom/events/event.cc
@@ -301,7 +301,7 @@
 
 ScriptValue Event::path(ScriptState* script_state) const {
   return ScriptValue(
-      script_state,
+      script_state->GetIsolate(),
       ToV8(PathInternal(script_state, kNonEmptyAfterDispatch), script_state));
 }
 
diff --git a/third_party/blink/renderer/core/events/error_event.cc b/third_party/blink/renderer/core/events/error_event.cc
index eb1f2e7..d0a80df 100644
--- a/third_party/blink/renderer/core/events/error_event.cc
+++ b/third_party/blink/renderer/core/events/error_event.cc
@@ -110,7 +110,7 @@
   // 2) Errors cannot be cloned (or serialized):
   if (World() != &script_state->World() || error_.IsEmpty())
     return ScriptValue::CreateNull(script_state->GetIsolate());
-  return ScriptValue(script_state, error_.Get(script_state));
+  return ScriptValue(script_state->GetIsolate(), error_.Get(script_state));
 }
 
 void ErrorEvent::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/events/message_event.cc b/third_party/blink/renderer/core/events/message_event.cc
index fc2e77b1..30a2bf6 100644
--- a/third_party/blink/renderer/core/events/message_event.cc
+++ b/third_party/blink/renderer/core/events/message_event.cc
@@ -302,7 +302,7 @@
       break;
   }
 
-  return ScriptValue(script_state, value);
+  return ScriptValue(isolate, value);
 }
 
 const AtomicString& MessageEvent::InterfaceName() const {
diff --git a/third_party/blink/renderer/core/events/pop_state_event.cc b/third_party/blink/renderer/core/events/pop_state_event.cc
index 1db86c7..7e917d7 100644
--- a/third_party/blink/renderer/core/events/pop_state_event.cc
+++ b/third_party/blink/renderer/core/events/pop_state_event.cc
@@ -64,9 +64,9 @@
     v8::Local<v8::Value> value = state_.NewLocal(isolate);
     scoped_refptr<SerializedScriptValue> serialized =
         SerializedScriptValue::SerializeAndSwallowExceptions(isolate, value);
-    return ScriptValue(script_state, serialized->Deserialize(isolate));
+    return ScriptValue(isolate, serialized->Deserialize(isolate));
   }
-  return ScriptValue(script_state, state_.NewLocal(isolate));
+  return ScriptValue(isolate, state_.NewLocal(isolate));
 }
 
 PopStateEvent* PopStateEvent::Create() {
diff --git a/third_party/blink/renderer/core/events/promise_rejection_event.cc b/third_party/blink/renderer/core/events/promise_rejection_event.cc
index d74b3c6..44f1173 100644
--- a/third_party/blink/renderer/core/events/promise_rejection_event.cc
+++ b/third_party/blink/renderer/core/events/promise_rejection_event.cc
@@ -36,9 +36,11 @@
 ScriptValue PromiseRejectionEvent::reason(ScriptState* script_state) const {
   // Return undefined when the value is accessed by a different world than the
   // world that created the value.
-  if (reason_.IsEmpty() || !CanBeDispatchedInWorld(script_state->World()))
-    return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
-  return ScriptValue(script_state,
+  if (reason_.IsEmpty() || !CanBeDispatchedInWorld(script_state->World())) {
+    return ScriptValue(script_state->GetIsolate(),
+                       v8::Undefined(script_state->GetIsolate()));
+  }
+  return ScriptValue(script_state->GetIsolate(),
                      reason_.NewLocal(script_state->GetIsolate()));
 }
 
diff --git a/third_party/blink/renderer/core/fetch/body.cc b/third_party/blink/renderer/core/fetch/body.cc
index e6031d03..8bc79a6 100644
--- a/third_party/blink/renderer/core/fetch/body.cc
+++ b/third_party/blink/renderer/core/fetch/body.cc
@@ -145,9 +145,10 @@
     v8::Local<v8::Value> parsed;
     if (v8::JSON::Parse(Resolver()->GetScriptState()->GetContext(),
                         input_string)
-            .ToLocal(&parsed))
-      ResolveLater(ScriptValue(Resolver()->GetScriptState(), parsed));
-    else
+            .ToLocal(&parsed)) {
+      ResolveLater(
+          ScriptValue(Resolver()->GetScriptState()->GetIsolate(), parsed));
+    } else
       Resolver()->Reject(trycatch.Exception());
   }
   DISALLOW_COPY_AND_ASSIGN(BodyJsonConsumer);
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc b/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
index 1ef31be4..0157f55 100644
--- a/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
+++ b/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
@@ -155,10 +155,10 @@
       scope.GetScriptState(), underlying_source, 0);
   ASSERT_TRUE(stream);
 
-  underlying_source->Enqueue(ScriptValue(scope.GetScriptState(),
-                                         ToV8(chunk1, scope.GetScriptState())));
-  underlying_source->Enqueue(ScriptValue(scope.GetScriptState(),
-                                         ToV8(chunk2, scope.GetScriptState())));
+  underlying_source->Enqueue(
+      ScriptValue(scope.GetIsolate(), ToV8(chunk1, scope.GetScriptState())));
+  underlying_source->Enqueue(
+      ScriptValue(scope.GetIsolate(), ToV8(chunk2, scope.GetScriptState())));
   underlying_source->Close();
 
   Checkpoint checkpoint;
@@ -548,8 +548,8 @@
 
   BodyStreamBuffer* buffer = MakeGarbageCollected<BodyStreamBuffer>(
       scope.GetScriptState(), consumer, nullptr);
-  ScriptValue reason(scope.GetScriptState(),
-                     V8String(scope.GetScriptState()->GetIsolate(), "reason"));
+  ScriptValue reason(scope.GetIsolate(),
+                     V8String(scope.GetIsolate(), "reason"));
   EXPECT_FALSE(consumer->IsCancelled());
   buffer->Cancel(scope.GetScriptState(), reason);
   EXPECT_TRUE(consumer->IsCancelled());
diff --git a/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc b/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
index 0b75bfb..1999d69 100644
--- a/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
+++ b/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
@@ -105,8 +105,8 @@
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
   auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
       script_state, underlying_source, 0);
-  underlying_source->Error(
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+  underlying_source->Error(ScriptValue(
+      script_state->GetIsolate(), v8::Undefined(script_state->GetIsolate())));
 
   Persistent<BytesConsumer> consumer =
       MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream,
@@ -157,11 +157,11 @@
     chunk3->Data()[2] = 0x49;
     chunk3->Data()[3] = 0x4a;
     underlying_source->Enqueue(
-        ScriptValue(script_state, ToV8(chunk1, script_state)));
+        ScriptValue(script_state->GetIsolate(), ToV8(chunk1, script_state)));
     underlying_source->Enqueue(
-        ScriptValue(script_state, ToV8(chunk2, script_state)));
+        ScriptValue(script_state->GetIsolate(), ToV8(chunk2, script_state)));
     underlying_source->Enqueue(
-        ScriptValue(script_state, ToV8(chunk3, script_state)));
+        ScriptValue(script_state->GetIsolate(), ToV8(chunk3, script_state)));
     underlying_source->Close();
   }
 
@@ -253,8 +253,8 @@
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
   auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
       script_state, underlying_source, 0);
-  underlying_source->Enqueue(
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+  underlying_source->Enqueue(ScriptValue(
+      script_state->GetIsolate(), v8::Undefined(script_state->GetIsolate())));
   underlying_source->Close();
 
   Persistent<BytesConsumer> consumer =
@@ -293,8 +293,8 @@
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
   auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
       script_state, underlying_source, 0);
-  underlying_source->Enqueue(
-      ScriptValue(script_state, v8::Null(script_state->GetIsolate())));
+  underlying_source->Enqueue(ScriptValue(script_state->GetIsolate(),
+                                         v8::Null(script_state->GetIsolate())));
   underlying_source->Close();
 
   Persistent<BytesConsumer> consumer =
@@ -334,7 +334,8 @@
   auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
       script_state, underlying_source, 0);
   underlying_source->Enqueue(
-      ScriptValue(script_state, V8String(script_state->GetIsolate(), "hello")));
+      ScriptValue(script_state->GetIsolate(),
+                  V8String(script_state->GetIsolate(), "hello")));
   underlying_source->Close();
 
   Persistent<BytesConsumer> consumer =
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index af0db8b9..5e8ec60 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -141,18 +141,6 @@
   return parent_local_frame ? parent_local_frame->TextZoomFactor() : 1;
 }
 
-bool ShouldUseClientLoFiForRequest(
-    const ResourceRequest& request,
-    WebURLRequest::PreviewsState frame_previews_state) {
-  if (request.GetPreviewsState() != WebURLRequest::kPreviewsUnspecified)
-    return request.GetPreviewsState() & WebURLRequest::kClientLoFiOn;
-
-  if (!(frame_previews_state & WebURLRequest::kClientLoFiOn))
-    return false;
-
-  return true;
-}
-
 }  // namespace
 
 template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>;
@@ -1289,11 +1277,6 @@
     context->Leave();
 }
 
-bool LocalFrame::IsClientLoFiAllowed(const ResourceRequest& request) const {
-  return Client() && ShouldUseClientLoFiForRequest(
-                         request, Client()->GetPreviewsStateForFrame());
-}
-
 LocalFrame::LazyLoadImageSetting LocalFrame::GetLazyLoadImageSetting() const {
   DCHECK(GetSettings());
   if (!RuntimeEnabledFeatures::LazyImageLoadingEnabled() ||
@@ -1456,8 +1439,7 @@
   WebURLRequest::PreviewsState previews_state =
       Client()->GetPreviewsStateForFrame();
   // Check for any data saving type of preview.
-  return previews_state &
-         (WebURLRequest::kClientLoFiOn | WebURLRequest::kNoScriptOn);
+  return previews_state & WebURLRequest::kNoScriptOn;
 }
 
 bool LocalFrame::IsAdSubframe() const {
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 3ae0936..c46222b 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -100,7 +100,6 @@
 class NodeTraversal;
 class PerformanceMonitor;
 class PluginData;
-class ResourceRequest;
 class ScriptController;
 class SmoothScrollSequencer;
 class SpellChecker;
@@ -323,9 +322,6 @@
   AdTracker* GetAdTracker() { return ad_tracker_; }
   void SetAdTrackerForTesting(AdTracker* ad_tracker);
 
-  // Returns true if Client Lo-Fi should be used for this request.
-  bool IsClientLoFiAllowed(const ResourceRequest&) const;
-
   enum class LazyLoadImageSetting {
     kDisabled,
     kEnabledExplicit,
diff --git a/third_party/blink/renderer/core/frame/local_frame_test.cc b/third_party/blink/renderer/core/frame/local_frame_test.cc
index 2d631832..f5fad34 100644
--- a/third_party/blink/renderer/core/frame/local_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_test.cc
@@ -17,12 +17,6 @@
 
 namespace {
 
-void MaybeAllowImagePlaceholder(DummyPageHolder* page_holder,
-                                FetchParameters& params) {
-  if (page_holder->GetFrame().IsClientLoFiAllowed(params.GetResourceRequest()))
-    params.SetClientLoFiPlaceholder();
-}
-
 void DisableLazyLoadAndDisableDataSaverHoldbackInSettings(Settings& settings) {
   settings.SetLazyLoadEnabled(false);
   settings.SetDataSaverHoldbackWebApi(false);
@@ -61,65 +55,10 @@
   }
 };
 
-TEST_F(LocalFrameTest, MaybeAllowPlaceholderImageUsesSpecifiedRequestValue) {
-  ResourceRequest request1;
-  request1.SetUrl(KURL("http://insecure.com"));
-  request1.SetPreviewsState(WebURLRequest::kClientLoFiOn);
-  FetchParameters params1(request1);
-  auto page_holder = std::make_unique<DummyPageHolder>(
-      IntSize(800, 600), nullptr,
-      MakeGarbageCollected<TestLocalFrameClient>(WebURLRequest::kPreviewsOff));
-  MaybeAllowImagePlaceholder(page_holder.get(), params1);
-  EXPECT_EQ(FetchParameters::kAllowPlaceholder,
-            params1.GetImageRequestOptimization());
-
-  ResourceRequest request2;
-  request2.SetUrl(KURL("https://secure.com"));
-  request2.SetPreviewsState(WebURLRequest::kPreviewsOff);
-  FetchParameters params2(request2);
-  auto page_holder2 = std::make_unique<DummyPageHolder>(
-      IntSize(800, 600), nullptr,
-      MakeGarbageCollected<TestLocalFrameClient>(WebURLRequest::kClientLoFiOn));
-  MaybeAllowImagePlaceholder(page_holder2.get(), params2);
-  EXPECT_EQ(FetchParameters::kNone, params2.GetImageRequestOptimization());
-}
-
-TEST_F(LocalFrameTest, MaybeAllowPlaceholderImageUsesFramePreviewsState) {
-  ResourceRequest request1;
-  request1.SetUrl(KURL("http://insecure.com"));
-  request1.SetPreviewsState(WebURLRequest::kPreviewsUnspecified);
-  FetchParameters params1(request1);
-  auto page_holder = std::make_unique<DummyPageHolder>(
-      IntSize(800, 600), nullptr,
-      MakeGarbageCollected<TestLocalFrameClient>(WebURLRequest::kClientLoFiOn));
-  MaybeAllowImagePlaceholder(page_holder.get(), params1);
-  EXPECT_EQ(FetchParameters::kAllowPlaceholder,
-            params1.GetImageRequestOptimization());
-  EXPECT_TRUE(page_holder->GetFrame().IsUsingDataSavingPreview());
-
-  ResourceRequest request2;
-  request2.SetUrl(KURL("http://insecure.com"));
-  request2.SetPreviewsState(WebURLRequest::kPreviewsUnspecified);
-  FetchParameters params2(request2);
-  auto page_holder2 = std::make_unique<DummyPageHolder>(
-      IntSize(800, 600), nullptr,
-      MakeGarbageCollected<TestLocalFrameClient>(
-          WebURLRequest::kServerLitePageOn));
-  MaybeAllowImagePlaceholder(page_holder2.get(), params2);
-  EXPECT_EQ(FetchParameters::kNone, params2.GetImageRequestOptimization());
-  EXPECT_FALSE(page_holder2->GetFrame().IsUsingDataSavingPreview());
-}
-
 TEST_F(LocalFrameTest, IsUsingDataSavingPreview) {
   EXPECT_TRUE(std::make_unique<DummyPageHolder>(
                   IntSize(800, 600), nullptr,
                   MakeGarbageCollected<TestLocalFrameClient>(
-                      WebURLRequest::kClientLoFiOn))
-                  ->GetFrame()
-                  .IsUsingDataSavingPreview());
-  EXPECT_TRUE(std::make_unique<DummyPageHolder>(
-                  IntSize(800, 600), nullptr,
-                  MakeGarbageCollected<TestLocalFrameClient>(
                       WebURLRequest::kNoScriptOn))
                   ->GetFrame()
                   .IsUsingDataSavingPreview());
diff --git a/third_party/blink/renderer/core/html/parser/preload_request.cc b/third_party/blink/renderer/core/html/parser/preload_request.cc
index f28f7f02..3e9be89 100644
--- a/third_party/blink/renderer/core/html/parser/preload_request.cc
+++ b/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -105,14 +105,8 @@
   }
 
   if (resource_type_ == ResourceType::kImage &&
-      params.Url().ProtocolIsInHTTPFamily()) {
-    if (const auto* frame = document->Loader()->GetFrame()) {
-      if (frame->IsClientLoFiAllowed(params.GetResourceRequest())) {
-        params.SetClientLoFiPlaceholder();
-      } else if (is_lazy_load_image_enabled_) {
-        params.SetLazyImagePlaceholder();
-      }
-    }
+      params.Url().ProtocolIsInHTTPFamily() && is_lazy_load_image_enabled_) {
+    params.SetLazyImagePlaceholder();
   }
 
   return PreloadHelper::StartPreload(resource_type_, params,
diff --git a/third_party/blink/renderer/core/html/portal/portal_activate_event.cc b/third_party/blink/renderer/core/html/portal/portal_activate_event.cc
index 1b442bd..0d5ebc3 100644
--- a/third_party/blink/renderer/core/html/portal/portal_activate_event.cc
+++ b/third_party/blink/renderer/core/html/portal/portal_activate_event.cc
@@ -80,7 +80,7 @@
   v8::Isolate* isolate = script_state->GetIsolate();
   v8::HandleScope handle_scope(isolate);
   if (!data_ && data_from_init_.IsEmpty())
-    return ScriptValue(script_state, v8::Null(isolate));
+    return ScriptValue(isolate, v8::Null(isolate));
 
   auto result =
       v8_data_.insert(script_state, TraceWrapperV8Reference<v8::Value>());
@@ -88,7 +88,7 @@
       result.stored_value->value;
 
   if (!result.is_new_entry)
-    return ScriptValue(script_state, relevant_data.NewLocal(isolate));
+    return ScriptValue(isolate, relevant_data.NewLocal(isolate));
 
   v8::Local<v8::Value> value;
   if (data_) {
@@ -101,7 +101,7 @@
   }
 
   relevant_data.Set(isolate, value);
-  return ScriptValue(script_state, value);
+  return ScriptValue(isolate, value);
 }
 
 void PortalActivateEvent::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/html/resources/controls_refresh.css b/third_party/blink/renderer/core/html/resources/controls_refresh.css
index 5982d59..2f2209e 100644
--- a/third_party/blink/renderer/core/html/resources/controls_refresh.css
+++ b/third_party/blink/renderer/core/html/resources/controls_refresh.css
@@ -75,29 +75,36 @@
   color: #c5c5c5;
 }
 
+meter::-webkit-meter-inner-element::before,
+meter::-webkit-meter-inner-element::after {
+  display: block;
+  content: "";
+  height: 25%;
+}
+
 meter::-webkit-meter-bar {
   background: #efefef;
   border-width: 1px;
+  height: 50%;
   border-style: solid;
-  border-color: #cecece;
-  border-radius: 2px;
+  border-color: rgba(118, 118, 118, 0.3);
+  border-radius: 20px;
   box-sizing: border-box;
-  padding: 1px;
 }
 
 meter::-webkit-meter-optimum-value {
   background: #107c10;
-  border-radius: 1px 0px 0px 1px;
+  border-radius: 20px 0px 0px 20px;
 }
 
 meter::-webkit-meter-suboptimum-value {
   background: #ffb900;
-  border-radius: 1px 0px 0px 1px;
+  border-radius: 20px 0px 0px 20px;
 }
 
 meter::-webkit-meter-even-less-good-value {
   background: #d83b01;
-  border-radius: 1px 0px 0px 1px;
+  border-radius: 20px 0px 0px 20px;
 }
 
 input[type="date" i]::-webkit-calendar-picker-indicator,
diff --git a/third_party/blink/renderer/core/html/resources/forced_colors.css b/third_party/blink/renderer/core/html/resources/forced_colors.css
index d60389d..1b4e582 100644
--- a/third_party/blink/renderer/core/html/resources/forced_colors.css
+++ b/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -178,21 +178,14 @@
     color: GrayText;
   }
 
-  progress::-webkit-progress-bar {
-    background: ButtonFace;
-  }
-
-  progress::-webkit-progress-value {
-    background: Highlight;
-  }
-
   meter::-webkit-meter-bar {
     background: ButtonFace;
+    border-color: WindowText;
   }
 
   meter::-webkit-meter-even-less-good-value,
   meter::-webkit-meter-optimum-value,
-  meter::-webkit-meter-suboptimal-value {
+  meter::-webkit-meter-suboptimum-value {
     background: Highlight;
   }
 }
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 13bad13..a3a6682 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -916,7 +916,7 @@
     sk_sp<SkImage> skia_image) {
   if (!skia_image) {
     resolver->Reject(
-        ScriptValue(resolver->GetScriptState(),
+        ScriptValue(resolver->GetScriptState()->GetIsolate(),
                     v8::Null(resolver->GetScriptState()->GetIsolate())));
     return;
   }
@@ -928,14 +928,14 @@
   }
   if (!image) {
     resolver->Reject(
-        ScriptValue(resolver->GetScriptState(),
+        ScriptValue(resolver->GetScriptState()->GetIsolate(),
                     v8::Null(resolver->GetScriptState()->GetIsolate())));
     return;
   }
   image = ApplyColorSpaceConversion(std::move(image), *(parsed_options.get()));
   if (!image) {
     resolver->Reject(
-        ScriptValue(resolver->GetScriptState(),
+        ScriptValue(resolver->GetScriptState()->GetIsolate(),
                     v8::Null(resolver->GetScriptState()->GetIsolate())));
     return;
   }
diff --git a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
index 3ff221a..ec4f27e6 100644
--- a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
+++ b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
@@ -45,8 +45,9 @@
   if (layout_worklet_world_v8_data_.IsEmpty())
     return ScriptValue::CreateNull(script_state->GetIsolate());
 
-  return ScriptValue(script_state, layout_worklet_world_v8_data_.NewLocal(
-                                       script_state->GetIsolate()));
+  return ScriptValue(
+      script_state->GetIsolate(),
+      layout_worklet_world_v8_data_.NewLocal(script_state->GetIsolate()));
 }
 
 void CustomLayoutConstraints::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
index ce90299..1019fd2 100644
--- a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
@@ -46,8 +46,9 @@
   if (layout_worklet_world_v8_data_.IsEmpty())
     return ScriptValue::CreateNull(script_state->GetIsolate());
 
-  return ScriptValue(script_state, layout_worklet_world_v8_data_.NewLocal(
-                                       script_state->GetIsolate()));
+  return ScriptValue(
+      script_state->GetIsolate(),
+      layout_worklet_world_v8_data_.NewLocal(script_state->GetIsolate()));
 }
 
 void CustomLayoutFragment::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index da53c25..a27b698 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -398,7 +398,10 @@
 }
 
 inline bool NeedsShaping(const NGInlineItem& item) {
-  return item.Type() == NGInlineItem::kText && !item.TextShapeResult();
+  return item.Type() == NGInlineItem::kText && !item.TextShapeResult() &&
+         // Text item with length==0 exists to maintain LayoutObject states such
+         // as ClearNeedsLayout, but not needed to shape.
+         item.Length();
 }
 
 // Determine if reshape is needed for ::first-line style.
@@ -1155,9 +1158,9 @@
     // If the text is from multiple items, split the ShapeResult to
     // corresponding items.
     DCHECK_GT(num_text_items, 0u);
-    std::unique_ptr<ShapeResult::ShapeRange[]> text_item_ranges =
-        std::make_unique<ShapeResult::ShapeRange[]>(num_text_items);
-    unsigned range_index = 0;
+    // "32" is heuristic, most major sites are up to 8 or so, wikipedia is 21.
+    Vector<ShapeResult::ShapeRange, 32> text_item_ranges;
+    text_item_ranges.ReserveInitialCapacity(num_text_items);
     for (; index < end_index; index++) {
       NGInlineItem& item = (*items)[index];
       if (item.Type() != NGInlineItem::kText || !item.Length())
@@ -1171,12 +1174,12 @@
       // item that has its first code unit keeps the glyph.
       scoped_refptr<ShapeResult> item_result =
           ShapeResult::CreateEmpty(*shape_result.get());
-      item.shape_result_ = item_result;
-      text_item_ranges[range_index++] = {item.StartOffset(), item.EndOffset(),
-                                         item_result.get()};
+      text_item_ranges.emplace_back(item.StartOffset(), item.EndOffset(),
+                                    item_result.get());
+      item.shape_result_ = std::move(item_result);
     }
-    DCHECK_EQ(range_index, num_text_items);
-    shape_result->CopyRanges(&text_item_ranges[0], num_text_items);
+    DCHECK_EQ(text_item_ranges.size(), num_text_items);
+    shape_result->CopyRanges(text_item_ranges.data(), text_item_ranges.size());
   }
 
 #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/layout/svg/BUILD.gn b/third_party/blink/renderer/core/layout/svg/BUILD.gn
index 8d013890..d8e784c 100644
--- a/third_party/blink/renderer/core/layout/svg/BUILD.gn
+++ b/third_party/blink/renderer/core/layout/svg/BUILD.gn
@@ -91,6 +91,8 @@
     "svg_text_metrics.h",
     "svg_text_query.cc",
     "svg_text_query.h",
+    "transform_helper.cc",
+    "transform_helper.h",
     "transformed_hit_test_location.cc",
     "transformed_hit_test_location.h",
   ]
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
index a1cc725..c9085ba3 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
@@ -28,6 +28,7 @@
 #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
 #include "third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.h"
 #include "third_party/blink/renderer/core/paint/svg_container_painter.h"
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
index e578f5d..48460002 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -97,6 +97,27 @@
   LayoutObject::WillBeDestroyed();
 }
 
+AffineTransform LayoutSVGModelObject::CalculateLocalTransform() const {
+  auto* element = GetElement();
+  if (element->HasTransform(SVGElement::kIncludeMotionTransform))
+    return element->CalculateTransform(SVGElement::kIncludeMotionTransform);
+  return AffineTransform();
+}
+
+bool LayoutSVGModelObject::CheckForImplicitTransformChange(
+    bool bbox_changed) const {
+  // If the transform is relative to the reference box, check relevant
+  // conditions to see if we need to recompute the transform.
+  switch (StyleRef().TransformBox()) {
+    case ETransformBox::kViewBox:
+      return SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this);
+    case ETransformBox::kFillBox:
+      return bbox_changed;
+  }
+  NOTREACHED();
+  return false;
+}
+
 void LayoutSVGModelObject::StyleDidChange(StyleDifference diff,
                                           const ComputedStyle* old_style) {
   // Since layout depends on the bounds of the filter, we need to force layout
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
index ab5ee1f0..9118a3f 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
@@ -80,6 +80,9 @@
  protected:
   void WillBeDestroyed() override;
 
+  AffineTransform CalculateLocalTransform() const;
+  bool CheckForImplicitTransformChange(bool bbox_changed) const;
+
  private:
   // LayoutSVGModelObject subclasses should use GetElement() instead.
   void GetNode() const = delete;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
index 659ee17..498d5d3 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
@@ -22,7 +22,7 @@
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h"
 
 #include "base/auto_reset.h"
-#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
index 3cb4654..30e10ca 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
 #include "third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/svg_root_painter.h"
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
index 4418ac8..6286842b0 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
 #include "third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.h"
 #include "third_party/blink/renderer/core/paint/svg_shape_painter.h"
 #include "third_party/blink/renderer/core/svg/svg_geometry_element.h"
@@ -58,14 +59,14 @@
       // Default is true, so we grab a AffineTransform object once from
       // SVGGeometryElement.
       needs_transform_update_(true),
-      // Default to false, since |needs_transform_update_| is true this will be
-      // updated the first time transforms are updated.
       transform_uses_reference_box_(false) {}
 
 LayoutSVGShape::~LayoutSVGShape() = default;
 
 void LayoutSVGShape::StyleDidChange(StyleDifference diff,
                                     const ComputedStyle* old_style) {
+  transform_uses_reference_box_ =
+      TransformHelper::DependsOnReferenceBox(StyleRef());
   LayoutSVGModelObject::StyleDidChange(diff, old_style);
   SVGResources::UpdatePaints(*GetElement(), old_style, StyleRef());
 }
@@ -94,7 +95,7 @@
   if (HasNonScalingStroke()) {
     // NonScalingStrokeTransform may depend on LocalTransform which in turn may
     // depend on ObjectBoundingBox, thus we need to call them in this order.
-    UpdateLocalTransform();
+    local_transform_ = CalculateLocalTransform();
     UpdateNonScalingStrokeData();
   }
 
@@ -209,42 +210,6 @@
   return ShapeDependentStrokeContains(location);
 }
 
-static inline bool TransformOriginIsFixed(const ComputedStyle& style) {
-  // If the transform box is view-box and the transform origin is absolute, then
-  // is does not depend on the reference box. For fill-box, the origin will
-  // always move with the bounding box.
-  return style.TransformBox() == ETransformBox::kViewBox &&
-         style.TransformOriginX().IsFixed() &&
-         style.TransformOriginY().IsFixed();
-}
-
-static inline bool TransformDependsOnReferenceBox(const ComputedStyle& style) {
-  // We're passing kExcludeMotionPath here because we're checking that
-  // explicitly later.
-  if (!TransformOriginIsFixed(style) &&
-      style.RequireTransformOrigin(ComputedStyle::kIncludeTransformOrigin,
-                                   ComputedStyle::kExcludeMotionPath))
-    return true;
-  if (style.Transform().DependsOnBoxSize())
-    return true;
-  if (style.Translate() && style.Translate()->DependsOnBoxSize())
-    return true;
-  if (style.HasOffset())
-    return true;
-  return false;
-}
-
-bool LayoutSVGShape::UpdateLocalTransform() {
-  auto* graphics_element = To<SVGGraphicsElement>(GetElement());
-  if (graphics_element->HasTransform(SVGElement::kIncludeMotionTransform)) {
-    local_transform_.SetTransform(graphics_element->CalculateTransform(
-        SVGElement::kIncludeMotionTransform));
-    return TransformDependsOnReferenceBox(StyleRef());
-  }
-  local_transform_ = AffineTransform();
-  return false;
-}
-
 void LayoutSVGShape::UpdateLayout() {
   LayoutAnalyzer::Scope analyzer(*this);
 
@@ -278,24 +243,14 @@
     update_parent_boundaries = true;
   }
 
-  // If the transform is relative to the reference box, check relevant
-  // conditions to see if we need to recompute the transform.
   if (!needs_transform_update_ && transform_uses_reference_box_) {
-    switch (StyleRef().TransformBox()) {
-      case ETransformBox::kViewBox:
-        needs_transform_update_ =
-            SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this);
-        break;
-      case ETransformBox::kFillBox:
-        needs_transform_update_ = bbox_changed;
-        break;
-    }
+    needs_transform_update_ = CheckForImplicitTransformChange(bbox_changed);
     if (needs_transform_update_)
       SetNeedsPaintPropertyUpdate();
   }
 
   if (needs_transform_update_) {
-    transform_uses_reference_box_ = UpdateLocalTransform();
+    local_transform_ = CalculateLocalTransform();
     needs_transform_update_ = false;
     update_parent_boundaries = true;
   }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
index b2563c7..1b11df34 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
@@ -179,7 +179,6 @@
   FloatRect ApproximateStrokeBoundingBox(const FloatRect& shape_bounds) const;
   FloatRect CalculateNonScalingStrokeBoundingBox() const;
   void UpdateNonScalingStrokeData();
-  bool UpdateLocalTransform();
 
  private:
   AffineTransform local_transform_;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
index 92f8d55..391b8dc 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
@@ -21,7 +21,7 @@
 
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h"
 
-#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
 #include "third_party/blink/renderer/core/svg/svg_g_element.h"
 #include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
 #include "third_party/blink/renderer/core/svg/svg_use_element.h"
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
index 7e4fc9e..544fa6e 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
@@ -23,6 +23,7 @@
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h"
 
 #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
 #include "third_party/blink/renderer/core/svg/svg_svg_element.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_support.h b/third_party/blink/renderer/core/layout/svg/svg_layout_support.h
index 249f9fa..92b33e4 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_layout_support.h
+++ b/third_party/blink/renderer/core/layout/svg/svg_layout_support.h
@@ -178,41 +178,6 @@
   AffineTransform saved_content_transformation_;
 };
 
-// The following enumeration is used to optimize cases where the scale is known
-// to be invariant (see: LayoutSVGContainer::layout and LayoutSVGroot). The
-// value 'Full' can be used in the general case when the scale change is
-// unknown, or known to change.
-enum class SVGTransformChange {
-  kNone,
-  kScaleInvariant,
-  kFull,
-};
-
-// Helper for computing ("classifying") a change to a transform using the
-// categoies defined above.
-class SVGTransformChangeDetector {
-  STACK_ALLOCATED();
-
- public:
-  explicit SVGTransformChangeDetector(const AffineTransform& previous)
-      : previous_transform_(previous) {}
-
-  SVGTransformChange ComputeChange(const AffineTransform& current) {
-    if (previous_transform_ == current)
-      return SVGTransformChange::kNone;
-    if (ScaleReference(previous_transform_) == ScaleReference(current))
-      return SVGTransformChange::kScaleInvariant;
-    return SVGTransformChange::kFull;
-  }
-
- private:
-  static std::pair<double, double> ScaleReference(
-      const AffineTransform& transform) {
-    return std::make_pair(transform.XScaleSquared(), transform.YScaleSquared());
-  }
-  AffineTransform previous_transform_;
-};
-
 template <typename LayoutObjectType>
 bool SVGLayoutSupport::ComputeHasNonIsolatedBlendingDescendants(
     const LayoutObjectType* object) {
diff --git a/third_party/blink/renderer/core/layout/svg/transform_helper.cc b/third_party/blink/renderer/core/layout/svg/transform_helper.cc
new file mode 100644
index 0000000..8e8e374
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/svg/transform_helper.cc
@@ -0,0 +1,95 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
+
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/core/svg/svg_length_context.h"
+#include "third_party/blink/renderer/platform/geometry/float_rect.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+
+namespace blink {
+
+static inline bool TransformOriginIsFixed(const ComputedStyle& style) {
+  // If the transform box is view-box and the transform origin is absolute,
+  // then is does not depend on the reference box. For fill-box, the origin
+  // will always move with the bounding box.
+  return style.TransformBox() == ETransformBox::kViewBox &&
+         style.TransformOriginX().IsFixed() &&
+         style.TransformOriginY().IsFixed();
+}
+
+bool TransformHelper::DependsOnReferenceBox(const ComputedStyle& style) {
+  // We're passing kExcludeMotionPath here because we're checking that
+  // explicitly later.
+  if (!TransformOriginIsFixed(style) &&
+      style.RequireTransformOrigin(ComputedStyle::kIncludeTransformOrigin,
+                                   ComputedStyle::kExcludeMotionPath))
+    return true;
+  if (style.Transform().DependsOnBoxSize())
+    return true;
+  if (style.Translate() && style.Translate()->DependsOnBoxSize())
+    return true;
+  if (style.HasOffset())
+    return true;
+  return false;
+}
+
+FloatRect TransformHelper::ComputeReferenceBox(
+    const LayoutObject& layout_object) {
+  const ComputedStyle& style = layout_object.StyleRef();
+  FloatRect reference_box;
+  if (style.TransformBox() == ETransformBox::kFillBox) {
+    reference_box = layout_object.ObjectBoundingBox();
+  } else {
+    DCHECK_EQ(style.TransformBox(), ETransformBox::kViewBox);
+    SVGLengthContext length_context(
+        DynamicTo<SVGElement>(layout_object.GetNode()));
+    FloatSize viewport_size;
+    length_context.DetermineViewport(viewport_size);
+    reference_box.SetSize(viewport_size);
+  }
+  const float zoom = style.EffectiveZoom();
+  if (zoom != 1)
+    reference_box.Scale(zoom);
+  return reference_box;
+}
+
+AffineTransform TransformHelper::ComputeTransform(
+    const LayoutObject& layout_object) {
+  const ComputedStyle& style = layout_object.StyleRef();
+  if (DependsOnReferenceBox(style)) {
+    UseCounter::Count(layout_object.GetDocument(),
+                      WebFeature::kTransformUsesBoxSizeOnSVG);
+  }
+
+  // CSS transforms operate with pre-scaled lengths. To make this work with SVG
+  // (which applies the zoom factor globally, at the root level) we
+  //
+  //  * pre-scale the reference box (to bring it into the same space as the
+  //    other CSS values) (Handled by ComputeSVGTransformReferenceBox)
+  //  * invert the zoom factor (to effectively compute the CSS transform under
+  //    a 1.0 zoom)
+  //
+  // Note: objectBoundingBox is an empty rect for elements like pattern or
+  // clipPath. See
+  // https://svgwg.org/svg2-draft/coords.html#ObjectBoundingBoxUnits
+  TransformationMatrix transform;
+  FloatRect reference_box = ComputeReferenceBox(layout_object);
+  style.ApplyTransform(transform, reference_box,
+                       ComputedStyle::kIncludeTransformOrigin,
+                       ComputedStyle::kIncludeMotionPath,
+                       ComputedStyle::kIncludeIndependentTransformProperties);
+  const float zoom = style.EffectiveZoom();
+  if (zoom != 1)
+    transform.Zoom(1 / zoom);
+  // Flatten any 3D transform.
+  return transform.ToAffineTransform();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/transform_helper.h b/third_party/blink/renderer/core/layout/svg/transform_helper.h
new file mode 100644
index 0000000..4423a05
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/svg/transform_helper.h
@@ -0,0 +1,71 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_TRANSFORM_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_TRANSFORM_HELPER_H_
+
+#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class ComputedStyle;
+class FloatRect;
+class LayoutObject;
+
+class TransformHelper {
+  STATIC_ONLY(TransformHelper);
+
+ public:
+  // Returns true if the passed in ComputedStyle has a transform that needs to
+  // resolve against the reference box.
+  static bool DependsOnReferenceBox(const ComputedStyle&);
+
+  // Computes the reference box for the LayoutObject based on the
+  // 'transform-box'. Applies zoom if needed.
+  static FloatRect ComputeReferenceBox(const LayoutObject&);
+
+  // Compute the transform for the LayoutObject based on the various
+  // 'transform*' properties.
+  static AffineTransform ComputeTransform(const LayoutObject&);
+};
+
+// The following enumeration is used to optimize cases where the scale is known
+// to be invariant (see: LayoutSVGContainer::UpdateLayout and
+// LayoutSVGRoot). The value 'Full' can be used in the general case when the
+// scale change is unknown, or known to have changed.
+enum class SVGTransformChange {
+  kNone,
+  kScaleInvariant,
+  kFull,
+};
+
+// Helper for computing ("classifying") a change to a transform using the
+// categories defined above.
+class SVGTransformChangeDetector {
+  STACK_ALLOCATED();
+
+ public:
+  explicit SVGTransformChangeDetector(const AffineTransform& previous)
+      : previous_transform_(previous) {}
+
+  SVGTransformChange ComputeChange(const AffineTransform& current) {
+    if (previous_transform_ == current)
+      return SVGTransformChange::kNone;
+    if (ScaleReference(previous_transform_) == ScaleReference(current))
+      return SVGTransformChange::kScaleInvariant;
+    return SVGTransformChange::kFull;
+  }
+
+ private:
+  static std::pair<double, double> ScaleReference(
+      const AffineTransform& transform) {
+    return std::make_pair(transform.XScaleSquared(), transform.YScaleSquared());
+  }
+  AffineTransform previous_transform_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_TRANSFORM_HELPER_H_
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc
index c01bf10..ddda6b7b 100644
--- a/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -521,9 +521,7 @@
     if (update_behavior != kUpdateForcedReload &&
         lazy_image_load_state_ == LazyImageLoadState::kNone) {
       const auto* frame = document.GetFrame();
-      if (frame->IsClientLoFiAllowed(params.GetResourceRequest())) {
-        params.SetClientLoFiPlaceholder();
-      } else if (auto* html_image = ToHTMLImageElementOrNull(GetElement())) {
+      if (auto* html_image = ToHTMLImageElementOrNull(GetElement())) {
         switch (LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
             *frame, html_image, params.Url())) {
           case LazyImageHelper::Eligibility::kEnabledFullyDeferred:
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
index bbee0646..bc61848 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
@@ -93,7 +93,7 @@
       v8::Local<v8::Value> error = V8ThrowException::CreateError(
           script_state_->GetIsolate(), "Parse failure.");
       module_script->SetParseErrorAndClearRecord(
-          ScriptValue(script_state_, error));
+          ScriptValue(script_state_->GetIsolate(), error));
     }
 
     EXPECT_TRUE(pending_clients_.Contains(url));
@@ -152,7 +152,7 @@
       ScriptState::Scope scope(script_state_);
       v8::Local<v8::Value> error = V8ThrowException::CreateError(
           script_state_->GetIsolate(), "Instantiation failure.");
-      return ScriptValue(script_state_, error);
+      return ScriptValue(script_state_->GetIsolate(), error);
     }
     instantiated_records_.insert(MakeGarbageCollected<BoxedV8Module>(
         script_state_->GetIsolate(), record));
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource.cc b/third_party/blink/renderer/core/loader/resource/image_resource.cc
index 4749a4d95..47f73bf1 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource.cc
@@ -558,36 +558,16 @@
   DCHECK(!is_scheduling_reload_);
   is_scheduling_reload_ = true;
 
-  if (GetResourceRequest().GetPreviewsState() & WebURLRequest::kClientLoFiOn) {
-    SetCachePolicyBypassingCache();
-  }
-
   // The reloaded image should not use any previews transformations.
   WebURLRequest::PreviewsState previews_state_for_reload =
       WebURLRequest::kPreviewsNoTransform;
-  WebURLRequest::PreviewsState old_previews_state =
-      GetResourceRequest().GetPreviewsState();
 
-  if (policy == kReloadIfNeeded && (GetResourceRequest().GetPreviewsState() &
-                                    WebURLRequest::kClientLoFiOn)) {
-    // If the image attempted to use Client LoFi, but encountered a decoding
-    // error and is being automatically reloaded, then also set the appropriate
-    // PreviewsState bit for that. This allows the embedder to count the
-    // bandwidth used for this reload against the data savings of the initial
-    // response.
-    previews_state_for_reload |= WebURLRequest::kClientLoFiAutoReload;
-  }
   SetPreviewsState(previews_state_for_reload);
 
   if (placeholder_option_ != PlaceholderOption::kDoNotReloadPlaceholder)
     ClearRangeRequestHeader();
 
-  if (old_previews_state & WebURLRequest::kClientLoFiOn &&
-      policy != kReloadAlways) {
-    placeholder_option_ = PlaceholderOption::kShowAndDoNotReloadPlaceholder;
-  } else {
     placeholder_option_ = PlaceholderOption::kDoNotReloadPlaceholder;
-  }
 
   if (IsLoading()) {
     Loader()->Cancel();
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_test.cc b/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
index 4c5c9ee..5bab2d3 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
@@ -1179,52 +1179,6 @@
                                          observer.get(), false);
 }
 
-TEST(ImageResourceTest, FetchAllowPlaceholderUnsuccessfulClientLoFi) {
-  KURL test_url(kTestURL);
-  ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
-  ResourceRequest request = ResourceRequest(test_url);
-  request.SetPreviewsState(WebURLRequest::kClientLoFiOn);
-  FetchParameters params{request};
-  params.SetAllowImagePlaceholder();
-  ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
-  EXPECT_EQ(FetchParameters::kAllowPlaceholder,
-            params.GetImageRequestOptimization());
-  EXPECT_EQ("bytes=0-2047",
-            image_resource->GetResourceRequest().HttpHeaderField("range"));
-  EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
-  auto observer =
-      std::make_unique<MockImageResourceObserver>(image_resource->GetContent());
-
-  const char kBadData[] = "notanimageresponse";
-
-  ResourceResponse bad_response(test_url);
-  bad_response.SetMimeType("image/jpeg");
-  bad_response.SetExpectedContentLength(sizeof(kBadData));
-  bad_response.SetHttpStatusCode(206);
-  bad_response.SetHttpHeaderField(
-      "content-range", BuildContentRange(sizeof(kBadData), sizeof(kJpegImage)));
-
-  image_resource->Loader()->DidReceiveResponse(
-      WrappedResourceResponse(bad_response));
-
-  EXPECT_EQ(0, observer->ImageChangedCount());
-
-  image_resource->Loader()->DidReceiveData(kBadData, sizeof(kBadData));
-
-  // The dimensions could not be extracted, so the full original image should be
-  // loading.
-  EXPECT_FALSE(observer->ImageNotifyFinishedCalled());
-  EXPECT_EQ(2, observer->ImageChangedCount());
-
-  TestThatReloadIsStartedThenServeReload(test_url, image_resource,
-                                         image_resource->GetContent(),
-                                         observer.get(), true);
-
-  EXPECT_FALSE(image_resource->GetContent()->GetImage()->IsBitmapImage());
-  EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
-}
-
 TEST(ImageResourceTest, FetchAllowPlaceholderPartialContentWithoutDimensions) {
   const struct {
     WebURLRequest::PreviewsState initial_previews_state;
@@ -1234,10 +1188,6 @@
   } tests[] = {
       {WebURLRequest::kPreviewsUnspecified, WebURLRequest::kPreviewsNoTransform,
        false},
-      {WebURLRequest::kClientLoFiOn,
-       WebURLRequest::kPreviewsNoTransform |
-           WebURLRequest::kClientLoFiAutoReload,
-       true},
   };
 
   for (const auto& test : tests) {
diff --git a/third_party/blink/renderer/core/script/js_module_script.cc b/third_party/blink/renderer/core/script/js_module_script.cc
index b343b30..5341b21 100644
--- a/third_party/blink/renderer/core/script/js_module_script.cc
+++ b/third_party/blink/renderer/core/script/js_module_script.cc
@@ -67,7 +67,7 @@
     // <spec step="8.1">Set script's parse error to result[0].</spec>
     v8::Local<v8::Value> error = exception_state.GetException();
     exception_state.ClearException();
-    script->SetParseErrorAndClearRecord(ScriptValue(script_state, error));
+    script->SetParseErrorAndClearRecord(ScriptValue(isolate, error));
 
     // <spec step="8.2">Return script.</spec>
     return script;
@@ -93,7 +93,7 @@
         V8ThrowException::CreateTypeError(isolate, error_message);
 
     // <spec step="9.2.2">Set script's parse error to error.</spec>
-    script->SetParseErrorAndClearRecord(ScriptValue(script_state, error));
+    script->SetParseErrorAndClearRecord(ScriptValue(isolate, error));
 
     // <spec step="9.2.3">Return script.</spec>
     return script;
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.cc b/third_party/blink/renderer/core/script/modulator_impl_base.cc
index cfc3cca..bb33b624 100644
--- a/third_party/blink/renderer/core/script/modulator_impl_base.cc
+++ b/third_party/blink/renderer/core/script/modulator_impl_base.cc
@@ -239,15 +239,17 @@
 
 ScriptValue ModulatorImplBase::CreateTypeError(const String& message) const {
   ScriptState::Scope scope(script_state_);
-  ScriptValue error(script_state_, V8ThrowException::CreateTypeError(
-                                       script_state_->GetIsolate(), message));
+  ScriptValue error(
+      script_state_->GetIsolate(),
+      V8ThrowException::CreateTypeError(script_state_->GetIsolate(), message));
   return error;
 }
 
 ScriptValue ModulatorImplBase::CreateSyntaxError(const String& message) const {
   ScriptState::Scope scope(script_state_);
-  ScriptValue error(script_state_, V8ThrowException::CreateSyntaxError(
-                                       script_state_->GetIsolate(), message));
+  ScriptValue error(script_state_->GetIsolate(),
+                    V8ThrowException::CreateSyntaxError(
+                        script_state_->GetIsolate(), message));
   return error;
 }
 
diff --git a/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc b/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
index 2b1c7ca..21cfd612 100644
--- a/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
+++ b/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
@@ -97,7 +97,7 @@
     v8::Local<v8::Value> error =
         V8ThrowException::CreateError(scope.GetIsolate(), "hoge");
     module_script->SetParseErrorAndClearRecord(
-        ScriptValue(scope.GetScriptState(), error));
+        ScriptValue(scope.GetIsolate(), error));
   }
   return module_script;
 }
diff --git a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
index c3a8152..30c6c68 100644
--- a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
+++ b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
@@ -102,7 +102,7 @@
   settings_object->GetModuleRecordResolver()->RegisterModuleScript(
       value_wrapper_module_script);
   value_wrapper_module_script->SetParseErrorAndClearRecord(
-      ScriptValue(settings_object->GetScriptState(), error));
+      ScriptValue(settings_object->GetScriptState()->GetIsolate(), error));
   // Step 7. "Return script."
   // [spec text]
   return value_wrapper_module_script;
diff --git a/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc b/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
index aae8fb8..e5ea5c46 100644
--- a/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
+++ b/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
@@ -81,7 +81,7 @@
 
 ScriptValue ByteLengthQueuingStrategy::highWaterMark(
     ScriptState* script_state) const {
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      high_water_mark_.NewLocal(script_state->GetIsolate()));
 }
 
@@ -89,7 +89,7 @@
   // We don't cache the result because normally this method will only be called
   // once anyway.
   return ScriptValue(
-      script_state,
+      script_state->GetIsolate(),
       ByteLengthQueuingStrategySizeFunction::CreateFunction(script_state));
 }
 
diff --git a/third_party/blink/renderer/core/streams/count_queuing_strategy.cc b/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
index 2b1aa3b..601fecf 100644
--- a/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
+++ b/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
@@ -52,7 +52,7 @@
 
 ScriptValue CountQueuingStrategy::highWaterMark(
     ScriptState* script_state) const {
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      high_water_mark_.NewLocal(script_state->GetIsolate()));
 }
 
@@ -60,7 +60,7 @@
   // We don't cache the result because normally this method will only be called
   // once anyway.
   return ScriptValue(
-      script_state,
+      script_state->GetIsolate(),
       CountQueuingStrategySizeFunction::CreateFunction(script_state));
 }
 
diff --git a/third_party/blink/renderer/core/streams/miscellaneous_operations.cc b/third_party/blink/renderer/core/streams/miscellaneous_operations.cc
index ff297a10..44d9914b 100644
--- a/third_party/blink/renderer/core/streams/miscellaneous_operations.cc
+++ b/third_party/blink/renderer/core/streams/miscellaneous_operations.cc
@@ -609,7 +609,7 @@
     return;
   }
   *writable_stream = dom_writable;
-  *readable_stream = ScriptValue(script_state, readable);
+  *readable_stream = ScriptValue(script_state->GetIsolate(), readable);
 }
 
 CORE_EXPORT WritableStream* PipeToCheckSourceAndDestination(
@@ -699,7 +699,7 @@
     exception_state.RethrowV8Exception(block.Exception());
     return ScriptValue();
   }
-  return ScriptValue(script_state, array);
+  return ScriptValue(script_state->GetIsolate(), array);
 }
 
 void ScriptValueToObject(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/readable_stream.cc b/third_party/blink/renderer/core/streams/readable_stream.cc
index e1088481..cefb778f 100644
--- a/third_party/blink/renderer/core/streams/readable_stream.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -13,20 +13,21 @@
 
 ReadableStream* ReadableStream::Create(ScriptState* script_state,
                                        ExceptionState& exception_state) {
-  return Create(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return Create(script_state,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                exception_state);
 }
 
 ReadableStream* ReadableStream::Create(ScriptState* script_state,
                                        ScriptValue underlying_source,
                                        ExceptionState& exception_state) {
-  return Create(
-      script_state, underlying_source,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return Create(script_state, underlying_source,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                exception_state);
 }
 
 ReadableStream* ReadableStream::Create(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc b/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
index 653cab0..f87d888 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
@@ -70,7 +70,8 @@
 void ReadableStreamDefaultController::enqueue(ScriptState* script_state,
                                               ExceptionState& exception_state) {
   enqueue(script_state,
-          ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
+          ScriptValue(script_state->GetIsolate(),
+                      v8::Undefined(script_state->GetIsolate())),
           exception_state);
 }
 
@@ -90,8 +91,8 @@
 }
 
 void ReadableStreamDefaultController::error(ScriptState* script_state) {
-  error(script_state,
-        ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+  error(script_state, ScriptValue(script_state->GetIsolate(),
+                                  v8::Undefined(script_state->GetIsolate())));
 }
 
 void ReadableStreamDefaultController::error(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/readable_stream_native.cc b/third_party/blink/renderer/core/streams/readable_stream_native.cc
index 717d99c..ff0a4dea 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_native.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_native.cc
@@ -1002,8 +1002,10 @@
       ToV8(underlying_source, script_state);
 
   auto* stream = MakeGarbageCollected<ReadableStreamNative>(
-      script_state, ScriptValue(script_state, underlying_source_v8),
-      ScriptValue(script_state, strategy_object), true, exception_state);
+      script_state,
+      ScriptValue(script_state->GetIsolate(), underlying_source_v8),
+      ScriptValue(script_state->GetIsolate(), strategy_object), true,
+      exception_state);
 
   if (exception_state.HadException()) {
     exception_state.ClearException();
@@ -1162,10 +1164,10 @@
 
 ScriptPromise ReadableStreamNative::cancel(ScriptState* script_state,
                                            ExceptionState& exception_state) {
-  return cancel(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return cancel(script_state,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                exception_state);
 }
 
 ScriptPromise ReadableStreamNative::cancel(ScriptState* script_state,
@@ -1195,7 +1197,7 @@
     return ScriptValue();
   }
 
-  return ScriptValue(script_state, ToV8(reader, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(reader, script_state));
 }
 
 ScriptValue ReadableStreamNative::getReader(ScriptState* script_state,
@@ -1216,10 +1218,10 @@
 ScriptValue ReadableStreamNative::pipeThrough(ScriptState* script_state,
                                               ScriptValue transform_stream,
                                               ExceptionState& exception_state) {
-  return pipeThrough(
-      script_state, transform_stream,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return pipeThrough(script_state, transform_stream,
+                     ScriptValue(script_state->GetIsolate(),
+                                 v8::Undefined(script_state->GetIsolate())),
+                     exception_state);
 }
 
 // https://streams.spec.whatwg.org/#rs-pipe-through
@@ -1263,10 +1265,10 @@
 ScriptPromise ReadableStreamNative::pipeTo(ScriptState* script_state,
                                            ScriptValue destination,
                                            ExceptionState& exception_state) {
-  return pipeTo(
-      script_state, destination,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return pipeTo(script_state, destination,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                exception_state);
 }
 
 ScriptPromise ReadableStreamNative::pipeTo(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/readable_stream_operations.cc b/third_party/blink/renderer/core/streams/readable_stream_operations.cc
index a387185a..7f58fdff 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_operations.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_operations.cc
@@ -111,7 +111,7 @@
     exception_state.RethrowV8Exception(block.Exception());
     return ScriptValue();
   }
-  return ScriptValue(script_state, result);
+  return ScriptValue(script_state->GetIsolate(), result);
 }
 
 ScriptValue ReadableStreamOperations::CreateCountQueuingStrategy(
@@ -261,7 +261,7 @@
     exception_state.RethrowV8Exception(block.Exception());
     return ScriptValue();
   }
-  return ScriptValue(script_state, result);
+  return ScriptValue(script_state->GetIsolate(), result);
 }
 
 void ReadableStreamOperations::Serialize(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc b/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
index b047091b..c2a350ee 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
@@ -135,23 +135,23 @@
 
   V8TestingScope scope;
   TryCatchScope try_catch_scope(scope.GetIsolate());
-  EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
-                   scope.GetScriptState(),
-                   ScriptValue(scope.GetScriptState(),
-                               v8::Undefined(scope.GetIsolate())),
-                   ASSERT_NO_EXCEPTION)
-                   .value_or(true));
+  EXPECT_FALSE(
+      ReadableStreamOperations::IsReadableStream(
+          scope.GetScriptState(),
+          ScriptValue(scope.GetIsolate(), v8::Undefined(scope.GetIsolate())),
+          ASSERT_NO_EXCEPTION)
+          .value_or(true));
   EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
                    scope.GetScriptState(),
                    ScriptValue::CreateNull(scope.GetIsolate()),
                    ASSERT_NO_EXCEPTION)
                    .value_or(true));
-  EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
-                   scope.GetScriptState(),
-                   ScriptValue(scope.GetScriptState(),
-                               v8::Object::New(scope.GetIsolate())),
-                   ASSERT_NO_EXCEPTION)
-                   .value_or(true));
+  EXPECT_FALSE(
+      ReadableStreamOperations::IsReadableStream(
+          scope.GetScriptState(),
+          ScriptValue(scope.GetIsolate(), v8::Object::New(scope.GetIsolate())),
+          ASSERT_NO_EXCEPTION)
+          .value_or(true));
   ScriptValue stream = EvalWithPrintingError(&scope, "new ReadableStream()");
   EXPECT_FALSE(stream.IsEmpty());
   EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
@@ -173,23 +173,23 @@
 
   V8TestingScope scope;
   TryCatchScope try_catch_scope(scope.GetIsolate());
-  EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
-                   scope.GetScriptState(),
-                   ScriptValue(scope.GetScriptState(),
-                               v8::Undefined(scope.GetIsolate())),
-                   ASSERT_NO_EXCEPTION)
-                   .value_or(true));
+  EXPECT_FALSE(
+      ReadableStreamOperations::IsReadableStreamDefaultReader(
+          scope.GetScriptState(),
+          ScriptValue(scope.GetIsolate(), v8::Undefined(scope.GetIsolate())),
+          ASSERT_NO_EXCEPTION)
+          .value_or(true));
   EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
                    scope.GetScriptState(),
                    ScriptValue::CreateNull(scope.GetIsolate()),
                    ASSERT_NO_EXCEPTION)
                    .value_or(true));
-  EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
-                   scope.GetScriptState(),
-                   ScriptValue(scope.GetScriptState(),
-                               v8::Object::New(scope.GetIsolate())),
-                   ASSERT_NO_EXCEPTION)
-                   .value_or(true));
+  EXPECT_FALSE(
+      ReadableStreamOperations::IsReadableStreamDefaultReader(
+          scope.GetScriptState(),
+          ScriptValue(scope.GetIsolate(), v8::Object::New(scope.GetIsolate())),
+          ASSERT_NO_EXCEPTION)
+          .value_or(true));
   ScriptValue stream = EvalWithPrintingError(&scope, "new ReadableStream()");
   ASSERT_FALSE(stream.IsEmpty());
 
@@ -402,7 +402,7 @@
       scope.GetScriptState(), erroring_source, 0);
   ASSERT_TRUE(errored);
   erroring_source->Error(
-      ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate())));
+      ScriptValue(scope.GetIsolate(), v8::Undefined(scope.GetIsolate())));
 
   EXPECT_EQ(ReadableStreamOperations::IsReadable(
                 scope.GetScriptState(),
@@ -444,7 +444,7 @@
       scope.GetScriptState(), erroring_source, 0);
   ASSERT_TRUE(errored);
   erroring_source->Error(
-      ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate())));
+      ScriptValue(scope.GetIsolate(), v8::Undefined(scope.GetIsolate())));
 
   EXPECT_EQ(ReadableStreamOperations::IsClosed(
                 scope.GetScriptState(),
@@ -486,7 +486,7 @@
       scope.GetScriptState(), erroring_source, 0);
   ASSERT_TRUE(errored);
   erroring_source->Error(
-      ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate())));
+      ScriptValue(scope.GetIsolate(), v8::Undefined(scope.GetIsolate())));
 
   EXPECT_EQ(ReadableStreamOperations::IsErrored(
                 scope.GetScriptState(),
@@ -531,8 +531,8 @@
   ASSERT_TRUE(
       result.V8Value().As<v8::Object>()->Get(context, 1).ToLocal(&v8_branch2));
 
-  ScriptValue new1(scope.GetScriptState(), v8_branch1);
-  ScriptValue new2(scope.GetScriptState(), v8_branch2);
+  ScriptValue new1(scope.GetIsolate(), v8_branch1);
+  ScriptValue new2(scope.GetIsolate(), v8_branch2);
 
   ASSERT_TRUE(ReadableStreamOperations::IsReadableStream(
                   scope.GetScriptState(), new1, ASSERT_NO_EXCEPTION)
@@ -564,8 +564,8 @@
   EXPECT_FALSE(it1->IsSet());
   EXPECT_FALSE(it2->IsSet());
 
-  source->Enqueue(ScriptValue(scope.GetScriptState(),
-                              V8String(scope.GetIsolate(), "hello")));
+  source->Enqueue(
+      ScriptValue(scope.GetIsolate(), V8String(scope.GetIsolate(), "hello")));
   v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
 
   EXPECT_TRUE(it1->IsSet());
@@ -590,8 +590,8 @@
       scope.GetScriptState(), source, 0);
   ASSERT_TRUE(stream);
 
-  source->Enqueue(ScriptValue(scope.GetScriptState(),
-                              V8String(scope.GetIsolate(), "hello")));
+  source->Enqueue(
+      ScriptValue(scope.GetIsolate(), V8String(scope.GetIsolate(), "hello")));
   ScriptValue internal_stream =
       CheckedGetInternalStream(scope.GetScriptState(), stream);
   auto* channel =
diff --git a/third_party/blink/renderer/core/streams/readable_stream_reader.cc b/third_party/blink/renderer/core/streams/readable_stream_reader.cc
index 66b5a1a..44b969d7 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_reader.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_reader.cc
@@ -58,9 +58,9 @@
 }
 
 ScriptPromise ReadableStreamReader::cancel(ScriptState* script_state) {
-  return cancel(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+  return cancel(script_state,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())));
 }
 
 ScriptPromise ReadableStreamReader::cancel(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/readable_stream_test.cc b/third_party/blink/renderer/core/streams/readable_stream_test.cc
index 2217f82..522f6f5 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_test.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_test.cc
@@ -111,9 +111,9 @@
   auto* underlying_source =
       MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
   ScriptValue js_underlying_source = ScriptValue(
-      scope.GetScriptState(),
+      scope.GetIsolate(),
       ToV8(underlying_source, scope.GetScriptState()->GetContext()->Global(),
-           scope.GetScriptState()->GetIsolate()));
+           scope.GetIsolate()));
 
   EXPECT_FALSE(underlying_source->IsStartCalled());
 
@@ -130,9 +130,9 @@
   auto* underlying_source =
       MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
   ScriptValue js_underlying_source = ScriptValue(
-      scope.GetScriptState(),
+      scope.GetIsolate(),
       ToV8(underlying_source, scope.GetScriptState()->GetContext()->Global(),
-           scope.GetScriptState()->GetIsolate()));
+           scope.GetIsolate()));
   ScriptValue js_empty_strategy = EvalWithPrintingError(&scope, "{}");
   ASSERT_FALSE(js_empty_strategy.IsEmpty());
   ReadableStream* stream =
@@ -148,9 +148,9 @@
   auto* underlying_source =
       MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
   ScriptValue js_underlying_source = ScriptValue(
-      scope.GetScriptState(),
+      scope.GetIsolate(),
       ToV8(underlying_source, scope.GetScriptState()->GetContext()->Global(),
-           scope.GetScriptState()->GetIsolate()));
+           scope.GetIsolate()));
   ScriptValue js_pathological_strategy =
       EvalWithPrintingError(&scope, "({get size() { throw Error('e'); }})");
   ASSERT_FALSE(js_pathological_strategy.IsEmpty());
@@ -167,13 +167,13 @@
 TEST_P(ReadableStreamTest, GetReader) {
   V8TestingScope scope;
   ScriptState* script_state = scope.GetScriptState();
+  v8::Isolate* isolate = scope.GetIsolate();
 
   auto* underlying_source =
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
-  ScriptValue js_underlying_source =
-      ScriptValue(script_state,
-                  ToV8(underlying_source, script_state->GetContext()->Global(),
-                       script_state->GetIsolate()));
+  ScriptValue js_underlying_source = ScriptValue(
+      isolate,
+      ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
   ReadableStream* stream = ReadableStream::Create(
       script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(stream);
@@ -219,13 +219,13 @@
 TEST_P(ReadableStreamTest, Cancel) {
   V8TestingScope scope;
   ScriptState* script_state = scope.GetScriptState();
+  v8::Isolate* isolate = scope.GetIsolate();
 
   auto* underlying_source =
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
-  ScriptValue js_underlying_source =
-      ScriptValue(script_state,
-                  ToV8(underlying_source, script_state->GetContext()->Global(),
-                       script_state->GetIsolate()));
+  ScriptValue js_underlying_source = ScriptValue(
+      isolate,
+      ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
   ReadableStream* stream = ReadableStream::Create(
       script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(stream);
@@ -244,13 +244,13 @@
 TEST_P(ReadableStreamTest, CancelWithNull) {
   V8TestingScope scope;
   ScriptState* script_state = scope.GetScriptState();
+  v8::Isolate* isolate = scope.GetIsolate();
 
   auto* underlying_source =
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
-  ScriptValue js_underlying_source =
-      ScriptValue(script_state,
-                  ToV8(underlying_source, script_state->GetContext()->Global(),
-                       script_state->GetIsolate()));
+  ScriptValue js_underlying_source = ScriptValue(
+      isolate,
+      ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
   ReadableStream* stream = ReadableStream::Create(
       script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(stream);
@@ -259,10 +259,8 @@
   EXPECT_FALSE(underlying_source->IsCancelledWithUndefined());
   EXPECT_FALSE(underlying_source->IsCancelledWithNull());
 
-  stream->cancel(
-      script_state,
-      ScriptValue(script_state, v8::Null(script_state->GetIsolate())),
-      ASSERT_NO_EXCEPTION);
+  stream->cancel(script_state, ScriptValue(isolate, v8::Null(isolate)),
+                 ASSERT_NO_EXCEPTION);
 
   EXPECT_TRUE(underlying_source->IsCancelled());
   EXPECT_FALSE(underlying_source->IsCancelledWithUndefined());
@@ -274,21 +272,19 @@
 TEST_P(ReadableStreamTest, Tee) {
   V8TestingScope scope;
   ScriptState* script_state = scope.GetScriptState();
+  v8::Isolate* isolate = scope.GetIsolate();
 
   auto* underlying_source =
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
-  ScriptValue js_underlying_source =
-      ScriptValue(script_state,
-                  ToV8(underlying_source, script_state->GetContext()->Global(),
-                       script_state->GetIsolate()));
+  ScriptValue js_underlying_source = ScriptValue(
+      isolate,
+      ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
   ReadableStream* stream = ReadableStream::Create(
       script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(stream);
 
-  underlying_source->Enqueue(
-      ScriptValue(script_state, V8String(script_state->GetIsolate(), "hello")));
-  underlying_source->Enqueue(
-      ScriptValue(script_state, V8String(script_state->GetIsolate(), ", bye")));
+  underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, "hello")));
+  underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, ", bye")));
   underlying_source->Close();
 
   ReadableStream* branch1 = nullptr;
@@ -356,6 +352,7 @@
 TEST_P(ReadableStreamTest, Error) {
   V8TestingScope scope;
   ScriptState* script_state = scope.GetScriptState();
+  v8::Isolate* isolate = scope.GetIsolate();
   ExceptionState& exception_state = scope.GetExceptionState();
 
   auto* underlying_source =
@@ -372,8 +369,7 @@
   EXPECT_EQ(stream->IsErrored(script_state, exception_state),
             base::make_optional(false));
 
-  underlying_source->Error(
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+  underlying_source->Error(ScriptValue(isolate, v8::Undefined(isolate)));
 
   EXPECT_EQ(stream->IsReadable(script_state, exception_state),
             base::make_optional(false));
@@ -414,6 +410,7 @@
 
   V8TestingScope scope;
   auto* script_state = scope.GetScriptState();
+  auto* isolate = scope.GetIsolate();
 
   auto* underlying_source =
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
@@ -431,10 +428,8 @@
       script_state, channel->port2(), ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(transferred);
 
-  underlying_source->Enqueue(
-      ScriptValue(script_state, V8String(script_state->GetIsolate(), "hello")));
-  underlying_source->Enqueue(
-      ScriptValue(script_state, V8String(script_state->GetIsolate(), ", bye")));
+  underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, "hello")));
+  underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, ", bye")));
   underlying_source->Close();
 
   EXPECT_EQ(ReadAll(scope, transferred),
@@ -450,13 +445,13 @@
       MakeGarbageCollected<TestUnderlyingSource>(script_state);
 
   ScriptValue js_underlying_source = ScriptValue(
-      script_state,
+      isolate,
       ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
   ReadableStream* stream = ReadableStream::Create(
       script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
   ASSERT_TRUE(stream);
 
-  ScriptValue abc = ScriptValue(script_state, V8String(isolate, "abc"));
+  ScriptValue abc = ScriptValue(isolate, V8String(isolate, "abc"));
   underlying_source->Enqueue(abc);
   underlying_source->Close();
 
diff --git a/third_party/blink/renderer/core/streams/readable_stream_wrapper.cc b/third_party/blink/renderer/core/streams/readable_stream_wrapper.cc
index 592654e..61c222c 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_wrapper.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_wrapper.cc
@@ -26,7 +26,7 @@
   ScriptPromise Read(ScriptState* script_state) override {
     return ReadableStreamOperations::DefaultReaderRead(
         script_state,
-        ScriptValue(script_state,
+        ScriptValue(script_state->GetIsolate(),
                     reader_.NewLocal(script_state->GetIsolate())));
   }
 
@@ -58,7 +58,7 @@
     v8::Local<v8::Object> object,
     ExceptionState& exception_state) {
   DCHECK(ReadableStreamOperations::IsReadableStreamForDCheck(
-      script_state, ScriptValue(script_state, object)));
+      script_state, ScriptValue(script_state->GetIsolate(), object)));
   object_.Set(script_state->GetIsolate(), object);
 
   v8::Isolate* isolate = script_state->GetIsolate();
@@ -151,10 +151,10 @@
 
 ScriptPromise ReadableStreamWrapper::cancel(ScriptState* script_state,
                                             ExceptionState& exception_state) {
-  return cancel(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return cancel(script_state,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                exception_state);
 }
 
 bool ReadableStreamWrapper::locked(ScriptState* script_state,
@@ -200,10 +200,10 @@
     ScriptState* script_state,
     ScriptValue transform_stream,
     ExceptionState& exception_state) {
-  return pipeThrough(
-      script_state, transform_stream,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return pipeThrough(script_state, transform_stream,
+                     ScriptValue(script_state->GetIsolate(),
+                                 v8::Undefined(script_state->GetIsolate())),
+                     exception_state);
 }
 
 // https://streams.spec.whatwg.org/#rs-pipe-through
@@ -249,10 +249,10 @@
 ScriptPromise ReadableStreamWrapper::pipeTo(ScriptState* script_state,
                                             ScriptValue destination,
                                             ExceptionState& exception_state) {
-  return pipeTo(
-      script_state, destination,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return pipeTo(script_state, destination,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                exception_state);
 }
 
 ScriptPromise ReadableStreamWrapper::pipeTo(ScriptState* script_state,
@@ -432,7 +432,7 @@
 
 ScriptValue ReadableStreamWrapper::GetInternalStream(
     ScriptState* script_state) const {
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      object_.NewLocal(script_state->GetIsolate()));
 }
 
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.cc b/third_party/blink/renderer/core/streams/transferable_streams.cc
index 82efecb..c99ce6d 100644
--- a/third_party/blink/renderer/core/streams/transferable_streams.cc
+++ b/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -121,7 +121,7 @@
   v8::Local<v8::Object> packed = CreateKeyValueObject(
       isolate, "t", v8::Number::New(isolate, static_cast<int>(type)), "v",
       value);
-  port->postMessage(script_state, ScriptValue(script_state, packed),
+  port->postMessage(script_state, ScriptValue(isolate, packed),
                     PostMessageOptions::Create(), exception_state);
 }
 
diff --git a/third_party/blink/renderer/core/streams/transform_stream.cc b/third_party/blink/renderer/core/streams/transform_stream.cc
index a88a0ef..193df1c 100644
--- a/third_party/blink/renderer/core/streams/transform_stream.cc
+++ b/third_party/blink/renderer/core/streams/transform_stream.cc
@@ -26,7 +26,7 @@
 
 TransformStream* TransformStream::Create(ScriptState* script_state,
                                          ExceptionState& exception_state) {
-  ScriptValue undefined(script_state,
+  ScriptValue undefined(script_state->GetIsolate(),
                         v8::Undefined(script_state->GetIsolate()));
   return Create(script_state, undefined, undefined, undefined, exception_state);
 }
@@ -35,7 +35,7 @@
     ScriptState* script_state,
     ScriptValue transform_stream_transformer,
     ExceptionState& exception_state) {
-  ScriptValue undefined(script_state,
+  ScriptValue undefined(script_state->GetIsolate(),
                         v8::Undefined(script_state->GetIsolate()));
   return Create(script_state, transform_stream_transformer, undefined,
                 undefined, exception_state);
@@ -46,7 +46,7 @@
     ScriptValue transform_stream_transformer,
     ScriptValue writable_strategy,
     ExceptionState& exception_state) {
-  ScriptValue undefined(script_state,
+  ScriptValue undefined(script_state->GetIsolate(),
                         v8::Undefined(script_state->GetIsolate()));
   return Create(script_state, transform_stream_transformer, writable_strategy,
                 undefined, exception_state);
diff --git a/third_party/blink/renderer/core/streams/underlying_source_base.cc b/third_party/blink/renderer/core/streams/underlying_source_base.cc
index f8a7f42..7afa0b6 100644
--- a/third_party/blink/renderer/core/streams/underlying_source_base.cc
+++ b/third_party/blink/renderer/core/streams/underlying_source_base.cc
@@ -45,7 +45,8 @@
 }
 
 ScriptValue UnderlyingSourceBase::type(ScriptState* script_state) const {
-  return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
+  return ScriptValue(script_state->GetIsolate(),
+                     v8::Undefined(script_state->GetIsolate()));
 }
 
 void UnderlyingSourceBase::ContextDestroyed(ExecutionContext*) {
diff --git a/third_party/blink/renderer/core/streams/writable_stream.cc b/third_party/blink/renderer/core/streams/writable_stream.cc
index f0817bf8..d08a22b 100644
--- a/third_party/blink/renderer/core/streams/writable_stream.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -17,20 +17,21 @@
 
 WritableStream* WritableStream::Create(ScriptState* script_state,
                                        ExceptionState& exception_state) {
-  return Create(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return Create(script_state,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                exception_state);
 }
 
 WritableStream* WritableStream::Create(ScriptState* script_state,
                                        ScriptValue underlying_sink,
                                        ExceptionState& exception_state) {
-  return Create(
-      script_state, underlying_sink,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return Create(script_state, underlying_sink,
+                ScriptValue(script_state->GetIsolate(),
+                            v8::Undefined(script_state->GetIsolate())),
+                exception_state);
 }
 
 WritableStream* WritableStream::Create(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
index 08652a6..da6e722 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
@@ -25,8 +25,8 @@
     : queue_(MakeGarbageCollected<QueueWithSizes>()) {}
 
 void WritableStreamDefaultController::error(ScriptState* script_state) {
-  error(script_state,
-        ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+  error(script_state, ScriptValue(script_state->GetIsolate(),
+                                  v8::Undefined(script_state->GetIsolate())));
 }
 
 void WritableStreamDefaultController::error(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc b/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc
index 0d78ec2..176bf68 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc
@@ -200,7 +200,7 @@
   }
 
   //  3. Return ! WritableStreamDefaultWriterGetDesiredSize(this).
-  return ScriptValue(script_state, GetDesiredSize(isolate, this));
+  return ScriptValue(isolate, GetDesiredSize(isolate, this));
 }
 
 ScriptPromise WritableStreamDefaultWriter::ready(
@@ -211,9 +211,9 @@
 }
 
 ScriptPromise WritableStreamDefaultWriter::abort(ScriptState* script_state) {
-  return abort(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+  return abort(script_state,
+               ScriptValue(script_state->GetIsolate(),
+                           v8::Undefined(script_state->GetIsolate())));
 }
 
 ScriptPromise WritableStreamDefaultWriter::abort(ScriptState* script_state,
@@ -277,9 +277,9 @@
 }
 
 ScriptPromise WritableStreamDefaultWriter::write(ScriptState* script_state) {
-  return write(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+  return write(script_state,
+               ScriptValue(script_state->GetIsolate(),
+                           v8::Undefined(script_state->GetIsolate())));
 }
 
 ScriptPromise WritableStreamDefaultWriter::write(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/streams/writable_stream_native.cc b/third_party/blink/renderer/core/streams/writable_stream_native.cc
index 370c942..b7da075 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_native.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream_native.cc
@@ -143,10 +143,10 @@
 
 ScriptPromise WritableStreamNative::abort(ScriptState* script_state,
                                           ExceptionState& exception_state) {
-  return abort(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return abort(script_state,
+               ScriptValue(script_state->GetIsolate(),
+                           v8::Undefined(script_state->GetIsolate())),
+               exception_state);
 }
 
 ScriptPromise WritableStreamNative::abort(ScriptState* script_state,
@@ -179,7 +179,7 @@
   // This call to ToV8() is only reached directly from JavaScript, and so
   // shouldn't be called while the execution context is being shutdown and so
   // shouldn't fail.
-  return ScriptValue(script_state, ToV8(writer, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(writer, script_state));
 }
 
 // General Writable Stream Abstract Operations
diff --git a/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc b/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
index 8ed9eff1..d51ea53 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
@@ -141,10 +141,10 @@
 
 ScriptPromise WritableStreamWrapper::abort(ScriptState* script_state,
                                            ExceptionState& exception_state) {
-  return abort(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return abort(script_state,
+               ScriptValue(script_state->GetIsolate(),
+                           v8::Undefined(script_state->GetIsolate())),
+               exception_state);
 }
 
 ScriptPromise WritableStreamWrapper::abort(ScriptState* script_state,
@@ -182,7 +182,7 @@
     exception_state.RethrowV8Exception(block.Exception());
     return ScriptValue();
   }
-  return ScriptValue(script_state, result);
+  return ScriptValue(script_state->GetIsolate(), result);
 }
 
 base::Optional<bool> WritableStreamWrapper::IsLocked(
@@ -246,7 +246,7 @@
 
 ScriptValue WritableStreamWrapper::GetInternalStream(
     ScriptState* script_state) const {
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      internal_stream_.NewLocal(script_state->GetIsolate()));
 }
 
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index d11464e1..973f7af 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -54,6 +54,7 @@
 #include "third_party/blink/renderer/core/style/shadow_list.h"
 #include "third_party/blink/renderer/core/style/style_difference.h"
 #include "third_party/blink/renderer/core/style/style_fetched_image.h"
+#include "third_party/blink/renderer/core/style/style_generated_image.h"
 #include "third_party/blink/renderer/core/style/style_image.h"
 #include "third_party/blink/renderer/core/style/style_inherited_variables.h"
 #include "third_party/blink/renderer/core/style/style_non_inherited_variables.h"
@@ -943,6 +944,22 @@
   MutablePaintImagesInternal()->push_back(image);
 }
 
+bool ComputedStyle::HasCSSPaintImagesUsingCustomProperty(
+    const AtomicString& custom_property_name) const {
+  if (PaintImagesInternal()) {
+    for (const auto& image : *PaintImagesInternal()) {
+      DCHECK(image);
+      // IsPaintImage is true for CSS Paint images only, please refer to the
+      // constructor of StyleGeneratedImage.
+      if (image->IsPaintImage()) {
+        return To<StyleGeneratedImage>(image.Get())
+            ->IsUsingCustomProperty(custom_property_name);
+      }
+    }
+  }
+  return false;
+}
+
 void ComputedStyle::AddCursor(StyleImage* image,
                               bool hot_spot_specified,
                               const IntPoint& hot_spot) {
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index c94a0d5..9ecbada 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2302,7 +2302,12 @@
   }
 
   // Paint utility functions.
-  void AddPaintImage(StyleImage*);
+  CORE_EXPORT void AddPaintImage(StyleImage*);
+
+  // Returns true if any property has an <image> value that is a CSS paint
+  // function that is using a given custom property.
+  bool HasCSSPaintImagesUsingCustomProperty(
+      const AtomicString& custom_property_name) const;
 
   // FIXME: reflections should belong to this helper function but they are
   // currently handled through their self-painting layers. So the layout code
diff --git a/third_party/blink/renderer/core/style/style_generated_image.cc b/third_party/blink/renderer/core/style/style_generated_image.cc
index cb6edac4..d903d26 100644
--- a/third_party/blink/renderer/core/style/style_generated_image.cc
+++ b/third_party/blink/renderer/core/style/style_generated_image.cc
@@ -78,6 +78,11 @@
   image_generator_value_->RemoveClient(observer);
 }
 
+bool StyleGeneratedImage::IsUsingCustomProperty(
+    const AtomicString& custom_property_name) const {
+  return image_generator_value_->IsUsingCustomProperty(custom_property_name);
+}
+
 scoped_refptr<Image> StyleGeneratedImage::GetImage(
     const ImageResourceObserver& observer,
     const Document& document,
diff --git a/third_party/blink/renderer/core/style/style_generated_image.h b/third_party/blink/renderer/core/style/style_generated_image.h
index 503bbc7e..b57ad91 100644
--- a/third_party/blink/renderer/core/style/style_generated_image.h
+++ b/third_party/blink/renderer/core/style/style_generated_image.h
@@ -60,6 +60,8 @@
                                 const FloatSize& target_size) const override;
   bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
 
+  bool IsUsingCustomProperty(const AtomicString& custom_property_name) const;
+
   void Trace(blink::Visitor*) override;
 
  private:
diff --git a/third_party/blink/renderer/core/svg/svg_element.cc b/third_party/blink/renderer/core/svg/svg_element.cc
index 6ca79db..adfd4d2 100644
--- a/third_party/blink/renderer/core/svg/svg_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_element.cc
@@ -49,6 +49,7 @@
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
 #include "third_party/blink/renderer/core/svg/properties/svg_property.h"
 #include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
 #include "third_party/blink/renderer/core/svg/svg_element_rare_data.h"
@@ -59,7 +60,6 @@
 #include "third_party/blink/renderer/core/svg_names.h"
 #include "third_party/blink/renderer/core/xml_names.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/wtf/threading.h"
 
 namespace blink {
@@ -297,76 +297,13 @@
           HasSVGRareData());
 }
 
-static inline bool TransformUsesBoxSize(const ComputedStyle& style) {
-  if ((style.TransformOriginX().IsPercent() ||
-       style.TransformOriginY().IsPercent()) &&
-      style.RequireTransformOrigin(ComputedStyle::kIncludeTransformOrigin,
-                                   ComputedStyle::kExcludeMotionPath))
-    return true;
-  if (style.Transform().DependsOnBoxSize())
-    return true;
-  if (style.Translate() && style.Translate()->DependsOnBoxSize())
-    return true;
-  if (style.HasOffset())
-    return true;
-  return false;
-}
-
-FloatRect ComputeSVGTransformReferenceBox(const LayoutObject& layout_object) {
-  const ComputedStyle& style = layout_object.StyleRef();
-  FloatRect reference_box;
-  if (style.TransformBox() == ETransformBox::kFillBox) {
-    reference_box = layout_object.ObjectBoundingBox();
-  } else {
-    DCHECK_EQ(style.TransformBox(), ETransformBox::kViewBox);
-    SVGLengthContext length_context(
-        DynamicTo<SVGElement>(layout_object.GetNode()));
-    FloatSize viewport_size;
-    length_context.DetermineViewport(viewport_size);
-    reference_box.SetSize(viewport_size);
-  }
-  const float zoom = style.EffectiveZoom();
-  if (zoom != 1)
-    reference_box.Scale(zoom);
-  return reference_box;
-}
-
 AffineTransform SVGElement::CalculateTransform(
     ApplyMotionTransform apply_motion_transform) const {
-  const ComputedStyle* style =
-      GetLayoutObject() ? GetLayoutObject()->Style() : nullptr;
+  const LayoutObject* layout_object = GetLayoutObject();
 
-  // If CSS property was set, use that, otherwise fallback to attribute (if
-  // set).
   AffineTransform matrix;
-  if (style && style->HasTransform()) {
-    if (TransformUsesBoxSize(*style))
-      UseCounter::Count(GetDocument(), WebFeature::kTransformUsesBoxSizeOnSVG);
-
-    // CSS transforms operate with pre-scaled lengths. To make this work with
-    // SVG (which applies the zoom factor globally, at the root level) we
-    //
-    //   * pre-scale the reference box (to bring it into the same space as the
-    //     other CSS values) (Handled by ComputeSVGTransformReferenceBox)
-    //   * invert the zoom factor (to effectively compute the CSS transform
-    //     under a 1.0 zoom)
-    //
-    // Note: objectBoundingBox is an emptyRect for elements like pattern or
-    // clipPath. See
-    // https://svgwg.org/svg2-draft/coords.html#ObjectBoundingBoxUnits
-    TransformationMatrix transform;
-    FloatRect reference_box =
-        ComputeSVGTransformReferenceBox(*GetLayoutObject());
-    style->ApplyTransform(
-        transform, reference_box, ComputedStyle::kIncludeTransformOrigin,
-        ComputedStyle::kIncludeMotionPath,
-        ComputedStyle::kIncludeIndependentTransformProperties);
-    const float zoom = style->EffectiveZoom();
-    if (zoom != 1)
-      transform.Zoom(1 / zoom);
-    // Flatten any 3D transform.
-    matrix = transform.ToAffineTransform();
-  }
+  if (layout_object && layout_object->StyleRef().HasTransform())
+    matrix = TransformHelper::ComputeTransform(*layout_object);
 
   // Apply any "motion transform" contribution if requested (and existing.)
   if (apply_motion_transform == kIncludeMotionTransform && HasSVGRareData())
diff --git a/third_party/blink/renderer/core/svg/svg_element.h b/third_party/blink/renderer/core/svg/svg_element.h
index a139aa8..256997e 100644
--- a/third_party/blink/renderer/core/svg/svg_element.h
+++ b/third_party/blink/renderer/core/svg/svg_element.h
@@ -37,7 +37,6 @@
 
 class AffineTransform;
 class Document;
-class FloatRect;
 class SVGAnimatedPropertyBase;
 class SubtreeLayoutScope;
 class SVGAnimatedString;
@@ -334,8 +333,6 @@
   }
 };
 
-FloatRect ComputeSVGTransformReferenceBox(const LayoutObject&);
-
 DEFINE_ELEMENT_TYPE_CASTS(SVGElement, IsSVGElement());
 
 template <>
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc
index 44066ef..33af28cb 100644
--- a/third_party/blink/renderer/core/testing/internals.cc
+++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -3037,7 +3037,7 @@
     int32_t int_value =
         static_cast<int32_t>(v8_value.As<v8::Integer>()->Value());
     return ScriptValue(
-        GetScriptState(),
+        GetScriptState()->GetIsolate(),
         v8::Integer::New(GetScriptState()->GetIsolate(), int_value + 1));
   }
 };
diff --git a/third_party/blink/renderer/core/timing/performance_mark.cc b/third_party/blink/renderer/core/timing/performance_mark.cc
index 8e52412..aea244d9 100644
--- a/third_party/blink/renderer/core/timing/performance_mark.cc
+++ b/third_party/blink/renderer/core/timing/performance_mark.cc
@@ -81,16 +81,16 @@
 ScriptValue PerformanceMark::detail(ScriptState* script_state) {
   v8::Isolate* isolate = script_state->GetIsolate();
   if (!serialized_detail_)
-    return ScriptValue(script_state, v8::Null(isolate));
+    return ScriptValue(isolate, v8::Null(isolate));
   auto result = deserialized_detail_map_.insert(
       script_state, TraceWrapperV8Reference<v8::Value>());
   TraceWrapperV8Reference<v8::Value>& relevant_data =
       result.stored_value->value;
   if (!result.is_new_entry)
-    return ScriptValue(script_state, relevant_data.NewLocal(isolate));
+    return ScriptValue(isolate, relevant_data.NewLocal(isolate));
   v8::Local<v8::Value> value = serialized_detail_->Deserialize(isolate);
   relevant_data.Set(isolate, value);
-  return ScriptValue(script_state, value);
+  return ScriptValue(isolate, value);
 }
 
 void PerformanceMark::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/timing/performance_measure.cc b/third_party/blink/renderer/core/timing/performance_measure.cc
index e3880e4c..dab264c 100644
--- a/third_party/blink/renderer/core/timing/performance_measure.cc
+++ b/third_party/blink/renderer/core/timing/performance_measure.cc
@@ -47,16 +47,16 @@
 ScriptValue PerformanceMeasure::detail(ScriptState* script_state) {
   v8::Isolate* isolate = script_state->GetIsolate();
   if (!serialized_detail_)
-    return ScriptValue(script_state, v8::Null(isolate));
+    return ScriptValue(isolate, v8::Null(isolate));
   auto result = deserialized_detail_map_.insert(
       script_state, TraceWrapperV8Reference<v8::Value>());
   TraceWrapperV8Reference<v8::Value>& relevant_data =
       result.stored_value->value;
   if (!result.is_new_entry)
-    return ScriptValue(script_state, relevant_data.NewLocal(isolate));
+    return ScriptValue(isolate, relevant_data.NewLocal(isolate));
   v8::Local<v8::Value> value = serialized_detail_->Deserialize(isolate);
   relevant_data.Set(isolate, value);
-  return ScriptValue(script_state, value);
+  return ScriptValue(isolate, value);
 }
 
 AtomicString PerformanceMeasure::entryType() const {
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
index 6409e93..a746409e 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
@@ -318,7 +318,7 @@
     }
   }
 
-  return ScriptValue(script_state, top);
+  return ScriptValue(script_state->GetIsolate(), top);
 }
 
 void TrustedTypePolicyFactory::CountTrustedTypeAssignmentError() {
diff --git a/third_party/blink/renderer/devtools/BUILD.gn b/third_party/blink/renderer/devtools/BUILD.gn
index c5386b70..f95ebbf 100644
--- a/third_party/blink/renderer/devtools/BUILD.gn
+++ b/third_party/blink/renderer/devtools/BUILD.gn
@@ -139,25 +139,7 @@
   "front_end/color_picker/module.json",
   "front_end/color_picker/spectrum.css",
   "front_end/color_picker/Spectrum.js",
-  "front_end/common/CharacterIdMap.js",
-  "front_end/common/Color.js",
-  "front_end/common/Console.js",
-  "front_end/common/ContentProvider.js",
   "front_end/common/module.json",
-  "front_end/common/ModuleExtensionInterfaces.js",
-  "front_end/common/Object.js",
-  "front_end/common/OutputStream.js",
-  "front_end/common/ParsedURL.js",
-  "front_end/common/Progress.js",
-  "front_end/common/ResourceType.js",
-  "front_end/common/SegmentedRange.js",
-  "front_end/common/Settings.js",
-  "front_end/common/StaticContentProvider.js",
-  "front_end/common/TextDictionary.js",
-  "front_end/common/Throttler.js",
-  "front_end/common/Trie.js",
-  "front_end/common/UIString.js",
-  "front_end/common/Worker.js",
   "front_end/components/DockController.js",
   "front_end/components/ImagePreview.js",
   "front_end/components/imagePreview.css",
@@ -961,6 +943,32 @@
   "front_end/root.js",
   "front_end/ui/ARIAUtils.js",
   "front_end/ui/ui.js",
+  "front_end/common/common.js",
+  "front_end/common/App.js",
+  "front_end/common/AppProvider.js",
+  "front_end/common/CharacterIdMap.js",
+  "front_end/common/Color.js",
+  "front_end/common/ContentProvider.js",
+  "front_end/common/EventTarget.js",
+  "front_end/common/JavaScriptMetaData.js",
+  "front_end/common/Linkifier.js",
+  "front_end/common/Object.js",
+  "front_end/common/Console.js",
+  "front_end/common/ParsedURL.js",
+  "front_end/common/Progress.js",
+  "front_end/common/QueryParamHandler.js",
+  "front_end/common/ResourceType.js",
+  "front_end/common/Revealer.js",
+  "front_end/common/Runnable.js",
+  "front_end/common/SegmentedRange.js",
+  "front_end/common/Settings.js",
+  "front_end/common/StaticContentProvider.js",
+  "front_end/common/StringOutputStream.js",
+  "front_end/common/TextDictionary.js",
+  "front_end/common/Throttler.js",
+  "front_end/common/Trie.js",
+  "front_end/common/UIString.js",
+  "front_end/common/Worker.js",
 ]
 
 devtools_test_files = [
@@ -1158,6 +1166,32 @@
   "$resources_out_dir/root.js",
   "$resources_out_dir/ui/ARIAUtils.js",
   "$resources_out_dir/ui/ui.js",
+  "$resources_out_dir/common/common.js",
+  "$resources_out_dir/common/App.js",
+  "$resources_out_dir/common/AppProvider.js",
+  "$resources_out_dir/common/CharacterIdMap.js",
+  "$resources_out_dir/common/Color.js",
+  "$resources_out_dir/common/ContentProvider.js",
+  "$resources_out_dir/common/EventTarget.js",
+  "$resources_out_dir/common/JavaScriptMetaData.js",
+  "$resources_out_dir/common/Linkifier.js",
+  "$resources_out_dir/common/Object.js",
+  "$resources_out_dir/common/Console.js",
+  "$resources_out_dir/common/ParsedURL.js",
+  "$resources_out_dir/common/Progress.js",
+  "$resources_out_dir/common/QueryParamHandler.js",
+  "$resources_out_dir/common/ResourceType.js",
+  "$resources_out_dir/common/Revealer.js",
+  "$resources_out_dir/common/Runnable.js",
+  "$resources_out_dir/common/SegmentedRange.js",
+  "$resources_out_dir/common/Settings.js",
+  "$resources_out_dir/common/StaticContentProvider.js",
+  "$resources_out_dir/common/StringOutputStream.js",
+  "$resources_out_dir/common/TextDictionary.js",
+  "$resources_out_dir/common/Throttler.js",
+  "$resources_out_dir/common/Trie.js",
+  "$resources_out_dir/common/UIString.js",
+  "$resources_out_dir/common/Worker.js",
 ]
 
 generated_applications = [
diff --git a/third_party/blink/renderer/devtools/front_end/common/App.js b/third_party/blink/renderer/devtools/front_end/common/App.js
new file mode 100644
index 0000000..f09920f
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/App.js
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @interface
+ */
+export default class App {
+  /**
+   * @param {!Document} document
+   */
+  presentUI(document) {
+  }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.App = App;
diff --git a/third_party/blink/renderer/devtools/front_end/common/AppProvider.js b/third_party/blink/renderer/devtools/front_end/common/AppProvider.js
new file mode 100644
index 0000000..77c20ca
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/AppProvider.js
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @interface
+ */
+export default class AppProvider {
+  /**
+   * @return {!Common.App}
+   */
+  createApp() {
+  }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.AppProvider = AppProvider;
diff --git a/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js b/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js
index 627df76..5241062 100644
--- a/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js
+++ b/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js
@@ -5,7 +5,7 @@
  * @template T
  * @unrestricted
  */
-Common.CharacterIdMap = class {
+export default class CharacterIdMap {
   constructor() {
     /** @type {!Map<T, string>} */
     this._elementToCharacter = new Map();
@@ -40,4 +40,13 @@
       return null;
     return object;
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.CharacterIdMap = CharacterIdMap;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Color.js b/third_party/blink/renderer/devtools/front_end/common/Color.js
index 1fa43f22..e45868c 100644
--- a/third_party/blink/renderer/devtools/front_end/common/Color.js
+++ b/third_party/blink/renderer/devtools/front_end/common/Color.js
@@ -30,10 +30,10 @@
 /**
  * @unrestricted
  */
-Common.Color = class {
+export default class Color {
   /**
    * @param {!Array.<number>} rgba
-   * @param {!Common.Color.Format} format
+   * @param {!Format} format
    * @param {string=} originalText
    */
   constructor(rgba, format, originalText) {
@@ -58,7 +58,7 @@
 
   /**
    * @param {string} text
-   * @return {?Common.Color}
+   * @return {?Color}
    */
   static parse(text) {
     // Simple - #hex, nickname
@@ -70,16 +70,16 @@
         let hex = match[1].toLowerCase();
         let format;
         if (hex.length === 3) {
-          format = Common.Color.Format.ShortHEX;
+          format = Format.ShortHEX;
           hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
         } else if (hex.length === 4) {
-          format = Common.Color.Format.ShortHEXA;
+          format = Format.ShortHEXA;
           hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2) +
               hex.charAt(3) + hex.charAt(3);
         } else if (hex.length === 6) {
-          format = Common.Color.Format.HEX;
+          format = Format.HEX;
         } else {
-          format = Common.Color.Format.HEXA;
+          format = Format.HEXA;
         }
         const r = parseInt(hex.substring(0, 2), 16);
         const g = parseInt(hex.substring(2, 4), 16);
@@ -87,15 +87,15 @@
         let a = 1;
         if (hex.length === 8)
           a = parseInt(hex.substring(6, 8), 16) / 255;
-        return new Common.Color([r / 255, g / 255, b / 255, a], format, text);
+        return new Color([r / 255, g / 255, b / 255, a], format, text);
       }
 
       if (match[2]) {  // nickname
         const nickname = match[2].toLowerCase();
-        if (nickname in Common.Color.Nicknames) {
-          const rgba = Common.Color.Nicknames[nickname];
-          const color = Common.Color.fromRGBA(rgba);
-          color._format = Common.Color.Format.Nickname;
+        if (nickname in Nicknames) {
+          const rgba = Nicknames[nickname];
+          const color = Color.fromRGBA(rgba);
+          color._format = Format.Nickname;
           color._originalText = text;
           return color;
         }
@@ -130,24 +130,24 @@
 
       if (match[1]) {  // rgb/rgba
         const rgba = [
-          Common.Color._parseRgbNumeric(values[0]), Common.Color._parseRgbNumeric(values[1]),
-          Common.Color._parseRgbNumeric(values[2]), hasAlpha ? Common.Color._parseAlphaNumeric(values[3]) : 1
+          Color._parseRgbNumeric(values[0]), Color._parseRgbNumeric(values[1]), Color._parseRgbNumeric(values[2]),
+          hasAlpha ? Color._parseAlphaNumeric(values[3]) : 1
         ];
         if (rgba.indexOf(null) > -1)
           return null;
-        return new Common.Color(rgba, hasAlpha ? Common.Color.Format.RGBA : Common.Color.Format.RGB, text);
+        return new Color(rgba, hasAlpha ? Format.RGBA : Format.RGB, text);
       }
 
       if (match[2]) {  // hsl/hsla
         const hsla = [
-          Common.Color._parseHueNumeric(values[0]), Common.Color._parseSatLightNumeric(values[1]),
-          Common.Color._parseSatLightNumeric(values[2]), hasAlpha ? Common.Color._parseAlphaNumeric(values[3]) : 1
+          Color._parseHueNumeric(values[0]), Color._parseSatLightNumeric(values[1]),
+          Color._parseSatLightNumeric(values[2]), hasAlpha ? Color._parseAlphaNumeric(values[3]) : 1
         ];
         if (hsla.indexOf(null) > -1)
           return null;
         const rgba = [];
-        Common.Color.hsl2rgb(hsla, rgba);
-        return new Common.Color(rgba, hasAlpha ? Common.Color.Format.HSLA : Common.Color.Format.HSL, text);
+        Color.hsl2rgb(hsla, rgba);
+        return new Color(rgba, hasAlpha ? Format.HSLA : Format.HSL, text);
       }
     }
 
@@ -156,20 +156,20 @@
 
   /**
    * @param {!Array.<number>} rgba
-   * @return {!Common.Color}
+   * @return {!Color}
    */
   static fromRGBA(rgba) {
-    return new Common.Color([rgba[0] / 255, rgba[1] / 255, rgba[2] / 255, rgba[3]], Common.Color.Format.RGBA);
+    return new Color([rgba[0] / 255, rgba[1] / 255, rgba[2] / 255, rgba[3]], Format.RGBA);
   }
 
   /**
    * @param {!Array.<number>} hsva
-   * @return {!Common.Color}
+   * @return {!Color}
    */
   static fromHSVA(hsva) {
     const rgba = [];
-    Common.Color.hsva2rgba(hsva, rgba);
-    return new Common.Color(rgba, Common.Color.Format.HSLA);
+    Color.hsva2rgba(hsva, rgba);
+    return new Color(rgba, Format.HSLA);
   }
 
   /**
@@ -194,7 +194,7 @@
    * return {number}
    */
   static _parseRgbNumeric(value) {
-    const parsed = Common.Color._parsePercentOrNumber(value);
+    const parsed = Color._parsePercentOrNumber(value);
     if (parsed === null)
       return null;
 
@@ -238,7 +238,7 @@
    * return {number}
    */
   static _parseAlphaNumeric(value) {
-    return Common.Color._parsePercentOrNumber(value);
+    return Color._parsePercentOrNumber(value);
   }
 
   /**
@@ -313,11 +313,11 @@
    * @param {!Array<number>} out_rgba
    */
   static hsva2rgba(hsva, out_rgba) {
-    Common.Color._hsva2hsla(hsva, Common.Color.hsva2rgba._tmpHSLA);
-    Common.Color.hsl2rgb(Common.Color.hsva2rgba._tmpHSLA, out_rgba);
+    Color._hsva2hsla(hsva, Color.hsva2rgba._tmpHSLA);
+    Color.hsl2rgb(Color.hsva2rgba._tmpHSLA, out_rgba);
 
-    for (let i = 0; i < Common.Color.hsva2rgba._tmpHSLA.length; i++)
-      Common.Color.hsva2rgba._tmpHSLA[i] = 0;
+    for (let i = 0; i < Color.hsva2rgba._tmpHSLA.length; i++)
+      Color.hsva2rgba._tmpHSLA[i] = 0;
   }
 
   /**
@@ -362,14 +362,14 @@
    * @return {number}
    */
   static calculateContrastRatio(fgRGBA, bgRGBA) {
-    Common.Color.blendColors(fgRGBA, bgRGBA, Common.Color.calculateContrastRatio._blendedFg);
+    Color.blendColors(fgRGBA, bgRGBA, Color.calculateContrastRatio._blendedFg);
 
-    const fgLuminance = Common.Color.luminance(Common.Color.calculateContrastRatio._blendedFg);
-    const bgLuminance = Common.Color.luminance(bgRGBA);
+    const fgLuminance = Color.luminance(Color.calculateContrastRatio._blendedFg);
+    const bgLuminance = Color.luminance(bgRGBA);
     const contrastRatio = (Math.max(fgLuminance, bgLuminance) + 0.05) / (Math.min(fgLuminance, bgLuminance) + 0.05);
 
-    for (let i = 0; i < Common.Color.calculateContrastRatio._blendedFg.length; i++)
-      Common.Color.calculateContrastRatio._blendedFg[i] = 0;
+    for (let i = 0; i < Color.calculateContrastRatio._blendedFg.length; i++)
+      Color.calculateContrastRatio._blendedFg[i] = 0;
 
     return contrastRatio;
   }
@@ -401,11 +401,11 @@
   }
 
   /**
-   * @param {!Common.Color} color
-   * @return {!Common.Color.Format}
+   * @param {!Color} color
+   * @return {!Format}
    */
   static detectColorFormat(color) {
-    const cf = Common.Color.Format;
+    const cf = Format;
     let format;
     const formatSetting = Common.moduleSetting('colorFormat').get();
     if (formatSetting === cf.Original)
@@ -423,7 +423,7 @@
   }
 
   /**
-   * @return {!Common.Color.Format}
+   * @return {!Format}
    */
   format() {
     return this._format;
@@ -498,7 +498,7 @@
   }
 
   /**
-   * @return {!Common.Color.Format}
+   * @return {!Format}
    */
   detectHEXFormat() {
     let canBeShort = true;
@@ -511,7 +511,7 @@
     }
 
     const hasAlpha = this.hasAlpha();
-    const cf = Common.Color.Format;
+    const cf = Format;
     if (canBeShort)
       return hasAlpha ? cf.ShortHEXA : cf.ShortHEX;
     return hasAlpha ? cf.HEXA : cf.HEX;
@@ -553,60 +553,60 @@
     }
 
     switch (format) {
-      case Common.Color.Format.Original:
+      case Format.Original:
         return this._originalText;
-      case Common.Color.Format.RGB:
+      case Format.RGB:
         if (this.hasAlpha())
           return null;
         return String.sprintf(
             'rgb(%d, %d, %d)', toRgbValue(this._rgba[0]), toRgbValue(this._rgba[1]), toRgbValue(this._rgba[2]));
-      case Common.Color.Format.RGBA:
+      case Format.RGBA:
         return String.sprintf(
             'rgba(%d, %d, %d, %f)', toRgbValue(this._rgba[0]), toRgbValue(this._rgba[1]), toRgbValue(this._rgba[2]),
             this._rgba[3]);
-      case Common.Color.Format.HSL:
+      case Format.HSL:
         if (this.hasAlpha())
           return null;
         const hsl = this.hsla();
         return String.sprintf(
             'hsl(%d, %d%, %d%)', Math.round(hsl[0] * 360), Math.round(hsl[1] * 100), Math.round(hsl[2] * 100));
-      case Common.Color.Format.HSLA:
+      case Format.HSLA:
         const hsla = this.hsla();
         return String.sprintf(
             'hsla(%d, %d%, %d%, %f)', Math.round(hsla[0] * 360), Math.round(hsla[1] * 100), Math.round(hsla[2] * 100),
             hsla[3]);
-      case Common.Color.Format.HEXA:
+      case Format.HEXA:
         return String
             .sprintf(
                 '#%s%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]),
                 toHexValue(this._rgba[3]))
             .toLowerCase();
-      case Common.Color.Format.HEX:
+      case Format.HEX:
         if (this.hasAlpha())
           return null;
         return String
             .sprintf('#%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]))
             .toLowerCase();
-      case Common.Color.Format.ShortHEXA:
+      case Format.ShortHEXA:
         const hexFormat = this.detectHEXFormat();
-        if (hexFormat !== Common.Color.Format.ShortHEXA && hexFormat !== Common.Color.Format.ShortHEX)
+        if (hexFormat !== Format.ShortHEXA && hexFormat !== Format.ShortHEX)
           return null;
         return String
             .sprintf(
                 '#%s%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
                 toShortHexValue(this._rgba[2]), toShortHexValue(this._rgba[3]))
             .toLowerCase();
-      case Common.Color.Format.ShortHEX:
+      case Format.ShortHEX:
         if (this.hasAlpha())
           return null;
-        if (this.detectHEXFormat() !== Common.Color.Format.ShortHEX)
+        if (this.detectHEXFormat() !== Format.ShortHEX)
           return null;
         return String
             .sprintf(
                 '#%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
                 toShortHexValue(this._rgba[2]))
             .toLowerCase();
-      case Common.Color.Format.Nickname:
+      case Format.Nickname:
         return this.nickname();
     }
 
@@ -635,17 +635,17 @@
    * @return {?string} nickname
    */
   nickname() {
-    if (!Common.Color._rgbaToNickname) {
-      Common.Color._rgbaToNickname = {};
-      for (const nickname in Common.Color.Nicknames) {
-        let rgba = Common.Color.Nicknames[nickname];
+    if (!Color._rgbaToNickname) {
+      Color._rgbaToNickname = {};
+      for (const nickname in Nicknames) {
+        let rgba = Nicknames[nickname];
         if (rgba.length !== 4)
           rgba = rgba.concat(1);
-        Common.Color._rgbaToNickname[rgba] = nickname;
+        Color._rgbaToNickname[rgba] = nickname;
       }
     }
 
-    return Common.Color._rgbaToNickname[this.canonicalRGBA()] || null;
+    return Color._rgbaToNickname[this.canonicalRGBA()] || null;
   }
 
   /**
@@ -660,7 +660,7 @@
   }
 
   /**
-   * @return {!Common.Color}
+   * @return {!Color}
    */
   invert() {
     const rgba = [];
@@ -668,37 +668,37 @@
     rgba[1] = 1 - this._rgba[1];
     rgba[2] = 1 - this._rgba[2];
     rgba[3] = this._rgba[3];
-    return new Common.Color(rgba, Common.Color.Format.RGBA);
+    return new Color(rgba, Format.RGBA);
   }
 
   /**
    * @param {number} alpha
-   * @return {!Common.Color}
+   * @return {!Color}
    */
   setAlpha(alpha) {
     const rgba = this._rgba.slice();
     rgba[3] = alpha;
-    return new Common.Color(rgba, Common.Color.Format.RGBA);
+    return new Color(rgba, Format.RGBA);
   }
 
   /**
-   * @param {!Common.Color} fgColor
-   * @return {!Common.Color}
+   * @param {!Color} fgColor
+   * @return {!Color}
    */
   blendWith(fgColor) {
     const rgba = [];
-    Common.Color.blendColors(fgColor._rgba, this._rgba, rgba);
-    return new Common.Color(rgba, Common.Color.Format.RGBA);
+    Color.blendColors(fgColor._rgba, this._rgba, rgba);
+    return new Color(rgba, Format.RGBA);
   }
-};
+}
 
 /** @type {!RegExp} */
-Common.Color.Regex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,4}|\b[a-zA-Z]+\b(?!-))/g;
+export const Regex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,4}|\b[a-zA-Z]+\b(?!-))/g;
 
 /**
  * @enum {string}
  */
-Common.Color.Format = {
+export const Format = {
   Original: 'original',
   Nickname: 'nickname',
   HEX: 'hex',
@@ -711,15 +711,7 @@
   HSLA: 'hsla'
 };
 
-
-/** @type {!Array<number>} */
-Common.Color.hsva2rgba._tmpHSLA = [0, 0, 0, 0];
-
-
-Common.Color.calculateContrastRatio._blendedFg = [0, 0, 0, 0];
-
-
-Common.Color.Nicknames = {
+export const Nicknames = {
   'aliceblue': [240, 248, 255],
   'antiquewhite': [250, 235, 215],
   'aqua': [0, 255, 255],
@@ -871,23 +863,23 @@
   'transparent': [0, 0, 0, 0],
 };
 
-Common.Color.PageHighlight = {
-  Content: Common.Color.fromRGBA([111, 168, 220, .66]),
-  ContentLight: Common.Color.fromRGBA([111, 168, 220, .5]),
-  ContentOutline: Common.Color.fromRGBA([9, 83, 148]),
-  Padding: Common.Color.fromRGBA([147, 196, 125, .55]),
-  PaddingLight: Common.Color.fromRGBA([147, 196, 125, .4]),
-  Border: Common.Color.fromRGBA([255, 229, 153, .66]),
-  BorderLight: Common.Color.fromRGBA([255, 229, 153, .5]),
-  Margin: Common.Color.fromRGBA([246, 178, 107, .66]),
-  MarginLight: Common.Color.fromRGBA([246, 178, 107, .5]),
-  EventTarget: Common.Color.fromRGBA([255, 196, 196, .66]),
-  Shape: Common.Color.fromRGBA([96, 82, 177, 0.8]),
-  ShapeMargin: Common.Color.fromRGBA([96, 82, 127, .6]),
-  CssGrid: Common.Color.fromRGBA([0x4b, 0, 0x82, 1])
+export const PageHighlight = {
+  Content: Color.fromRGBA([111, 168, 220, .66]),
+  ContentLight: Color.fromRGBA([111, 168, 220, .5]),
+  ContentOutline: Color.fromRGBA([9, 83, 148]),
+  Padding: Color.fromRGBA([147, 196, 125, .55]),
+  PaddingLight: Color.fromRGBA([147, 196, 125, .4]),
+  Border: Color.fromRGBA([255, 229, 153, .66]),
+  BorderLight: Color.fromRGBA([255, 229, 153, .5]),
+  Margin: Color.fromRGBA([246, 178, 107, .66]),
+  MarginLight: Color.fromRGBA([246, 178, 107, .5]),
+  EventTarget: Color.fromRGBA([255, 196, 196, .66]),
+  Shape: Color.fromRGBA([96, 82, 177, 0.8]),
+  ShapeMargin: Color.fromRGBA([96, 82, 127, .6]),
+  CssGrid: Color.fromRGBA([0x4b, 0, 0x82, 1])
 };
 
-Common.Color.Generator = class {
+export class Generator {
   /**
    * @param {!{min: number, max: number}|number=} hueSpace
    * @param {!{min: number, max: number, count: (number|undefined)}|number=} satSpace
@@ -949,4 +941,32 @@
     index %= count;
     return space.min + Math.floor(index / (count - 1) * (space.max - space.min));
   }
-};
+}
+
+/** @type {!Array<number>} */
+Color.hsva2rgba._tmpHSLA = [0, 0, 0, 0];
+
+Color.calculateContrastRatio._blendedFg = [0, 0, 0, 0];
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.Color = Color;
+
+Common.Color.Regex = Regex;
+
+/**
+ * @enum {string}
+ */
+Common.Color.Format = Format;
+Common.Color.Nicknames = Nicknames;
+Common.Color.PageHighlight = PageHighlight;
+
+/**
+ * @constructor
+ */
+Common.Color.Generator = Generator;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Console.js b/third_party/blink/renderer/devtools/front_end/common/Console.js
index 71350cb1..9695527 100644
--- a/third_party/blink/renderer/devtools/front_end/common/Console.js
+++ b/third_party/blink/renderer/devtools/front_end/common/Console.js
@@ -4,7 +4,7 @@
 /**
  * @unrestricted
  */
-Common.Console = class extends Common.Object {
+export default class Console extends Common.Object {
   constructor() {
     super();
     /** @type {!Array.<!Common.Console.Message>} */
@@ -61,17 +61,17 @@
   showPromise() {
     return Common.Revealer.reveal(this);
   }
-};
+}
 
 /** @enum {symbol} */
-Common.Console.Events = {
+export const Events = {
   MessageAdded: Symbol('messageAdded')
 };
 
 /**
  * @enum {string}
  */
-Common.Console.MessageLevel = {
+export const MessageLevel = {
   Info: 'info',
   Warning: 'warning',
   Error: 'error'
@@ -80,7 +80,7 @@
 /**
  * @unrestricted
  */
-Common.Console.Message = class {
+export class Message {
   /**
    * @param {string} text
    * @param {!Common.Console.MessageLevel} level
@@ -93,6 +93,28 @@
     this.timestamp = (typeof timestamp === 'number') ? timestamp : Date.now();
     this.show = show;
   }
-};
+}
 
-Common.console = new Common.Console();
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+Common.console = new Console();
+
+/**
+ * @constructor
+ */
+Common.Console = Console;
+
+/** @enum {symbol} */
+Common.Console.Events = Events;
+
+/**
+ * @enum {string}
+ */
+Common.Console.MessageLevel = MessageLevel;
+
+/**
+ * @constructor
+ */
+Common.Console.Message = Message;
diff --git a/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js b/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js
index 349adfe..adb72086 100644
--- a/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js
+++ b/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js
@@ -30,28 +30,30 @@
 /**
  * @interface
  */
-Common.ContentProvider = function() {};
-
-Common.ContentProvider.prototype = {
+export default class ContentProvider {
   /**
    * @return {string}
    */
-  contentURL() {},
+  contentURL() {
+  }
 
   /**
    * @return {!Common.ResourceType}
    */
-  contentType() {},
+  contentType() {
+  }
 
   /**
    * @return {!Promise<boolean>}
    */
-  contentEncoded() {},
+  contentEncoded() {
+  }
 
   /**
    * @return {!Promise<string>}
    */
-  requestContent() {},
+  requestContent() {
+  }
 
   /**
    * @param {string} query
@@ -60,12 +62,12 @@
    * @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
    */
   searchInContent(query, caseSensitive, isRegex) {}
-};
+}
 
 /**
  * @unrestricted
  */
-Common.ContentProvider.SearchMatch = class {
+export class SearchMatch {
   /**
    * @param {number} lineNumber
    * @param {string} lineContent
@@ -74,7 +76,7 @@
     this.lineNumber = lineNumber;
     this.lineContent = lineContent;
   }
-};
+}
 
 /**
  * @param {string} content
@@ -83,7 +85,7 @@
  * @param {boolean} isRegex
  * @return {!Array.<!Common.ContentProvider.SearchMatch>}
  */
-Common.ContentProvider.performSearchInContent = function(content, query, caseSensitive, isRegex) {
+export const performSearchInContent = function(content, query, caseSensitive, isRegex) {
   const regex = createSearchRegex(query, caseSensitive, isRegex);
 
   const text = new TextUtils.Text(content);
@@ -104,7 +106,7 @@
  * @param {?string=} charset
  * @return {?string}
  */
-Common.ContentProvider.contentAsDataURL = function(content, mimeType, contentEncoded, charset) {
+export const contentAsDataURL = function(content, mimeType, contentEncoded, charset) {
   const maxDataUrlSize = 1024 * 1024;
   if (content === null || content.length > maxDataUrlSize)
     return null;
@@ -112,3 +114,19 @@
   return 'data:' + mimeType + (charset ? ';charset=' + charset : '') + (contentEncoded ? ';base64' : '') + ',' +
       content;
 };
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.ContentProvider = ContentProvider;
+
+/**
+ * @constructor
+ */
+Common.ContentProvider.SearchMatch = SearchMatch;
+Common.ContentProvider.performSearchInContent = performSearchInContent;
+Common.ContentProvider.contentAsDataURL = contentAsDataURL;
diff --git a/third_party/blink/renderer/devtools/front_end/common/EventTarget.js b/third_party/blink/renderer/devtools/front_end/common/EventTarget.js
new file mode 100644
index 0000000..61f4719
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/EventTarget.js
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @param {!Array<!Common.EventTarget.EventDescriptor>} eventList
+ */
+export function removeEventListeners(eventList) {
+  for (const eventInfo of eventList)
+    eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.listener, eventInfo.thisObject);
+  // Do not hold references on unused event descriptors.
+  eventList.splice(0);
+}
+
+/**
+ * @interface
+ */
+export default class EventTarget {
+  /**
+   * @param {symbol} eventType
+   * @param {function(!Common.Event)} listener
+   * @param {!Object=} thisObject
+   * @return {!Common.EventTarget.EventDescriptor}
+   */
+  addEventListener(eventType, listener, thisObject) {
+  }
+
+  /**
+   * @param {symbol} eventType
+   * @return {!Promise<*>}
+   */
+  once(eventType) {
+  }
+
+  /**
+   * @param {string|symbol} eventType
+   * @param {function(!Common.Event)} listener
+   * @param {!Object=} thisObject
+   */
+  removeEventListener(eventType, listener, thisObject) {
+  }
+
+  /**
+   * @param {symbol} eventType
+   * @return {boolean}
+   */
+  hasEventListeners(eventType) {
+  }
+
+  /**
+   * @param {symbol} eventType
+   * @param {*=} eventData
+   */
+  dispatchEventToListeners(eventType, eventData) {
+  }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @typedef {!{data: *}}
+ */
+Common.Event;
+
+/**
+ * @interface
+ */
+Common.EventTarget = EventTarget;
+
+EventTarget.removeEventListeners = removeEventListeners;
+
+/**
+ * @typedef {!{eventTarget: !Common.EventTarget, eventType: (string|symbol), thisObject: (!Object|undefined), listener: function(!Common.Event)}}
+ */
+Common.EventTarget.EventDescriptor;
diff --git a/third_party/blink/renderer/devtools/front_end/common/JavaScriptMetaData.js b/third_party/blink/renderer/devtools/front_end/common/JavaScriptMetaData.js
new file mode 100644
index 0000000..9e3eda83
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/JavaScriptMetaData.js
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @interface
+ */
+export default class JavaScriptMetadata {
+  /**
+   * @param {string} name
+   * @return {?Array<!Array<string>>}
+   */
+  signaturesForNativeFunction(name) {
+  }
+
+  /**
+   * @param {string} name
+   * @param {string} receiverClassName
+   * @return {?Array<!Array<string>>}
+   */
+  signaturesForInstanceMethod(name, receiverClassName) {
+  }
+
+  /**
+   * @param {string} name
+   * @param {string} receiverConstructorName
+   * @return {?Array<!Array<string>>}
+   */
+  signaturesForStaticMethod(name, receiverConstructorName) {
+  }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.JavaScriptMetadata = JavaScriptMetadata;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Linkifier.js b/third_party/blink/renderer/devtools/front_end/common/Linkifier.js
new file mode 100644
index 0000000..14c161b
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/Linkifier.js
@@ -0,0 +1,42 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @interface
+ */
+export default class Linkifier {
+  /**
+   * @param {!Object} object
+   * @param {!Common.Linkifier.Options=} options
+   * @return {!Node}
+   */
+  linkify(object, options) {
+  }
+}
+
+/**
+ * @param {?Object} object
+ * @param {!Common.Linkifier.Options=} options
+ * @return {!Promise<!Node>}
+ */
+export function linkify(object, options) {
+  if (!object)
+    return Promise.reject(new Error('Can\'t linkify ' + object));
+  return self.runtime.extension(Common.Linkifier, object)
+      .instance()
+      .then(linkifier => linkifier.linkify(object, options));
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.Linkifier = Linkifier;
+Common.Linkifier.linkify = linkify;
+
+/** @typedef {{tooltip: (string|undefined), preventKeyboardFocus: (boolean|undefined)}} */
+Common.Linkifier.Options;
diff --git a/third_party/blink/renderer/devtools/front_end/common/ModuleExtensionInterfaces.js b/third_party/blink/renderer/devtools/front_end/common/ModuleExtensionInterfaces.js
deleted file mode 100644
index 5120202..0000000
--- a/third_party/blink/renderer/devtools/front_end/common/ModuleExtensionInterfaces.js
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @interface
- */
-Common.Revealer = function() {};
-
-/**
- * @param {?Object} revealable
- * @param {boolean=} omitFocus
- * @return {!Promise.<undefined>}
- */
-Common.Revealer.reveal = function(revealable, omitFocus) {
-  if (!revealable)
-    return Promise.reject(new Error('Can\'t reveal ' + revealable));
-  return self.runtime.allInstances(Common.Revealer, revealable).then(reveal);
-
-  /**
-   * @param {!Array.<!Common.Revealer>} revealers
-   * @return {!Promise.<undefined>}
-   */
-  function reveal(revealers) {
-    const promises = [];
-    for (let i = 0; i < revealers.length; ++i)
-      promises.push(revealers[i].reveal(/** @type {!Object} */ (revealable), omitFocus));
-    return Promise.race(promises);
-  }
-};
-
-/**
- * @param {?Object} revealable
- * @return {?string}
- */
-Common.Revealer.revealDestination = function(revealable) {
-  const extension = self.runtime.extension(Common.Revealer, revealable);
-  if (!extension)
-    return null;
-  return extension.descriptor()['destination'];
-};
-
-Common.Revealer.prototype = {
-  /**
-   * @param {!Object} object
-   * @param {boolean=} omitFocus
-   * @return {!Promise}
-   */
-  reveal(object, omitFocus) {}
-};
-
-/**
- * @interface
- */
-Common.App = function() {};
-
-Common.App.prototype = {
-  /**
-   * @param {!Document} document
-   */
-  presentUI(document) {}
-};
-
-/**
- * @interface
- */
-Common.AppProvider = function() {};
-
-Common.AppProvider.prototype = {
-  /**
-   * @return {!Common.App}
-   */
-  createApp() {}
-};
-
-/**
- * @interface
- */
-Common.QueryParamHandler = function() {};
-
-Common.QueryParamHandler.prototype = {
-  /**
-   * @param {string} value
-   */
-  handleQueryParam(value) {}
-};
-
-/**
- * @interface
- */
-Common.Runnable = function() {};
-
-Common.Runnable.prototype = {
-  /**
-   * @return {!Promise}
-   */
-  run() {}
-};
-
-/**
- * @interface
- */
-Common.Linkifier = function() {};
-
-Common.Linkifier.prototype = {
-  /**
-   * @param {!Object} object
-   * @param {!Common.Linkifier.Options=} options
-   * @return {!Node}
-   */
-  linkify(object, options) {}
-};
-
-/**
- * @param {?Object} object
- * @param {!Common.Linkifier.Options=} options
- * @return {!Promise<!Node>}
- */
-Common.Linkifier.linkify = function(object, options) {
-  if (!object)
-    return Promise.reject(new Error('Can\'t linkify ' + object));
-  return self.runtime.extension(Common.Linkifier, object)
-      .instance()
-      .then(linkifier => linkifier.linkify(object, options));
-};
-
-/** @typedef {{tooltip: (string|undefined), preventKeyboardFocus: (boolean|undefined)}} */
-Common.Linkifier.Options;
-
-/**
- * @interface
- */
-Common.JavaScriptMetadata = function() {};
-Common.JavaScriptMetadata.prototype = {
-
-  /**
-   * @param {string} name
-   * @return {?Array<!Array<string>>}
-   */
-  signaturesForNativeFunction(name) {},
-
-  /**
-   * @param {string} name
-   * @param {string} receiverClassName
-   * @return {?Array<!Array<string>>}
-   */
-  signaturesForInstanceMethod(name, receiverClassName) {},
-
-  /**
-   * @param {string} name
-   * @param {string} receiverConstructorName
-   * @return {?Array<!Array<string>>}
-   */
-  signaturesForStaticMethod(name, receiverConstructorName) {}
-};
diff --git a/third_party/blink/renderer/devtools/front_end/common/Object.js b/third_party/blink/renderer/devtools/front_end/common/Object.js
index 9f5e522..fa618cbc 100644
--- a/third_party/blink/renderer/devtools/front_end/common/Object.js
+++ b/third_party/blink/renderer/devtools/front_end/common/Object.js
@@ -27,7 +27,7 @@
  * @implements {Common.EventTarget}
  * @unrestricted
  */
-Common.Object = class {
+export default class ObjectWrapper {
   constructor() {
     /** @type {(!Map<string|symbol, !Array<!Common.Object._listenerCallbackTuple>>|undefined)} */
     this._listeners;
@@ -115,69 +115,18 @@
         listeners[i].listener.call(listeners[i].thisObject, event);
     }
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
 
 /**
- * @typedef {!{data: *}}
+ * @constructor
  */
-Common.Event;
+Common.Object = ObjectWrapper;
 
 /**
  * @typedef {!{thisObject: (!Object|undefined), listener: function(!Common.Event), disposed: (boolean|undefined)}}
  */
 Common.Object._listenerCallbackTuple;
-
-/**
- * @interface
- */
-Common.EventTarget = function() {};
-
-/**
- * @typedef {!{eventTarget: !Common.EventTarget, eventType: (string|symbol), thisObject: (!Object|undefined), listener: function(!Common.Event)}}
- */
-Common.EventTarget.EventDescriptor;
-
-/**
- * @param {!Array<!Common.EventTarget.EventDescriptor>} eventList
- */
-Common.EventTarget.removeEventListeners = function(eventList) {
-  for (const eventInfo of eventList)
-    eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.listener, eventInfo.thisObject);
-  // Do not hold references on unused event descriptors.
-  eventList.splice(0);
-};
-
-Common.EventTarget.prototype = {
-  /**
-   * @param {symbol} eventType
-   * @param {function(!Common.Event)} listener
-   * @param {!Object=} thisObject
-   * @return {!Common.EventTarget.EventDescriptor}
-   */
-  addEventListener(eventType, listener, thisObject) {},
-
-  /**
-   * @param {symbol} eventType
-   * @return {!Promise<*>}
-   */
-  once(eventType) {},
-
-  /**
-   * @param {string|symbol} eventType
-   * @param {function(!Common.Event)} listener
-   * @param {!Object=} thisObject
-   */
-  removeEventListener(eventType, listener, thisObject) {},
-
-  /**
-   * @param {symbol} eventType
-   * @return {boolean}
-   */
-  hasEventListeners(eventType) {},
-
-  /**
-   * @param {symbol} eventType
-   * @param {*=} eventData
-   */
-  dispatchEventToListeners(eventType, eventData) {},
-};
diff --git a/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js b/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js
index 9bdc4692..26dedde 100644
--- a/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js
+++ b/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js
@@ -29,7 +29,7 @@
 /**
  * @unrestricted
  */
-Common.ParsedURL = class {
+export default class ParsedURL {
   /**
    * @param {string} url
    */
@@ -388,8 +388,7 @@
       return this.url.substring(this.scheme.length + 3);
     return this.url;
   }
-};
-
+}
 
 /**
  * @return {?Common.ParsedURL}
@@ -400,3 +399,12 @@
     return parsedURL;
   return null;
 };
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.ParsedURL = ParsedURL;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Progress.js b/third_party/blink/renderer/devtools/front_end/common/Progress.js
index 669ecf0..2f24102 100644
--- a/third_party/blink/renderer/devtools/front_end/common/Progress.js
+++ b/third_party/blink/renderer/devtools/front_end/common/Progress.js
@@ -27,47 +27,51 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /**
  * @interface
  */
-Common.Progress = function() {};
-
-Common.Progress.prototype = {
+export default class Progress {
   /**
    * @param {number} totalWork
    */
-  setTotalWork(totalWork) {},
+  setTotalWork(totalWork) {
+  }
 
   /**
    * @param {string} title
    */
-  setTitle(title) {},
+  setTitle(title) {
+  }
 
   /**
    * @param {number} worked
    * @param {string=} title
    */
-  setWorked(worked, title) {},
+  setWorked(worked, title) {
+  }
 
   /**
    * @param {number=} worked
    */
-  worked(worked) {},
+  worked(worked) {
+  }
 
-  done() {},
+  done() {
+  }
 
   /**
    * @return {boolean}
    */
   isCanceled() {
     return false;
-  },
-};
+  }
+}
 
 /**
  * @unrestricted
  */
-Common.CompositeProgress = class {
+export class CompositeProgress {
   /**
    * @param {!Common.Progress} parent
    */
@@ -107,13 +111,13 @@
     }
     this._parent.setWorked(done / totalWeights);
   }
-};
+}
 
 /**
  * @implements {Common.Progress}
  * @unrestricted
  */
-Common.SubProgress = class {
+export class SubProgress {
   /**
    * @param {!Common.CompositeProgress} composite
    * @param {number=} weight
@@ -176,13 +180,13 @@
   worked(worked) {
     this.setWorked(this._worked + (worked || 1));
   }
-};
+}
 
 /**
  * @implements {Common.Progress}
  * @unrestricted
  */
-Common.ProgressProxy = class {
+export class ProgressProxy {
   /**
    * @param {?Common.Progress} delegate
    * @param {function()=} doneCallback
@@ -246,4 +250,28 @@
     if (this._delegate)
       this._delegate.worked(worked);
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.Progress = Progress;
+
+/**
+ * @constructor
+ */
+Common.CompositeProgress = CompositeProgress;
+
+/**
+ * @constructor
+ */
+Common.SubProgress = SubProgress;
+
+/**
+ * @constructor
+ */
+Common.ProgressProxy = ProgressProxy;
diff --git a/third_party/blink/renderer/devtools/front_end/common/QueryParamHandler.js b/third_party/blink/renderer/devtools/front_end/common/QueryParamHandler.js
new file mode 100644
index 0000000..60a1036
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/QueryParamHandler.js
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @interface
+ */
+export default class QueryParamHandler {
+  /**
+   * @param {string} value
+   */
+  handleQueryParam(value) {
+  }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.QueryParamHandler = QueryParamHandler;
diff --git a/third_party/blink/renderer/devtools/front_end/common/ResourceType.js b/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
index 5a69005e..068df21f 100644
--- a/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
+++ b/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
@@ -30,11 +30,11 @@
 /**
  * @unrestricted
  */
-Common.ResourceType = class {
+export default class ResourceType {
   /**
    * @param {string} name
    * @param {string} title
-   * @param {!Common.ResourceCategory} category
+   * @param {!ResourceCategory} category
    * @param {boolean} isTextType
    */
   constructor(name, title, category, isTextType) {
@@ -46,45 +46,45 @@
 
   /**
    * @param {string} mimeType
-   * @return {!Common.ResourceType}
+   * @return {!ResourceType}
    */
   static fromMimeType(mimeType) {
     if (mimeType.startsWith('text/html'))
-      return Common.resourceTypes.Document;
+      return resourceTypes.Document;
     if (mimeType.startsWith('text/css'))
-      return Common.resourceTypes.Stylesheet;
+      return resourceTypes.Stylesheet;
     if (mimeType.startsWith('image/'))
-      return Common.resourceTypes.Image;
+      return resourceTypes.Image;
     if (mimeType.startsWith('text/'))
-      return Common.resourceTypes.Script;
+      return resourceTypes.Script;
 
     if (mimeType.includes('font'))
-      return Common.resourceTypes.Font;
+      return resourceTypes.Font;
     if (mimeType.includes('script'))
-      return Common.resourceTypes.Script;
+      return resourceTypes.Script;
     if (mimeType.includes('octet'))
-      return Common.resourceTypes.Other;
+      return resourceTypes.Other;
     if (mimeType.includes('application'))
-      return Common.resourceTypes.Script;
+      return resourceTypes.Script;
 
-    return Common.resourceTypes.Other;
+    return resourceTypes.Other;
   }
 
   /**
    * @param {string} url
-   * @return {?Common.ResourceType}
+   * @return {?ResourceType}
    */
   static fromURL(url) {
-    return Common.ResourceType._resourceTypeByExtension.get(Common.ParsedURL.extractExtension(url)) || null;
+    return ResourceType._resourceTypeByExtension.get(Common.ParsedURL.extractExtension(url)) || null;
   }
 
   /**
    * @param {string} name
-   * @return {?Common.ResourceType}
+   * @return {?ResourceType}
    */
   static fromName(name) {
-    for (const resourceTypeId in Common.resourceTypes) {
-      const resourceType = Common.resourceTypes[resourceTypeId];
+    for (const resourceTypeId in resourceTypes) {
+      const resourceType = resourceTypes[resourceTypeId];
       if (resourceType.name() === name)
         return resourceType;
     }
@@ -97,11 +97,11 @@
    */
   static mimeFromURL(url) {
     const name = Common.ParsedURL.extractName(url);
-    if (Common.ResourceType._mimeTypeByName.has(name))
-      return Common.ResourceType._mimeTypeByName.get(name);
+    if (ResourceType._mimeTypeByName.has(name))
+      return ResourceType._mimeTypeByName.get(name);
 
     const ext = Common.ParsedURL.extractExtension(url).toLowerCase();
-    return Common.ResourceType._mimeTypeByExtension.get(ext);
+    return ResourceType._mimeTypeByExtension.get(ext);
   }
 
   /**
@@ -109,7 +109,7 @@
    * @return {string|undefined}
    */
   static mimeFromExtension(ext) {
-    return Common.ResourceType._mimeTypeByExtension.get(ext);
+    return ResourceType._mimeTypeByExtension.get(ext);
   }
 
   /**
@@ -127,7 +127,7 @@
   }
 
   /**
-   * @return {!Common.ResourceCategory}
+   * @return {!ResourceCategory}
    */
   category() {
     return this._category;
@@ -202,12 +202,12 @@
       return 'text/css';
     return '';
   }
-};
+}
 
 /**
  * @unrestricted
  */
-Common.ResourceCategory = class {
+export class ResourceCategory {
   /**
    * @param {string} title
    * @param {string} shortTitle
@@ -216,67 +216,68 @@
     this.title = title;
     this.shortTitle = shortTitle;
   }
-};
+}
 
-Common.resourceCategories = {
-  XHR: new Common.ResourceCategory('XHR and Fetch', 'XHR'),
-  Script: new Common.ResourceCategory('Scripts', 'JS'),
-  Stylesheet: new Common.ResourceCategory('Stylesheets', 'CSS'),
-  Image: new Common.ResourceCategory('Images', 'Img'),
-  Media: new Common.ResourceCategory('Media', 'Media'),
-  Font: new Common.ResourceCategory('Fonts', 'Font'),
-  Document: new Common.ResourceCategory('Documents', 'Doc'),
-  WebSocket: new Common.ResourceCategory('WebSockets', 'WS'),
-  Manifest: new Common.ResourceCategory('Manifest', 'Manifest'),
-  Other: new Common.ResourceCategory('Other', 'Other')
+/**
+ * @enum {!ResourceCategory}
+ */
+export const resourceCategories = {
+  XHR: new ResourceCategory('XHR and Fetch', 'XHR'),
+  Script: new ResourceCategory('Scripts', 'JS'),
+  Stylesheet: new ResourceCategory('Stylesheets', 'CSS'),
+  Image: new ResourceCategory('Images', 'Img'),
+  Media: new ResourceCategory('Media', 'Media'),
+  Font: new ResourceCategory('Fonts', 'Font'),
+  Document: new ResourceCategory('Documents', 'Doc'),
+  WebSocket: new ResourceCategory('WebSockets', 'WS'),
+  Manifest: new ResourceCategory('Manifest', 'Manifest'),
+  Other: new ResourceCategory('Other', 'Other')
 };
 
 /**
  * Keep these in sync with WebCore::InspectorPageAgent::resourceTypeJson
- * @enum {!Common.ResourceType}
+ * @enum {!ResourceType}
  */
-Common.resourceTypes = {
-  XHR: new Common.ResourceType('xhr', 'XHR', Common.resourceCategories.XHR, true),
-  Fetch: new Common.ResourceType('fetch', 'Fetch', Common.resourceCategories.XHR, true),
-  EventSource: new Common.ResourceType('eventsource', 'EventSource', Common.resourceCategories.XHR, true),
-  Script: new Common.ResourceType('script', 'Script', Common.resourceCategories.Script, true),
-  Stylesheet: new Common.ResourceType('stylesheet', 'Stylesheet', Common.resourceCategories.Stylesheet, true),
-  Image: new Common.ResourceType('image', 'Image', Common.resourceCategories.Image, false),
-  Media: new Common.ResourceType('media', 'Media', Common.resourceCategories.Media, false),
-  Font: new Common.ResourceType('font', 'Font', Common.resourceCategories.Font, false),
-  Document: new Common.ResourceType('document', 'Document', Common.resourceCategories.Document, true),
-  TextTrack: new Common.ResourceType('texttrack', 'TextTrack', Common.resourceCategories.Other, true),
-  WebSocket: new Common.ResourceType('websocket', 'WebSocket', Common.resourceCategories.WebSocket, false),
-  Other: new Common.ResourceType('other', 'Other', Common.resourceCategories.Other, false),
-  SourceMapScript: new Common.ResourceType('sm-script', 'Script', Common.resourceCategories.Script, true),
-  SourceMapStyleSheet:
-      new Common.ResourceType('sm-stylesheet', 'Stylesheet', Common.resourceCategories.Stylesheet, true),
-  Manifest: new Common.ResourceType('manifest', 'Manifest', Common.resourceCategories.Manifest, true),
-  SignedExchange: new Common.ResourceType('signed-exchange', 'SignedExchange', Common.resourceCategories.Other, false),
+export const resourceTypes = {
+  XHR: new ResourceType('xhr', 'XHR', resourceCategories.XHR, true),
+  Fetch: new ResourceType('fetch', 'Fetch', resourceCategories.XHR, true),
+  EventSource: new ResourceType('eventsource', 'EventSource', resourceCategories.XHR, true),
+  Script: new ResourceType('script', 'Script', resourceCategories.Script, true),
+  Stylesheet: new ResourceType('stylesheet', 'Stylesheet', resourceCategories.Stylesheet, true),
+  Image: new ResourceType('image', 'Image', resourceCategories.Image, false),
+  Media: new ResourceType('media', 'Media', resourceCategories.Media, false),
+  Font: new ResourceType('font', 'Font', resourceCategories.Font, false),
+  Document: new ResourceType('document', 'Document', resourceCategories.Document, true),
+  TextTrack: new ResourceType('texttrack', 'TextTrack', resourceCategories.Other, true),
+  WebSocket: new ResourceType('websocket', 'WebSocket', resourceCategories.WebSocket, false),
+  Other: new ResourceType('other', 'Other', resourceCategories.Other, false),
+  SourceMapScript: new ResourceType('sm-script', 'Script', resourceCategories.Script, true),
+  SourceMapStyleSheet: new ResourceType('sm-stylesheet', 'Stylesheet', resourceCategories.Stylesheet, true),
+  Manifest: new ResourceType('manifest', 'Manifest', resourceCategories.Manifest, true),
+  SignedExchange: new ResourceType('signed-exchange', 'SignedExchange', resourceCategories.Other, false),
 };
 
 
-Common.ResourceType._mimeTypeByName = new Map([
+export const _mimeTypeByName = new Map([
   // CoffeeScript
   ['Cakefile', 'text/x-coffeescript']
 ]);
 
-Common.ResourceType._resourceTypeByExtension = new Map([
-  ['js', Common.resourceTypes.Script], ['mjs', Common.resourceTypes.Script],
+export const _resourceTypeByExtension = new Map([
+  ['js', resourceTypes.Script], ['mjs', resourceTypes.Script],
 
-  ['css', Common.resourceTypes.Stylesheet], ['xsl', Common.resourceTypes.Stylesheet],
+  ['css', resourceTypes.Stylesheet], ['xsl', resourceTypes.Stylesheet],
 
-  ['jpeg', Common.resourceTypes.Image], ['jpg', Common.resourceTypes.Image], ['svg', Common.resourceTypes.Image],
-  ['gif', Common.resourceTypes.Image], ['png', Common.resourceTypes.Image], ['ico', Common.resourceTypes.Image],
-  ['tiff', Common.resourceTypes.Image], ['tif', Common.resourceTypes.Image], ['bmp', Common.resourceTypes.Image],
+  ['jpeg', resourceTypes.Image], ['jpg', resourceTypes.Image], ['svg', resourceTypes.Image],
+  ['gif', resourceTypes.Image], ['png', resourceTypes.Image], ['ico', resourceTypes.Image],
+  ['tiff', resourceTypes.Image], ['tif', resourceTypes.Image], ['bmp', resourceTypes.Image],
 
-  ['webp', Common.resourceTypes.Media],
+  ['webp', resourceTypes.Media],
 
-  ['ttf', Common.resourceTypes.Font], ['otf', Common.resourceTypes.Font], ['ttc', Common.resourceTypes.Font],
-  ['woff', Common.resourceTypes.Font]
+  ['ttf', resourceTypes.Font], ['otf', resourceTypes.Font], ['ttc', resourceTypes.Font], ['woff', resourceTypes.Font]
 ]);
 
-Common.ResourceType._mimeTypeByExtension = new Map([
+export const _mimeTypeByExtension = new Map([
   // Web extensions
   ['js', 'text/javascript'], ['mjs', 'text/javascript'], ['css', 'text/css'], ['html', 'text/html'],
   ['htm', 'text/html'], ['xml', 'application/xml'], ['xsl', 'application/xml'],
@@ -346,3 +347,31 @@
   // Font
   ['ttf', 'font/opentype'], ['otf', 'font/opentype'], ['ttc', 'font/opentype'], ['woff', 'application/font-woff']
 ]);
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @enum {!ResourceType}
+ */
+Common.resourceTypes = resourceTypes;
+
+/**
+ * @enum {!ResourceCategory}
+ */
+Common.resourceCategories = resourceCategories;
+
+/**
+ * @constructor
+ */
+Common.ResourceCategory = ResourceCategory;
+
+/**
+ * @constructor
+ */
+Common.ResourceType = ResourceType;
+
+Common.ResourceType._mimeTypeByName = _mimeTypeByName;
+Common.ResourceType._resourceTypeByExtension = _resourceTypeByExtension;
+Common.ResourceType._mimeTypeByExtension = _mimeTypeByExtension;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Revealer.js b/third_party/blink/renderer/devtools/front_end/common/Revealer.js
new file mode 100644
index 0000000..467c6e5
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/Revealer.js
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @interface
+ */
+export default class Revealer {
+  /**
+   * @param {!Object} object
+   * @param {boolean=} omitFocus
+   * @return {!Promise}
+   */
+  reveal(object, omitFocus) {
+  }
+}
+
+/**
+ * @param {?Object} revealable
+ * @param {boolean=} omitFocus
+ * @return {!Promise.<undefined>}
+ */
+export const reveal = function(revealable, omitFocus) {
+  if (!revealable)
+    return Promise.reject(new Error('Can\'t reveal ' + revealable));
+  return self.runtime.allInstances(Common.Revealer, revealable).then(reveal);
+
+  /**
+   * @param {!Array.<!Common.Revealer>} revealers
+   * @return {!Promise.<undefined>}
+   */
+  function reveal(revealers) {
+    const promises = [];
+    for (let i = 0; i < revealers.length; ++i)
+      promises.push(revealers[i].reveal(/** @type {!Object} */ (revealable), omitFocus));
+    return Promise.race(promises);
+  }
+};
+
+/**
+ * @param {?Object} revealable
+ * @return {?string}
+ */
+export const revealDestination = function(revealable) {
+  const extension = self.runtime.extension(Common.Revealer, revealable);
+  if (!extension)
+    return null;
+  return extension.descriptor()['destination'];
+};
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.Revealer = Revealer;
+Common.Revealer.reveal = reveal;
+Common.Revealer.revealDestination = revealDestination;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Runnable.js b/third_party/blink/renderer/devtools/front_end/common/Runnable.js
new file mode 100644
index 0000000..5edda69
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/Runnable.js
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @interface
+ */
+export default class Runnable {
+  /**
+   * @return {!Promise}
+   */
+  run() {
+  }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.Runnable = Runnable;
diff --git a/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js b/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js
index ddb66da..9436ba1 100644
--- a/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js
+++ b/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js
@@ -4,7 +4,7 @@
 /**
  * @unrestricted
  */
-Common.Segment = class {
+export class Segment {
   /**
    * @param {number} begin
    * @param {number} end
@@ -25,12 +25,12 @@
   intersects(that) {
     return this.begin < that.end && that.begin < this.end;
   }
-};
+}
 
 /**
  * @unrestricted
  */
-Common.SegmentedRange = class {
+export default class SegmentedRange {
   /**
    * @param {(function(!Common.Segment, !Common.Segment): ?Common.Segment)=} mergeCallback
    */
@@ -108,4 +108,18 @@
     merged.end = Math.max(first.end, second.end);
     return merged;
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.Segment = Segment;
+
+/**
+ * @constructor
+ */
+Common.SegmentedRange = SegmentedRange;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Settings.js b/third_party/blink/renderer/devtools/front_end/common/Settings.js
index 2c1e9844..ede3af62 100644
--- a/third_party/blink/renderer/devtools/front_end/common/Settings.js
+++ b/third_party/blink/renderer/devtools/front_end/common/Settings.js
@@ -31,7 +31,7 @@
 /**
  * @unrestricted
  */
-Common.Settings = class {
+export default class Settings {
   /**
    * @param {!Common.SettingsStorage} globalStorage
    * @param {!Common.SettingsStorage} localStorage
@@ -164,12 +164,12 @@
     }
     return this._globalStorage;
   }
-};
+}
 
 /**
  * @unrestricted
  */
-Common.SettingsStorage = class {
+export class SettingsStorage {
   /**
    * @param {!Object} object
    * @param {function(string, string)=} setCallback
@@ -244,13 +244,13 @@
     for (let i = 0; i < 10 && i < keys.length; ++i)
       Common.console.log('Setting: \'' + keys[i] + '\', size: ' + sizes[keys[i]]);
   }
-};
+}
 
 /**
  * @template V
  * @unrestricted
  */
-Common.Setting = class {
+export class Setting {
   /**
    * @param {!Common.Settings} settings
    * @param {string} name
@@ -376,12 +376,12 @@
     Common.console.error(errorMessage);
     this._storage._dumpSizes();
   }
-};
+}
 
 /**
  * @unrestricted
  */
-Common.RegExpSetting = class extends Common.Setting {
+export class RegExpSetting extends Setting {
   /**
    * @param {!Common.Settings} settings
    * @param {string} name
@@ -448,12 +448,12 @@
     }
     return this._regex;
   }
-};
+}
 
 /**
  * @unrestricted
  */
-Common.VersionController = class {
+export class VersionController {
   updateVersion() {
     const localStorageVersion =
         window.localStorage ? window.localStorage[Common.VersionController._currentVersionName] : 0;
@@ -877,20 +877,12 @@
     if (breakpointsSetting.get().length > maxBreakpointsCount)
       breakpointsSetting.set([]);
   }
-};
-
-Common.VersionController._currentVersionName = 'inspectorVersion';
-Common.VersionController.currentVersion = 28;
-
-/**
- * @type {!Common.Settings}
- */
-Common.settings;
+}
 
 /**
  * @enum {symbol}
  */
-Common.SettingStorageType = {
+export const SettingStorageType = {
   Global: Symbol('Global'),
   Local: Symbol('Local'),
   Session: Symbol('Session')
@@ -900,14 +892,58 @@
  * @param {string} settingName
  * @return {!Common.Setting}
  */
-Common.moduleSetting = function(settingName) {
+export function moduleSetting(settingName) {
   return Common.settings.moduleSetting(settingName);
-};
+}
 
 /**
  * @param {string} settingName
  * @return {!Common.Setting}
  */
-Common.settingForTest = function(settingName) {
+export function settingForTest(settingName) {
   return Common.settings.settingForTest(settingName);
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.Settings = Settings;
+
+/**
+ * @constructor
+ */
+Common.SettingsStorage = SettingsStorage;
+
+/**
+ * @constructor
+ */
+Common.Setting = Setting;
+
+/**
+ * @constructor
+ */
+Common.RegExpSetting = RegExpSetting;
+Common.settingForTest = settingForTest;
+
+/**
+ * @constructor
+ */
+Common.VersionController = VersionController;
+Common.moduleSetting = moduleSetting;
+
+/**
+ * @enum {symbol}
+ */
+Common.SettingStorageType = SettingStorageType;
+
+Common.VersionController._currentVersionName = 'inspectorVersion';
+Common.VersionController.currentVersion = 28;
+
+/**
+ * @type {!Common.Settings}
+ */
+Common.settings;
diff --git a/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js b/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js
index 96fd157..9575a9a 100644
--- a/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js
+++ b/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js
@@ -5,7 +5,7 @@
  * @implements {Common.ContentProvider}
  * @unrestricted
  */
-Common.StaticContentProvider = class {
+export default class StaticContentProvider {
   /**
    * @param {string} contentURL
    * @param {!Common.ResourceType} contentType
@@ -71,4 +71,13 @@
     const content = await this._lazyContent();
     return content ? Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex) : [];
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.StaticContentProvider = StaticContentProvider;
diff --git a/third_party/blink/renderer/devtools/front_end/common/OutputStream.js b/third_party/blink/renderer/devtools/front_end/common/StringOutputStream.js
similarity index 65%
rename from third_party/blink/renderer/devtools/front_end/common/OutputStream.js
rename to third_party/blink/renderer/devtools/front_end/common/StringOutputStream.js
index 1e72025..abd6b49 100644
--- a/third_party/blink/renderer/devtools/front_end/common/OutputStream.js
+++ b/third_party/blink/renderer/devtools/front_end/common/StringOutputStream.js
@@ -5,25 +5,25 @@
 /**
  * @interface
  */
-Common.OutputStream = function() {};
-
-Common.OutputStream.prototype = {
+export class OutputStream {
   /**
    * @param {string} data
    * @return {!Promise}
    */
-  write(data) {},
+  async write(data) {
+  }
 
   /**
    * @return {!Promise}
    */
-  close() {}
-};
+  async close() {
+  }
+}
 
 /**
  * @implements {Common.OutputStream}
  */
-Common.StringOutputStream = class {
+export default class StringOutputStream {
   constructor() {
     this._data = '';
   }
@@ -40,7 +40,7 @@
   /**
    * @override
    */
-  close() {
+  async close() {
   }
 
   /**
@@ -49,4 +49,14 @@
   data() {
     return this._data;
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.OutputStream = OutputStream;
+Common.StringOutputStream = StringOutputStream;
diff --git a/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js b/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js
index 9c555b2..e190f39 100644
--- a/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js
+++ b/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js
@@ -31,7 +31,7 @@
 /**
  * @unrestricted
  */
-Common.TextDictionary = class {
+export default class TextDictionary {
   constructor() {
     /** @type {!Map<string, number>} */
     this._words = new Map();
@@ -92,4 +92,10 @@
     this._words.clear();
     this._index.clear();
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+Common.TextDictionary = TextDictionary;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Throttler.js b/third_party/blink/renderer/devtools/front_end/common/Throttler.js
index a88e78f5..21c5f797 100644
--- a/third_party/blink/renderer/devtools/front_end/common/Throttler.js
+++ b/third_party/blink/renderer/devtools/front_end/common/Throttler.js
@@ -1,10 +1,11 @@
 // Copyright 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
+
 /**
  * @unrestricted
  */
-Common.Throttler = class {
+export default class Throttler {
   /**
    * @param {number} timeout
    */
@@ -108,7 +109,13 @@
   _getTime() {
     return window.performance.now();
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+Common.Throttler = Throttler;
 
 /** @typedef {function(!Error=)} */
 Common.Throttler.FinishCallback;
diff --git a/third_party/blink/renderer/devtools/front_end/common/Trie.js b/third_party/blink/renderer/devtools/front_end/common/Trie.js
index 98291c50..22afde9f 100644
--- a/third_party/blink/renderer/devtools/front_end/common/Trie.js
+++ b/third_party/blink/renderer/devtools/front_end/common/Trie.js
@@ -4,7 +4,7 @@
 /**
  * @unrestricted
  */
-Common.Trie = class {
+export default class Trie {
   constructor() {
     this.clear();
   }
@@ -132,4 +132,10 @@
     /** @type {!Array<number>} */
     this._freeNodes = [];
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+Common.Trie = Trie;
diff --git a/third_party/blink/renderer/devtools/front_end/common/UIString.js b/third_party/blink/renderer/devtools/front_end/common/UIString.js
index cd5f7d08e..64b1fcc 100644
--- a/third_party/blink/renderer/devtools/front_end/common/UIString.js
+++ b/third_party/blink/renderer/devtools/front_end/common/UIString.js
@@ -29,57 +29,55 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-self['Common'] = self['Common'] || {};
-
 /**
  * @param {string} string
  * @param {...*} vararg
  * @return {string}
  */
-Common.UIString = function(string, vararg) {
+export default function UIString(string, vararg) {
   return String.vsprintf(Common.localize(string), Array.prototype.slice.call(arguments, 1));
-};
+}
 
 /**
  * @param {string} string
  * @param {?ArrayLike} values
  * @return {string}
  */
-Common.serializeUIString = function(string, values = []) {
+export function serializeUIString(string, values = []) {
   const messageParts = [string];
   const serializedMessage = {messageParts, values};
   return JSON.stringify(serializedMessage);
-};
+}
 
 /**
  * @param {string} serializedMessage
  * @return {*}
  */
-Common.deserializeUIString = function(serializedMessage) {
+export function deserializeUIString(serializedMessage) {
   if (!serializedMessage)
     return {};
 
   return JSON.parse(serializedMessage);
-};
+}
 
 /**
  * @param {string} string
  * @return {string}
  */
-Common.localize = function(string) {
+export function localize(string) {
   return string;
-};
+}
 
 /**
  * @unrestricted
  */
-Common.UIStringFormat = class {
+export class UIStringFormat {
   /**
    * @param {string} format
    */
   constructor(format) {
     /** @type {string} */
-    this._localizedFormat = Common.localize(format);
+    this._localizedFormat = localize(format);
     /** @type {!Array.<!Object>} */
     this._tokenizedFormat = String.tokenizeFormatString(this._localizedFormat, String.standardFormatters);
   }
@@ -104,10 +102,7 @@
             this._tokenizedFormat)
         .formattedResult;
   }
-};
-
-/** @type {!WeakMap<!Array<string>, string>} */
-Common._substitutionStrings = new WeakMap();
+}
 
 /**
  * @param {!Array<string>|string} strings
@@ -124,3 +119,20 @@
   }
   return Common.UIString(substitutionString, ...Array.prototype.slice.call(arguments, 1));
 };
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.UIStringFormat = UIStringFormat;
+
+Common.UIString = UIString;
+Common.serializeUIString = serializeUIString;
+Common.deserializeUIString = deserializeUIString;
+Common.localize = localize;
+
+/** @type {!WeakMap<!Array<string>, string>} */
+Common._substitutionStrings = new WeakMap();
diff --git a/third_party/blink/renderer/devtools/front_end/common/Worker.js b/third_party/blink/renderer/devtools/front_end/common/Worker.js
index 5bdaced..a9c31a6 100644
--- a/third_party/blink/renderer/devtools/front_end/common/Worker.js
+++ b/third_party/blink/renderer/devtools/front_end/common/Worker.js
@@ -31,7 +31,7 @@
 /**
  * @unrestricted
  */
-Common.Worker = class {
+export default class WorkerWrapper {
   /**
    * @param {string} appName
    */
@@ -91,4 +91,13 @@
   set onerror(listener) {
     this._workerPromise.then(worker => worker.onerror = listener);
   }
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.Worker = WorkerWrapper;
diff --git a/third_party/blink/renderer/devtools/front_end/common/common.js b/third_party/blink/renderer/devtools/front_end/common/common.js
new file mode 100644
index 0000000..fe28919
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/common/common.js
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './EventTarget.js';
+import './Object.js';
+
+// Do not reorder these imports as it breaks dependencies.
+
+import * as App from './App.js';
+import * as AppProvider from './AppProvider.js';
+import * as CharacterIdMap from './CharacterIdMap.js';
+import * as Color from './Color.js';
+import * as Console from './Console.js';
+import * as ContentProvider from './ContentProvider.js';
+import * as EventTarget from './EventTarget.js';
+import * as JavaScriptMetaData from './JavaScriptMetaData.js';
+import * as Linkifier from './Linkifier.js';
+import * as Object from './Object.js';
+import * as ParsedURL from './ParsedURL.js';
+import * as Progress from './Progress.js';
+import * as QueryParamHandler from './QueryParamHandler.js';
+import * as ResourceType from './ResourceType.js';
+import * as Revealer from './Revealer.js';
+import * as Runnable from './Runnable.js';
+import * as SegmentedRange from './SegmentedRange.js';
+import * as Settings from './Settings.js';
+import * as StaticContentProvider from './StaticContentProvider.js';
+import * as StringOutputStream from './StringOutputStream.js';
+import * as TextDictionary from './TextDictionary.js';
+import * as Throttler from './Throttler.js';
+import * as Trie from './Trie.js';
+import * as UIString from './UIString.js';
+import * as Worker from './Worker.js';
+
+export {
+  App,
+  AppProvider,
+  CharacterIdMap,
+  Color,
+  Console,
+  ContentProvider,
+  EventTarget,
+  JavaScriptMetaData,
+  Linkifier,
+  Object,
+  ParsedURL,
+  Progress,
+  QueryParamHandler,
+  ResourceType,
+  Revealer,
+  Runnable,
+  SegmentedRange,
+  Settings,
+  StaticContentProvider,
+  StringOutputStream,
+  TextDictionary,
+  Throttler,
+  Trie,
+  UIString,
+  Worker,
+};
diff --git a/third_party/blink/renderer/devtools/front_end/common/module.json b/third_party/blink/renderer/devtools/front_end/common/module.json
index 99b5427..e685577 100644
--- a/third_party/blink/renderer/devtools/front_end/common/module.json
+++ b/third_party/blink/renderer/devtools/front_end/common/module.json
@@ -3,10 +3,12 @@
         "text_utils",
         "platform"
     ],
-    "scripts": [
+    "modules": [
+        "common.js",
+        "EventTarget.js",
+        "Object.js",
         "Worker.js",
         "TextDictionary.js",
-        "Object.js",
         "Color.js",
         "Console.js",
         "ContentProvider.js",
@@ -15,12 +17,20 @@
         "ResourceType.js",
         "Settings.js",
         "StaticContentProvider.js",
-        "OutputStream.js",
         "SegmentedRange.js",
         "Throttler.js",
         "Trie.js",
         "UIString.js",
-        "ModuleExtensionInterfaces.js",
+        "Revealer.js",
+        "App.js",
+        "AppProvider.js",
+        "JavaScriptMetaData.js",
+        "Linkifier.js",
+        "QueryParamHandler.js",
+        "Revealer.js",
+        "Runnable.js",
+        "StringOutputStream.js",
         "CharacterIdMap.js"
-    ]
+    ],
+    "scripts": []
 }
diff --git a/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js b/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
index 5502e1fa..1b9a8a4 100644
--- a/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
+++ b/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
@@ -49,6 +49,12 @@
     this._currentPollPromise = null;
     /** @type {?boolean} */
     this._shouldResumePollingOnResume = false;
+    /** @type {!Array<!{rawCoverageData:!Array<!Protocol.Profiler.ScriptCoverage>,stamp:number}>} */
+    this._jsBacklog = [];
+    /** @type {!Array<!{rawCoverageData:!Array<!Protocol.CSS.RuleUsage>,stamp:number}>} */
+    this._cssBacklog = [];
+    /** @type {?boolean} */
+    this._performanceTraceRecording = false;
   }
 
   /**
@@ -103,12 +109,11 @@
    * @return {!Promise}
    */
   async _pollLoop() {
-    const coveragePollingPeriodMs = 700;
     this._clearTimer();
     this._currentPollPromise = this._pollAndCallback();
     await this._currentPollPromise;
-    if (this._suspensionState === Coverage.SuspensionState.Active)
-      this._pollTimer = setTimeout(() => this._pollLoop(), coveragePollingPeriodMs);
+    if (this._suspensionState === Coverage.SuspensionState.Active || this._performanceTraceRecording)
+      this._pollTimer = setTimeout(() => this._pollLoop(), Coverage.CoverageModel._coveragePollingPeriodMs);
   }
 
   async stopPolling() {
@@ -123,13 +128,14 @@
    * @return {!Promise<undefined>}
    */
   async _pollAndCallback() {
-    if (this._suspensionState === Coverage.SuspensionState.Suspended)
+    if (this._suspensionState === Coverage.SuspensionState.Suspended && !this._performanceTraceRecording)
       return;
     const updates = await this._takeAllCoverage();
     // This conditional should never trigger, as all intended ways to stop
     // polling are awaiting the `_currentPollPromise` before suspending.
     console.assert(
-        this._suspensionState !== Coverage.SuspensionState.Suspended, 'CoverageModel was suspended while polling.');
+        this._suspensionState !== Coverage.SuspensionState.Suspended || this._performanceTraceRecording,
+        'CoverageModel was suspended while polling.');
     if (updates.length)
       this.dispatchEventToListeners(Coverage.CoverageModel.Events.CoverageUpdated, updates);
   }
@@ -145,12 +151,18 @@
    * Stops polling as preparation for suspension. This function is idempotent
    * due because it changes the state to suspending.
    * @override
+   * @param {string=} reason - optionally provide a reason, so the model can respond accordingly
    * @return {!Promise<undefined>}
    */
-  async preSuspendModel() {
+  async preSuspendModel(reason) {
     if (this._suspensionState !== Coverage.SuspensionState.Active)
       return;
     this._suspensionState = Coverage.SuspensionState.Suspending;
+    if (reason === 'performance-timeline') {
+      this._performanceTraceRecording = true;
+      // Keep polling to the backlog if a performance trace is recorded.
+      return;
+    }
     if (this._currentPollPromise) {
       await this.stopPolling();
       this._shouldResumePollingOnResume = true;
@@ -159,9 +171,10 @@
 
   /**
    * @override
+   * @param {string=} reason - optionally provide a reason, so the model can respond accordingly
    * @return {!Promise<undefined>}
    */
-  async suspendModel() {
+  async suspendModel(reason) {
     this._suspensionState = Coverage.SuspensionState.Suspended;
   }
 
@@ -170,7 +183,6 @@
    * @return {!Promise<undefined>}
    */
   async resumeModel() {
-    this._suspensionState = Coverage.SuspensionState.Active;
   }
 
   /**
@@ -180,9 +192,11 @@
    * @return {!Promise<undefined>}
    */
   async postResumeModel() {
+    this._suspensionState = Coverage.SuspensionState.Active;
+    this._performanceTraceRecording = false;
     if (this._shouldResumePollingOnResume) {
-      await this.startPolling();
       this._shouldResumePollingOnResume = false;
+      await this.startPolling();
     }
   }
 
@@ -235,25 +249,40 @@
   async _takeJSCoverage() {
     if (!this._cpuProfilerModel)
       return [];
-    let rawCoverageData = await this._cpuProfilerModel.takePreciseCoverage();
+    const now = Date.now();
+    let freshRawCoverageData = await this._cpuProfilerModel.takePreciseCoverage();
     if (this._bestEffortCoveragePromise) {
       const bestEffortCoverage = await this._bestEffortCoveragePromise;
       this._bestEffortCoveragePromise = null;
-      rawCoverageData = bestEffortCoverage.concat(rawCoverageData);
+      freshRawCoverageData = bestEffortCoverage.concat(freshRawCoverageData);
     }
-    return this._processJSCoverage(rawCoverageData);
+    if (this._suspensionState !== Coverage.SuspensionState.Active) {
+      if (freshRawCoverageData.length > 0)
+        this._jsBacklog.push({rawCoverageData: freshRawCoverageData, stamp: now});
+
+      return [];
+    }
+    const results = [];
+    for (const {rawCoverageData, stamp} of this._jsBacklog)
+      results.push(this._processJSCoverage(rawCoverageData, stamp));
+
+    this._jsBacklog = [];
+    if (freshRawCoverageData.length > 0)
+      results.push(this._processJSCoverage(freshRawCoverageData, now));
+    return results.flat();
   }
 
   /**
    * @param {!Array<!Protocol.Profiler.ScriptCoverage>} scriptsCoverage
    * @return {!Array<!Coverage.CoverageInfo>}
    */
-  _processJSCoverage(scriptsCoverage) {
+  _processJSCoverage(scriptsCoverage, stamp) {
     const updatedEntries = [];
     for (const entry of scriptsCoverage) {
       const script = this._debuggerModel.scriptForId(entry.scriptId);
       if (!script)
         continue;
+
       const ranges = [];
       let type = Coverage.CoverageType.JavaScript;
       for (const func of entry.functions) {
@@ -268,7 +297,7 @@
       }
       const subentry = this._addCoverage(
           script, script.contentLength, script.lineOffset, script.columnOffset, ranges,
-          /** @type {!Coverage.CoverageType} */ (type));
+          /** @type {!Coverage.CoverageType} */ (type), stamp);
       if (subentry)
         updatedEntries.push(subentry);
     }
@@ -281,15 +310,29 @@
   async _takeCSSCoverage() {
     if (!this._cssModel)
       return [];
-    const rawCoverageData = await this._cssModel.takeCoverageDelta();
-    return this._processCSSCoverage(rawCoverageData);
+    const now = Date.now();
+    const freshRawCoverageData = await this._cssModel.takeCoverageDelta();
+    if (this._suspensionState !== Coverage.SuspensionState.Active) {
+      if (freshRawCoverageData.length > 0)
+        this._cssBacklog.push({rawCoverageData: freshRawCoverageData, stamp: now});
+
+      return [];
+    }
+    const results = [];
+    for (const {rawCoverageData, stamp} of this._cssBacklog)
+      results.push(this._processCSSCoverage(rawCoverageData, stamp));
+
+    this._cssBacklog = [];
+    if (freshRawCoverageData.length > 0)
+      results.push(this._processCSSCoverage(freshRawCoverageData, now));
+    return results.flat();
   }
 
   /**
    * @param {!Array<!Protocol.CSS.RuleUsage>} ruleUsageList
    * @return {!Array<!Coverage.CoverageInfo>}
    */
-  _processCSSCoverage(ruleUsageList) {
+  _processCSSCoverage(ruleUsageList, stamp) {
     const updatedEntries = [];
     /** @type {!Map<!SDK.CSSStyleSheetHeader, !Array<!Coverage.RangeUseCount>>} */
     const rulesByStyleSheet = new Map();
@@ -309,7 +352,7 @@
       const ranges = /** @type {!Array<!Coverage.RangeUseCount>} */ (entry[1]);
       const subentry = this._addCoverage(
           styleSheetHeader, styleSheetHeader.contentLength, styleSheetHeader.startLine, styleSheetHeader.startColumn,
-          ranges, Coverage.CoverageType.CSS);
+          ranges, Coverage.CoverageType.CSS, stamp);
       if (subentry)
         updatedEntries.push(subentry);
     }
@@ -320,7 +363,7 @@
    * @param {!Array<!Coverage.RangeUseCount>} ranges
    * @return {!Array<!Coverage.CoverageSegment>}
    */
-  static _convertToDisjointSegments(ranges) {
+  static _convertToDisjointSegments(ranges, stamp) {
     ranges.sort((a, b) => a.startOffset - b.startOffset);
 
     const result = [];
@@ -355,7 +398,7 @@
           return;
         }
       }
-      result.push({end: end, count: count});
+      result.push({end: end, count: count, stamp: stamp});
     }
 
     return result;
@@ -370,7 +413,7 @@
    * @param {!Coverage.CoverageType} type
    * @return {?Coverage.CoverageInfo}
    */
-  _addCoverage(contentProvider, contentLength, startLine, startColumn, ranges, type) {
+  _addCoverage(contentProvider, contentLength, startLine, startColumn, ranges, type, stamp) {
     const url = contentProvider.contentURL();
     if (!url)
       return null;
@@ -382,9 +425,9 @@
 
     const coverageInfo = urlCoverage._ensureEntry(contentProvider, contentLength, startLine, startColumn, type);
     this._coverageByContentProvider.set(contentProvider, coverageInfo);
-    const segments = Coverage.CoverageModel._convertToDisjointSegments(ranges);
+    const segments = Coverage.CoverageModel._convertToDisjointSegments(ranges, stamp);
     if (segments.length && segments.peekLast().end < contentLength)
-      segments.push({end: contentLength});
+      segments.push({end: contentLength, stamp: stamp});
     const oldUsedSize = coverageInfo._usedSize;
     coverageInfo.mergeCoverage(segments);
     if (coverageInfo._usedSize === oldUsedSize)
@@ -464,13 +507,16 @@
   }
 };
 
-SDK.SDKModel.register(Coverage.CoverageModel, SDK.Target.Capability.None, false);
-
 /** @enum {symbol} */
 Coverage.CoverageModel.Events = {
   CoverageUpdated: Symbol('CoverageUpdated')
 };
 
+/** @type {number} */
+Coverage.CoverageModel._coveragePollingPeriodMs = 200;
+
+SDK.SDKModel.register(Coverage.CoverageModel, SDK.Target.Capability.None, false);
+
 Coverage.URLCoverageInfo = class {
   /**
    * @param {string} url
@@ -528,6 +574,10 @@
     return this._isContentScript;
   }
 
+  entries() {
+    return this._coverageInfoByLocation.values();
+  }
+
   /**
    * @param {!Common.ContentProvider} contentProvider
    * @param {number} contentLength
@@ -572,6 +622,7 @@
     this._contentProvider = contentProvider;
     this._size = size;
     this._usedSize = 0;
+    this._statsByTimestamp = new Map();
     this._lineOffset = lineOffset;
     this._columnOffset = columnOffset;
     this._coverageType = type;
@@ -609,6 +660,14 @@
     this._updateStats();
   }
 
+  usedByTimestamp() {
+    return this._statsByTimestamp;
+  }
+
+  size() {
+    return this._size;
+  }
+
   /**
    * @param {number} start
    * @param {number} end
@@ -639,8 +698,9 @@
           typeof a.count === 'number' || typeof b.count === 'number' ? (a.count || 0) + (b.count || 0) : undefined;
       const end = Math.min(a.end, b.end);
       const last = result.peekLast();
-      if (!last || last.count !== count)
-        result.push({end: end, count: count});
+      const stamp = Math.min(a.stamp, b.stamp);
+      if (!last || last.count !== count || last.stamp !== stamp)
+        result.push({end: end, count: count, stamp: stamp});
       else
         last.end = end;
       if (a.end <= b.end)
@@ -657,12 +717,19 @@
   }
 
   _updateStats() {
+    this._statsByTimestamp = new Map();
     this._usedSize = 0;
 
     let last = 0;
     for (const segment of this._segments) {
-      if (segment.count)
-        this._usedSize += segment.end - last;
+      if (!this._statsByTimestamp.has(segment.stamp))
+        this._statsByTimestamp.set(segment.stamp, 0);
+
+      if (segment.count) {
+        const used = segment.end - last;
+        this._usedSize += used;
+        this._statsByTimestamp.set(segment.stamp, this._statsByTimestamp.get(segment.stamp) + used);
+      }
       last = segment.end;
     }
   }
diff --git a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js
index 44b9b2e..7750502 100644
--- a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js
+++ b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js
@@ -2,6 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 // Release build has Runtime.js bundled.
+
+// FIXME(http://crbug.com/1007254)
+const __import = path => {
+  const relativePath = new URL(path, self.location.href);
+  return eval(`import('${relativePath}')`);
+};
+
 if (!self.Runtime)
   self.importScripts('Runtime.js');
-Runtime.startWorker('heap_snapshot_worker');
+__import('./common/common.js').then(_ => Runtime.startWorker('heap_snapshot_worker'));
diff --git a/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js b/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js
index 022a911..4002240 100644
--- a/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js
+++ b/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js
@@ -71,4 +71,4 @@
  *  receiver: (string|undefined),
  * }>}
  */
-JavaScriptMetadata.NativeFunctions;
\ No newline at end of file
+JavaScriptMetadata.NativeFunctions;
diff --git a/third_party/blink/renderer/devtools/front_end/network/networkLogView.css b/third_party/blink/renderer/devtools/front_end/network/networkLogView.css
index b42f2ab..51ca477 100644
--- a/third_party/blink/renderer/devtools/front_end/network/networkLogView.css
+++ b/third_party/blink/renderer/devtools/front_end/network/networkLogView.css
@@ -135,9 +135,15 @@
 .network-log-grid.data-grid tr.selected.network-error-row,
 .network-log-grid.data-grid tr.selected.network-error-row .network-cell-subtitle,
 .network-log-grid.data-grid tr.selected.network-error-row .network-dim-cell {
-    color: rgb(230, 0, 0);
+    color: rgb(230, 0, 0) !important;
 }
 
+.network-log-grid.data-grid:focus tr.selected.network-error-row,
+.network-log-grid.data-grid:focus tr.selected.network-error-row .network-cell-subtitle,
+.network-log-grid.data-grid:focus tr.selected.network-error-row .network-dim-cell {
+    background: hsl(0, 100%, 97%) !important;
+    color: rgb(230, 0, 0) !important;
+}
 .initiator-column .devtools-link {
     color: inherit;
 }
diff --git a/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js b/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
index 54c6cb5..df6ad0b 100644
--- a/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
+++ b/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
@@ -28,7 +28,10 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/** @typedef {string} */
+/**
+ * @typedef {string}
+ * @suppress {checkTypes}
+ */
 Protocol.Error = Symbol('Protocol.Error');
 
 /**
diff --git a/third_party/blink/renderer/devtools/front_end/root.js b/third_party/blink/renderer/devtools/front_end/root.js
index 4590c37c..022ced9 100644
--- a/third_party/blink/renderer/devtools/front_end/root.js
+++ b/third_party/blink/renderer/devtools/front_end/root.js
@@ -2,4 +2,5 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import './common/common.js';
 import './ui/ui.js';
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/Target.js b/third_party/blink/renderer/devtools/front_end/sdk/Target.js
index 8db7ff2..a9f47b7 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/Target.js
+++ b/third_party/blink/renderer/devtools/front_end/sdk/Target.js
@@ -198,15 +198,16 @@
   }
 
   /**
+   * @param {string=} reason - optionally provide a reason, so models can respond accordingly
    * @return {!Promise}
    */
-  async suspend() {
+  async suspend(reason) {
     if (this._isSuspended)
       return Promise.resolve();
     this._isSuspended = true;
 
-    await Promise.all(Array.from(this.models().values(), m => m.preSuspendModel()));
-    await Promise.all(Array.from(this.models().values(), m => m.suspendModel()));
+    await Promise.all(Array.from(this.models().values(), m => m.preSuspendModel(reason)));
+    await Promise.all(Array.from(this.models().values(), m => m.suspendModel(reason)));
   }
 
   /**
@@ -285,16 +286,18 @@
   /**
    * Override this method to perform tasks that are required to suspend the
    * model and that still need other models in an unsuspended state.
+   * @param {string=} reason - optionally provide a reason, the model can respond accordingly
    * @return {!Promise}
    */
-  preSuspendModel() {
+  preSuspendModel(reason) {
     return Promise.resolve();
   }
 
   /**
+   * @param {string=} reason - optionally provide a reason, the model can respond accordingly
    * @return {!Promise}
    */
-  suspendModel() {
+  suspendModel(reason) {
     return Promise.resolve();
   }
 
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js b/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
index 1e8196d..81cef967 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
+++ b/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
@@ -19,14 +19,15 @@
   }
 
   /**
+   * @param {string=} reason - optionally provide a reason, so targets can respond accordingly
    * @return {!Promise}
    */
-  suspendAllTargets() {
+  suspendAllTargets(reason) {
     if (this._isSuspended)
       return Promise.resolve();
     this._isSuspended = true;
     this.dispatchEventToListeners(SDK.TargetManager.Events.SuspendStateChanged);
-    return Promise.all(this._targets.map(target => target.suspend()));
+    return Promise.all(this._targets.map(target => target.suspend(reason)));
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js b/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js
index 865d130..93bc05c 100644
--- a/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js
+++ b/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js
@@ -799,16 +799,17 @@
     originDisplay.appendChild(Security.SecurityPanel.createHighlightedUrl(origin, originState.securityState));
 
     const originNetworkDiv = titleSection.createChild('div', 'view-network-button');
-    const originNetworkButton = UI.createTextButton('View requests in Network Panel', e => {
+    const originNetworkLink = originNetworkDiv.createChild('span', 'devtools-link origin-button');
+    originNetworkLink.textContent = ls`View requests in Network Panel`;
+    originNetworkLink.addEventListener('click', e => {
       e.consume();
       const parsedURL = new Common.ParsedURL(origin);
       Network.NetworkPanel.revealAndFilter([
         {filterType: Network.NetworkLogView.FilterType.Domain, filterValue: parsedURL.host},
         {filterType: Network.NetworkLogView.FilterType.Scheme, filterValue: parsedURL.scheme}
       ]);
-    }, 'origin-button');
-    UI.ARIAUtils.markAsLink(originNetworkButton);
-    originNetworkDiv.appendChild(originNetworkButton);
+    });
+    UI.ARIAUtils.markAsLink(originNetworkLink);
 
     if (originState.securityDetails) {
       const connectionSection = this.element.createChild('div', 'origin-view-section');
@@ -976,13 +977,19 @@
         function toggleSANTruncation() {
           if (sanDiv.classList.contains('truncated-san')) {
             sanDiv.classList.remove('truncated-san');
+            truncatedSANToggle.classList.remove('show-more');
+            truncatedSANToggle.classList.add('show-less');
             truncatedSANToggle.textContent = ls`Show less`;
           } else {
             sanDiv.classList.add('truncated-san');
+            truncatedSANToggle.classList.add('show-more');
+            truncatedSANToggle.classList.remove('show-less');
             truncatedSANToggle.textContent = ls`Show more (${sanList.length} total)`;
           }
         }
-        const truncatedSANToggle = UI.createTextButton(ls`Show more (${sanList.length} total)`, toggleSANTruncation);
+
+        const truncatedSANToggle = sanDiv.createChild('span', 'devtools-link');
+        truncatedSANToggle.addEventListener('click', toggleSANTruncation);
         sanDiv.appendChild(truncatedSANToggle);
         toggleSANTruncation();
       }
diff --git a/third_party/blink/renderer/devtools/front_end/security/mainView.css b/third_party/blink/renderer/devtools/front_end/security/mainView.css
index e3e17aa..7282dbce 100644
--- a/third_party/blink/renderer/devtools/front_end/security/mainView.css
+++ b/third_party/blink/renderer/devtools/front_end/security/mainView.css
@@ -141,6 +141,7 @@
 
 .security-certificate-button {
     margin-top: 8px;
+    margin-left: 0;
 }
 
 .security-explanation .security-property {
diff --git a/third_party/blink/renderer/devtools/front_end/security/originView.css b/third_party/blink/renderer/devtools/front_end/security/originView.css
index b5495d0..7b970b7 100644
--- a/third_party/blink/renderer/devtools/front_end/security/originView.css
+++ b/third_party/blink/renderer/devtools/front_end/security/originView.css
@@ -39,7 +39,7 @@
 
 .security-origin-view .origin-display {
     font-size: 12px;
-    padding-left: 38px;
+    padding-left: 32px;
     display: flex;
     align-items: center;
 }
@@ -52,7 +52,7 @@
     display: inline-block;
     vertical-align: middle;
     position: absolute;
-    left: 16px;
+    left: 13px;
 }
 
 .security-origin-view .origin-view-section-title {
@@ -118,8 +118,29 @@
 
 .origin-button {
     margin-top: 4px;
+    margin-left: 0;
 }
 
 .origin-view-section:last-child  {
     border-bottom:none;
 }
+
+.devtools-link {
+    display: inline-flex;
+}
+
+.devtools-link.show-less:after,
+.devtools-link.show-more:after {
+    content: '';
+    width: 0;
+    height: 0;
+    border: 4px solid transparent;
+    border-top-color:rgb(17, 85, 204);
+    align-self: center;
+    transform: translateY(25%);
+    margin-left: 8px;
+}
+
+.devtools-link.show-less:after {
+    transform: rotate(180deg) translateY(25%);
+}
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp b/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp
index 33b7dc1..18a339b 100644
--- a/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp
@@ -129,6 +129,9 @@
   <message name="IDS_DEVTOOLS_d42c8bbf1d0f4a65f4dec450f2bc4439" desc="Text in Security Panel of the Security panel">
     Key exchange
   </message>
+  <message name="IDS_DEVTOOLS_daa52ee980b16f68bc0d3a9b5cc8deb7" desc="Text in Security Panel of the Security panel">
+    View requests in Network Panel
+  </message>
   <message name="IDS_DEVTOOLS_decb9f523d4cf5dc037b61cb555e6bf3" desc="Not secure div text content in Security Panel of the Security panel">
     Not secure
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js b/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
index 92d4a31..12cf4215 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
+++ b/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
@@ -187,7 +187,7 @@
     // There might be a significant delay in the beginning of timeline recording
     // caused by starting CPU profiler, that needs to traverse JS heap to collect
     // all the functions data.
-    await SDK.targetManager.suspendAllTargets();
+    await SDK.targetManager.suspendAllTargets('performance-timeline');
     if (enableJSSampling && Runtime.queryParam('timelineTracingJSProfileDisabled'))
       await this._startProfilingOnAllModels();
     if (!this._tracingManager)
diff --git a/third_party/blink/renderer/devtools/scripts/check_localizability.js b/third_party/blink/renderer/devtools/scripts/check_localizability.js
index 98e695c..a001b19 100644
--- a/third_party/blink/renderer/devtools/scripts/check_localizability.js
+++ b/third_party/blink/renderer/devtools/scripts/check_localizability.js
@@ -46,7 +46,7 @@
     if (process.argv[2] === '-a')
       filePathPromises.push(localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.js']));
     else
-      filePaths = process.argv.slice(2);
+      filePaths = process.argv.slice(2).filter(localizationUtils.shouldParseDirectory);
     await Promise.all(filePathPromises);
 
     filePaths.push(localizationUtils.SHARED_STRINGS_PATH);
diff --git a/third_party/blink/renderer/devtools/scripts/compile_frontend.py b/third_party/blink/renderer/devtools/scripts/compile_frontend.py
index 78a553da..0f251eb 100755
--- a/third_party/blink/renderer/devtools/scripts/compile_frontend.py
+++ b/third_party/blink/renderer/devtools/scripts/compile_frontend.py
@@ -245,7 +245,7 @@
     'SIMPLE_OPTIMIZATIONS',
     '--warning_level',
     'VERBOSE',
-    '--language_in=ECMASCRIPT_2017',
+    '--language_in=ECMASCRIPT_NEXT',
     '--language_out=ES5_STRICT',
     '--extra_annotation_name',
     'suppressReceiverCheck',
@@ -279,9 +279,9 @@
         '--externs',
         namespace_externs_path,
         '--js',
-        RUNTIME_FILE,
-        '--js',
         ROOT_MODULE_FILE,
+        '--js',
+        RUNTIME_FILE,
     ]
 
     all_files = descriptors.all_compiled_files()
@@ -318,7 +318,6 @@
     namespace_externs_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)
     try:
         for namespace in namespaces:
-            namespace_externs_file.write('/** @const */\n')
             namespace_externs_file.write('var %s = {};\n' % namespace)
     finally:
         namespace_externs_file.close()
diff --git a/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js b/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
index ee1a0a6..faf1d24b 100644
--- a/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
+++ b/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
@@ -23,8 +23,8 @@
   TEMP_LITERAL: 'TemplateLiteral'
 };
 
-const excludeFiles = ['lighthouse-dt-bundle.js', 'Tests.js'];
-const excludeDirs = ['test_runner', 'Images', 'langpacks', 'node_modules'];
+const excludeFiles = ['Tests.js'];
+const excludeDirs = ['test_runner', 'Images', 'langpacks', 'node_modules', 'lighthouse'];
 const cppSpecialCharactersMap = {
   '"': '\\"',
   '\\': '\\\\',
@@ -333,5 +333,6 @@
   SHARED_STRINGS_PATH,
   sanitizeStringIntoCppFormat,
   sanitizeStringIntoFrontendFormat,
+  shouldParseDirectory,
   verifyFunctionCallee
 };
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
index c6929f5..f4602a70 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
@@ -263,8 +263,8 @@
   v8::Local<v8::Value> v8_state = serialized_state
                                       ? serialized_state->Deserialize(isolate)
                                       : v8::Undefined(isolate).As<v8::Value>();
-  ScriptValue options_value(script_state, v8_options);
-  ScriptValue state_value(script_state, v8_state);
+  ScriptValue options_value(isolate, v8_options);
+  ScriptValue state_value(isolate, v8_state);
 
   ScriptValue instance;
   if (!definition->ConstructorFunction()
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc
index fb79cdf..1eeba64 100644
--- a/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc
+++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc
@@ -31,8 +31,14 @@
   last_update_time_ = local_time;
 
   if (needs_update) {
+    // The playback rate is needed to calculate whether the effect is current or
+    // not (https://drafts.csswg.org/web-animations-1/#current). Since we only
+    // use this information to create a ComputedEffectTiming, which does not
+    // include that information, we do not need to supply one.
+    base::Optional<double> playback_rate = base::nullopt;
     calculated_ = specified_timing_.CalculateTimings(
-        local_time, Timing::AnimationDirection::kForwards, false);
+        local_time, Timing::AnimationDirection::kForwards, false,
+        playback_rate);
   }
 
   return specified_timing_.getComputedTiming(calculated_,
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc
index 01592306..49cd93c 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc
@@ -184,7 +184,7 @@
   RequestInit* request_init = RequestInit::Create();
   request_init->setMethod("POST");
   request_init->setBody(blink::ScriptValue(
-      scope.GetScriptState(), ToV8(body_text, scope.GetScriptState())));
+      scope.GetIsolate(), ToV8(body_text, scope.GetScriptState())));
   Request* image_request =
       Request::Create(scope.GetScriptState(), image_url.GetString(),
                       request_init, scope.GetExceptionState());
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
index d20d3a2..849a7b8 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -161,7 +161,7 @@
     if (exception_state.HadException()) {
       ScriptPromise rejection =
           ScriptPromise::Reject(GetScriptState(), exception_state);
-      return ScriptValue(GetScriptState(), rejection.V8Value());
+      return ScriptValue(GetScriptState()->GetIsolate(), rejection.V8Value());
     }
 
     for (const auto& response : responses) {
@@ -170,21 +170,21 @@
             GetScriptState(),
             V8ThrowException::CreateTypeError(GetScriptState()->GetIsolate(),
                                               "Request failed"));
-        return ScriptValue(GetScriptState(), rejection.V8Value());
+        return ScriptValue(GetScriptState()->GetIsolate(), rejection.V8Value());
       }
       if (VaryHeaderContainsAsterisk(response)) {
         ScriptPromise rejection = ScriptPromise::Reject(
             GetScriptState(),
             V8ThrowException::CreateTypeError(GetScriptState()->GetIsolate(),
                                               "Vary header contains *"));
-        return ScriptValue(GetScriptState(), rejection.V8Value());
+        return ScriptValue(GetScriptState()->GetIsolate(), rejection.V8Value());
       }
     }
 
     ScriptPromise put_promise =
         cache_->PutImpl(GetScriptState(), method_name_, requests_, responses,
                         exception_state, trace_id_);
-    return ScriptValue(GetScriptState(), put_promise.V8Value());
+    return ScriptValue(GetScriptState()->GetIsolate(), put_promise.V8Value());
   }
 
   void Trace(blink::Visitor* visitor) override {
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc b/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc
index ef4542d3..ce39523 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc
+++ b/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc
@@ -33,6 +33,7 @@
 
     Vector<uint8_t> png_data;
     SkPngEncoder::Options options;
+    options.fZLibLevel = 1;
     if (!ImageEncoder::Encode(&png_data, pixmap, options))
       return nullptr;
 
diff --git a/third_party/blink/renderer/modules/crypto/crypto_key.cc b/third_party/blink/renderer/modules/crypto/crypto_key.cc
index 39da74d..b6ff20c8 100644
--- a/third_party/blink/renderer/modules/crypto/crypto_key.cc
+++ b/third_party/blink/renderer/modules/crypto/crypto_key.cc
@@ -165,7 +165,7 @@
       result.push_back(KeyUsageToString(usage));
   }
 
-  return ScriptValue(script_state, ToV8(result, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(result, script_state));
 }
 
 bool CryptoKey::CanBeUsedForAlgorithm(const WebCryptoAlgorithm& algorithm,
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc
index e5f77707..a0655337 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc
@@ -137,8 +137,10 @@
 ScriptValue MediaKeyStatusMap::get(ScriptState* script_state,
                                    const ArrayBufferOrArrayBufferView& key_id) {
   uint32_t index = IndexOf(key_id);
-  if (index >= entries_.size())
-    return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
+  if (index >= entries_.size()) {
+    return ScriptValue(script_state->GetIsolate(),
+                       v8::Undefined(script_state->GetIsolate()));
+  }
   return ScriptValue::From(script_state, at(index).Status());
 }
 
diff --git a/third_party/blink/renderer/modules/mediasource/track_default.cc b/third_party/blink/renderer/modules/mediasource/track_default.cc
index 46283ee2..c9373a9 100644
--- a/third_party/blink/renderer/modules/mediasource/track_default.cc
+++ b/third_party/blink/renderer/modules/mediasource/track_default.cc
@@ -29,7 +29,7 @@
 }
 
 ScriptValue TrackDefault::kinds(ScriptState* script_state) const {
-  return ScriptValue(script_state, ToV8(kinds_, script_state));
+  return ScriptValue(script_state->GetIsolate(), ToV8(kinds_, script_state));
 }
 
 TrackDefault* TrackDefault::Create(const AtomicString& type,
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index f89ca1d..34723eb 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -849,6 +849,7 @@
           "webgpu/gpu_extent_3d.idl",
           "webgpu/gpu_fence_descriptor.idl",
           "webgpu/gpu_limits.idl",
+          "webgpu/gpu_object_descriptor_base.idl",
           "webgpu/gpu_origin_3d.idl",
           "webgpu/gpu_pipeline_descriptor_base.idl",
           "webgpu/gpu_pipeline_layout_descriptor.idl",
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
index 131721c..caaac03 100644
--- a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
+++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
@@ -128,7 +128,7 @@
            .ToChecked()) {
     return ScriptValue();
   }
-  return ScriptValue(script_state, result);
+  return ScriptValue(script_state->GetIsolate(), result);
 }
 
 ScriptPromise NativeFileSystemDirectoryHandle::removeEntry(
diff --git a/third_party/blink/renderer/modules/nfc/ndef_record.cc b/third_party/blink/renderer/modules/nfc/ndef_record.cc
index 4b2f74c..17b2a60 100644
--- a/third_party/blink/renderer/modules/nfc/ndef_record.cc
+++ b/third_party/blink/renderer/modules/nfc/ndef_record.cc
@@ -248,7 +248,7 @@
       exception_state);
   if (exception_state.HadException())
     return ScriptValue::CreateNull(script_state->GetIsolate());
-  return ScriptValue(script_state, json_object);
+  return ScriptValue(script_state->GetIsolate(), json_object);
 }
 
 const WTF::Vector<uint8_t>& NDEFRecord::data() const {
diff --git a/third_party/blink/renderer/modules/notifications/notification.cc b/third_party/blink/renderer/modules/notifications/notification.cc
index 88db765..2e71ed3 100644
--- a/third_party/blink/renderer/modules/notifications/notification.cc
+++ b/third_party/blink/renderer/modules/notifications/notification.cc
@@ -353,7 +353,7 @@
   scoped_refptr<SerializedScriptValue> serialized_value =
       SerializedScriptValue::Create(data, length);
 
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      serialized_value->Deserialize(script_state->GetIsolate()));
 }
 
diff --git a/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc b/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc
index 005e13b..14618ea 100644
--- a/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc
+++ b/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc
@@ -62,7 +62,7 @@
            .ToLocal(&v8_value)) {
     return ScriptValue();
   }
-  return ScriptValue(script_state, v8_value);
+  return ScriptValue(script_state->GetIsolate(), v8_value);
 }
 
 PaymentMethodData* ToPaymentMethodData(
diff --git a/third_party/blink/renderer/modules/payments/payment_instruments.cc b/third_party/blink/renderer/modules/payments/payment_instruments.cc
index 9eaf510..2aa69c4a 100644
--- a/third_party/blink/renderer/modules/payments/payment_instruments.cc
+++ b/third_party/blink/renderer/modules/payments/payment_instruments.cc
@@ -427,7 +427,7 @@
                                    ExceptionState::kGetterContext,
                                    "PaymentInstruments", "get");
     instrument->setCapabilities(
-        ScriptValue(resolver->GetScriptState(),
+        ScriptValue(resolver->GetScriptState()->GetIsolate(),
                     FromJSONString(resolver->GetScriptState()->GetIsolate(),
                                    resolver->GetScriptState()->GetContext(),
                                    stored_instrument->stringified_capabilities,
diff --git a/third_party/blink/renderer/modules/payments/payment_method_change_event.cc b/third_party/blink/renderer/modules/payments/payment_method_change_event.cc
index 633b3c7..47c8e2d 100644
--- a/third_party/blink/renderer/modules/payments/payment_method_change_event.cc
+++ b/third_party/blink/renderer/modules/payments/payment_method_change_event.cc
@@ -29,7 +29,7 @@
     ScriptState* script_state) const {
   if (method_details_.IsEmpty())
     return ScriptValue::CreateNull(script_state->GetIsolate());
-  return ScriptValue(script_state,
+  return ScriptValue(script_state->GetIsolate(),
                      method_details_.GetAcrossWorld(script_state));
 }
 
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc
index 8bae474..0fe17df 100644
--- a/third_party/blink/renderer/modules/payments/payment_request.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -1211,7 +1211,8 @@
       ClearResolversAndCloseMojoConnection();
       return;
     }
-    init->setMethodDetails(ScriptValue(script_state, parsed_value));
+    init->setMethodDetails(
+        ScriptValue(script_state->GetIsolate(), parsed_value));
   }
 
   PaymentRequestUpdateEvent* event = PaymentMethodChangeEvent::Create(
diff --git a/third_party/blink/renderer/modules/payments/payment_request_event.cc b/third_party/blink/renderer/modules/payments/payment_request_event.cc
index d189e77..b60d272 100644
--- a/third_party/blink/renderer/modules/payments/payment_request_event.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request_event.cc
@@ -296,7 +296,7 @@
           change_payment_method_resolver_.Clear();
           return;
         }
-        mod->setData(ScriptValue(script_state, parsed_value));
+        mod->setData(ScriptValue(script_state->GetIsolate(), parsed_value));
         modifiers->emplace_back(mod);
       }
     }
@@ -315,7 +315,8 @@
       change_payment_method_resolver_.Clear();
       return;
     }
-    dictionary->setPaymentMethodErrors(ScriptValue(script_state, parsed_value));
+    dictionary->setPaymentMethodErrors(
+        ScriptValue(script_state->GetIsolate(), parsed_value));
   }
 
   change_payment_method_resolver_->Resolve(
diff --git a/third_party/blink/renderer/modules/payments/payment_response.cc b/third_party/blink/renderer/modules/payments/payment_response.cc
index 0116fdc..e95bb6f 100644
--- a/third_party/blink/renderer/modules/payments/payment_response.cc
+++ b/third_party/blink/renderer/modules/payments/payment_response.cc
@@ -104,7 +104,8 @@
 }
 
 ScriptValue PaymentResponse::details(ScriptState* script_state) const {
-  return ScriptValue(script_state, details_.GetAcrossWorld(script_state));
+  return ScriptValue(script_state->GetIsolate(),
+                     details_.GetAcrossWorld(script_state));
 }
 
 ScriptPromise PaymentResponse::complete(ScriptState* script_state,
diff --git a/third_party/blink/renderer/modules/payments/payment_response_test.cc b/third_party/blink/renderer/modules/payments/payment_response_test.cc
index 1a8a37c..35d6d02 100644
--- a/third_party/blink/renderer/modules/payments/payment_response_test.cc
+++ b/third_party/blink/renderer/modules/payments/payment_response_test.cc
@@ -82,7 +82,7 @@
   ASSERT_TRUE(details.V8Value()->IsObject());
 
   ScriptValue transaction_id(
-      scope.GetScriptState(),
+      scope.GetIsolate(),
       details.V8Value()
           .As<v8::Object>()
           ->Get(scope.GetContext(),
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index a40b6f0..c0de493a 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -1995,20 +1995,21 @@
 
 ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
                                           ExceptionState& exception_state) {
-  return getStats(
-      script_state,
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return getStats(script_state,
+                  ScriptValue(script_state->GetIsolate(),
+                              v8::Undefined(script_state->GetIsolate())),
+                  ScriptValue(script_state->GetIsolate(),
+                              v8::Undefined(script_state->GetIsolate())),
+                  exception_state);
 }
 
 ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
                                           ScriptValue callback_or_selector,
                                           ExceptionState& exception_state) {
-  return getStats(
-      script_state, std::move(callback_or_selector),
-      ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
-      exception_state);
+  return getStats(script_state, std::move(callback_or_selector),
+                  ScriptValue(script_state->GetIsolate(),
+                              v8::Undefined(script_state->GetIsolate())),
+                  exception_state);
 }
 
 ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
diff --git a/third_party/blink/renderer/modules/push_messaging/push_message_data.cc b/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
index 28e48e6..3ba9a309 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
+++ b/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
@@ -83,7 +83,7 @@
   if (exception_state.HadException())
     return ScriptValue();
 
-  return ScriptValue(script_state, parsed);
+  return ScriptValue(script_state->GetIsolate(), parsed);
 }
 
 String PushMessageData::text() const {
diff --git a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
index bee279ef7..8adab28 100644
--- a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
@@ -220,6 +220,13 @@
   }
 
   void TearDown() override {
+    // Drain queued tasks posted from the worker thread in order to avoid tasks
+    // bound with unretained objects from running after tear down. Worker
+    // termination may post such tasks (see https://crbug,com/1007616).
+    // TODO(nhiroki): Stop using synchronous WaitableEvent, and instead use
+    // QuitClosure to wait until all the tasks run before test completion.
+    test::RunPendingTasks();
+
     Platform::Current()
         ->GetURLLoaderMockFactory()
         ->UnregisterAllURLsAndClearMemoryCache();
@@ -240,8 +247,8 @@
       Thread::Current()->GetTaskRunner());
   testing::Mock::VerifyAndClearExpectations(mock_client_.get());
 
+  // Terminate the worker immediately after start.
   worker_->TerminateWorkerContext();
-  // The worker thread was started. Wait for shutdown tasks to finish.
   worker_->WaitForShutdownForTesting();
 }
 
@@ -256,12 +263,15 @@
       Thread::Current()->GetTaskRunner());
   testing::Mock::VerifyAndClearExpectations(mock_client_.get());
 
+  // Terminate the worker while waiting for the debugger.
   worker_->TerminateWorkerContext();
   worker_->WaitForShutdownForTesting();
 }
 
+// TODO(nhiroki): Remove this. This test is the same with
+// TerminateSoonAfterStart() because off-the-main-thread worker script loading
+// got enabled by default.
 TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileLoadingScript) {
-  // Load the shadow page.
   worker_->StartWorkerContext(
       CreateStartData(),
       /*installed_scripts_manager_params=*/nullptr,
@@ -271,12 +281,10 @@
 
   // Terminate before finishing the script load.
   worker_->TerminateWorkerContext();
-  // The worker thread was started. Wait for shutdown tasks to finish.
   worker_->WaitForShutdownForTesting();
 }
 
 TEST_F(WebEmbeddedWorkerImplTest, ScriptNotFound) {
-  // Load the shadow page.
   WebURL script_url = url_test_helpers::ToKURL(kNotFoundScriptURL);
   WebURLResponse response;
   response.SetMimeType("text/javascript");
@@ -297,8 +305,7 @@
 
   mock_client_->WaitUntilFailedToLoadClassicScript();
 
-  // The worker thread was started. Ask to shutdown and wait for shutdown
-  // tasks to finish.
+  // Terminate the worker for cleanup.
   worker_->TerminateWorkerContext();
   worker_->WaitForShutdownForTesting();
 }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
index ae1686c..72e7eb1 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
@@ -153,7 +153,7 @@
           std::make_unique<ProcessorCreationParams>(
               name, std::move(message_port_channel)));
 
-  ScriptValue options(script_state,
+  ScriptValue options(isolate,
                       ToV8(node_options->Deserialize(isolate), script_state));
 
   ScriptValue instance;
@@ -310,9 +310,9 @@
   // wrapper of v8::Object instance.
   ScriptValue result;
   if (!definition->ProcessFunction()
-           ->Invoke(processor, ScriptValue(script_state, inputs),
-                    ScriptValue(script_state, outputs),
-                    ScriptValue(script_state, param_values))
+           ->Invoke(processor, ScriptValue(isolate, inputs),
+                    ScriptValue(isolate, outputs),
+                    ScriptValue(isolate, param_values))
            .To(&result)) {
     // process() method call failed for some reason or an exception was thrown
     // by the user supplied code. Disable the processor to exclude it from the
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc
index d720ccf..2607d5b 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc
@@ -41,8 +41,12 @@
   if (processor_info_list->size() == 0)
     return;
 
+  // This method is called by a loading task which calls
+  // WorkletModuleTreeClient::NotifyModuleTreeLoadFinished and
+  // SynchronizeWorkletProcessorInfoList needs to run in FIFO order with other
+  // loading tasks.
   PostCrossThreadTask(
-      *GetParentExecutionContextTaskRunners()->Get(TaskType::kInternalMedia),
+      *GetParentExecutionContextTaskRunners()->Get(TaskType::kInternalLoading),
       FROM_HERE,
       CrossThreadBindOnce(
           &AudioWorkletMessagingProxy::SynchronizeWorkletProcessorInfoList,
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
index 0e4c2a1..3567e85 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
@@ -624,7 +624,8 @@
       DCHECK_GE(location, 0);
       WebGLUniformLocation* uniform_location =
           WebGLUniformLocation::Create(program, location);
-      return ScriptValue(script_state, ToV8(uniform_location, script_state));
+      return ScriptValue(script_state->GetIsolate(),
+                         ToV8(uniform_location, script_state));
     }
     default: {
       return WebGLAny(script_state, location);
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 2eea4dd..a009ccb 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -3038,7 +3038,7 @@
       ToV8(extension, script_state->GetContext()->Global(),
            script_state->GetIsolate());
 
-  return ScriptValue(script_state, wrapped_extension);
+  return ScriptValue(script_state->GetIsolate(), wrapped_extension);
 }
 
 ScriptValue WebGLRenderingContextBase::getFramebufferAttachmentParameter(
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
index bedd1100..7aa2a529 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_device.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -116,8 +116,8 @@
   v8::Local<v8::Object> creation_context = script_state->GetContext()->Global();
 
   return HeapVector<ScriptValue>({
-      ScriptValue(script_state, ToV8(gpu_buffer, creation_context, isolate)),
-      ScriptValue(script_state, ToV8(array_buffer, creation_context, isolate)),
+      ScriptValue(isolate, ToV8(gpu_buffer, creation_context, isolate)),
+      ScriptValue(isolate, ToV8(array_buffer, creation_context, isolate)),
   });
 }
 
@@ -138,7 +138,7 @@
       ToV8(array_buffer, creation_context, isolate),
   };
 
-  ScriptValue result(script_state, v8::Array::New(isolate, elements, 2));
+  ScriptValue result(isolate, v8::Array::New(isolate, elements, 2));
 
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_object_descriptor_base.idl b/third_party/blink/renderer/modules/webgpu/gpu_object_descriptor_base.idl
new file mode 100644
index 0000000..020c0e21
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/gpu_object_descriptor_base.idl
@@ -0,0 +1,9 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://gpuweb.github.io/gpuweb/
+
+dictionary GPUObjectDescriptorBase {
+    DOMString? label;
+};
diff --git a/third_party/blink/renderer/platform/OWNERS b/third_party/blink/renderer/platform/OWNERS
index ff5335a..8b254a8 100644
--- a/third_party/blink/renderer/platform/OWNERS
+++ b/third_party/blink/renderer/platform/OWNERS
@@ -10,6 +10,7 @@
 jochen@chromium.org
 kbr@chromium.org
 kinuko@chromium.org
+kojii@chromium.org
 mkwst@chromium.org
 noel@chromium.org
 pdr@chromium.org
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index 66cbb2e..396a3b93 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -575,10 +575,6 @@
   RuntimeEnabledFeatures::SetWebAuthEnabled(enable);
 }
 
-void WebRuntimeFeatures::EnableClientPlaceholdersForServerLoFi(bool enable) {
-  RuntimeEnabledFeatures::SetClientPlaceholdersForServerLoFiEnabled(enable);
-}
-
 void WebRuntimeFeatures::EnableLazyInitializeMediaControls(bool enable) {
   RuntimeEnabledFeatures::SetLazyInitializeMediaControlsEnabled(enable);
 }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
index 5fa78fbb..eeb7e99 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -263,8 +263,9 @@
   void CopyRange(unsigned start, unsigned end, ShapeResult*) const;
 
   struct ShapeRange {
-    // ShapeRange(unsigned start, unsigned end, ShapeResult* target)
-    //    : start(start), end(end), target(target){};
+    ShapeRange(unsigned start, unsigned end, ShapeResult* target)
+        : start(start), end(end), target(target) {}
+
     unsigned start;
     unsigned end;
     ShapeResult* target;
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
index b3767544..0cb6e49 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
@@ -109,12 +109,6 @@
   options_.synchronous_policy = kRequestSynchronously;
 }
 
-void FetchParameters::SetClientLoFiPlaceholder() {
-  resource_request_.SetPreviewsState(resource_request_.GetPreviewsState() |
-                                     WebURLRequest::kClientLoFiOn);
-  SetAllowImagePlaceholder();
-}
-
 void FetchParameters::SetLazyImagePlaceholder() {
   resource_request_.SetPreviewsState(resource_request_.GetPreviewsState() |
                                      WebURLRequest::kLazyImageLoadDeferred);
@@ -141,10 +135,8 @@
     // Make sure that the request isn't marked as using an image preview type,
     // since without loading an image placeholder, Client Lo-Fi isn't really
     // in use.
-    resource_request_.SetPreviewsState(
-        resource_request_.GetPreviewsState() &
-        ~(WebURLRequest::kClientLoFiOn |
-          WebURLRequest::kLazyImageLoadDeferred));
+    resource_request_.SetPreviewsState(resource_request_.GetPreviewsState() &
+                                       ~WebURLRequest::kLazyImageLoadDeferred);
     return;
   }
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
index 7eee031..8cc76c62 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -176,10 +176,6 @@
     return image_request_optimization_;
   }
 
-  // Configures the request to load an image as a placeholder and sets the
-  // Client LoFi preview bit.
-  void SetClientLoFiPlaceholder();
-
   // Configures the request to load an image as a placeholder or defers the
   // image and sets the lazy image load bit.
   void SetLazyImagePlaceholder();
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index cc6d92d..759900d 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -292,9 +292,6 @@
       status: "experimental",
     },
     {
-      name: "ClientPlaceholdersForServerLoFi",
-    },
-    {
       name: "CompositeAfterPaint",
     },
     {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index bef10ee4..9c539f21 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3226,6 +3226,7 @@
 crbug.com/618969 external/wpt/css/css-grid/subgrid/ [ Skip ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-pan-y-css_touch.html [ Timeout ]
 crbug.com/626703 [ Win10 ] external/wpt/payment-request/payment-request-hasenrolledinstrument-method.tentative.https.html [ Failure Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/css/motion/offset-path-ray-contain-003.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/motion/offset-path-ray-contain-003.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index 08236bb..72e56301 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -36913,6 +36913,18 @@
      {}
     ]
    ],
+   "css/css-color/opacity-overlapping-letters.html": [
+    [
+     "css/css-color/opacity-overlapping-letters.html",
+     [
+      [
+       "/css/css-color/opacity-overlapping-letters-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-color/rgb-001.html": [
     [
      "css/css-color/rgb-001.html",
@@ -43297,6 +43309,18 @@
      {}
     ]
    ],
+   "css/css-flexbox/flex-minimum-height-flex-items-019.html": [
+    [
+     "css/css-flexbox/flex-minimum-height-flex-items-019.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [
     [
      "css/css-flexbox/flex-minimum-width-flex-items-001.xht",
@@ -130303,6 +130327,9 @@
    "css/css-backgrounds/parsing/background-position-y-valid-expected.txt": [
     []
    ],
+   "css/css-backgrounds/parsing/border-shorthand-expected.txt": [
+    []
+   ],
    "css/css-backgrounds/reference/60x60-green-background.html": [
     []
    ],
@@ -130876,6 +130903,9 @@
    "css/css-color/lab-007-ref.html": [
     []
    ],
+   "css/css-color/opacity-overlapping-letters-ref.html": [
+    []
+   ],
    "css/css-color/rebeccapurple-ref.html": [
     []
    ],
@@ -202482,6 +202512,12 @@
      {}
     ]
    ],
+   "css/css-backgrounds/parsing/border-color-shorthand.html": [
+    [
+     "css/css-backgrounds/parsing/border-color-shorthand.html",
+     {}
+    ]
+   ],
    "css/css-backgrounds/parsing/border-color-valid.html": [
     [
      "css/css-backgrounds/parsing/border-color-valid.html",
@@ -202530,6 +202566,12 @@
      {}
     ]
    ],
+   "css/css-backgrounds/parsing/border-image-shorthand.sub.html": [
+    [
+     "css/css-backgrounds/parsing/border-image-shorthand.sub.html",
+     {}
+    ]
+   ],
    "css/css-backgrounds/parsing/border-image-slice-computed.html": [
     [
      "css/css-backgrounds/parsing/border-image-slice-computed.html",
@@ -202614,6 +202656,12 @@
      {}
     ]
    ],
+   "css/css-backgrounds/parsing/border-shorthand.html": [
+    [
+     "css/css-backgrounds/parsing/border-shorthand.html",
+     {}
+    ]
+   ],
    "css/css-backgrounds/parsing/border-style-computed.html": [
     [
      "css/css-backgrounds/parsing/border-style-computed.html",
@@ -202626,6 +202674,12 @@
      {}
     ]
    ],
+   "css/css-backgrounds/parsing/border-style-shorthand.html": [
+    [
+     "css/css-backgrounds/parsing/border-style-shorthand.html",
+     {}
+    ]
+   ],
    "css/css-backgrounds/parsing/border-style-valid.html": [
     [
      "css/css-backgrounds/parsing/border-style-valid.html",
@@ -202650,6 +202704,12 @@
      {}
     ]
    ],
+   "css/css-backgrounds/parsing/border-width-shorthand.html": [
+    [
+     "css/css-backgrounds/parsing/border-width-shorthand.html",
+     {}
+    ]
+   ],
    "css/css-backgrounds/parsing/border-width-valid.html": [
     [
      "css/css-backgrounds/parsing/border-width-valid.html",
@@ -353782,6 +353842,10 @@
    "6e4d28e7983d62979f4dad843c007b964db00706",
    "testharness"
   ],
+  "css/css-backgrounds/parsing/border-color-shorthand.html": [
+   "012567830eaea7eaf65b33539c0f207639b94c24",
+   "testharness"
+  ],
   "css/css-backgrounds/parsing/border-color-valid.html": [
    "a4cd7748ac207427812235e9868012b1a193641c",
    "testharness"
@@ -353814,6 +353878,10 @@
    "f90ef71191e48ee399eac37cea9c356faaa486f5",
    "testharness"
   ],
+  "css/css-backgrounds/parsing/border-image-shorthand.sub.html": [
+   "37fb998d6c2a5ee15fb8d8dd99cfd8942c7372eb",
+   "testharness"
+  ],
   "css/css-backgrounds/parsing/border-image-slice-computed.html": [
    "bfc8714d9838b5966cb90119391631538a632e2f",
    "testharness"
@@ -353855,7 +353923,7 @@
    "testharness"
   ],
   "css/css-backgrounds/parsing/border-invalid.html": [
-   "71404f2ce3e18fe336f076ce72ad028c4f665861",
+   "870e741f445e17d7408475aad41a7dc06c5a02cf",
    "testharness"
   ],
   "css/css-backgrounds/parsing/border-radius-computed.html": [
@@ -353870,6 +353938,14 @@
    "738362f96933c34fae38e6adfa9a82a556fc1f3b",
    "testharness"
   ],
+  "css/css-backgrounds/parsing/border-shorthand-expected.txt": [
+   "f78d14d1f75bbaeb39b547fa94bd3498e7f45f1b",
+   "support"
+  ],
+  "css/css-backgrounds/parsing/border-shorthand.html": [
+   "30491a534ec65abd673a80a278c3f6aa47f82220",
+   "testharness"
+  ],
   "css/css-backgrounds/parsing/border-style-computed.html": [
    "e890be11289fa057b1d543f16e8b215f389a6a71",
    "testharness"
@@ -353878,12 +353954,16 @@
    "27fa45116fd150d69a77850f837ee43f7032c601",
    "testharness"
   ],
+  "css/css-backgrounds/parsing/border-style-shorthand.html": [
+   "b85804e287e669fc69a27249270cbb9704216561",
+   "testharness"
+  ],
   "css/css-backgrounds/parsing/border-style-valid.html": [
    "0b592180280ce6c8eb87567e1c39f197353365c3",
    "testharness"
   ],
   "css/css-backgrounds/parsing/border-valid.html": [
-   "37b876ce4e97b2aa2ae08cb3447d42a658fcf56d",
+   "8c52b428ba93bb81817336f3eddba61a6fff6cce",
    "testharness"
   ],
   "css/css-backgrounds/parsing/border-width-computed.html": [
@@ -353894,6 +353974,10 @@
    "ec7eb72a9ac404a59390b9c89f7ae710f6620412",
    "testharness"
   ],
+  "css/css-backgrounds/parsing/border-width-shorthand.html": [
+   "07461bc94d96aa39f82d58f3fbc9237072070226",
+   "testharness"
+  ],
   "css/css-backgrounds/parsing/border-width-valid.html": [
    "552416df3d2fe1a08aeb8145c5d263770543aa5e",
    "testharness"
@@ -355286,6 +355370,14 @@
    "61a98dcb7bb02fab3db18ed337eee5ddb07724fc",
    "reftest"
   ],
+  "css/css-color/opacity-overlapping-letters-ref.html": [
+   "913aa7bc3c9f08ca0d346d473fefaa1b1a8dd9f1",
+   "support"
+  ],
+  "css/css-color/opacity-overlapping-letters.html": [
+   "34b444e26c97a5db7488716d9eed3e3675e3271f",
+   "reftest"
+  ],
   "css/css-color/parsing/color-computed.html": [
    "973b454aaddd25dadbe5a7309c9d9bb131c1abbf",
    "testharness"
@@ -358670,6 +358762,10 @@
    "983cac476e83ae97355cc6ad3fc55c6f732a6bf2",
    "reftest"
   ],
+  "css/css-flexbox/flex-minimum-height-flex-items-019.html": [
+   "3572a6cc88e50ade3a8f7faff5a343bc84d9f581",
+   "reftest"
+  ],
   "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [
    "cd18483ba414160c46e30bc282dec0c2fcd2f418",
    "reftest"
@@ -434083,15 +434179,15 @@
    "testharness"
   ],
   "html/dom/idlharness.https_exclude=(Document_Window_HTML._)-expected.txt": [
-   "862e87da6505c90d8079255be9c3ce5fbba5a2d3",
+   "2eb6b3acdd8a86bbdab64d4fabf848f20d4b2643",
    "support"
   ],
   "html/dom/idlharness.https_include=(Document_Window)-expected.txt": [
-   "8213dc41405702cd91b1654923ed051ca539d772",
+   "a0c458b1a274f50be22a12d328596e9022c5fc71",
    "support"
   ],
   "html/dom/idlharness.https_include=HTML._-expected.txt": [
-   "6c354e7c79dfdca17f716eb6f3c865329880b609",
+   "4160b1c5814a573ea7cbb6bd7b4352f248d3cbd5",
    "support"
   ],
   "html/dom/idlharness.worker-expected.txt": [
@@ -449559,7 +449655,7 @@
    "manual"
   ],
   "html/webappapis/scripting/events/event-handler-all-global-events-expected.txt": [
-   "d36897687510194fefa9bf509bdb18a9582ff3a3",
+   "3ae75ce4a8ba76b185dffc8ba3bf07b56ad0bb47",
    "support"
   ],
   "html/webappapis/scripting/events/event-handler-all-global-events.html": [
@@ -449567,7 +449663,7 @@
    "testharness"
   ],
   "html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt": [
-   "e317caa2eed655788bc1829e5d9fe136a1a958cb",
+   "caef6028d9d1bdc3d444463152fc6375b6c69fbf",
    "support"
   ],
   "html/webappapis/scripting/events/event-handler-attributes-body-window.html": [
@@ -449575,7 +449671,7 @@
    "testharness"
   ],
   "html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt": [
-   "c4e1cb872f0b7645b46d61ffc9d1011a7d235e00",
+   "4dcaee309fd1f12e83f6d67eb4e655212624ea53",
    "support"
   ],
   "html/webappapis/scripting/events/event-handler-attributes-frameset-window.html": [
@@ -449587,7 +449683,7 @@
    "support"
   ],
   "html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt": [
-   "9ce3c849d501f9042a3d4b59ca860c55707327c6",
+   "14bbc1ec4479e7f72ff845bab53de33da156fa7d",
    "support"
   ],
   "html/webappapis/scripting/events/event-handler-attributes-windowless-body.html": [
@@ -451291,7 +451387,7 @@
    "support"
   ],
   "interfaces/IndexedDB.idl": [
-   "9373f4e43bf8ab0fe51371839dd614b83c54cb9c",
+   "2af9eb2a3245d2229dc5b7505713795405ff0ba9",
    "support"
   ],
   "interfaces/InputDeviceCapabilities.idl": [
@@ -451527,7 +451623,7 @@
    "support"
   ],
   "interfaces/html.idl": [
-   "d856cd578aa0a0d15f09d0c95bebf48b0f95c0d6",
+   "8347c5d4cdc9b00550efcec7f2a77993f2b7ccf6",
    "support"
   ],
   "interfaces/image-capture.idl": [
@@ -451563,7 +451659,7 @@
    "support"
   ],
   "interfaces/magnetometer.idl": [
-   "be6cbc9d47a8da6a16613c8d88bbc824e7372de3",
+   "da1f22bb6685a38164c1eb16d3a6c07290e7833a",
    "support"
   ],
   "interfaces/media-capabilities.idl": [
@@ -451671,7 +451767,7 @@
    "support"
   ],
   "interfaces/proximity.idl": [
-   "570a29fd37b09304871409dd811498fef8b3cf19",
+   "d4c8fae3a5438058262108f4848414763138080a",
    "support"
   ],
   "interfaces/push-api.idl": [
@@ -451743,7 +451839,7 @@
    "support"
   ],
   "interfaces/touch-events.idl": [
-   "1a8c9d7d24ece0ea221b6863ce8ea3595bcbb697",
+   "84c48284a1b9bdcd79954008decdaeac9d2bf2eb",
    "support"
   ],
   "interfaces/trusted-types.tentative.idl": [
@@ -451755,7 +451851,7 @@
    "support"
   ],
   "interfaces/url.idl": [
-   "998052da6ef1b3aada6b81a4ff5868ee11e3b477",
+   "b0b237e8524a8621f0ddcd8367ebad6fd5f2fb5b",
    "support"
   ],
   "interfaces/user-timing.idl": [
@@ -483271,7 +483367,7 @@
    "support"
   ],
   "signed-exchange/README.md": [
-   "f1dbfe6d1adbe7ef7663c5298692872897ce3e0c",
+   "4032edf22f34f596d74da5ee0e4019c5dcf1c69c",
    "support"
   ],
   "signed-exchange/appcache/appcache.manifest": [
@@ -483975,7 +484071,7 @@
    "testharness"
   ],
   "storage-access-api/hasStorageAccess.sub.window.js": [
-   "1352d7589f051b31ec577eb7d0c85daf4a58d8f2",
+   "c4d6e3a8b9a856007a299b7f2b1112188547ebd1",
    "testharness"
   ],
   "storage-access-api/helpers.js": [
@@ -492047,7 +492143,7 @@
    "support"
   ],
   "tools/wptrunner/requirements.txt": [
-   "3584c93a199716d0b9809dc4180195647887d1a0",
+   "9eeb836230c39def1291c210a9690cbb5b24c117",
    "support"
   ],
   "tools/wptrunner/requirements_android_webview.txt": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-color-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-color-shorthand.html
new file mode 100644
index 0000000..0125678
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-color-shorthand.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders Module Level 3: border-color sets longhands</title>
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-color">
+<meta name="assert" content="border-color supports the full grammar '<color>{1,4}'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/shorthand-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_shorthand_value('border-color', 'currentcolor', {
+  'border-top-color': 'currentcolor',
+  'border-right-color': 'currentcolor',
+  'border-bottom-color': 'currentcolor',
+  'border-left-color': 'currentcolor'
+});
+
+test_shorthand_value('border-color', 'red yellow', {
+  'border-top-color': 'red',
+  'border-right-color': 'yellow',
+  'border-bottom-color': 'red',
+  'border-left-color': 'yellow'
+});
+
+test_shorthand_value('border-color', 'red yellow green', {
+  'border-top-color': 'red',
+  'border-right-color': 'yellow',
+  'border-bottom-color': 'green',
+  'border-left-color': 'yellow'
+});
+
+test_shorthand_value('border-color', 'red yellow green blue', {
+  'border-top-color': 'red',
+  'border-right-color': 'yellow',
+  'border-bottom-color': 'green',
+  'border-left-color': 'blue'
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-image-shorthand.sub.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-image-shorthand.sub.html
new file mode 100644
index 0000000..37fb998d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-image-shorthand.sub.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders Module Level 3: border-image sets longhands</title>
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-image">
+<meta name="assert" content="border-image supports the full grammar ' <‘border-image-source’> || <‘border-image-slice’> [ / <‘border-image-width’> | / <‘border-image-width’>? / <‘border-image-outset’> ]? || <‘border-image-repeat’>'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/shorthand-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_shorthand_value('border-image', 'none', {
+  'border-image-source': 'none',
+  'border-image-slice': '100%',
+  'border-image-width': '1',
+  'border-image-outset': '0',
+  'border-image-repeat': 'stretch'
+});
+
+test_shorthand_value('border-image', 'url("http://{{host}}/") 1 2 3 4 fill', {
+  'border-image-source': 'url("http://{{host}}/")',
+  'border-image-slice': '1 2 3 4 fill',
+  'border-image-width': '1',
+  'border-image-outset': '0',
+  'border-image-repeat': 'stretch'
+});
+
+test_shorthand_value('border-image', 'repeat round', {
+  'border-image-source': 'none',
+  'border-image-slice': '100%',
+  'border-image-width': '1',
+  'border-image-outset': '0',
+  'border-image-repeat': 'repeat round'
+});
+
+test_shorthand_value('border-image', 'url("http://{{host}}/") fill 1 2% 3 4%', {
+  'border-image-source': 'url("http://{{host}}/")',
+  'border-image-slice': '1 2% 3 4% fill',
+  'border-image-width': '1',
+  'border-image-outset': '0',
+  'border-image-repeat': 'stretch'
+});
+
+test_shorthand_value('border-image', '1 2% 3 4% / 5% / 6', {
+  'border-image-source': 'none',
+  'border-image-slice': '1 2% 3 4%',
+  'border-image-width': '5%',
+  'border-image-outset': '6',
+  'border-image-repeat': 'stretch'
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-invalid.html
index 71404f2..870e741 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-invalid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-invalid.html
@@ -3,9 +3,8 @@
 <head>
 <meta charset="utf-8">
 <title>CSS Backgrounds and Borders Module Level 3: parsing border with invalid values</title>
-<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
 <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-shorthands">
-<meta name="assert" content="border-width supports only the grammar '<line-width> || <line-style> || <color>'.">
+<meta name="assert" content="border supports only the grammar '<line-width> || <line-style> || <color>'.">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/parsing-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-shorthand-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-shorthand-expected.txt
new file mode 100644
index 0000000..f78d14d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-shorthand-expected.txt
@@ -0,0 +1,37 @@
+This is a testharness.js-based test.
+PASS e.style['border'] = "5px dotted blue" should set border-bottom-color
+PASS e.style['border'] = "5px dotted blue" should set border-bottom-style
+PASS e.style['border'] = "5px dotted blue" should set border-bottom-width
+FAIL e.style['border'] = "5px dotted blue" should set border-image-outset assert_equals: border-image-outset should be canonical expected "0" but got "initial"
+FAIL e.style['border'] = "5px dotted blue" should set border-image-repeat assert_equals: border-image-repeat should be canonical expected "stretch" but got "initial"
+FAIL e.style['border'] = "5px dotted blue" should set border-image-slice assert_equals: border-image-slice should be canonical expected "100%" but got "initial"
+FAIL e.style['border'] = "5px dotted blue" should set border-image-source assert_equals: border-image-source should be canonical expected "none" but got "initial"
+FAIL e.style['border'] = "5px dotted blue" should set border-image-width assert_equals: border-image-width should be canonical expected "1" but got "initial"
+PASS e.style['border'] = "5px dotted blue" should set border-left-color
+PASS e.style['border'] = "5px dotted blue" should set border-left-style
+PASS e.style['border'] = "5px dotted blue" should set border-left-width
+PASS e.style['border'] = "5px dotted blue" should set border-right-color
+PASS e.style['border'] = "5px dotted blue" should set border-right-style
+PASS e.style['border'] = "5px dotted blue" should set border-right-width
+PASS e.style['border'] = "5px dotted blue" should set border-top-color
+PASS e.style['border'] = "5px dotted blue" should set border-top-style
+PASS e.style['border'] = "5px dotted blue" should set border-top-width
+PASS e.style['border'] = "5px dotted blue" should not set unrelated longhands
+FAIL e.style['border-top'] = "thin" should set border-top-color assert_equals: border-top-color should be canonical expected "currentcolor" but got "initial"
+FAIL e.style['border-top'] = "thin" should set border-top-style assert_equals: border-top-style should be canonical expected "none" but got "initial"
+PASS e.style['border-top'] = "thin" should set border-top-width
+PASS e.style['border-top'] = "thin" should not set unrelated longhands
+FAIL e.style['border-right'] = "double" should set border-right-color assert_equals: border-right-color should be canonical expected "currentcolor" but got "initial"
+PASS e.style['border-right'] = "double" should set border-right-style
+FAIL e.style['border-right'] = "double" should set border-right-width assert_equals: border-right-width should be canonical expected "medium" but got "initial"
+PASS e.style['border-right'] = "double" should not set unrelated longhands
+PASS e.style['border-bottom'] = "green" should set border-bottom-color
+FAIL e.style['border-bottom'] = "green" should set border-bottom-style assert_equals: border-bottom-style should be canonical expected "none" but got "initial"
+FAIL e.style['border-bottom'] = "green" should set border-bottom-width assert_equals: border-bottom-width should be canonical expected "medium" but got "initial"
+PASS e.style['border-bottom'] = "green" should not set unrelated longhands
+PASS e.style['border-left'] = "1px dotted red" should set border-left-color
+PASS e.style['border-left'] = "1px dotted red" should set border-left-style
+PASS e.style['border-left'] = "1px dotted red" should set border-left-width
+PASS e.style['border-left'] = "1px dotted red" should not set unrelated longhands
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-shorthand.html
new file mode 100644
index 0000000..30491a53
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-shorthand.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders Module Level 3: border sets longhands</title>
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-shorthands">
+<meta name="assert" content="border supports the full grammar '<line-width> || <line-style> || <color>'.">
+<meta name="assert" content="The border shorthand also resets border-image to its initial value.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/shorthand-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_shorthand_value('border', '5px dotted blue', {
+  'border-top-width': '5px',
+  'border-right-width': '5px',
+  'border-bottom-width': '5px',
+  'border-left-width': '5px',
+  'border-top-style': 'dotted',
+  'border-right-style': 'dotted',
+  'border-bottom-style': 'dotted',
+  'border-left-style': 'dotted',
+  'border-top-color': 'blue',
+  'border-right-color': 'blue',
+  'border-bottom-color': 'blue',
+  'border-left-color': 'blue',
+
+  'border-image-source': 'none',
+  'border-image-slice': '100%',
+  'border-image-width': '1',
+  'border-image-outset': '0',
+  'border-image-repeat': 'stretch'
+});
+
+test_shorthand_value('border-top', 'thin', {
+  'border-top-width': 'thin',
+  'border-top-style': 'none',
+  'border-top-color': 'currentcolor'
+});
+
+test_shorthand_value('border-right', 'double', {
+  'border-right-width': 'medium',
+  'border-right-style': 'double',
+  'border-right-color': 'currentcolor'
+});
+
+test_shorthand_value('border-bottom', 'green', {
+  'border-bottom-width': 'medium',
+  'border-bottom-style': 'none',
+  'border-bottom-color': 'green'
+});
+
+test_shorthand_value('border-left', '1px dotted red', {
+  'border-left-width': '1px',
+  'border-left-style': 'dotted',
+  'border-left-color': 'red'
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-style-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-style-shorthand.html
new file mode 100644
index 0000000..b85804e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-style-shorthand.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders Module Level 3: border-style sets longhands</title>
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-style">
+<meta name="assert" content="border-style supports the full grammar '<line-style>{1,4}'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/shorthand-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_shorthand_value('border-style', 'none', {
+  'border-top-style': 'none',
+  'border-right-style': 'none',
+  'border-bottom-style': 'none',
+  'border-left-style': 'none'
+});
+
+test_shorthand_value('border-style', 'inset outset', {
+  'border-top-style': 'inset',
+  'border-right-style': 'outset',
+  'border-bottom-style': 'inset',
+  'border-left-style': 'outset'
+});
+
+test_shorthand_value('border-style', 'hidden dotted dashed', {
+  'border-top-style': 'hidden',
+  'border-right-style': 'dotted',
+  'border-bottom-style': 'dashed',
+  'border-left-style': 'dotted'
+});
+
+test_shorthand_value('border-style', 'solid double groove ridge', {
+  'border-top-style': 'solid',
+  'border-right-style': 'double',
+  'border-bottom-style': 'groove',
+  'border-left-style': 'ridge'
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-valid.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-valid.html
index 37b876ce..8c52b42 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-valid.html
@@ -3,9 +3,8 @@
 <head>
 <meta charset="utf-8">
 <title>CSS Backgrounds and Borders Module Level 3: parsing border with valid values</title>
-<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
 <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-shorthands">
-<meta name="assert" content="border-width supports the full grammar '<line-width> || <line-style> || <color>'.">
+<meta name="assert" content="border supports the full grammar '<line-width> || <line-style> || <color>'.">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/parsing-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-width-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-width-shorthand.html
new file mode 100644
index 0000000..07461bc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-width-shorthand.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders Module Level 3: border-width sets longhands</title>
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-width">
+<meta name="assert" content="border-width supports the full grammar '<line-width>{1,4}'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/shorthand-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_shorthand_value('border-width', '5px', {
+  'border-top-width': '5px',
+  'border-right-width': '5px',
+  'border-bottom-width': '5px',
+  'border-left-width': '5px'
+});
+
+test_shorthand_value('border-width', 'thick thin', {
+  'border-top-width': 'thick',
+  'border-right-width': 'thin',
+  'border-bottom-width': 'thick',
+  'border-left-width': 'thin'
+});
+
+test_shorthand_value('border-width', 'thin medium thick', {
+  'border-top-width': 'thin',
+  'border-right-width': 'medium',
+  'border-bottom-width': 'thick',
+  'border-left-width': 'medium'
+});
+
+test_shorthand_value('border-width', '1px 2px 3px 4px', {
+  'border-top-width': '1px',
+  'border-right-width': '2px',
+  'border-bottom-width': '3px',
+  'border-left-width': '4px'
+});
+</script>
+</body>
+</html>
diff --git "a/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_exclude=\050Document_Window_HTML._\051-expected.txt" "b/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_exclude=\050Document_Window_HTML._\051-expected.txt"
index 862e87d..2eb6b3a 100644
--- "a/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_exclude=\050Document_Window_HTML._\051-expected.txt"
+++ "b/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_exclude=\050Document_Window_HTML._\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1271 tests; 1224 PASS, 47 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1272 tests; 1224 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS Partial interface mixin DocumentOrShadowRoot: original interface mixin defined
@@ -1226,6 +1226,7 @@
 PASS SVGElement interface: attribute onseeked
 PASS SVGElement interface: attribute onseeking
 PASS SVGElement interface: attribute onselect
+FAIL SVGElement interface: attribute onslotchange assert_true: The prototype object must have a property "onslotchange" expected true got false
 PASS SVGElement interface: attribute onstalled
 PASS SVGElement interface: attribute onsubmit
 PASS SVGElement interface: attribute onsuspend
diff --git "a/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_include=\050Document_Window\051-expected.txt" "b/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_include=\050Document_Window\051-expected.txt"
index 8213dc41..a0c458b1 100644
--- "a/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_include=\050Document_Window\051-expected.txt"
+++ "b/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_include=\050Document_Window\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 803 tests; 779 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 809 tests; 779 PASS, 30 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS Partial interface mixin DocumentOrShadowRoot: original interface mixin defined
@@ -139,6 +139,7 @@
 PASS Window interface: attribute onseeked
 PASS Window interface: attribute onseeking
 PASS Window interface: attribute onselect
+FAIL Window interface: attribute onslotchange assert_own_property: The global object must have a property "onslotchange" expected property "onslotchange" missing
 PASS Window interface: attribute onstalled
 PASS Window interface: attribute onsubmit
 PASS Window interface: attribute onsuspend
@@ -283,6 +284,7 @@
 PASS Window interface: window must inherit property "onseeked" with the proper type
 PASS Window interface: window must inherit property "onseeking" with the proper type
 PASS Window interface: window must inherit property "onselect" with the proper type
+FAIL Window interface: window must inherit property "onslotchange" with the proper type assert_own_property: expected property "onslotchange" missing
 PASS Window interface: window must inherit property "onstalled" with the proper type
 PASS Window interface: window must inherit property "onsubmit" with the proper type
 PASS Window interface: window must inherit property "onsuspend" with the proper type
@@ -429,6 +431,7 @@
 PASS Document interface: attribute onseeked
 PASS Document interface: attribute onseeking
 PASS Document interface: attribute onselect
+FAIL Document interface: attribute onslotchange assert_true: The prototype object must have a property "onslotchange" expected true got false
 PASS Document interface: attribute onstalled
 PASS Document interface: attribute onsubmit
 PASS Document interface: attribute onsuspend
@@ -550,6 +553,7 @@
 PASS Document interface: iframe.contentDocument must inherit property "onseeked" with the proper type
 PASS Document interface: iframe.contentDocument must inherit property "onseeking" with the proper type
 PASS Document interface: iframe.contentDocument must inherit property "onselect" with the proper type
+FAIL Document interface: iframe.contentDocument must inherit property "onslotchange" with the proper type assert_inherits: property "onslotchange" not found in prototype chain
 PASS Document interface: iframe.contentDocument must inherit property "onstalled" with the proper type
 PASS Document interface: iframe.contentDocument must inherit property "onsubmit" with the proper type
 PASS Document interface: iframe.contentDocument must inherit property "onsuspend" with the proper type
@@ -671,6 +675,7 @@
 PASS Document interface: new Document() must inherit property "onseeked" with the proper type
 PASS Document interface: new Document() must inherit property "onseeking" with the proper type
 PASS Document interface: new Document() must inherit property "onselect" with the proper type
+FAIL Document interface: new Document() must inherit property "onslotchange" with the proper type assert_inherits: property "onslotchange" not found in prototype chain
 PASS Document interface: new Document() must inherit property "onstalled" with the proper type
 PASS Document interface: new Document() must inherit property "onsubmit" with the proper type
 PASS Document interface: new Document() must inherit property "onsuspend" with the proper type
@@ -792,6 +797,7 @@
 PASS Document interface: documentWithHandlers must inherit property "onseeked" with the proper type
 PASS Document interface: documentWithHandlers must inherit property "onseeking" with the proper type
 PASS Document interface: documentWithHandlers must inherit property "onselect" with the proper type
+FAIL Document interface: documentWithHandlers must inherit property "onslotchange" with the proper type assert_inherits: property "onslotchange" found on object expected in prototype chain
 PASS Document interface: documentWithHandlers must inherit property "onstalled" with the proper type
 PASS Document interface: documentWithHandlers must inherit property "onsubmit" with the proper type
 PASS Document interface: documentWithHandlers must inherit property "onsuspend" with the proper type
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_include=HTML._-expected.txt b/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_include=HTML._-expected.txt
index 6c354e7..4160b1c 100644
--- a/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_include=HTML._-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/dom/idlharness.https_include=HTML._-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 3589 tests; 3551 PASS, 38 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 3591 tests; 3551 PASS, 40 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS Partial interface mixin DocumentOrShadowRoot: original interface mixin defined
@@ -157,6 +157,7 @@
 PASS HTMLElement interface: attribute onseeked
 PASS HTMLElement interface: attribute onseeking
 PASS HTMLElement interface: attribute onselect
+FAIL HTMLElement interface: attribute onslotchange assert_true: The prototype object must have a property "onslotchange" expected true got false
 PASS HTMLElement interface: attribute onstalled
 PASS HTMLElement interface: attribute onsubmit
 PASS HTMLElement interface: attribute onsuspend
@@ -247,6 +248,7 @@
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "onseeked" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "onseeking" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "onselect" with the proper type
+FAIL HTMLElement interface: document.createElement("noscript") must inherit property "onslotchange" with the proper type assert_inherits: property "onslotchange" not found in prototype chain
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "onstalled" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "onsubmit" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "onsuspend" with the proper type
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-all-global-events-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-all-global-events-expected.txt
index d3689768..3ae75ce 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-all-global-events-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-all-global-events-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 305 tests; 297 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 310 tests; 298 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS onabort: must be on the appropriate locations for GlobalEventHandlers
 PASS onabort: the default value must be null
 PASS onabort: the content attribute must be compiled into a function as the corresponding property
@@ -270,6 +270,11 @@
 PASS onselect: the content attribute must be compiled into a function as the corresponding property
 PASS onselect: the content attribute must execute when an event is dispatched
 PASS onselect: dispatching an Event at a <meta> element must trigger element.onselect
+FAIL onslotchange: must be on the appropriate locations for GlobalEventHandlers assert_true: Window has an own property named "onslotchange" expected true got false
+FAIL onslotchange: the default value must be null assert_equals: The default value of the property is null for a Window instance expected (object) null but got (undefined) undefined
+FAIL onslotchange: the content attribute must be compiled into a function as the corresponding property assert_equals: The onslotchange property must be a function expected "function" but got "undefined"
+FAIL onslotchange: the content attribute must execute when an event is dispatched assert_true: Dispatching an event must run the code expected true got undefined
+PASS onslotchange: dispatching an Event at a <meta> element must trigger element.onslotchange
 PASS onstalled: must be on the appropriate locations for GlobalEventHandlers
 PASS onstalled: the default value must be null
 PASS onstalled: the content attribute must be compiled into a function as the corresponding property
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
index e317caa..caef602 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-body-window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 309 tests; 297 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 312 tests; 297 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS shadowed blur (document.body)
 PASS shadowed error (document.body)
 PASS shadowed focus (document.body)
@@ -71,6 +71,7 @@
 PASS not shadowed seeked (document.body)
 PASS not shadowed seeking (document.body)
 PASS not shadowed select (document.body)
+FAIL not shadowed slotchange (document.body) assert_equals: alternative body should reflect expected (object) null but got (undefined) undefined
 PASS not shadowed stalled (document.body)
 PASS not shadowed submit (document.body)
 PASS not shadowed suspend (document.body)
@@ -174,6 +175,7 @@
 PASS not shadowed seeked (document.createElement("body"))
 PASS not shadowed seeking (document.createElement("body"))
 PASS not shadowed select (document.createElement("body"))
+FAIL not shadowed slotchange (document.createElement("body")) assert_equals: body should reflect expected (object) null but got (undefined) undefined
 PASS not shadowed stalled (document.createElement("body"))
 PASS not shadowed submit (document.createElement("body"))
 PASS not shadowed suspend (document.createElement("body"))
@@ -277,6 +279,7 @@
 PASS not shadowed seeked (window)
 PASS not shadowed seeking (window)
 PASS not shadowed select (window)
+FAIL not shadowed slotchange (window) assert_equals: body should reflect expected (object) null but got (undefined) undefined
 PASS not shadowed stalled (window)
 PASS not shadowed submit (window)
 PASS not shadowed suspend (window)
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
index c4e1cb8..4dcaee30 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-frameset-window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 309 tests; 297 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 312 tests; 297 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS shadowed blur (document.body)
 PASS shadowed error (document.body)
 PASS shadowed focus (document.body)
@@ -71,6 +71,7 @@
 PASS not shadowed seeked (document.body)
 PASS not shadowed seeking (document.body)
 PASS not shadowed select (document.body)
+FAIL not shadowed slotchange (document.body) assert_equals: alternative body should reflect expected (object) null but got (undefined) undefined
 PASS not shadowed stalled (document.body)
 PASS not shadowed submit (document.body)
 PASS not shadowed suspend (document.body)
@@ -174,6 +175,7 @@
 PASS not shadowed seeked (document.createElement("frameset"))
 PASS not shadowed seeking (document.createElement("frameset"))
 PASS not shadowed select (document.createElement("frameset"))
+FAIL not shadowed slotchange (document.createElement("frameset")) assert_equals: body should reflect expected (object) null but got (undefined) undefined
 PASS not shadowed stalled (document.createElement("frameset"))
 PASS not shadowed submit (document.createElement("frameset"))
 PASS not shadowed suspend (document.createElement("frameset"))
@@ -277,6 +279,7 @@
 PASS not shadowed seeked (window)
 PASS not shadowed seeking (window)
 PASS not shadowed select (window)
+FAIL not shadowed slotchange (window) assert_equals: body should reflect expected (object) null but got (undefined) undefined
 PASS not shadowed stalled (window)
 PASS not shadowed submit (window)
 PASS not shadowed suspend (window)
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt
index 9ce3c84..14bbc1e 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-attributes-windowless-body-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 206 tests; 202 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 208 tests; 202 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Return null when getting the blur event handler of a windowless body
 PASS Ignore setting of blur window event handlers on windowless body
 PASS Return null when getting the error event handler of a windowless body
@@ -93,6 +93,7 @@
 PASS seeked is unaffected on a windowless body
 PASS seeking is unaffected on a windowless body
 PASS select is unaffected on a windowless body
+FAIL slotchange is unaffected on a windowless body assert_equals: expected (object) null but got (undefined) undefined
 PASS stalled is unaffected on a windowless body
 PASS submit is unaffected on a windowless body
 PASS suspend is unaffected on a windowless body
@@ -196,6 +197,7 @@
 PASS seeked is unaffected on a windowless frameset
 PASS seeking is unaffected on a windowless frameset
 PASS select is unaffected on a windowless frameset
+FAIL slotchange is unaffected on a windowless frameset assert_equals: expected (object) null but got (undefined) undefined
 PASS stalled is unaffected on a windowless frameset
 PASS submit is unaffected on a windowless frameset
 PASS suspend is unaffected on a windowless frameset
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/IndexedDB.idl b/third_party/blink/web_tests/external/wpt/interfaces/IndexedDB.idl
index 9373f4e..2af9eb2 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/IndexedDB.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/IndexedDB.idl
@@ -163,7 +163,7 @@
                                        optional boolean lowerOpen = false,
                                        optional boolean upperOpen = false);
 
-  boolean _includes(any key);
+  boolean includes(any key);
 };
 
 [Exposed=(Window,Worker)]
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/html.idl b/third_party/blink/web_tests/external/wpt/interfaces/html.idl
index d856cd5..8347c5d 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/html.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/html.idl
@@ -100,9 +100,10 @@
   readonly attribute Element? activeElement;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLElement : Element {
+  [HTMLConstructor] constructor();
+
   // metadata attributes
   [CEReactions] attribute DOMString title;
   [CEReactions] attribute DOMString lang;
@@ -128,9 +129,10 @@
 HTMLElement includes ElementContentEditable;
 HTMLElement includes HTMLOrSVGElement;
 
-// Note: intentionally not [HTMLConstructor]
 [Exposed=Window]
-interface HTMLUnknownElement : HTMLElement { };
+interface HTMLUnknownElement : HTMLElement {
+  // Note: intentionally no [HTMLConstructor]
+};
 
 interface mixin HTMLOrSVGElement {
   [SameObject] readonly attribute DOMStringMap dataset;
@@ -150,32 +152,37 @@
   [CEReactions] deleter void (DOMString name);
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLHtmlElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
-interface HTMLHeadElement : HTMLElement {};
+[Exposed=Window]
+interface HTMLHeadElement : HTMLElement {
+  [HTMLConstructor] constructor();
+};
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTitleElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString text;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLBaseElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString href;
   [CEReactions] attribute DOMString target;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLLinkElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString href;
   [CEReactions] attribute DOMString? crossOrigin;
   [CEReactions] attribute DOMString rel;
@@ -194,9 +201,10 @@
 };
 HTMLLinkElement includes LinkStyle;
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLMetaElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString name;
   [CEReactions] attribute DOMString httpEquiv;
   [CEReactions] attribute DOMString content;
@@ -204,50 +212,57 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLStyleElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString media;
 
   // also has obsolete members
 };
 HTMLStyleElement includes LinkStyle;
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLBodyElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
 HTMLBodyElement includes WindowEventHandlers;
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLHeadingElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLParagraphElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLHRElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLPreElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLQuoteElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString cite;
 };
 
@@ -261,9 +276,10 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLUListElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
@@ -282,21 +298,24 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLDListElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLDivElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLAnchorElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString target;
   [CEReactions] attribute DOMString download;
   [CEReactions] attribute USVString ping;
@@ -313,9 +332,10 @@
 };
 HTMLAnchorElement includes HTMLHyperlinkElementUtils;
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLDataElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString value;
 };
 
@@ -325,13 +345,15 @@
   [CEReactions] attribute DOMString dateTime;
 };
 
-[Exposed=Window,
- HTMLConstructor]
-interface HTMLSpanElement : HTMLElement {};
+[Exposed=Window]
+interface HTMLSpanElement : HTMLElement {
+  [HTMLConstructor] constructor();
+};
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLBRElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
@@ -349,20 +371,23 @@
   [CEReactions] attribute USVString hash;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLModElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString cite;
   [CEReactions] attribute DOMString dateTime;
 };
 
-[Exposed=Window,
- HTMLConstructor]
-interface HTMLPictureElement : HTMLElement {};
+[Exposed=Window]
+interface HTMLPictureElement : HTMLElement {
+  [HTMLConstructor] constructor();
+};
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLSourceElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString src;
   [CEReactions] attribute DOMString type;
   [CEReactions] attribute USVString srcset;
@@ -395,9 +420,10 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLIFrameElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString src;
   [CEReactions] attribute DOMString srcdoc;
   [CEReactions] attribute DOMString name;
@@ -415,9 +441,10 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLEmbedElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString src;
   [CEReactions] attribute DOMString type;
   [CEReactions] attribute DOMString width;
@@ -427,9 +454,10 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLObjectElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString data;
   [CEReactions] attribute DOMString type;
   [CEReactions] attribute DOMString name;
@@ -451,9 +479,10 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLParamElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString name;
   [CEReactions] attribute DOMString value;
 
@@ -476,9 +505,10 @@
  NamedConstructor=Audio(optional DOMString src)]
 interface HTMLAudioElement : HTMLMediaElement {};
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTrackElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString kind;
   [CEReactions] attribute USVString src;
   [CEReactions] attribute DOMString srclang;
@@ -679,16 +709,18 @@
   (VideoTrack or AudioTrack or TextTrack)? track = null;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLMapElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString name;
   [SameObject] readonly attribute HTMLCollection areas;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLAreaElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString alt;
   [CEReactions] attribute DOMString coords;
   [CEReactions] attribute DOMString shape;
@@ -703,9 +735,10 @@
 };
 HTMLAreaElement includes HTMLHyperlinkElementUtils;
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTableElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute HTMLTableCaptionElement? caption;
   HTMLTableCaptionElement createCaption();
   [CEReactions] void deleteCaption();
@@ -728,23 +761,26 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTableCaptionElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTableColElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute unsigned long span;
 
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTableSectionElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [SameObject] readonly attribute HTMLCollection rows;
   HTMLTableRowElement insertRow(optional long index = -1);
   [CEReactions] void deleteRow(long index);
@@ -752,9 +788,10 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTableRowElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   readonly attribute long rowIndex;
   readonly attribute long sectionRowIndex;
   [SameObject] readonly attribute HTMLCollection cells;
@@ -764,9 +801,10 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTableCellElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute unsigned long colSpan;
   [CEReactions] attribute unsigned long rowSpan;
   [CEReactions] attribute DOMString headers;
@@ -807,17 +845,19 @@
   boolean reportValidity();
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLLabelElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   readonly attribute HTMLFormElement? form;
   [CEReactions] attribute DOMString htmlFor;
   readonly attribute HTMLElement? control;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLInputElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString accept;
   [CEReactions] attribute DOMString alt;
   [CEReactions] attribute DOMString autocomplete;
@@ -878,9 +918,10 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLButtonElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute boolean disabled;
   readonly attribute HTMLFormElement? form;
   [CEReactions] attribute USVString formAction;
@@ -902,9 +943,10 @@
   readonly attribute NodeList labels;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLSelectElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString autocomplete;
   [CEReactions] attribute boolean disabled;
   readonly attribute HTMLFormElement? form;
@@ -938,15 +980,17 @@
   readonly attribute NodeList labels;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLDataListElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [SameObject] readonly attribute HTMLCollection options;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLOptGroupElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute boolean disabled;
   [CEReactions] attribute DOMString label;
 };
@@ -966,9 +1010,10 @@
   readonly attribute long index;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTextAreaElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString autocomplete;
   [CEReactions] attribute unsigned long cols;
   [CEReactions] attribute DOMString dirName;
@@ -1006,9 +1051,10 @@
   void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction);
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLOutputElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [SameObject, PutForwards=value] readonly attribute DOMTokenList htmlFor;
   readonly attribute HTMLFormElement? form;
   [CEReactions] attribute DOMString name;
@@ -1027,18 +1073,20 @@
   readonly attribute NodeList labels;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLProgressElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute double value;
   [CEReactions] attribute double max;
   readonly attribute double position;
   readonly attribute NodeList labels;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLMeterElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute double value;
   [CEReactions] attribute double min;
   [CEReactions] attribute double max;
@@ -1048,9 +1096,10 @@
   readonly attribute NodeList labels;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLFieldSetElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute boolean disabled;
   readonly attribute HTMLFormElement? form;
   [CEReactions] attribute DOMString name;
@@ -1067,9 +1116,10 @@
   void setCustomValidity(DOMString error);
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLLegendElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   readonly attribute HTMLFormElement? form;
 
   // also has obsolete members
@@ -1107,15 +1157,17 @@
   required FormData formData;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLDetailsElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute boolean open;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLDialogElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute boolean open;
   attribute DOMString returnValue;
   [CEReactions] void show();
@@ -1123,9 +1175,10 @@
   [CEReactions] void close(optional DOMString returnValue);
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLScriptElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute USVString src;
   [CEReactions] attribute DOMString type;
   [CEReactions] attribute boolean noModule;
@@ -1139,15 +1192,17 @@
   // also has obsolete members
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLTemplateElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   readonly attribute DocumentFragment content;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLSlotElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString name;
   sequence<Node> assignedNodes(optional AssignedNodesOptions options = {});
   sequence<Element> assignedElements(optional AssignedNodesOptions options = {});
@@ -1395,19 +1450,21 @@
   readonly attribute double ideographicBaseline;
 };
 
-[Constructor(unsigned long sw, unsigned long sh),
- Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh),
- Exposed=(Window,Worker),
+[Exposed=(Window,Worker),
  Serializable]
 interface ImageData {
+  constructor(unsigned long sw, unsigned long sh);
+  constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh);
+
   readonly attribute unsigned long width;
   readonly attribute unsigned long height;
   readonly attribute Uint8ClampedArray data;
 };
 
-[Constructor(optional (Path2D or DOMString) path),
- Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface Path2D {
+  constructor(optional (Path2D or DOMString) path);
+
   void addPath(Path2D path, optional DOMMatrix2DInit transform = {});
 };
 Path2D includes CanvasPath;
@@ -1431,8 +1488,10 @@
 
 enum OffscreenRenderingContextId { "2d", "bitmaprenderer", "webgl", "webgl2" };
 
-[Constructor([EnforceRange] unsigned long long width, [EnforceRange] unsigned long long height), Exposed=(Window,Worker), Transferable]
+[Exposed=(Window,Worker), Transferable]
 interface OffscreenCanvas : EventTarget {
+  constructor([EnforceRange] unsigned long long width, [EnforceRange] unsigned long long height);
+
   attribute [EnforceRange] unsigned long long width;
   attribute [EnforceRange] unsigned long long height;
 
@@ -1737,9 +1796,10 @@
   readonly attribute boolean onLine;
 };
 
-[Constructor(DOMString type, optional ErrorEventInit eventInitDict = {}),
- Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface ErrorEvent : Event {
+  constructor(DOMString type, optional ErrorEventInit eventInitDict = {});
+
   readonly attribute DOMString message;
   readonly attribute USVString filename;
   readonly attribute unsigned long lineno;
@@ -1755,8 +1815,10 @@
   any error = null;
 };
 
-[Constructor(DOMString type, PromiseRejectionEventInit eventInitDict), Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface PromiseRejectionEvent : Event {
+  constructor(DOMString type, PromiseRejectionEventInit eventInitDict);
+
   readonly attribute Promise<any> promise;
   readonly attribute any reason;
 };
@@ -1834,6 +1896,7 @@
   attribute EventHandler onseeked;
   attribute EventHandler onseeking;
   attribute EventHandler onselect;
+  attribute EventHandler onslotchange;
   attribute EventHandler onstalled;
   attribute EventHandler onsubmit;
   attribute EventHandler onsuspend;
@@ -2012,9 +2075,10 @@
 Window includes AnimationFrameProvider;
 DedicatedWorkerGlobalScope includes AnimationFrameProvider;
 
-[Constructor(DOMString type, optional MessageEventInit eventInitDict = {}),
- Exposed=(Window,Worker,AudioWorklet)]
+[Exposed=(Window,Worker,AudioWorklet)]
 interface MessageEvent : Event {
+  constructor(DOMString type, optional MessageEventInit eventInitDict = {});
+
   readonly attribute any data;
   readonly attribute USVString origin;
   readonly attribute DOMString lastEventId;
@@ -2034,8 +2098,10 @@
 
 typedef (WindowProxy or MessagePort or ServiceWorker) MessageEventSource;
 
-[Constructor(USVString url, optional EventSourceInit eventSourceInitDict = {}), Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface EventSource : EventTarget {
+  constructor(USVString url, optional EventSourceInit eventSourceInitDict = {});
+
   readonly attribute USVString url;
   readonly attribute boolean withCredentials;
 
@@ -2057,8 +2123,10 @@
 };
 
 enum BinaryType { "blob", "arraybuffer" };
-[Constructor(USVString url, optional (DOMString or sequence<DOMString>) protocols = []), Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface WebSocket : EventTarget {
+  constructor(USVString url, optional (DOMString or sequence<DOMString>) protocols = []);
+
   readonly attribute USVString url;
 
   // ready state
@@ -2086,9 +2154,10 @@
   void send(ArrayBufferView data);
 };
 
-[Constructor(DOMString type, optional CloseEventInit eventInitDict = {}),
- Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface CloseEvent : Event {
+  constructor(DOMString type, optional CloseEventInit eventInitDict = {});
+
   readonly attribute boolean wasClean;
   readonly attribute unsigned short code;
   readonly attribute USVString reason;
@@ -2122,8 +2191,10 @@
   sequence<object> transfer = [];
 };
 
-[Constructor(DOMString name), Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface BroadcastChannel : EventTarget {
+  constructor(DOMString name);
+
   readonly attribute DOMString name;
   void postMessage(any message);
   void close();
@@ -2172,9 +2243,10 @@
   attribute EventHandler onerror;
 };
 
-[Constructor(USVString scriptURL, optional WorkerOptions options = {}),
- Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface Worker : EventTarget {
+  constructor(USVString scriptURL, optional WorkerOptions options = {});
+
   void terminate();
 
   void postMessage(any message, sequence<object> transfer);
@@ -2193,9 +2265,10 @@
 
 Worker includes AbstractWorker;
 
-[Constructor(USVString scriptURL, optional (DOMString or WorkerOptions) options = {}),
- Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface SharedWorker : EventTarget {
+  constructor(USVString scriptURL, optional (DOMString or WorkerOptions) options = {});
+
   readonly attribute MessagePort port;
 };
 SharedWorker includes AbstractWorker;
@@ -2264,9 +2337,10 @@
   Storage? storageArea = null;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLMarqueeElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString behavior;
   [CEReactions] attribute DOMString bgColor;
   [CEReactions] attribute DOMString direction;
@@ -2287,17 +2361,19 @@
   void stop();
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLFrameSetElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString cols;
   [CEReactions] attribute DOMString rows;
 };
 HTMLFrameSetElement includes WindowEventHandlers;
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLFrameElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute DOMString name;
   [CEReactions] attribute DOMString scrolling;
   [CEReactions] attribute USVString src;
@@ -2348,9 +2424,10 @@
   [CEReactions] attribute DOMString width;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLDirectoryElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute boolean compact;
 };
 
@@ -2367,9 +2444,10 @@
   [CEReactions] attribute DOMString name;
 };
 
-[Exposed=Window,
- HTMLConstructor]
+[Exposed=Window]
 interface HTMLFontElement : HTMLElement {
+  [HTMLConstructor] constructor();
+
   [CEReactions] attribute [TreatNullAs=EmptyString] DOMString color;
   [CEReactions] attribute DOMString face;
   [CEReactions] attribute DOMString size;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/magnetometer.idl b/third_party/blink/web_tests/external/wpt/interfaces/magnetometer.idl
index be6cbc9..da1f22b 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/magnetometer.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/magnetometer.idl
@@ -3,9 +3,10 @@
 // (https://github.com/tidoust/reffy-reports)
 // Source: Magnetometer (https://w3c.github.io/magnetometer/)
 
-[Constructor(optional MagnetometerSensorOptions sensorOptions = {}), SecureContext,
+[SecureContext,
   Exposed=Window]
 interface Magnetometer : Sensor {
+  constructor(optional MagnetometerSensorOptions sensorOptions = {});
   readonly attribute double? x;
   readonly attribute double? y;
   readonly attribute double? z;
@@ -17,9 +18,10 @@
   MagnetometerLocalCoordinateSystem referenceFrame = "device";
 };
 
-[Constructor(optional MagnetometerSensorOptions sensorOptions = {}), SecureContext,
+[SecureContext,
   Exposed=Window]
 interface UncalibratedMagnetometer : Sensor {
+  constructor(optional MagnetometerSensorOptions sensorOptions = {});
   readonly attribute double? x;
   readonly attribute double? y;
   readonly attribute double? z;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/proximity.idl b/third_party/blink/web_tests/external/wpt/interfaces/proximity.idl
index 570a29f..d4c8fae 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/proximity.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/proximity.idl
@@ -3,7 +3,7 @@
 // (https://github.com/tidoust/reffy-reports)
 // Source: Proximity Sensor (https://w3c.github.io/proximity/)
 
-[Constructor(optional SensorOptions sensorOptions), SecureContext, Exposed=Window]
+[Constructor(optional SensorOptions sensorOptions = {}), SecureContext, Exposed=Window]
 interface ProximitySensor : Sensor {
   readonly attribute double? distance;
   readonly attribute double? max;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/touch-events.idl b/third_party/blink/web_tests/external/wpt/interfaces/touch-events.idl
index 1a8c9d7..84c4828 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/touch-events.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/touch-events.idl
@@ -9,46 +9,47 @@
 };
 
 dictionary TouchInit {
-    required long identifier;
+    required long        identifier;
     required EventTarget target;
-             double clientX = 0;
-             double clientY = 0;
-             double screenX = 0;
-             double screenY = 0;
-             double pageX = 0;
-             double pageY = 0;
-             float radiusX = 0;
-             float radiusY = 0;
-             float rotationAngle = 0;
-             float force = 0;
-             double altitudeAngle = 0;
-             double azimuthAngle = 0;
-             TouchType touchType = "direct";
+             double      clientX = 0;
+             double      clientY = 0;
+             double      screenX = 0;
+             double      screenY = 0;
+             double      pageX = 0;
+             double      pageY = 0;
+             float       radiusX = 0;
+             float       radiusY = 0;
+             float       rotationAngle = 0;
+             float       force = 0;
+             double      altitudeAngle = 0;
+             double      azimuthAngle = 0;
+             TouchType   touchType = "direct";
 };
 
-[Constructor(TouchInit touchInitDict), Exposed=Window]
+[Exposed=Window]
 interface Touch {
-    readonly        attribute long identifier;
+    constructor(TouchInit touchInitDict);
+    readonly        attribute long        identifier;
     readonly        attribute EventTarget target;
-    readonly        attribute double screenX;
-    readonly        attribute double screenY;
-    readonly        attribute double clientX;
-    readonly        attribute double clientY;
-    readonly        attribute double pageX;
-    readonly        attribute double pageY;
-    readonly        attribute float radiusX;
-    readonly        attribute float radiusY;
-    readonly        attribute float rotationAngle;
-    readonly        attribute float force;
-    readonly        attribute float altitudeAngle;
-    readonly        attribute float azimuthAngle;
-    readonly        attribute TouchType touchType;
+    readonly        attribute double      screenX;
+    readonly        attribute double      screenY;
+    readonly        attribute double      clientX;
+    readonly        attribute double      clientY;
+    readonly        attribute double      pageX;
+    readonly        attribute double      pageY;
+    readonly        attribute float       radiusX;
+    readonly        attribute float       radiusY;
+    readonly        attribute float       rotationAngle;
+    readonly        attribute float       force;
+    readonly        attribute float       altitudeAngle;
+    readonly        attribute float       azimuthAngle;
+    readonly        attribute TouchType   touchType;
 };
 
 [Exposed=Window]
 interface TouchList {
     readonly        attribute unsigned long length;
-    getter Touch? item(unsigned long index);
+    getter Touch? item (unsigned long index);
 };
 
 dictionary TouchEventInit : EventModifierInit {
@@ -57,8 +58,9 @@
              sequence<Touch> changedTouches = [];
 };
 
-[Constructor(DOMString type, optional TouchEventInit eventInitDict = {}), Exposed=Window]
+[Exposed=Window]
 interface TouchEvent : UIEvent {
+    constructor(DOMString type, optional TouchEventInit eventInitDict = {});
     readonly        attribute TouchList touches;
     readonly        attribute TouchList targetTouches;
     readonly        attribute TouchList changedTouches;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/url.idl b/third_party/blink/web_tests/external/wpt/interfaces/url.idl
index 998052d..b0b237e 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/url.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/url.idl
@@ -3,10 +3,11 @@
 // (https://github.com/tidoust/reffy-reports)
 // Source: URL Standard (https://url.spec.whatwg.org/)
 
-[Constructor(USVString url, optional USVString base),
- Exposed=(Window,Worker),
+[Exposed=(Window,Worker),
  LegacyWindowAlias=webkitURL]
 interface URL {
+  constructor(USVString url, optional USVString base);
+
   stringifier attribute USVString href;
   readonly attribute USVString origin;
            attribute USVString protocol;
@@ -23,9 +24,10 @@
   USVString toJSON();
 };
 
-[Constructor(optional (sequence<sequence<USVString>> or record<USVString, USVString> or USVString) init = ""),
- Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface URLSearchParams {
+  constructor(optional (sequence<sequence<USVString>> or record<USVString, USVString> or USVString) init = "");
+
   void append(USVString name, USVString value);
   void delete(USVString name);
   USVString? get(USVString name);
diff --git a/third_party/blink/web_tests/external/wpt/signed-exchange/README.md b/third_party/blink/web_tests/external/wpt/signed-exchange/README.md
index f1dbfe6..4032edf 100644
--- a/third_party/blink/web_tests/external/wpt/signed-exchange/README.md
+++ b/third_party/blink/web_tests/external/wpt/signed-exchange/README.md
@@ -1,5 +1,5 @@
 This directory contains tests for the
-[b2 implementation snapshot](https://tools.ietf.org/html/draft-yasskin-httpbis-origin-signed-exchanges-impl-02) of the
+[b3 implementation snapshot](https://tools.ietf.org/html/draft-yasskin-httpbis-origin-signed-exchanges-impl-03) of the
 [Signed HTTP Exchanges](https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html).
 
 `resources` directory contains pregenerated signed exchanges and
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
index 3584c93..9eeb8362 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
@@ -3,6 +3,6 @@
 mozlog==4.2.0
 mozdebug==0.1.1
 pillow==6.1.0
-urllib3[secure]==1.25.5
+urllib3[secure]==1.25.6
 requests==2.22.0
 six==1.12.0
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt
index 8450824..35c5a82 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt
@@ -10,10 +10,10 @@
 PASS Does not return finished animations that do not fill forwards
 PASS Returns finished animations that fill forwards
 PASS Returns animations yet to reach their active phase
-FAIL Does not return reversed finished animations that do not fill backwards assert_array_equals: lengths differ, expected 0 got 1
+PASS Does not return reversed finished animations that do not fill backwards
 PASS Returns reversed finished animations that fill backwards
 FAIL Returns reversed animations yet to reach their active phase assert_array_equals: lengths differ, expected 1 got 0
-FAIL Does not return animations with zero playback rate in before phase assert_array_equals: lengths differ, expected 0 got 1
+PASS Does not return animations with zero playback rate in before phase
 PASS Does not return animations with zero playback rate in after phase
 PASS Returns animations based on dynamic changes to individual animations' duration
 PASS Returns animations based on dynamic changes to individual animations' end delay
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range-expected.png
deleted file mode 100644
index 991b245..0000000
--- a/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range.html b/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range.html
deleted file mode 100644
index 10427f6d..0000000
--- a/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<input type=range /><br><br>
-<input type=range disabled />
-<script>
-    if (window.testRunner)
-        testRunner.setUseMockTheme(false);
-</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
new file mode 100644
index 0000000..14938d3
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range_meter_progress.html b/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range_meter_progress.html
new file mode 100644
index 0000000..dd612a1
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui-high-contrast/range_meter_progress.html
@@ -0,0 +1,10 @@
+<input type=range /><br><br>
+<input type=range disabled /><br><br>
+<progress max="100" value="50"></progress><br><br>
+<meter min="0" max="100" low="30" high="60" optimum="100" value="80"></meter><br><br>
+<meter min="0" max="100" low="30" high="60" optimum="100" value="45"></meter><br><br>
+<meter min="0" max="100" low="30" high="60" optimum="100" value="25"></meter><br><br>
+<script>
+  if (window.testRunner)
+    testRunner.setUseMockTheme(false);
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index cfb9006..2715f6b 100644
--- a/third_party/blink/web_tests/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/meter/meter-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/meter/meter-appearance-basic.html
index ea5c4dc..1d71d7d 100644
--- a/third_party/blink/web_tests/fast/forms/controls-new-ui/meter/meter-appearance-basic.html
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/meter/meter-appearance-basic.html
@@ -10,7 +10,7 @@
   meter.optimumvalstyled::-webkit-meter-optimum-value { background: cadetblue; border-style: solid; border-width: 2px; border-color: blue; }
   meter.suboptimumvalstyled::-webkit-meter-suboptimum-value { background: cadetblue; border-style: solid; border-width: 2px; border-color: blue; }
   meter.evenlessgoodvalstyled::-webkit-meter-even-less-good-value { background: cadetblue; border-style: solid; border-width: 2px; border-color: blue; }
-  meter#bar-paddings::-webkit-meter-bar { padding: 5px; }
+  meter#bar-paddings::-webkit-meter-bar { padding: 2px; }
 </style>
 </head>
 <body>
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
new file mode 100644
index 0000000..dbed8a4
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/progress/progress-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/progress/progress-appearance-basic.html
new file mode 100644
index 0000000..cc52e28
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/progress/progress-appearance-basic.html
@@ -0,0 +1,13 @@
+<progress max="100" value="0"></progress><br><br>
+<progress max="100" value="1"></progress><br><br>
+<progress max="100" value="5"></progress><br><br>
+<progress max="100" value="50"></progress><br><br>
+<progress max="100" value="95"></progress><br><br>
+<progress max="100" value="99"></progress><br><br>
+<progress max="100" value="100"></progress><br><br>
+<progress max="100" value="50" style="height:30px"></progress><br><br>
+<script>
+if (window.testRunner)
+  testRunner.setUseMockTheme(false);
+</script>
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/devtools/coverage/segments-merge-expected.txt b/third_party/blink/web_tests/http/tests/devtools/coverage/segments-merge-expected.txt
index 82930a96..51dcf28 100644
--- a/third_party/blink/web_tests/http/tests/devtools/coverage/segments-merge-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/coverage/segments-merge-expected.txt
@@ -3,22 +3,35 @@
 A: []
 B: []
 merged: []
-A: [{"end":10,"count":1}]
+A: [{"end":10,"count":1,"stamp":100}]
 B: []
-merged: [{"end":10,"count":1}]
-A: [{"end":10,"count":1}]
-B: [{"end":10,"count":1}]
-merged: [{"end":10,"count":2}]
-A: [{"end":10,"count":1}]
-B: [{"end":20,"count":1}]
-merged: [{"end":10,"count":2},{"end":20,"count":1}]
-A: [{"end":10,"count":1},{"end":20,"count":1}]
+merged: [{"end":10,"count":1,"stamp":100}]
+A: [{"end":10,"count":1,"stamp":100}]
+B: [{"end":10,"count":1,"stamp":100}]
+merged: [{"end":10,"count":2,"stamp":100}]
+A: [{"end":10,"count":1,"stamp":100}]
+B: [{"end":20,"count":1,"stamp":100}]
+merged: [{"end":10,"count":2,"stamp":100},{"end":20,"count":1,"stamp":100}]
+A: [{"end":10,"count":1,"stamp":100},{"end":20,"count":1,"stamp":100}]
 B: []
-merged: [{"end":10,"count":1},{"end":20,"count":1}]
-A: [{"end":30,"count":1}]
-B: [{"end":10},{"end":20,"count":2}]
-merged: [{"end":10,"count":1},{"end":20,"count":3},{"end":30,"count":1}]
-A: [{"end":30}]
-B: [{"end":10},{"end":20,"count":2}]
-merged: [{"end":10},{"end":20,"count":2},{"end":30}]
+merged: [{"end":10,"count":1,"stamp":100},{"end":20,"count":1,"stamp":100}]
+A: [{"end":30,"count":1,"stamp":100}]
+B: [{"end":10,"stamp":100},{"end":20,"count":2,"stamp":100}]
+merged: [{"end":10,"count":1,"stamp":100},{"end":20,"count":3,"stamp":100},{"end":30,"count":1,"stamp":100}]
+A: [{"end":30,"stamp":100}]
+B: [{"end":10,"stamp":100},{"end":20,"count":2,"stamp":100}]
+merged: [{"end":10,"stamp":100},{"end":20,"count":2,"stamp":100},{"end":30,"stamp":100}]
+Merging different stamps should result in the minimum timestamp
+A: [{"end":10,"count":1,"stamp":100}]
+B: [{"end":10,"count":1,"stamp":200}]
+merged: [{"end":10,"count":2,"stamp":100}]
+A: [{"end":10,"count":1,"stamp":100}]
+B: [{"end":20,"count":1,"stamp":200}]
+merged: [{"end":10,"count":2,"stamp":100},{"end":20,"count":1,"stamp":200}]
+A: [{"end":10,"count":1,"stamp":100},{"end":20,"count":1,"stamp":200}]
+B: []
+merged: [{"end":10,"count":1,"stamp":100},{"end":20,"count":1,"stamp":200}]
+A: [{"end":30,"count":1,"stamp":100}]
+B: [{"end":10,"stamp":100},{"end":20,"count":2,"stamp":200}]
+merged: [{"end":10,"count":1,"stamp":100},{"end":20,"count":3,"stamp":100},{"end":30,"count":1,"stamp":100}]
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/coverage/segments-merge.js b/third_party/blink/web_tests/http/tests/devtools/coverage/segments-merge.js
index f0f6f51a..f4f76f4 100644
--- a/third_party/blink/web_tests/http/tests/devtools/coverage/segments-merge.js
+++ b/third_party/blink/web_tests/http/tests/devtools/coverage/segments-merge.js
@@ -7,12 +7,18 @@
   await TestRunner.loadModule('coverage');
 
   testAndDump([], []);
-  testAndDump([{end: 10, count: 1}], []);
-  testAndDump([{end: 10, count: 1}], [{end: 10, count: 1}]);
-  testAndDump([{end: 10, count: 1}], [{end: 20, count: 1}]);
-  testAndDump([{end: 10, count: 1}, {end: 20, count: 1}], []);
-  testAndDump([{end: 30, count: 1}], [{end: 10, count: undefined}, {end: 20, count: 2}]);
-  testAndDump([{end: 30, count: undefined}], [{end: 10, count: undefined}, {end: 20, count: 2}]);
+  testAndDump([{end: 10, count: 1, stamp: 100}], []);
+  testAndDump([{end: 10, count: 1, stamp: 100}], [{end: 10, count: 1, stamp: 100}]);
+  testAndDump([{end: 10, count: 1, stamp: 100}], [{end: 20, count: 1, stamp: 100}]);
+  testAndDump([{end: 10, count: 1, stamp: 100}, {end: 20, count: 1, stamp: 100}], []);
+  testAndDump([{end: 30, count: 1, stamp: 100}], [{end: 10, count: undefined, stamp: 100}, {end: 20, count: 2, stamp: 100}]);
+  testAndDump([{end: 30, count: undefined, stamp: 100}], [{end: 10, count: undefined, stamp: 100}, {end: 20, count: 2, stamp: 100}]);
+
+  TestRunner.addResult(`Merging different stamps should result in the minimum timestamp`);
+  testAndDump([{end: 10, count: 1, stamp: 100}], [{end: 10, count: 1, stamp: 200}]);
+  testAndDump([{end: 10, count: 1, stamp: 100}], [{end: 20, count: 1, stamp: 200}]);
+  testAndDump([{end: 10, count: 1, stamp: 100}, {end: 20, count: 1, stamp: 200}], []);
+  testAndDump([{end: 30, count: 1, stamp: 100}], [{end: 10, count: undefined, stamp: 100}, {end: 20, count: 2, stamp: 200}]);
 
   TestRunner.completeTest();
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance-expected.txt
index 0778002..263c0db 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance-expected.txt
@@ -26,9 +26,9 @@
             </SPAN>
         </DIV>
         <DIV class=view-network-button >
-            <BUTTON class=origin-button text-button type=button role=link >
+            <SPAN class=devtools-link origin-button role=link >
 View requests in Network Panel
-            </BUTTON>
+            </SPAN>
         </DIV>
     </DIV>
     <DIV class=origin-view-section >
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-noncryptographic-secure-origin-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-noncryptographic-secure-origin-expected.txt
index c5eb398..45bd944 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-noncryptographic-secure-origin-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-noncryptographic-secure-origin-expected.txt
@@ -26,9 +26,9 @@
             </SPAN>
         </DIV>
         <DIV class=view-network-button >
-            <BUTTON class=origin-button text-button type=button role=link >
+            <SPAN class=devtools-link origin-button role=link >
 View requests in Network Panel
-            </BUTTON>
+            </SPAN>
         </DIV>
     </DIV>
     <DIV class=origin-view-section >
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial-expected.txt
index b88d357..3f74b2bc 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial-expected.txt
@@ -54,9 +54,9 @@
             </SPAN>
         </DIV>
         <DIV class=view-network-button >
-            <BUTTON class=origin-button text-button type=button role=link >
+            <SPAN class=devtools-link origin-button role=link >
 View requests in Network Panel
-            </BUTTON>
+            </SPAN>
         </DIV>
     </DIV>
     <DIV class=origin-view-section >
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state-expected.txt
index f5329b6..0c877fa 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state-expected.txt
@@ -70,9 +70,9 @@
             </SPAN>
         </DIV>
         <DIV class=view-network-button >
-            <BUTTON class=origin-button text-button type=button role=link >
+            <SPAN class=devtools-link origin-button role=link >
 View requests in Network Panel
-            </BUTTON>
+            </SPAN>
         </DIV>
     </DIV>
     <DIV class=origin-view-section >
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js
index ade00e1..c842f58b 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js
@@ -140,6 +140,22 @@
     return eval(`${source}\n//# sourceURL=${url}`);
   };
 
+  async loadScriptModule(path) {
+    const source = await this._fetch(this._testBaseURL + path);
+
+    return new Promise((resolve, reject) => {
+      const src = URL.createObjectURL(new Blob([source], { type: 'application/javascript' }));
+      const script = Object.assign(document.createElement('script'), {
+        src,
+        type: 'module',
+        onerror: reject,
+        onload: resolve
+      });
+
+      document.head.appendChild(script);
+    })
+  };
+
   browserP() {
     return this._browserSession.protocol;
   }
diff --git a/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js b/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
index 6239b7f..17053bf 100644
--- a/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
+++ b/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
@@ -6,12 +6,18 @@
 
   // This script is supposed to be evaluated in inspector-protocol/heap-profiler tests
   // and the relative paths below are relative to that location.
-  await testRunner.loadScript('../../../../blink/renderer/devtools/front_end/platform/utilities.js');
-  await testRunner.loadScript('../../../../blink/renderer/devtools/front_end/common/UIString.js');
-  await testRunner.loadScript('../../../../blink/renderer/devtools/front_end/heap_snapshot_model/HeapSnapshotModel.js');
-  await testRunner.loadScript('../../../../blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js');
-  await testRunner.loadScript('../../../../blink/renderer/devtools/front_end/text_utils/TextUtils.js');
-  await testRunner.loadScript('../../../../blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js');
+  await testRunner.loadScriptModule(
+      '../../../../blink/renderer/devtools/front_end/platform/utilities.js');
+  await testRunner.loadScriptModule(
+      '../../../../blink/renderer/devtools/front_end/common/UIString.js');
+  await testRunner.loadScriptModule(
+      '../../../../blink/renderer/devtools/front_end/heap_snapshot_model/HeapSnapshotModel.js');
+  await testRunner.loadScriptModule(
+      '../../../../blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js');
+  await testRunner.loadScriptModule(
+      '../../../../blink/renderer/devtools/front_end/text_utils/TextUtils.js');
+  await testRunner.loadScriptModule(
+      '../../../../blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js');
 
   async function takeHeapSnapshotInternal(command) {
     var loader = new HeapSnapshotWorker.HeapSnapshotLoader();
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index 03bf9513..b5d7836 100644
--- a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index 59255b0..000f4d5 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
index 5f3abce9..749dfba 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
new file mode 100644
index 0000000..e0432bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index 7ea65b9..73687cc9 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
new file mode 100644
index 0000000..cc212a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
index 2185947b..2b6f102 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
new file mode 100644
index 0000000..e0432bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index 7ea65b9..73687cc9 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
new file mode 100644
index 0000000..cc212a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
index 2185947b..2b6f102 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
new file mode 100644
index 0000000..e0432bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index 7ea65b9..73687cc9 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
new file mode 100644
index 0000000..cc212a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
index 2185947b..2b6f102 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
new file mode 100644
index 0000000..e0432bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index 7ea65b9..73687cc9 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
new file mode 100644
index 0000000..cc212a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
index 2185947b..2b6f102 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
new file mode 100644
index 0000000..1016a1a4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index c8a0d46..0ec1a84 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
new file mode 100644
index 0000000..0b595a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
new file mode 100644
index 0000000..e0432bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index 7ea65b9..73687cc9 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
new file mode 100644
index 0000000..cc212a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
index 2185947b..2b6f102 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png b/third_party/blink/web_tests/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
new file mode 100644
index 0000000..918e395
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/range_meter_progress-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
index c15930a..ab85159c 100644
--- a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
new file mode 100644
index 0000000..e7559c0
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/progress/progress-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
index 0dbe488..8d0e340 100644
--- a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index dad8440..b38a037b 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-10-1-51-g4881f75b7
-Revision: 4881f75b7ca04a35da4b467b46b28ae52b176482
+Version: VER-2-10-1-52-gdb4083fd7
+Revision: db4083fd7f19fd3fbd5d5a8e60d5c8e0f19778bd
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
 License File: src/docs/FTL.TXT
diff --git a/tools/ipc_messages_log.py b/tools/ipc_messages_log.py
index 26284d1..ff27487e 100755
--- a/tools/ipc_messages_log.py
+++ b/tools/ipc_messages_log.py
@@ -19,6 +19,8 @@
 Chromium is checked out using git.
 """
 
+from __future__ import print_function
+
 import optparse
 import os
 import re
@@ -99,11 +101,11 @@
     match = re.match(msg_start_re, line)
     if match:
       msg_start = match.group(1)
-      # print "msg_start = " + msg_start
+      # print("msg_start = " + msg_start)
     match = re.match(msg_def_re, line)
     if match:
       msg_name = match.group(1)
-      # print "msg_name = " + msg_name
+      # print("msg_name = " + msg_name)
     if msg_start and msg_name:
       msg_id = _GetMsgId(msg_start, line_number, msg_start_table)
       msg_map[msg_id] = msg_name
@@ -128,7 +130,7 @@
       line = re.sub(unknown_msg_re,
                     _ResolveMsg(int(match.group(1)), msg_map),
                     line)
-    print line
+    print(line)
 
 
 def _GetMsgMap():
diff --git a/tools/json_schema_compiler/feature_compiler.py b/tools/json_schema_compiler/feature_compiler.py
index d29e285..dc9e8ee 100644
--- a/tools/json_schema_compiler/feature_compiler.py
+++ b/tools/json_schema_compiler/feature_compiler.py
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import argparse
 import copy
 from datetime import datetime
diff --git a/tools/json_schema_compiler/features_compiler.py b/tools/json_schema_compiler/features_compiler.py
index 9552504..1b744e2 100755
--- a/tools/json_schema_compiler/features_compiler.py
+++ b/tools/json_schema_compiler/features_compiler.py
@@ -8,6 +8,8 @@
   features_compiler.py --destdir gen --root /home/Work/src _permissions.json
 """
 
+from __future__ import print_function
+
 import optparse
 import os
 
@@ -75,4 +77,4 @@
   result = _GenerateSchema(filenames[0], opts.root, opts.destdir,
                            opts.namespace)
   if not opts.destdir:
-    print result
+    print(result)
diff --git a/tools/json_schema_compiler/json_schema.py b/tools/json_schema_compiler/json_schema.py
index e00c11d7..e980e9693 100644
--- a/tools/json_schema_compiler/json_schema.py
+++ b/tools/json_schema_compiler/json_schema.py
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import copy
 
 import json_parse
@@ -58,4 +60,3 @@
   # Return a copy of the object so that any changes a caller makes won't affect
   # the next caller.
   return copy.deepcopy(_cache[filename])
-
diff --git a/tools/json_schema_compiler/model.py b/tools/json_schema_compiler/model.py
index 0d2e240..cafd0e1 100644
--- a/tools/json_schema_compiler/model.py
+++ b/tools/json_schema_compiler/model.py
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import os.path
 
 from json_parse import OrderedDict
diff --git a/tools/json_schema_compiler/preview.py b/tools/json_schema_compiler/preview.py
index db4550e..208e7fa 100755
--- a/tools/json_schema_compiler/preview.py
+++ b/tools/json_schema_compiler/preview.py
@@ -6,6 +6,8 @@
 """Server for viewing the compiled C++ code from tools/json_schema_compiler.
 """
 
+from __future__ import print_function
+
 import cc_generator
 import code
 import cpp_type_generator
diff --git a/tools/linux/dump-static-initializers.py b/tools/linux/dump-static-initializers.py
index de271dd4..c448b26 100755
--- a/tools/linux/dump-static-initializers.py
+++ b/tools/linux/dump-static-initializers.py
@@ -23,6 +23,8 @@
 they reference.
 """
 
+from __future__ import print_function
+
 import optparse
 import re
 import subprocess
@@ -252,18 +254,19 @@
 
     if opts.diffable:
       if ref_output:
-        print '\n'.join('# ' + qualified_filename + ' ' + r for r in ref_output)
+        print('\n'.join(
+            '# ' + qualified_filename + ' ' + r for r in ref_output))
       else:
-        print '# %s: (empty initializer list)' % qualified_filename
+        print('# %s: (empty initializer list)' % qualified_filename)
     else:
-      print '%s (initializer offset 0x%x size 0x%x)' % (qualified_filename,
-                                                        addr, size)
-      print ''.join('  %s\n' % r for r in ref_output)
+      print('%s (initializer offset 0x%x size 0x%x)' % (qualified_filename,
+                                                        addr, size))
+      print(''.join('  %s\n' % r for r in ref_output))
 
   if opts.diffable:
-    print '#',
-  print 'Found %d static initializers in %d files.' % (initializer_count,
-                                                       file_count)
+    print('#', end=' ')
+  print('Found %d static initializers in %d files.' % (initializer_count,
+                                                       file_count))
 
   return 0
 
diff --git a/tools/linux/procfs.py b/tools/linux/procfs.py
index ef19b25e..7211b98 100755
--- a/tools/linux/procfs.py
+++ b/tools/linux/procfs.py
@@ -9,6 +9,7 @@
 # as reasonablly possible. Translation is done when requested. It is to make it
 # always possible to probe the original data.
 
+from __future__ import print_function
 
 import collections
 import logging
@@ -725,20 +726,20 @@
     procs[pid] = _ProcessMemory(pid)
     procs[pid].read_all()
 
-    print '=== PID: %d ===' % pid
+    print('=== PID: %d ===' % pid)
 
-    print '   stat: %d' % procs[pid].stat.vsize
-    print '  statm: %d' % (procs[pid].statm.size * 4096)
-    print ' status: %d (Peak:%d)' % (procs[pid].status.vm_size * 1024,
-                                     procs[pid].status.vm_peak * 1024)
-    print '  smaps: %d' % (procs[pid].smaps.size * 1024)
-    print 'pagemap: %d' % procs[pid].pagemap.vsize
-    print '   stat: %d' % (procs[pid].stat.rss * 4096)
-    print '  statm: %d' % (procs[pid].statm.resident * 4096)
-    print ' status: %d (Peak:%d)' % (procs[pid].status.vm_rss * 1024,
-                                     procs[pid].status.vm_hwm * 1024)
-    print '  smaps: %d' % (procs[pid].smaps.rss * 1024)
-    print 'pagemap: %d' % procs[pid].pagemap.present
+    print('   stat: %d' % procs[pid].stat.vsize)
+    print('  statm: %d' % (procs[pid].statm.size * 4096))
+    print(' status: %d (Peak:%d)' % (procs[pid].status.vm_size * 1024,
+                                     procs[pid].status.vm_peak * 1024))
+    print('  smaps: %d' % (procs[pid].smaps.size * 1024))
+    print('pagemap: %d' % procs[pid].pagemap.vsize)
+    print('   stat: %d' % (procs[pid].stat.rss * 4096))
+    print('  statm: %d' % (procs[pid].statm.resident * 4096))
+    print(' status: %d (Peak:%d)' % (procs[pid].status.vm_rss * 1024,
+                                     procs[pid].status.vm_hwm * 1024))
+    print('  smaps: %d' % (procs[pid].smaps.rss * 1024))
+    print('pagemap: %d' % procs[pid].pagemap.present)
 
   return 0
 
diff --git a/tools/mac/dump-static-initializers.py b/tools/mac/dump-static-initializers.py
index 061cf523..3a389ca 100755
--- a/tools/mac/dump-static-initializers.py
+++ b/tools/mac/dump-static-initializers.py
@@ -16,6 +16,8 @@
 present, use show_mod_init_func.py.
 """
 
+from __future__ import print_function
+
 import optparse
 import re
 import subprocess
@@ -52,9 +54,9 @@
       else:
         match = dsymutil_re.search(line)
         if match:
-          print current_filename
-          print current_o_filename
-          print
+          print(current_filename)
+          print(current_o_filename)
+          print()
 
 
 def main():
diff --git a/tools/mac/rewrite_modern_objc.py b/tools/mac/rewrite_modern_objc.py
index 64cd839..1828cdc 100755
--- a/tools/mac/rewrite_modern_objc.py
+++ b/tools/mac/rewrite_modern_objc.py
@@ -13,6 +13,8 @@
 re-run gn, and then run this script.
 """
 
+from __future__ import print_function
+
 import argparse
 import glob
 import json
@@ -68,13 +70,15 @@
 
     had_error = False
     if 'gomacc' in clang_cmd:
-      print >>sys.stderr, 'need builddir with use_goma not set'
+      print('need builddir with use_goma not set', file=sys.stderr)
       had_error = True
     if 'jumbo' in clang_cmd:
-      print >>sys.stderr, 'need builddir with use_jumbo_build not set'
+      print('need builddir with use_jumbo_build not set', file=sys.stderr)
       had_error = True
     if 'precompile.h-m' in clang_cmd:
-      print >>sys.stderr, 'need builddir with enable_precompiled_headers=false'
+      print(
+          'need builddir with enable_precompiled_headers=false',
+          file=sys.stderr)
       had_error = True
     if had_error:
       sys.exit(1)
@@ -120,11 +124,11 @@
     #flags += ['-Xclang', '-objcmt-migrate-designated-init']
     clang_cmd += ' ' + ' '.join(flags)
 
-    print objc_file
+    print(objc_file)
     subprocess.check_call(clang_cmd, shell=True, cwd=cmd['directory'])
 
   if not os.path.exists(remap_file):
-    print 'no changes'
+    print('no changes')
     return
 
   # Done with rewriting. Now the read the above-described 'remap' file and
@@ -136,11 +140,11 @@
       # Ignore rewritten header files not containing args.substr too.
       continue
     if math.trunc(os.path.getmtime(infile)) != int(mtime):
-      print '%s was modified since rewriting; exiting' % infile
+      print('%s was modified since rewriting; exiting' % infile)
       sys.exit(1)
     os.rename(outfile, infile)  # Copy rewritten file over.
 
-  print 'all done. commit, run `git cl format`, commit again, and upload!'
+  print('all done. commit, run `git cl format`, commit again, and upload!')
 
 
 if __name__ == '__main__':
diff --git a/tools/mac/show_mod_init_func.py b/tools/mac/show_mod_init_func.py
index c41a2102..6774b6a6 100755
--- a/tools/mac/show_mod_init_func.py
+++ b/tools/mac/show_mod_init_func.py
@@ -14,6 +14,8 @@
 dump-static-initializers.py instead.
 """
 
+from __future__ import print_function
+
 import optparse
 import subprocess
 import sys
@@ -28,9 +30,9 @@
     return
   symbols = SymbolizeAddresses(binary, initializers)
 
-  print binary
+  print(binary)
   for initializer in zip(initializers, symbols):
-    print '%s @ %s' % initializer
+    print('%s @ %s' % initializer)
 
 
 def GetModuleInitializers(binary):
diff --git a/tools/mac/symbolicate_crash.py b/tools/mac/symbolicate_crash.py
index 731cc85f..2dabce4 100755
--- a/tools/mac/symbolicate_crash.py
+++ b/tools/mac/symbolicate_crash.py
@@ -15,6 +15,8 @@
   <http://developer.apple.com/tools/xcode/symbolizingcrashdumps.html>
 """
 
+from __future__ import print_function
+
 import optparse
 import os.path
 import re
@@ -88,7 +90,7 @@
       # list of |addresses|.
       symbol_names = self._RunAtos(binary_base, dsym_file, address_list)
       if not symbol_names:
-        print 'Error loading symbols for ' + image_name
+        print('Error loading symbols for ' + image_name)
         continue
 
       # Attaches a list of symbol names to stack frames. This assumes that the
@@ -351,7 +353,7 @@
     a smart-zip with the data returned by atos in |symbols|. Note that the
     indices must match for this to succeed."""
     if len(symbols) != len(address_tuples):
-      print 'symbols do not match'
+      print('symbols do not match')
 
     # Each line of output from atos is in this format:
     # |<symbol> (in <image>) (<file>:<line>)|.
@@ -427,31 +429,31 @@
 
 def PrettyPrintReport(report):
   """Takes a crash report and prints it like the crash server would."""
-  print 'Process    : ' + report.report_info['Process']
-  print 'Version    : ' + report.report_info['Version']
-  print 'Date       : ' + report.report_info['Date/Time']
-  print 'OS Version : ' + report.report_info['OS Version']
-  print
+  print('Process    : ' + report.report_info['Process'])
+  print('Version    : ' + report.report_info['Version'])
+  print('Date       : ' + report.report_info['Date/Time'])
+  print('OS Version : ' + report.report_info['OS Version'])
+  print()
   if 'Crashed Thread' in report.report_info:
-    print 'Crashed Thread : ' + report.report_info['Crashed Thread']
-    print
+    print('Crashed Thread : ' + report.report_info['Crashed Thread'])
+    print()
   if 'Event' in report.report_info:
-    print 'Event      : ' + report.report_info['Event']
-    print
+    print('Event      : ' + report.report_info['Event'])
+    print()
 
   for thread in report.threads:
-    print
+    print()
     if thread.did_crash:
       exc_type = report.report_info['Exception Type'].split(' ')[0]
       exc_code = report.report_info['Exception Codes'].replace('at', '@')
-      print '*CRASHED* ( ' + exc_type + ' / ' + exc_code + ' )'
+      print('*CRASHED* ( ' + exc_type + ' / ' + exc_code + ' )')
     # Version 7 reports have spindump-style output (with a stepped stack trace),
     # so remove the first tab to get better alignment.
     if report.report_version == 7:
       for line in repr(thread).split('\n'):
-        print line.replace('\t', '  ', 1)
+        print(line.replace('\t', '  ', 1))
     else:
-      print thread
+      print(thread)
 
 
 def Main(args):
@@ -489,11 +491,11 @@
 
   # Check that the symbols exist.
   if not os.path.isdir(symbol_path):
-    print >>sys.stderr, 'Symbol path %s is not a directory' % symbol_path
+    print('Symbol path %s is not a directory' % symbol_path, file=sys.stderr)
     return 2
 
-  print >>sys.stderr, 'Using symbols from ' + symbol_path
-  print >>sys.stderr, '=' * 80
+  print('Using symbols from ' + symbol_path, file=sys.stderr)
+  print('=' * 80, file=sys.stderr)
 
   report.Symbolicate(symbol_path)
   PrettyPrintReport(report)
diff --git a/tools/make-gtest-filter.py b/tools/make-gtest-filter.py
index 22c0e1d..4a6b3206 100755
--- a/tools/make-gtest-filter.py
+++ b/tools/make-gtest-filter.py
@@ -20,6 +20,8 @@
 > make-gtest-filter.py --line=123 ./myfile_unittest.cc
 """
 
+from __future__ import print_function
+
 import argparse
 import fileinput
 import re
@@ -61,7 +63,7 @@
   fixtures = set([t.split('.')[0] for t in tests])
   test_filters = [c + '.*' for c in fixtures]
   instantiation_filters = ['*/' + c + '.*/*' for c in fixtures]
-  print ':'.join(test_filters + instantiation_filters)
+  print(':'.join(test_filters + instantiation_filters))
 else:
   instantiations = ['*/' + c + '/*' for c in tests]
-  print ':'.join(tests + instantiations)
+  print(':'.join(tests + instantiations))
diff --git a/tools/media_engagement_preload/make_dafsa.py b/tools/media_engagement_preload/make_dafsa.py
index fd73c68..bc9b3815 100755
--- a/tools/media_engagement_preload/make_dafsa.py
+++ b/tools/media_engagement_preload/make_dafsa.py
@@ -3,6 +3,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import array
 import json
 import sys
diff --git a/tools/memory_inspector/memory_inspector/backends/adb_client.py b/tools/memory_inspector/memory_inspector/backends/adb_client.py
index 36d7d8c..88a6d3f 100644
--- a/tools/memory_inspector/memory_inspector/backends/adb_client.py
+++ b/tools/memory_inspector/memory_inspector/backends/adb_client.py
@@ -10,6 +10,8 @@
 requiring only that an adb daemon (adb start-server) is running on the host.
 """
 
+from __future__ import print_function
+
 import logging
 import os
 import pipes
@@ -280,34 +282,35 @@
   """Some minimal non-automated end-to-end testing."""
   import tempfile
   local_test_file = tempfile.mktemp()
-  print 'Starting test, please  make sure at least one device is connected'
+  print('Starting test, please  make sure at least one device is connected')
   devices = ListDevices()
-  print 'Devices:', devices
+  print('Devices:', devices)
   device = GetDevice(devices[0].serial)
   assert device.IsConnected()
   device.RestartShellAsRoot()
   device.WaitForDevice()
   build_fingerprint = device.Shell(['getprop', 'ro.build.fingerprint']).strip()
-  print 'Build fingerprint', build_fingerprint
+  print('Build fingerprint', build_fingerprint)
   device.RemountSystemPartition()
   assert 'rw' in device.Shell('cat /proc/mounts | grep system')
   mode, size, _ = device.Stat('/system/bin/sh')
   assert mode == 0100755, oct(mode)
   assert size > 1024
-  print 'Pulling a large file'
+  print('Pulling a large file')
   device.Pull('/system/lib/libwebviewchromium.so', local_test_file)
-  print 'Pushing a large file'
+  print('Pushing a large file')
   device.Push(local_test_file, '/data/local/tmp/file name.so')
   remote_md5 = device.Shell('md5 /system/lib/libwebviewchromium.so')[:32]
   remote_md5_copy = device.Shell(['md5', '/data/local/tmp/file name.so'])[:32]
   size = device.Stat('/data/local/tmp/file name.so')[1]
   assert size == os.path.getsize(local_test_file)
   device.Shell(['rm', '/data/local/tmp/file name.so'])
-  print 'Remote MD5 of the original file is', remote_md5
-  print 'Remote MD5 of the copied file is', remote_md5_copy
+  print('Remote MD5 of the original file is', remote_md5)
+  print('Remote MD5 of the copied file is', remote_md5_copy)
   os.unlink(local_test_file)
   assert remote_md5 == remote_md5_copy
-  print '[TEST PASSED]'
+  print('[TEST PASSED]')
+
 
 if __name__ == '__main__':
   _EndToEndTest()
diff --git a/tools/memory_inspector/memory_inspector/frontends/command_line.py b/tools/memory_inspector/memory_inspector/frontends/command_line.py
index 7987e9c..098a409f 100644
--- a/tools/memory_inspector/memory_inspector/frontends/command_line.py
+++ b/tools/memory_inspector/memory_inspector/frontends/command_line.py
@@ -4,6 +4,8 @@
 
 """Command line frontend for Memory Inspector"""
 
+from __future__ import print_function
+
 import json
 import memory_inspector
 import optparse
@@ -55,7 +57,7 @@
         device_id = device.id
 
   if number_of_devices == 0:
-    print "No devices connected"
+    print("No devices connected")
     return -1
 
   if number_of_devices > 1:
@@ -65,40 +67,38 @@
 
   device = backends.GetDevice(options.backend, device_id)
   if not device:
-    print 'Device', device_id, 'does not exist'
+    print('Device', device_id, 'does not exist')
     return -1
 
   device.Initialize()
   if args[0] == 'ps':
     if not options.filter_process_name:
-      print 'Listing all processes'
+      print('Listing all processes')
     else:
-      print ('Listing processes matching '
-          + options.filter_process_name.lower())
-    print ''
-    print '%-10s : %-50s : %12s %12s %12s' % (
-        'Process ID', 'Process Name', 'RUN_TIME', 'THREADS',
-        'MEM_RSS_KB')
-    print ''
+      print('Listing processes matching ' + options.filter_process_name.lower())
+    print('')
+    print('%-10s : %-50s : %12s %12s %12s' %
+          ('Process ID', 'Process Name', 'RUN_TIME', 'THREADS', 'MEM_RSS_KB'))
+    print('')
     for process in device.ListProcesses():
       if (not options.filter_process_name or
           options.filter_process_name.lower() in process.name.lower()):
         stats = process.GetStats()
         run_time_min, run_time_sec = divmod(stats.run_time, 60)
-        print '%10s : %-50s : %6s m %2s s %8s %12s' % (
-            process.pid, _Truncate(process.name, 50), run_time_min,
-            run_time_sec, stats.threads, stats.vm_rss)
+        print('%10s : %-50s : %6s m %2s s %8s %12s' %
+              (process.pid, _Truncate(process.name, 50), run_time_min,
+               run_time_sec, stats.threads, stats.vm_rss))
     return 0
 
   if not options.process_id:
-    print 'You need to provide --process_id'
+    print('You need to provide --process_id')
     return -1
 
   process = device.GetProcess(options.process_id)
 
   if not process:
-    print 'Cannot find process [%d] on device %s' % (
-        options.process_id, device.id)
+    print('Cannot find process [%d] on device %s' % (options.process_id,
+                                                     device.id))
     return -1
   elif args[0] == 'stats':
     _ListProcessStats(process)
@@ -112,46 +112,45 @@
 
 
 def _ListDevices(backend_name):
-  print 'Device list:'
-  print ''
+  print('Device list:')
+  print('')
   for device in backends.ListDevices():
     if device.backend.name == backend_name:
-      print '%-16s : %s' % (device.id, device.name)
+      print('%-16s : %s' % (device.id, device.name))
 
 
 def _ListProcessStats(process):
   """Prints process stats periodically
   """
-  print 'Stats for process: [%d] %s' % (process.pid, process.name)
-  print '%-10s : %-50s : %12s %12s %13s %12s %14s' % (
-      'Process ID', 'Process Name', 'RUN_TIME', 'THREADS',
-      'CPU_USAGE', 'MEM_RSS_KB', 'PAGE_FAULTS')
-  print ''
+  print('Stats for process: [%d] %s' % (process.pid, process.name))
+  print('%-10s : %-50s : %12s %12s %13s %12s %14s' %
+        ('Process ID', 'Process Name', 'RUN_TIME', 'THREADS', 'CPU_USAGE',
+         'MEM_RSS_KB', 'PAGE_FAULTS'))
+  print('')
   while True:
     stats = process.GetStats()
     run_time_min, run_time_sec = divmod(stats.run_time, 60)
-    print '%10s : %-50s : %6s m %2s s %8s %12s %13s %11s' % (
-        process.pid, _Truncate(process.name, 50), run_time_min, run_time_sec,
-        stats.threads, stats.cpu_usage, stats.vm_rss, stats.page_faults)
+    print('%10s : %-50s : %6s m %2s s %8s %12s %13s %11s' %
+          (process.pid, _Truncate(process.name, 50), run_time_min, run_time_sec,
+           stats.threads, stats.cpu_usage, stats.vm_rss, stats.page_faults))
     time.sleep(1)
 
 
 def _ListProcessMmaps(process):
   """Prints process memory maps
   """
-  print 'Memory Maps for process: [%d] %s' % (process.pid, process.name)
-  print '%-10s %-10s %6s %12s %12s %13s %13s %-40s' % (
-      'START', 'END', 'FLAGS', 'PRIV.DIRTY', 'PRIV.CLEAN',
-      'SHARED DIRTY', 'SHARED CLEAN', 'MAPPED_FILE')
-  print '%38s %12s %12s %13s' % ('(kb)', '(kb)', '(kb)', '(kb)')
-  print ''
+  print('Memory Maps for process: [%d] %s' % (process.pid, process.name))
+  print('%-10s %-10s %6s %12s %12s %13s %13s %-40s' %
+        ('START', 'END', 'FLAGS', 'PRIV.DIRTY', 'PRIV.CLEAN', 'SHARED DIRTY',
+         'SHARED CLEAN', 'MAPPED_FILE'))
+  print('%38s %12s %12s %13s' % ('(kb)', '(kb)', '(kb)', '(kb)'))
+  print('')
   maps = process.DumpMemoryMaps()
   for entry in maps.entries:
-    print '%-10x %-10x %6s %12s %12s %13s %13s %-40s' % (
-        entry.start, entry.end, entry.prot_flags,
-        entry.priv_dirty_bytes / 1024, entry.priv_clean_bytes / 1024,
-        entry.shared_dirty_bytes / 1024,
-        entry.shared_clean_bytes / 1024, entry.mapped_file)
+    print('%-10x %-10x %6s %12s %12s %13s %13s %-40s' % (
+        entry.start, entry.end, entry.prot_flags, entry.priv_dirty_bytes / 1024,
+        entry.priv_clean_bytes / 1024, entry.shared_dirty_bytes / 1024,
+        entry.shared_clean_bytes / 1024, entry.mapped_file))
 
 
 def _ListProcessClassifiedMmaps(process, mmap_rule):
@@ -159,12 +158,12 @@
   """
   maps = process.DumpMemoryMaps()
   if not os.path.exists(mmap_rule):
-    print 'File', mmap_rule, 'not found'
+    print('File', mmap_rule, 'not found')
     return
   with open(mmap_rule) as f:
     rules = mmap_classifier.LoadRules(f.read())
   classified_results_tree =  mmap_classifier.Classify(maps, rules)
-  print json.dumps(classified_results_tree, cls=serialization.Encoder)
+  print(json.dumps(classified_results_tree, cls=serialization.Encoder))
 
 
 def _Truncate(name, max_length):
diff --git a/tools/memory_inspector/start_web_ui b/tools/memory_inspector/start_web_ui
index 3d0f8d81..41463512 100755
--- a/tools/memory_inspector/start_web_ui
+++ b/tools/memory_inspector/start_web_ui
@@ -3,6 +3,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import argparse
 import logging
 
@@ -31,7 +33,7 @@
 if __name__ == '__main__':
   options = _ParseArguments()
   logging.getLogger().setLevel(logging.WARNING)
-  print 'Serving on port %d' % options.port
+  print('Serving on port %d' % options.port)
   if not options.no_browser:
     import webbrowser
     webbrowser.open('http://127.0.0.1:%d' % options.port)
diff --git a/tools/metrics/actions/extract_actions.py b/tools/metrics/actions/extract_actions.py
index 5c49416..2318929 100755
--- a/tools/metrics/actions/extract_actions.py
+++ b/tools/metrics/actions/extract_actions.py
@@ -21,6 +21,8 @@
 will also be saved in a backup file.
 """
 
+from __future__ import print_function
+
 __author__ = 'evanm (Evan Martin)'
 
 from HTMLParser import HTMLParser
@@ -438,7 +440,7 @@
     close_called = True
     parser.close()
   except Exception, e:
-    print "Error encountered for path %s" % path
+    print("Error encountered for path %s" % path)
     raise e
   finally:
     if not close_called:
@@ -771,8 +773,8 @@
 
   AddLiteralActions(actions)
 
-  # print "Scanned {0} number of files".format(number_of_files_total)
-  # print "Found {0} entries".format(len(actions))
+  # print("Scanned {0} number of files".format(number_of_files_total))
+  # print("Found {0} entries".format(len(actions)))
 
   AddAutomaticResetBannerActions(actions)
   AddBookmarkManagerActions(actions)
diff --git a/tools/metrics/common/diff_util.py b/tools/metrics/common/diff_util.py
index a4553df6..def7e2d5 100644
--- a/tools/metrics/common/diff_util.py
+++ b/tools/metrics/common/diff_util.py
@@ -6,6 +6,8 @@
 user-managed files are correct.
 """
 
+from __future__ import print_function
+
 import logging
 import os
 import webbrowser
@@ -39,7 +41,7 @@
     temp.write(html_diff)
     temp.close()  # Close the file so the browser process can access it.
     webbrowser.open('file://' + temp.name)
-    print prompt
+    print(prompt)
     response = raw_input('(Y/n): ').strip().lower()
   finally:
     temp.close()  # May be called on already closed file.
diff --git a/tools/metrics/common/presubmit_util.py b/tools/metrics/common/presubmit_util.py
index e8e1a50b..46bd42e 100644
--- a/tools/metrics/common/presubmit_util.py
+++ b/tools/metrics/common/presubmit_util.py
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import difflib
 import logging
 import os
@@ -85,7 +87,7 @@
   if diff:
     for line in difflib.unified_diff(original_xml.splitlines(),
                                      pretty.splitlines()):
-      print line
+      print(line)
     return 0
 
   logging.info('Creating backup file: %s', backup_filename)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 7df4212..f8e80796 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -13101,6 +13101,7 @@
   <int value="7" label="Failed non-root renderpass"/>
   <int value="8" label="Failed too many overlays"/>
   <int value="9" label="Failed no hw overlay support (deprecated)"/>
+  <int value="10" label="Failed quad has rounded corners"/>
 </enum>
 
 <enum name="DeclarativeAPIFunctionType">
@@ -18122,6 +18123,7 @@
   <int value="606" label="DeviceLoginScreenHighContrastEnabled"/>
   <int value="607" label="DeviceLoginScreenVirtualKeyboardEnabled"/>
   <int value="608" label="CloudExtensionRequestEnabled"/>
+  <int value="609" label="DeviceLoginScreenSystemInfoEnforced"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
@@ -35121,6 +35123,7 @@
   <int value="-1692384483" label="disambiguate-autofill-server-name-types"/>
   <int value="-1691892152" label="SafeSearchUrlReporting:disabled"/>
   <int value="-1691668194" label="enable-new-bookmark-apps"/>
+  <int value="-1691602043" label="DisableOfficeEditingComponentApp:enabled"/>
   <int value="-1691281364" label="enable-notification-action-icons"/>
   <int value="-1687406612" label="UseSkiaRenderer:disabled"/>
   <int value="-1686782572" label="ChromeHomeInactivitySheetExpansion:disabled"/>
@@ -35929,6 +35932,7 @@
   <int value="-684223908" label="enable-android-wallpapers-app"/>
   <int value="-683370370" label="EnableAppDataSearch:enabled"/>
   <int value="-683306022" label="OverscrollHistoryNavigation:enabled"/>
+  <int value="-682580680" label="DisableOfficeEditingComponentApp:disabled"/>
   <int value="-680787130" label="ExperimentalVRFeatures:disabled"/>
   <int value="-680589442" label="MacRTL:disabled"/>
   <int value="-674804217" label="SoleIntegration:enabled"/>
@@ -47220,6 +47224,9 @@
   <int value="5" label="Touch To Fill">
     User is browsing with the Touch To Fill feature enabled.
   </int>
+  <int value="6" label="Fill On Select">
+    User is browsing with the Fill On Select feature enabled.
+  </int>
 </enum>
 
 <enum name="PasswordManagerHttpCredentialType">
diff --git a/tools/metrics/histograms/find_unmapped_histograms.py b/tools/metrics/histograms/find_unmapped_histograms.py
index 2fb75b2..478cdb8b 100644
--- a/tools/metrics/histograms/find_unmapped_histograms.py
+++ b/tools/metrics/histograms/find_unmapped_histograms.py
@@ -10,6 +10,8 @@
 
 """
 
+from __future__ import print_function
+
 import hashlib
 import logging
 import optparse
@@ -315,8 +317,8 @@
     parts = location_map[histogram].split(':')
     assert len(parts) == 2
     (filename, line_number) = parts
-    print '%s,%s,%s,%s' % (filename, line_number, histogram,
-                           hashHistogramName(histogram))
+    print('%s,%s,%s,%s' % (filename, line_number, histogram,
+                           hashHistogramName(histogram)))
 
 
 def output_log(unmapped_histograms, location_map, verbose):
diff --git a/tools/metrics/histograms/histogram_ownership.py b/tools/metrics/histograms/histogram_ownership.py
index 5d7f9cff..7014e0c 100755
--- a/tools/metrics/histograms/histogram_ownership.py
+++ b/tools/metrics/histograms/histogram_ownership.py
@@ -7,6 +7,8 @@
 histograms.
 """
 
+from __future__ import print_function
+
 import extract_histograms
 import os
 import sys
@@ -48,9 +50,10 @@
 
     if not obsolete:
       if owners:
-        print name, ' '.join(owners)
+        print(name, ' '.join(owners))
       else:
-        print name, 'NO_OWNER'
+        print(name, 'NO_OWNER')
+
 
 if __name__ == '__main__':
   main()
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index f93788f..4b99b7ec 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -26738,7 +26738,7 @@
 </histogram>
 
 <histogram name="Cryptohome.InstallAttributesUsage"
-    enum="InstallAttributesValidationEvent" expires_after="M80">
+    enum="InstallAttributesUsageEvent" expires_after="M80">
   <owner>vsavu@google.com</owner>
   <owner>igorcov@chromium.com</owner>
   <summary>
@@ -38851,7 +38851,7 @@
 </histogram>
 
 <histogram name="Event.Latency.ScrollBegin.Touch.AverageLag" units="pixels"
-    expires_after="M79">
+    expires_after="M85">
   <owner>eirage@chromium.org</owner>
   <owner>nzolghadr@chromium.org</owner>
   <summary>
@@ -39514,7 +39514,7 @@
 
 <histogram
     name="Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionNegative"
-    units="pixels" expires_after="M79">
+    units="pixels" expires_after="M85">
   <owner>eirage@chromium.org</owner>
   <owner>nzolghadr@chromium.org</owner>
   <summary>
@@ -39535,7 +39535,7 @@
 
 <histogram
     name="Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionPositive"
-    units="pixels" expires_after="M79">
+    units="pixels" expires_after="M85">
   <owner>eirage@chromium.org</owner>
   <owner>nzolghadr@chromium.org</owner>
   <summary>
@@ -62274,17 +62274,6 @@
   </summary>
 </histogram>
 
-<histogram name="Media.MCVD.ForwardVideoFrameTiming" units="ms"
-    expires_after="2019-12-31">
-  <owner>liberato@chromium.org</owner>
-  <owner>sandersd@chromium.org</owner>
-  <owner>tguilbert@chromium.org</owner>
-  <summary>
-    The time between MediaCodec::dequeueOutputBuffer() and the dispatch of the
-    corresponding VideoFrame from MediaCodecVideoDecoder.
-  </summary>
-</histogram>
-
 <histogram name="Media.MeanTimeBetweenRebuffers" units="ms"
     expires_after="2020-02-02">
   <owner>dalecurtis@chromium.org</owner>
@@ -66627,6 +66616,9 @@
 
 <histogram name="Memory.Experimental.WMIRefresher.InitDiskIdleTimeConfigStatus"
     enum="WMIRefresherInitStatus" expires_after="2019-09-30">
+  <obsolete>
+    Obsolete as of 09/2019
+  </obsolete>
   <owner>sebmarchand@chromium.org</owner>
   <summary>
     The result of configuring the WMIRefresher to read the disk idle time
@@ -133192,7 +133184,7 @@
 </histogram>
 
 <histogram name="Signin.TokenServiceDiceCompatible" enum="Boolean"
-    expires_after="2019-11-01">
+    expires_after="2020-02-01">
   <owner>msalama@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <summary>
@@ -142177,14 +142169,21 @@
 </histogram>
 
 <histogram name="Sync.LocalDataFailedToLoad" enum="SyncModelTypes"
-    expires_after="M82">
+    expires_after="M78">
+  <obsolete>
+    Removed 2019-09. Was only ever recorded for passwords.
+  </obsolete>
   <owner>vasilii@chromium.org</owner>
   <summary>
     Counts cases when a sync type failed to load the local data during startup.
   </summary>
 </histogram>
 
-<histogram name="Sync.LocalModelOutOfSync" enum="SyncModelTypes">
+<histogram name="Sync.LocalModelOutOfSync" enum="SyncModelTypes"
+    expires_after="M78">
+  <obsolete>
+    Removed 2019-09. Was only ever recorded for bookmarks.
+  </obsolete>
   <owner>zea@chromium.org</owner>
   <summary>
     Counts instances of out of sync local models detected during startup.
diff --git a/tools/metrics/histograms/print_histogram_names.py b/tools/metrics/histograms/print_histogram_names.py
index 9c93500..d4f5d11b 100755
--- a/tools/metrics/histograms/print_histogram_names.py
+++ b/tools/metrics/histograms/print_histogram_names.py
@@ -5,6 +5,8 @@
 
 """Prints all histogram names."""
 
+from __future__ import print_function
+
 import os
 import sys
 
@@ -22,8 +24,8 @@
     raise Error("Error parsing inputs.")
   names = extract_histograms.ExtractNames(histograms)
   for name in names:
-    print name
+    print(name)
+
 
 if __name__ == '__main__':
   main()
-
diff --git a/tools/metrics/histograms/update_bad_message_reasons.py b/tools/metrics/histograms/update_bad_message_reasons.py
index c274f46e..3b2acce 100644
--- a/tools/metrics/histograms/update_bad_message_reasons.py
+++ b/tools/metrics/histograms/update_bad_message_reasons.py
@@ -8,13 +8,15 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import sys
 
 from update_histogram_enum import UpdateHistogramEnum
 
 if __name__ == '__main__':
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
diff --git a/tools/metrics/histograms/update_editor_commands.py b/tools/metrics/histograms/update_editor_commands.py
index 87e15ef..664e9c5e 100644
--- a/tools/metrics/histograms/update_editor_commands.py
+++ b/tools/metrics/histograms/update_editor_commands.py
@@ -8,6 +8,8 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import logging
 import os
 import re
@@ -60,7 +62,7 @@
       if re.match(ENUM_END_MARKER, line):
         inside_enum = False
       else:
-          # Inside enum: generate new xml entry
+        # Inside enum: generate new xml entry
         m = re.match("^{ \"([\w]+)\", \{([\w]+)", line.strip())
         if m:
           result.append((m.group(1), int(m.group(2))))
@@ -86,8 +88,8 @@
   # Find ExtensionFunctions enum.
   for enum_node in document.getElementsByTagName('enum'):
     if enum_node.attributes['name'].value == ENUM_NAME:
-        extension_functions_enum_node = enum_node
-        break
+      extension_functions_enum_node = enum_node
+      break
   else:
     raise UserError('No policy enum node found')
 
@@ -114,7 +116,7 @@
 
 def main():
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
diff --git a/tools/metrics/histograms/update_extension_histograms.py b/tools/metrics/histograms/update_extension_histograms.py
index ca3e12d..05261f5 100644
--- a/tools/metrics/histograms/update_extension_histograms.py
+++ b/tools/metrics/histograms/update_extension_histograms.py
@@ -9,6 +9,8 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import os
 import sys
 
@@ -16,7 +18,7 @@
 
 if __name__ == '__main__':
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
diff --git a/tools/metrics/histograms/update_extension_permission.py b/tools/metrics/histograms/update_extension_permission.py
index 85073f98..751c3c9 100644
--- a/tools/metrics/histograms/update_extension_permission.py
+++ b/tools/metrics/histograms/update_extension_permission.py
@@ -8,6 +8,8 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import os
 import sys
 
@@ -15,7 +17,7 @@
 
 if __name__ == '__main__':
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
diff --git a/tools/metrics/histograms/update_feature_policy_enum.py b/tools/metrics/histograms/update_feature_policy_enum.py
index 39533278..4bc4f8b 100755
--- a/tools/metrics/histograms/update_feature_policy_enum.py
+++ b/tools/metrics/histograms/update_feature_policy_enum.py
@@ -9,6 +9,8 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import os
 import sys
 
@@ -16,7 +18,7 @@
 
 if __name__ == '__main__':
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
diff --git a/tools/metrics/histograms/update_gpu_driver_bug_workaround_entries.py b/tools/metrics/histograms/update_gpu_driver_bug_workaround_entries.py
index 7d3523cb..6f9cd16 100755
--- a/tools/metrics/histograms/update_gpu_driver_bug_workaround_entries.py
+++ b/tools/metrics/histograms/update_gpu_driver_bug_workaround_entries.py
@@ -9,6 +9,8 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import os.path
 import re
 import sys
@@ -40,7 +42,7 @@
 
 def main():
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
diff --git a/tools/metrics/histograms/update_net_error_codes.py b/tools/metrics/histograms/update_net_error_codes.py
index df346c4f..c676a24 100755
--- a/tools/metrics/histograms/update_net_error_codes.py
+++ b/tools/metrics/histograms/update_net_error_codes.py
@@ -9,6 +9,8 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import os.path
 import re
 import sys
@@ -42,7 +44,7 @@
       # CERT_END is not a real NET_ERROR and does not have a stable value.
       # Don't include it.
       if name == 'CERT_END':
-          continue
+        continue
 
       errors[code] = name
 
@@ -51,7 +53,7 @@
 
 def main():
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
diff --git a/tools/metrics/histograms/update_net_trust_anchors.py b/tools/metrics/histograms/update_net_trust_anchors.py
index 95c4be79..d34a018 100755
--- a/tools/metrics/histograms/update_net_trust_anchors.py
+++ b/tools/metrics/histograms/update_net_trust_anchors.py
@@ -9,6 +9,8 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import json
 import os.path
 import sys
@@ -22,7 +24,7 @@
 
 def main():
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
diff --git a/tools/metrics/histograms/update_policies.py b/tools/metrics/histograms/update_policies.py
index c90edc7..c19730a 100644
--- a/tools/metrics/histograms/update_policies.py
+++ b/tools/metrics/histograms/update_policies.py
@@ -8,6 +8,8 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
+from __future__ import print_function
+
 import os
 import re
 import sys
@@ -51,8 +53,8 @@
   # Find EnterprisePolicies enum.
   for enum_node in doc.getElementsByTagName('enum'):
     if enum_node.attributes['name'].value == POLICIES_ENUM_NAME:
-        policy_enum_node = enum_node
-        break
+      policy_enum_node = enum_node
+      break
   else:
     raise UserError('No policy enum node found')
 
@@ -89,8 +91,8 @@
   # Find EnterprisePolicies enum.
   for enum_node in doc.getElementsByTagName('enum'):
     if enum_node.attributes['name'].value == POLICY_ATOMIC_GROUPS_ENUM_NAME:
-        atomic_group_enum_node = enum_node
-        break
+      atomic_group_enum_node = enum_node
+      break
   else:
     raise UserError('No policy atomic group enum node found')
 
@@ -115,7 +117,7 @@
 
 def main():
   if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
+    print('No arguments expected!', file=sys.stderr)
     sys.stderr.write(__doc__)
     sys.exit(1)
 
@@ -140,5 +142,5 @@
   try:
     main()
   except UserError as e:
-    print >>sys.stderr, e.message
+    print(e.message, file=sys.stderr)
     sys.exit(1)
diff --git a/tools/metrics/histograms/update_use_counter_feature_enum.py b/tools/metrics/histograms/update_use_counter_feature_enum.py
index 81784a3..ba24d2ec 100755
--- a/tools/metrics/histograms/update_use_counter_feature_enum.py
+++ b/tools/metrics/histograms/update_use_counter_feature_enum.py
@@ -9,6 +9,8 @@
 output for correctness.
 """
 
+from __future__ import print_function
+
 import optparse
 import os
 import sys
@@ -20,7 +22,7 @@
 def PrintEnumForDashboard(enum_dict):
   """Prints enum_items formatted for use in uma.py of Chromium dashboard."""
   for key in sorted(enum_dict.iterkeys()):
-    print '  %d: \'%s\',' % (key, enum_dict[key])
+    print('  %d: \'%s\',' % (key, enum_dict[key]))
 
 
 if __name__ == '__main__':
diff --git a/tools/multi_process_rss.py b/tools/multi_process_rss.py
index 100d0f7..733428d 100755
--- a/tools/multi_process_rss.py
+++ b/tools/multi_process_rss.py
@@ -17,6 +17,7 @@
 # The command line above counts the RSS of 1) process 12345, 2) process 23456
 # and 3) all descendant processes of process 23456.
 
+from __future__ import print_function
 
 import collections
 import logging
@@ -134,7 +135,7 @@
     return 1
 
   # TODO(dmikurube): Classify this total RSS.
-  print len(pageframes) * 4096
+  print(len(pageframes) * 4096)
 
   return 0
 
diff --git a/tools/nocompile_driver.py b/tools/nocompile_driver.py
index fedb351..8f983259 100755
--- a/tools/nocompile_driver.py
+++ b/tools/nocompile_driver.py
@@ -13,6 +13,8 @@
   http://dev.chromium.org/developers/testing/no-compile-tests
 """
 
+from __future__ import print_function
+
 import StringIO
 import ast
 import os
@@ -312,10 +314,10 @@
   """
   outputs = [None, None]
   for i, stream_name in ((0, "stdout"), (1, "stderr")):
-      stream = test[stream_name]
-      stream.seek(0)
-      outputs[i] = stream.read()
-      stream.close()
+    stream = test[stream_name]
+    stream.seek(0)
+    outputs[i] = stream.read()
+    stream.close()
 
   return outputs
 
@@ -419,9 +421,8 @@
 
 def main():
   if len(sys.argv) < 6 or sys.argv[5] != '--':
-    print ('Usage: %s <compiler> <parallelism> <sourcefile> <resultfile> '
-           '-- <cflags...>' %
-           sys.argv[0])
+    print('Usage: %s <compiler> <parallelism> <sourcefile> <resultfile> '
+          '-- <cflags...>' % sys.argv[0])
     sys.exit(1)
 
   # Force us into the "C" locale so the compiler doesn't localize its output.
@@ -513,9 +514,9 @@
 
   resultfile.close()
   if return_code != 0:
-    print ("No-compile driver failure with return_code %d. Result log:" %
-           return_code)
-    print resultlog.getvalue()
+    print("No-compile driver failure with return_code %d. Result log:" %
+          return_code)
+    print(resultlog.getvalue())
   sys.exit(return_code)
 
 
diff --git a/tools/omahaproxy.py b/tools/omahaproxy.py
index 75bf43d..13dc5d3 100755
--- a/tools/omahaproxy.py
+++ b/tools/omahaproxy.py
@@ -9,6 +9,8 @@
 information.
 """
 
+from __future__ import print_function
+
 import json
 import optparse
 import os
@@ -23,7 +25,7 @@
   try:
     data = json.load(urllib.urlopen(URL))
   except Exception as e:
-    print 'Error: could not load %s\n\n%s' % (URL, str(e))
+    print('Error: could not load %s\n\n%s' % (URL, str(e)))
     return 1
 
   # Iterate to find out valid values for OS, channel, and field options.
@@ -79,11 +81,11 @@
       if opts.field not in version:
         continue
 
-      print version[opts.field]
+      print(version[opts.field])
       return 0
 
-  print 'Error: unable to find %s for Chrome %s %s.' % (
-      opts.field, opts.os, opts.channel)
+  print('Error: unable to find %s for Chrome %s %s.' % (opts.field, opts.os,
+                                                        opts.channel))
   return 1
 
 if __name__ == '__main__':
diff --git a/tools/origin_trials/check_token.py b/tools/origin_trials/check_token.py
index ba0bacbf..1490f08a 100755
--- a/tools/origin_trials/check_token.py
+++ b/tools/origin_trials/check_token.py
@@ -12,6 +12,9 @@
 
 Run "check_token.py -h" for more help on usage.
 """
+
+from __future__ import print_function
+
 import argparse
 import base64
 from datetime import datetime
@@ -104,8 +107,8 @@
     try:
       key_file = open(os.path.expanduser(private_key_file), mode="rb")
     except IOError as exc:
-      print "Unable to open key file: %s" % private_key_file
-      print "(%s)" % exc
+      print("Unable to open key file: %s" % private_key_file)
+      print("(%s)" % exc)
       sys.exit(1)
 
     private_key = key_file.read(64)
@@ -115,7 +118,7 @@
     # half.
     if (len(private_key) < 64 or
       ed25519.publickey(private_key[:32]) != private_key[32:]):
-      print "Unable to use the specified private key file."
+      print("Unable to use the specified private key file.")
       sys.exit(1)
 
     public_key = private_key[32:]
@@ -123,13 +126,13 @@
   try:
     token_contents = base64.b64decode(args.token)
   except TypeError as exc:
-    print "Error decoding the token (%s)" % exc
+    print("Error decoding the token (%s)" % exc)
     sys.exit(1)
 
 
   # Only version 2 currently supported.
   if (len(token_contents) < (VERSION_OFFSET + VERSION_SIZE)):
-    print "Token is malformed - too short."
+    print("Token is malformed - too short.")
     sys.exit(1)
 
   version = token_contents[VERSION_OFFSET:(VERSION_OFFSET + VERSION_SIZE)]
@@ -139,15 +142,15 @@
     for x in version:
       version_number <<= 8
       version_number += ord(x)
-    print "Token has wrong version: %d" % version_number
+    print("Token has wrong version: %d" % version_number)
     sys.exit(1)
 
   # Token must be large enough to contain a version, signature, and payload
   # length.
   minimum_token_length = PAYLOAD_LENGTH_OFFSET + PAYLOAD_LENGTH_SIZE
   if (len(token_contents) < minimum_token_length):
-    print "Token is malformed - too short: %d bytes, minimum is %d" % \
-      (len(token_contents), minimum_token_length)
+    print("Token is malformed - too short: %d bytes, minimum is %d" % \
+      (len(token_contents), minimum_token_length))
     sys.exit(1)
 
   # Extract the length of the signed data (Big-endian).
@@ -158,8 +161,8 @@
   # Validate that the stated length matches the actual payload length.
   actual_payload_length = len(token_contents) - PAYLOAD_OFFSET
   if (payload_length != actual_payload_length):
-    print "Token is %d bytes, expected %d" % (actual_payload_length,
-                                              payload_length)
+    print("Token is %d bytes, expected %d" % (actual_payload_length,
+                                              payload_length))
     sys.exit(1)
 
   # Extract the version-specific contents of the token.
@@ -173,30 +176,30 @@
   try:
     ed25519.checkvalid(signature, signed_data, public_key)
   except Exception as exc:
-    print "Signature invalid (%s)" % exc
+    print("Signature invalid (%s)" % exc)
     sys.exit(1)
 
   try:
     payload = token_contents[PAYLOAD_OFFSET:].decode('utf-8')
   except UnicodeError as exc:
-    print "Unable to decode token contents (%s)" % exc
+    print("Unable to decode token contents (%s)" % exc)
     sys.exit(1)
 
   try:
     token_data = json.loads(payload)
   except Exception as exc:
-    print "Unable to parse payload (%s)" % exc
-    print "Payload: %s" % payload
+    print("Unable to parse payload (%s)" % exc)
+    print("Payload: %s" % payload)
     sys.exit(1)
 
-  print
-  print "Token data: %s" % token_data
-  print
+  print()
+  print("Token data: %s" % token_data)
+  print()
 
   # Extract the required fields
   for field in ["origin", "feature", "expiry"]:
     if field not in token_data:
-      print "Token is missing required field: %s" % field
+      print("Token is missing required field: %s" % field)
       sys.exit(1)
 
   origin = token_data["origin"]
@@ -207,14 +210,14 @@
   is_subdomain = token_data.get("isSubdomain")
 
   # Output the token details
-  print "Token details:"
-  print " Origin: %s" % origin
-  print " Is Subdomain: %s" % is_subdomain
-  print " Feature: %s" % trial_name
-  print " Expiry: %d (%s UTC)" % (expiry, datetime.utcfromtimestamp(expiry))
-  print " Signature: %s" % ", ".join('0x%02x' % ord(x) for x in signature)
-  print " Signature (Base64): %s" % base64.b64encode(signature)
-  print
+  print("Token details:")
+  print(" Origin: %s" % origin)
+  print(" Is Subdomain: %s" % is_subdomain)
+  print(" Feature: %s" % trial_name)
+  print(" Expiry: %d (%s UTC)" % (expiry, datetime.utcfromtimestamp(expiry)))
+  print(" Signature: %s" % ", ".join('0x%02x' % ord(x) for x in signature))
+  print(" Signature (Base64): %s" % base64.b64encode(signature))
+  print()
 
 if __name__ == "__main__":
   main()
diff --git a/tools/origin_trials/generate_token.py b/tools/origin_trials/generate_token.py
index ea52984..8971033c 100755
--- a/tools/origin_trials/generate_token.py
+++ b/tools/origin_trials/generate_token.py
@@ -13,6 +13,9 @@
 
 Run "generate_token.py -h" for more help on usage.
 """
+
+from __future__ import print_function
+
 import argparse
 import base64
 from datetime import datetime
@@ -168,23 +171,24 @@
   try:
     ed25519.checkvalid(signature, data_to_sign, private_key[32:])
   except Exception, exc:
-    print "There was an error generating the signature."
-    print "(The original error was: %s)" % exc
+    print("There was an error generating the signature.")
+    print("(The original error was: %s)" % exc)
     sys.exit(1)
 
 
   # Output the token details
-  print "Token details:"
-  print " Origin: %s" % args.origin
-  print " Is Subdomain: %s" % args.is_subdomain
-  print " Feature: %s" % args.trial_name
-  print " Expiry: %d (%s UTC)" % (expiry, datetime.utcfromtimestamp(expiry))
-  print " Signature: %s" % ", ".join('0x%02x' % ord(x) for x in signature)
-  print " Signature (Base64): %s" % base64.b64encode(signature)
-  print
+  print("Token details:")
+  print(" Origin: %s" % args.origin)
+  print(" Is Subdomain: %s" % args.is_subdomain)
+  print(" Feature: %s" % args.trial_name)
+  print(" Expiry: %d (%s UTC)" % (expiry, datetime.utcfromtimestamp(expiry)))
+  print(" Signature: %s" % ", ".join('0x%02x' % ord(x) for x in signature))
+  print(" Signature (Base64): %s" % base64.b64encode(signature))
+  print()
 
   # Output the properly-formatted token.
-  print FormatToken(VERSION, signature, token_data)
+  print(FormatToken(VERSION, signature, token_data))
+
 
 if __name__ == "__main__":
   main()
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index 5a021a4c..607eb2e 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -48,6 +48,7 @@
   'system_health.memory_mobile/browse:news:cnn',
   'system_health.memory_mobile/load:media:facebook_photos',
   'system_health.memory_mobile/load:news:cnn',
+  'system_health.memory_mobile/load:news:nytimes',
   'system_health.memory_mobile/load:news:reddit',
   'system_health.memory_mobile/load:news:washingtonpost',
   'system_health.memory_mobile/load:tools:stackoverflow',
diff --git a/tools/perf/page_sets/data/system_health_mobile.json b/tools/perf/page_sets/data/system_health_mobile.json
index 1c5d7fa4..90419ab5 100644
--- a/tools/perf/page_sets/data/system_health_mobile.json
+++ b/tools/perf/page_sets/data/system_health_mobile.json
@@ -204,6 +204,9 @@
         "load:news:nytimes": {
             "DEFAULT": "system_health_mobile_009.wprgo"
         },
+        "load:news:nytimes:2019": {
+            "DEFAULT": "system_health_mobile_79b5ecd0df.wprgo"
+        },
         "load:news:qq": {
             "DEFAULT": "system_health_mobile_010.wprgo"
         },
diff --git a/tools/perf/page_sets/data/system_health_mobile_79b5ecd0df.wprgo.sha1 b/tools/perf/page_sets/data/system_health_mobile_79b5ecd0df.wprgo.sha1
new file mode 100644
index 0000000..72cedab
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_79b5ecd0df.wprgo.sha1
@@ -0,0 +1 @@
+79b5ecd0dfd66bbe516c8ed48cba83580f12f4ea
\ No newline at end of file
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py
index af9647c..a8d61658 100644
--- a/tools/perf/page_sets/system_health/loading_stories.py
+++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -196,6 +196,11 @@
   SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
   TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2016]
 
+class LoadNytimesMobileStory2019(_LoadingStory):
+  NAME = 'load:news:nytimes:2019'
+  URL = 'http://mobile.nytimes.com'
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+  TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2019]
 
 class LoadQqMobileStory(_LoadingStory):
   NAME = 'load:news:qq'
diff --git a/tools/perry.py b/tools/perry.py
index 0ea8ce5..4a0ed00 100755
--- a/tools/perry.py
+++ b/tools/perry.py
@@ -16,6 +16,8 @@
 You might want to run it in `screen` as it'll take a while.
 """
 
+from __future__ import print_function
+
 import argparse
 import os
 import multiprocessing
@@ -69,7 +71,7 @@
 
 def _PrintStatus(i, total, failed):
   status = '%d of %d tested (%d failures)' % (i+1, total, failed)
-  print '\r%s%s' % (status, '\x1B[K'),
+  print('\r%s%s' % (status, '\x1B[K'), end=' ')
   sys.stdout.flush()
 
 
@@ -77,7 +79,7 @@
   parser = argparse.ArgumentParser(description="Find failing pairs of tests.")
   parser.add_argument('binary', help='Path to gtest binary or wrapper script.')
   args = parser.parse_args()
-  print 'Getting test list...'
+  print('Getting test list...')
   all_tests = _GetTestList(args.binary)
   permuted = [(args.binary, x, y) for x in all_tests for y in all_tests]
 
@@ -87,8 +89,8 @@
   for i, result in enumerate(pool.imap_unordered(
       _CheckForFailure, permuted, 1)):
     if result:
-      print '\n--gtest_filter=%s:%s failed\n\n%s\n\n' % (
-          result[0], result[1], result[2])
+      print('\n--gtest_filter=%s:%s failed\n\n%s\n\n' % (result[0], result[1],
+                                                         result[2]))
       failed.append(result)
     _PrintStatus(i, total_count, len(failed))
 
@@ -96,9 +98,9 @@
   pool.join()
 
   if failed:
-    print 'Failed pairs:'
+    print('Failed pairs:')
     for f in failed:
-      print f[0], f[1]
+      print(f[0], f[1])
 
   return 0
 
diff --git a/tools/polymer/generate_gn.py b/tools/polymer/generate_gn.py
index 6219723..5e8db46 100755
--- a/tools/polymer/generate_gn.py
+++ b/tools/polymer/generate_gn.py
@@ -3,6 +3,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 from bs4 import BeautifulSoup
 from datetime import date
 import os.path as path
@@ -84,8 +86,8 @@
 
     if targets:
         current_year = date.today().year
-        print _COMPILED_RESOURCES_TEMPLATE % (current_year, created_by,
-                                              _COMPILE_JS, targets)
+        print(_COMPILED_RESOURCES_TEMPLATE % (current_year, created_by,
+                                              _COMPILE_JS, targets))
 
 
 if __name__ == '__main__':
diff --git a/tools/polymer/generate_gn_v3.py b/tools/polymer/generate_gn_v3.py
index 5d6ff1a..9afde34 100755
--- a/tools/polymer/generate_gn_v3.py
+++ b/tools/polymer/generate_gn_v3.py
@@ -3,6 +3,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 from datetime import date
 import json
 import os.path as path
@@ -76,8 +78,8 @@
 
     if targets:
       current_year = date.today().year
-      print _COMPILED_RESOURCES_TEMPLATE % (current_year, created_by,
-                                            _COMPILE_JS, targets)
+      print(_COMPILED_RESOURCES_TEMPLATE % (current_year, created_by,
+                                            _COMPILE_JS, targets))
 
 
 if __name__ == '__main__':
diff --git a/tools/polymer/polymer_grdp_to_txt.py b/tools/polymer/polymer_grdp_to_txt.py
index 92130ac..0080261e 100755
--- a/tools/polymer/polymer_grdp_to_txt.py
+++ b/tools/polymer/polymer_grdp_to_txt.py
@@ -3,6 +3,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import argparse
 import sys
 import xml.sax
@@ -35,7 +37,7 @@
 
   xml_handler = PathsExtractor(args.polymer_version)
   xml.sax.parse(args.input, xml_handler)
-  print '\n'.join(sorted(xml_handler.paths))
+  print('\n'.join(sorted(xml_handler.paths)))
 
 
 if __name__ == '__main__':
diff --git a/tools/polymer/txt_to_polymer_grdp.py b/tools/polymer/txt_to_polymer_grdp.py
index 096dce9..b241ed29 100755
--- a/tools/polymer/txt_to_polymer_grdp.py
+++ b/tools/polymer/txt_to_polymer_grdp.py
@@ -4,6 +4,8 @@
 # found in the LICENSE file.
 
 from __future__ import with_statement
+from __future__ import print_function
+
 import argparse
 import os
 import string
@@ -100,11 +102,15 @@
         'name': PathToGritId(polymer_version, path),
         'path': path})
 
-  print FILE_TEMPLATE % {
-    'contents': '\n'.join(lines),
-        'web_animations': '' if polymer_version == '3' else
-            DEFINITION_TEMPLATE_WEB_ANIMATIONS,
-        'version' : polymer_version }
+  print(FILE_TEMPLATE % {
+      'contents':
+          '\n'.join(lines),
+      'web_animations':
+          '' if polymer_version == '3' else DEFINITION_TEMPLATE_WEB_ANIMATIONS,
+      'version':
+          polymer_version
+  })
+
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
diff --git a/tools/python/google/gethash_timer.py b/tools/python/google/gethash_timer.py
index 9c4bd46..7d0fb24 100755
--- a/tools/python/google/gethash_timer.py
+++ b/tools/python/google/gethash_timer.py
@@ -21,6 +21,8 @@
                      CSV format: sample_number,response_code,elapsed_time_ms
 """
 
+from __future__ import print_function
+
 import getopt
 import httplib
 import sys
@@ -100,7 +102,7 @@
   '''
   global g_file_handle
   output_list = (sample_count, response_code, elapsed_time)
-  print 'Request: %d, status: %d, elapsed time: %f ms' % output_list
+  print('Request: %d, status: %d, elapsed time: %f ms' % output_list)
   if g_file_handle is not None:
     g_file_handle.write(('%d,%d,%f' % output_list) + '\n')
     g_file_handle.flush()
@@ -132,16 +134,16 @@
     elif option == '-o' or option == '--output':
       file_name = value
     else:
-      print 'Bad option: %s' % option
+      print('Bad option: %s' % option)
       return 1
   try:
-    print 'Starting Timed GetHash ----------'
+    print('Starting Timed GetHash ----------')
     SetupOutputFile(file_name)
     RunTimedGetHash(period, samples)
   except KeyboardInterrupt:
     pass
 
-  print 'Timed GetHash complete ----------'
+  print('Timed GetHash complete ----------')
   g_file_handle.close()
 
 
diff --git a/tools/python/google/httpd_utils.py b/tools/python/google/httpd_utils.py
index 4a03ffc7..b157197 100755
--- a/tools/python/google/httpd_utils.py
+++ b/tools/python/google/httpd_utils.py
@@ -5,6 +5,8 @@
 
 """A class to help start/stop a local apache http server."""
 
+from __future__ import print_function
+
 import logging
 import optparse
 import os
@@ -182,8 +184,8 @@
   options, args = option_parser.parse_args()
 
   if not options.server:
-    print ("Usage: %s -k {start|stop} [-r document_root] [--apache2]" %
-           sys.argv[0])
+    print("Usage: %s -k {start|stop} [-r document_root] [--apache2]" %
+          sys.argv[0])
     return 1
 
   document_root = None
diff --git a/tools/python/google/process_utils.py b/tools/python/google/process_utils.py
index 64c92ea..845369a 100644
--- a/tools/python/google/process_utils.py
+++ b/tools/python/google/process_utils.py
@@ -3,6 +3,8 @@
 # found in the LICENSE file.
 """Shared process-related utility functions."""
 
+from __future__ import print_function
+
 import errno
 import os
 import subprocess
@@ -62,7 +64,9 @@
   Raises:
     CommandNotFound if the command executable could not be found.
   """
-  print '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n', ###
+  print(
+      '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n',
+      end=' ')
 
   if verbose:
     out = subprocess.PIPE
@@ -98,7 +102,7 @@
       # \n.  (We could write \r instead, which doesn't get converted to \r\n,
       # but that's probably more troublesome for people trying to read the
       # files.)
-      print line + '\n',
+      print(line + '\n', end=' ')
 
       # Python on windows writes the buffer only when it reaches 4k. This is
       # not fast enough for all purposes.
@@ -162,7 +166,9 @@
   eofs = [False for i in xrange(command_num)]
 
   for command in commands:
-    print '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n',
+    print(
+        '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n',
+        end=' ')
 
   if verbose:
     out = subprocess.PIPE
@@ -205,7 +211,7 @@
           # write \n.  (We could write \r instead, which doesn't get converted
           # to \r\n, but that's probably more troublesome for people trying to
           # read the files.)
-          print line + '\n',
+          print(line + '\n', end=' ')
       else:
         eofs[i] = True
     if eof_all:
diff --git a/tools/real_world_impact/real_world_impact.py b/tools/real_world_impact/real_world_impact.py
index 494d68b..a1af6a2 100755
--- a/tools/real_world_impact/real_world_impact.py
+++ b/tools/real_world_impact/real_world_impact.py
@@ -16,6 +16,8 @@
 # In future it might be possible to extend this to other kinds of differences,
 # e.g. page load times.
 
+from __future__ import print_function
+
 import argparse
 from argparse import RawTextHelpFormatter
 from contextlib import closing
@@ -96,15 +98,15 @@
 
 def CheckPrerequisites():
   if not find_executable("wget"):
-    print "wget not found! Install wget and re-run this."
+    print("wget not found! Install wget and re-run this.")
     return False
   if not os.path.exists(image_diff):
-    print "image_diff not found (%s)!" % image_diff
-    print "Build the image_diff target and re-run this."
+    print("image_diff not found (%s)!" % image_diff)
+    print("Build the image_diff target and re-run this.")
     return False
   if not os.path.exists(content_shell):
-    print "Content shell not found (%s)!" % content_shell
-    print "Build Release/content_shell and re-run this."
+    print("Content shell not found (%s)!" % content_shell)
+    print("Build Release/content_shell and re-run this.")
     return False
   return True
 
@@ -118,7 +120,7 @@
   # TODO(johnme): Should probably update this when it gets too stale...
   csv_path = os.path.join(data_dir, "top-1m.csv")
   if not os.path.exists(csv_path):
-    print "Downloading list of top 1,000,000 sites from Alexa..."
+    print("Downloading list of top 1,000,000 sites from Alexa...")
     csv_url = "http://s3.amazonaws.com/alexa-static/top-1m.csv.zip"
     with closing(urlopen(csv_url)) as stream:
       ZipFile(StringIO(stream.read())).extract("top-1m.csv", data_dir)
@@ -136,10 +138,10 @@
   urls_path = os.path.join(data_dir, "%06d_urls.txt" % num_sites)
   if not os.path.exists(urls_path):
     if action == 'compare':
-      print ("Error: you must run 'before %d' and 'after %d' before "
-             "running 'compare %d'") % (num_sites, num_sites, num_sites)
+      print("Error: you must run 'before %d' and 'after %d' before "
+            "running 'compare %d'" % (num_sites, num_sites, num_sites))
       return False
-    print "Picking %d sample urls..." % num_sites
+    print("Picking %d sample urls..." % num_sites)
 
     # TODO(johnme): For now this just gets the top num_sites entries. In future
     # this should pick a weighted random sample. For example, it could fit a
@@ -177,7 +179,7 @@
   elapsed = round(elapsed * 10) / 10.0
   m = elapsed / 60
   s = elapsed % 60
-  print "Took %dm%.1fs" % (m, s), detail
+  print("Took %dm%.1fs" % (m, s), detail)
 
 
 def DownloadStaticCopyTask(url):
@@ -216,10 +218,10 @@
       success = False
     else:
       with print_lock:
-        print "Downloaded:", url
+        print("Downloaded:", url)
   if not success:
     with print_lock:
-      print "Failed to download:", url
+      print("Failed to download:", url)
     return False
   return True
 
@@ -235,7 +237,7 @@
       new_urls.append(url)
 
   if new_urls:
-    print "Downloading static copies of %d sites..." % len(new_urls)
+    print("Downloading static copies of %d sites..." % len(new_urls))
     start_time = time.time()
 
     results = multiprocessing.Pool(20).map(DownloadStaticCopyTask, new_urls)
@@ -303,7 +305,7 @@
 
 
 def RunDrt():
-  print "Taking screenshots of %d pages..." % len(urls)
+  print("Taking screenshots of %d pages..." % len(urls))
   start_time = time.time()
 
   results = multiprocessing.Pool().map(RunDrtTask, urls, 1)
@@ -355,7 +357,7 @@
 
 
 def CompareResults():
-  print "Running image_diff on %d pages..." % len(urls)
+  print("Running image_diff on %d pages..." % len(urls))
   start_time = time.time()
 
   results = multiprocessing.Pool().map(CompareResultsTask, urls)
diff --git a/tools/remove_duplicate_includes.py b/tools/remove_duplicate_includes.py
index cdf9b0d..f09d8cc 100755
--- a/tools/remove_duplicate_includes.py
+++ b/tools/remove_duplicate_includes.py
@@ -11,6 +11,8 @@
 Usage: remove_duplicate_includes.py --dry-run components/foo components/bar
 """
 
+from __future__ import print_function
+
 import argparse
 import collections
 import logging
@@ -45,8 +47,8 @@
     if match:
       h_file_path = os.path.join(os.getcwd(), match.group(2))
       if h_file_path not in h_path_to_include_set:
-        print 'First include did not match to a known .h file, skipping ' + \
-          cc_file_name + ', line: ' + match.group(1)
+        print('First include did not match to a known .h file, skipping ' + \
+          cc_file_name + ', line: ' + match.group(1))
         return None
       return h_path_to_include_set[h_file_path]
 
@@ -64,10 +66,10 @@
   for line in input_lines:
       match = INCLUDE_REGEX.search(line)
       if match and match.group(2) in include_set:
-        print 'Removed ' + match.group(1) + ' from ' + cc_file_name
+        print('Removed ' + match.group(1) + ' from ' + cc_file_name)
         lastLineWasOmitted = True
       elif lastCopiedLineWasEmpty and lastLineWasOmitted and IsEmpty(line):
-        print 'Removed empty line from ' + cc_file_name
+        print('Removed empty line from ' + cc_file_name)
         lastLineWasOmitted = True
       else:
         lastCopiedLineWasEmpty = IsEmpty(line)
diff --git a/tools/roll_webgl_conformance.py b/tools/roll_webgl_conformance.py
index 62a4075..5be24f9 100755
--- a/tools/roll_webgl_conformance.py
+++ b/tools/roll_webgl_conformance.py
@@ -3,6 +3,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import argparse
 import collections
 import logging
@@ -125,7 +127,7 @@
   changelog_url = GetChangeLogURL(webgl_current.git_repo_url,
                                   change_str)
   if webgl_current.git_commit == webgl_new.git_commit:
-    print 'WARNING: WebGL repository is unchanged; proceeding with no-op roll'
+    print('WARNING: WebGL repository is unchanged; proceeding with no-op roll')
 
   def GetExtraTrybotString():
     s = ''
@@ -311,11 +313,11 @@
         self._RunCommand(base_try_cmd)
 
       cl_info = self._GetCLInfo()
-      print 'Issue: %d URL: %s' % (cl_info.issue, cl_info.url)
+      print('Issue: %d URL: %s' % (cl_info.issue, cl_info.url))
 
     # Checkout master again.
     self._RunCommand(['git', 'checkout', 'master'])
-    print 'Roll branch left as ' + ROLL_BRANCH_NAME
+    print('Roll branch left as ' + ROLL_BRANCH_NAME)
     return 0
 
   def _UpdateDep(self, deps_filename, dep_relative_to_src, commit_info):
@@ -338,9 +340,9 @@
     # happens all the time, update an autogenerated text file in this
     # directory.
     with open(txt_filename, 'w') as fh:
-      print >> fh, '# AUTOGENERATED FILE - DO NOT EDIT'
-      print >> fh, '# SEE roll_webgl_conformance.py'
-      print >> fh, 'Current webgl revision %s' % commit_info.git_commit
+      print('# AUTOGENERATED FILE - DO NOT EDIT', file=fh)
+      print('# SEE roll_webgl_conformance.py', file=fh)
+      print('Current webgl revision %s' % commit_info.git_commit, file=fh)
 
   def _DeleteRollBranch(self):
     self._RunCommand(['git', 'checkout', 'master'])
@@ -373,7 +375,7 @@
     if active_branch == ROLL_BRANCH_NAME:
       active_branch = 'master'
     if ROLL_BRANCH_NAME in branches:
-      print 'Aborting pending roll.'
+      print('Aborting pending roll.')
       self._RunCommand(['git', 'checkout', ROLL_BRANCH_NAME])
       # Ignore an error here in case an issue wasn't created for some reason.
       self._RunCommand(['git', 'cl', 'set_close'], ignore_exit_code=True)
diff --git a/tools/run-swarmed.py b/tools/run-swarmed.py
index 6bb6576..dfae81b 100755
--- a/tools/run-swarmed.py
+++ b/tools/run-swarmed.py
@@ -20,6 +20,8 @@
 See //docs/workflow/debugging-with-swarming.md for more details.
 """
 
+from __future__ import print_function
+
 import argparse
 import multiprocessing
 import os
@@ -178,10 +180,12 @@
   subprocess.check_call(
       ['tools/mb/mb.py', 'isolate', '//' + args.out_dir, args.target_name])
 
-  print 'If you get authentication errors, follow:'
-  print '  https://www.chromium.org/developers/testing/isolated-testing/for-swes#TOC-Login-on-the-services'
+  print('If you get authentication errors, follow:')
+  print(
+      '  https://www.chromium.org/developers/testing/isolated-testing/for-swes#TOC-Login-on-the-services'
+  )
 
-  print 'Uploading to isolate server, this can take a while...'
+  print('Uploading to isolate server, this can take a while...')
   archive_output = subprocess.check_output(
       ['tools/swarming_client/isolate.py', 'archive',
        '-I', 'https://isolateserver.appspot.com',
@@ -194,7 +198,7 @@
   os.makedirs(args.results)
 
   try:
-    print 'Triggering %d tasks...' % args.copies
+    print('Triggering %d tasks...' % args.copies)
     pool = multiprocessing.Pool()
     spawn_args = map(lambda i: (i, args, isolated_hash), range(args.copies))
     spawn_results = pool.imap_unordered(_Spawn, spawn_args)
@@ -207,13 +211,16 @@
       errors = sum(1 for x in exit_codes if x == INTERNAL_ERROR_EXIT_CODE)
       failures = len(exit_codes) - successes - errors
       clear_to_eol = '\033[K'
-      print('\r[%d/%d] collected: '
-            '%d successes, %d failures, %d bot errors...%s' % (len(exit_codes),
-                args.copies, successes, failures, errors, clear_to_eol)),
+      print(
+          '\r[%d/%d] collected: '
+          '%d successes, %d failures, %d bot errors...%s' %
+          (len(exit_codes), args.copies, successes, failures, errors,
+           clear_to_eol),
+          end=' ')
       sys.stdout.flush()
 
-    print
-    print 'Results logs collected into', os.path.abspath(args.results) + '.'
+    print()
+    print('Results logs collected into', os.path.abspath(args.results) + '.')
   finally:
     pool.close()
     pool.join()
diff --git a/ui/base/x/x11_window.cc b/ui/base/x/x11_window.cc
index 7ea41fb..6a35f69 100644
--- a/ui/base/x/x11_window.cc
+++ b/ui/base/x/x11_window.cc
@@ -478,7 +478,7 @@
 }
 
 void XWindow::Activate() {
-  if (!IsVisible() || !activatable_)
+  if (!IsXWindowVisible() || !activatable_)
     return;
 
   BeforeActivationStateChanged();
@@ -611,7 +611,7 @@
   bounds_in_pixels_ = bounds_in_pixels;
 }
 
-bool XWindow::IsVisible() const {
+bool XWindow::IsXWindowVisible() const {
   // On Windows, IsVisible() returns true for minimized windows.  On X11, a
   // minimized window is not mapped, so an explicit IsMinimized() check is
   // necessary.
diff --git a/ui/base/x/x11_window.h b/ui/base/x/x11_window.h
index ccfeba43..a666603 100644
--- a/ui/base/x/x11_window.h
+++ b/ui/base/x/x11_window.h
@@ -111,7 +111,7 @@
 
   void SetSize(const gfx::Size& size_in_pixels);
   void SetBounds(const gfx::Rect& requested_bounds);
-  bool IsVisible() const;
+  bool IsXWindowVisible() const;
   bool IsMinimized() const;
   bool IsMaximized() const;
   bool IsFullscreen() const;
diff --git a/ui/native_theme/native_theme_aura.cc b/ui/native_theme/native_theme_aura.cc
index d65523f..fafcd27 100644
--- a/ui/native_theme/native_theme_aura.cc
+++ b/ui/native_theme/native_theme_aura.cc
@@ -31,41 +31,31 @@
 namespace ui {
 
 namespace {
-
 // Constants for painting overlay scrollbars. Other properties needed outside
 // this painting code are defined in overlay_scrollbar_constants_aura.h.
 constexpr int kOverlayScrollbarMinimumLength = 32;
-
 // 2 pixel border with 1 pixel center patch. The border is 2 pixels despite the
 // stroke width being 1 so that the inner pixel can match the center tile
 // color. This prevents color interpolation between the patches.
 constexpr int kOverlayScrollbarBorderPatchWidth = 2;
 constexpr int kOverlayScrollbarCenterPatchSize = 1;
-
 const SkColor kTrackColor = SkColorSetRGB(0xF1, 0xF1, 0xF1);
 const SkScalar kScrollRadius =
     1;  // select[multiple] radius+width are set in css
-
 const int kCheckboxBorderRadius = 2;
-const int kCheckboxAndRadioBorderWidth = 1;
-
 const int kInputBorderRadius = 2;
-const int kInputBorderWidth = 1;
-const SkScalar kButtonBorderRadius = 2.f;
-const SkScalar kButtonBorderWidth = 1.f;
-
-const SkScalar kSliderTrackRadius = 40.f;
-
-const int kSliderThumbWidth = 21;
-const int kSliderThumbHeight = 21;
-const SkScalar kSliderThumbBorderWidth = 2.f;
-const SkScalar kSliderThumbBorderHoveredWidth = 4.f;
-
+const SkScalar kBorderWidth = 1.f;
+const SkScalar kSliderTrackBorderRadius = 40.f;
+const SkScalar kSliderTrackHeight = 8.f;
+const int kSliderThumbSize = 16;
+const SkScalar kSliderThumbBorderWidth = 1.f;
+const SkScalar kSliderThumbBorderHoveredWidth = 1.f;
 const SkScalar kMenuListArrowStrokeWidth = 1.f;
-
 // The "dash" is 8x2 px by default (the checkbox is 13x13 px).
 const SkScalar kIndeterminateInsetWidthRatio = (13 - 8) / 2.0f / 13;
 const SkScalar kIndeterminateInsetHeightRatio = (13 - 2) / 2.0f / 13;
+// Default height for progress is 16px and the track is 8px.
+const SkScalar kTrackHeightRatio = 8.0f / 16;
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -618,14 +608,12 @@
   cc::PaintFlags flags;
   flags.setAntiAlias(true);
 
-  const SkScalar borderWidth = SkIntToScalar(kCheckboxAndRadioBorderWidth);
-
   // Paint the background (is not visible behind the rounded corners).
   // Note we need to shrink the rect for background a little bit so we don't see
   // artifacts introduced by antialiasing between the border and the background
   // near the rounded corners of checkbox.
   const auto background_rect =
-      skrect.makeInset(borderWidth * 0.2f, borderWidth * 0.2f);
+      skrect.makeInset(kBorderWidth * 0.2f, kBorderWidth * 0.2f);
   PaintLightenLayer(canvas, background_rect, state, borderRadius, color_scheme);
   flags.setColor(ControlsBackgroundColorForState(state, color_scheme));
   flags.setStyle(cc::PaintFlags::kFill_Style);
@@ -635,13 +623,14 @@
   if (!(is_checkbox && button.checked)) {
     // Shrink half border width so the final pixels of the border will be within
     // the rectangle.
-    const auto border_rect = skrect.makeInset(borderWidth / 2, borderWidth / 2);
+    const auto border_rect =
+        skrect.makeInset(kBorderWidth / 2, kBorderWidth / 2);
     SkColor border_color =
         button.checked ? ControlsAccentColorForState(state, color_scheme)
                        : ControlsBorderColorForState(state, color_scheme);
     flags.setColor(border_color);
     flags.setStyle(cc::PaintFlags::kStroke_Style);
-    flags.setStrokeWidth(borderWidth);
+    flags.setStrokeWidth(kBorderWidth);
     canvas->drawRoundRect(border_rect, borderRadius, borderRadius, flags);
   }
 
@@ -660,11 +649,10 @@
   }
 
   SkRect bounds = gfx::RectToSkRect(rect);
-  const SkScalar borderWidth = SkIntToScalar(kInputBorderWidth);
   const SkScalar borderRadius = SkIntToScalar(kInputBorderRadius);
 
   // Paint the background (is not visible behind the rounded corners).
-  bounds.inset(borderWidth / 2, borderWidth / 2);
+  bounds.inset(kBorderWidth / 2, kBorderWidth / 2);
   cc::PaintFlags fill_flags;
   fill_flags.setStyle(cc::PaintFlags::kFill_Style);
   if (text.background_color != 0) {
@@ -677,7 +665,7 @@
   cc::PaintFlags stroke_flags;
   stroke_flags.setColor(ControlsBorderColorForState(state, color_scheme));
   stroke_flags.setStyle(cc::PaintFlags::kStroke_Style);
-  stroke_flags.setStrokeWidth(borderWidth);
+  stroke_flags.setStrokeWidth(kBorderWidth);
   canvas->drawRoundRect(bounds, borderRadius, borderRadius, stroke_flags);
 }
 
@@ -721,42 +709,43 @@
   }
 
   // Paint the background (is not visible behind the rounded corners).
-  skrect.inset(kButtonBorderWidth / 2, kButtonBorderWidth / 2);
-  PaintLightenLayer(canvas, skrect, state, kButtonBorderRadius, color_scheme);
+  skrect.inset(kBorderWidth / 2, kBorderWidth / 2);
+  PaintLightenLayer(canvas, skrect, state, kInputBorderRadius, color_scheme);
   flags.setColor(ControlsFillColorForState(state, color_scheme));
-  canvas->drawRoundRect(skrect, kButtonBorderRadius, kButtonBorderRadius,
-                        flags);
+  canvas->drawRoundRect(skrect, kInputBorderRadius, kInputBorderRadius, flags);
 
   // Paint the border: 1px solid.
   if (button.has_border) {
     flags.setStyle(cc::PaintFlags::kStroke_Style);
-    flags.setStrokeWidth(kButtonBorderWidth);
+    flags.setStrokeWidth(kBorderWidth);
     flags.setColor(ControlsBorderColorForState(state, color_scheme));
-    canvas->drawRoundRect(skrect, kButtonBorderRadius, kButtonBorderRadius,
+    canvas->drawRoundRect(skrect, kInputBorderRadius, kInputBorderRadius,
                           flags);
   }
 }
 
 SkRect AlignSliderTrack(const gfx::Rect& slider_rect,
                         const NativeTheme::SliderExtraParams& slider,
-                        bool is_value) {
-  const int kAlignment = 2;
-  const int mid_x = slider_rect.x() + slider_rect.width() / 2;
-  const int mid_y = slider_rect.y() + slider_rect.height() / 2;
+                        bool is_value,
+                        float track_height) {
+  const float kAlignment = track_height / 2;
+  const float mid_x = slider_rect.x() + slider_rect.width() / 2.0f;
+  const float mid_y = slider_rect.y() + slider_rect.height() / 2.0f;
   SkRect aligned_rect;
 
   if (slider.vertical) {
-    const int top = is_value ? slider_rect.y() + slider.thumb_y + kAlignment
-                             : slider_rect.y();
-    aligned_rect.setLTRB(std::max(slider_rect.x(), mid_x - kAlignment), top,
-                         std::min(slider_rect.right(), mid_x + kAlignment),
-                         slider_rect.bottom());
+    const float top = is_value ? slider_rect.y() + slider.thumb_y + kAlignment
+                               : slider_rect.y();
+    aligned_rect.setLTRB(
+        std::max(float(slider_rect.x()), mid_x - kAlignment), top,
+        std::min(float(slider_rect.right()), mid_x + kAlignment),
+        slider_rect.bottom());
   } else {
-    const int right = is_value ? slider_rect.x() + slider.thumb_x + kAlignment
-                               : slider_rect.right();
-    aligned_rect.setLTRB(slider_rect.x(),
-                         std::max(slider_rect.y(), mid_y - kAlignment), right,
-                         std::min(slider_rect.bottom(), mid_y + kAlignment));
+    const float right = is_value ? slider_rect.x() + slider.thumb_x + kAlignment
+                                 : slider_rect.right();
+    aligned_rect.setLTRB(
+        slider_rect.x(), std::max(float(slider_rect.y()), mid_y - kAlignment),
+        right, std::min(float(slider_rect.bottom()), mid_y + kAlignment));
   }
 
   return aligned_rect;
@@ -775,16 +764,27 @@
   // Paint the entire slider track.
   cc::PaintFlags flags;
   flags.setAntiAlias(true);
-  flags.setColor(GetControlColor(kFill, color_scheme));
-  SkRect track_rect = AlignSliderTrack(rect, slider, false);
-  canvas->drawRoundRect(track_rect, kSliderTrackRadius, kSliderTrackRadius,
-                        flags);
+  flags.setColor(ControlsFillColorForState(state, color_scheme));
+  SkRect track_rect = AlignSliderTrack(rect, slider, false, kSliderTrackHeight);
+  canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
+                        kSliderTrackBorderRadius, flags);
 
   // Paint the value slider track.
   flags.setColor(ControlsAccentColorForState(state, color_scheme));
-  SkRect value_rect = AlignSliderTrack(rect, slider, true);
-  canvas->drawRoundRect(value_rect, kSliderTrackRadius, kSliderTrackRadius,
-                        flags);
+  SkRect value_rect = AlignSliderTrack(rect, slider, true, kSliderTrackHeight);
+  canvas->drawRoundRect(value_rect, kSliderTrackBorderRadius,
+                        kSliderTrackBorderRadius, flags);
+
+  // Paint the border.
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  flags.setStrokeWidth(kBorderWidth);
+  SkColor border_color = ControlsBorderColorForState(state, color_scheme);
+  if (!UsesHighContrastColors() && state != kDisabled)
+    border_color = SkColorSetA(border_color, 0x80);
+  flags.setColor(border_color);
+  track_rect.inset(kBorderWidth / 2, kBorderWidth / 2);
+  canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
+                        kSliderTrackBorderRadius, flags);
 }
 
 void NativeThemeAura::PaintSliderThumb(cc::PaintCanvas* canvas,
@@ -821,6 +821,57 @@
   canvas->drawRoundRect(thumb_rect, radius, radius, flags);
 }
 
+void NativeThemeAura::PaintProgressBar(
+    cc::PaintCanvas* canvas,
+    State state,
+    const gfx::Rect& rect,
+    const ProgressBarExtraParams& progress_bar,
+    ColorScheme color_scheme) const {
+  if (!features::IsFormControlsRefreshEnabled()) {
+    return NativeThemeBase::PaintProgressBar(canvas, state, rect, progress_bar,
+                                             color_scheme);
+  }
+
+  DCHECK(!rect.IsEmpty());
+
+  // Paint the track.
+  cc::PaintFlags flags;
+  flags.setAntiAlias(true);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  flags.setColor(GetControlColor(kFill, color_scheme));
+  SliderExtraParams slider;
+  slider.vertical = false;
+  float track_height = rect.height() * kTrackHeightRatio;
+  SkRect track_rect = AlignSliderTrack(rect, slider, false, track_height);
+  canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
+                        kSliderTrackBorderRadius, flags);
+
+  // Paint the progress value bar.
+  const SkScalar kMinimumProgressValueWidth = 2;
+  SkScalar adjusted_width = progress_bar.value_rect_width;
+  if (adjusted_width > 0 && adjusted_width < kMinimumProgressValueWidth)
+    adjusted_width = kMinimumProgressValueWidth;
+  gfx::Rect original_value_rect(progress_bar.value_rect_x,
+                                progress_bar.value_rect_y, adjusted_width,
+                                progress_bar.value_rect_height);
+  SkRect value_rect =
+      AlignSliderTrack(original_value_rect, slider, false, track_height);
+  flags.setColor(GetControlColor(kAccent, color_scheme));
+  canvas->drawRoundRect(value_rect, kSliderTrackBorderRadius,
+                        kSliderTrackBorderRadius, flags);
+
+  // Paint the border.
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  flags.setStrokeWidth(kBorderWidth);
+  SkColor border_color = GetControlColor(kBorder, color_scheme);
+  if (!UsesHighContrastColors())
+    border_color = SkColorSetA(border_color, 0x80);
+  flags.setColor(border_color);
+  track_rect.inset(kBorderWidth / 2, kBorderWidth / 2);
+  canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
+                        kSliderTrackBorderRadius, flags);
+}
+
 void NativeThemeAura::PaintMenuList(cc::PaintCanvas* canvas,
                                     State state,
                                     const gfx::Rect& rect,
@@ -897,7 +948,7 @@
   }
 
   if (part == kSliderThumb && features::IsFormControlsRefreshEnabled()) {
-    return gfx::Size(kSliderThumbWidth, kSliderThumbHeight);
+    return gfx::Size(kSliderThumbSize, kSliderThumbSize);
   }
 
   return NativeThemeBase::GetPartSize(part, state, extra);
diff --git a/ui/native_theme/native_theme_aura.h b/ui/native_theme/native_theme_aura.h
index 2e8b80f..10ee38d 100644
--- a/ui/native_theme/native_theme_aura.h
+++ b/ui/native_theme/native_theme_aura.h
@@ -71,6 +71,11 @@
                                const gfx::Rect& rect,
                                const MenuItemExtraParams& menu_item,
                                ColorScheme color_scheme) const override;
+  void PaintProgressBar(cc::PaintCanvas* canvas,
+                        State state,
+                        const gfx::Rect& rect,
+                        const ProgressBarExtraParams& progress_bar,
+                        ColorScheme color_scheme) const override;
   void PaintArrowButton(cc::PaintCanvas* gc,
                         const gfx::Rect& rect,
                         Part direction,
diff --git a/ui/ozone/platform/drm/host/drm_window_host.cc b/ui/ozone/platform/drm/host/drm_window_host.cc
index a5fe459..f7edb74 100644
--- a/ui/ozone/platform/drm/host/drm_window_host.cc
+++ b/ui/ozone/platform/drm/host/drm_window_host.cc
@@ -74,6 +74,11 @@
 void DrmWindowHost::Close() {
 }
 
+bool DrmWindowHost::IsVisible() const {
+  NOTREACHED();
+  return true;
+}
+
 void DrmWindowHost::PrepareForShutdown() {}
 
 void DrmWindowHost::SetBounds(const gfx::Rect& bounds) {
diff --git a/ui/ozone/platform/drm/host/drm_window_host.h b/ui/ozone/platform/drm/host/drm_window_host.h
index 4cbcd4ba..d6ae9e0 100644
--- a/ui/ozone/platform/drm/host/drm_window_host.h
+++ b/ui/ozone/platform/drm/host/drm_window_host.h
@@ -61,6 +61,7 @@
   void Show() override;
   void Hide() override;
   void Close() override;
+  bool IsVisible() const override;
   void PrepareForShutdown() override;
   void SetBounds(const gfx::Rect& bounds) override;
   gfx::Rect GetBounds() override;
diff --git a/ui/ozone/platform/scenic/scenic_window.cc b/ui/ozone/platform/scenic/scenic_window.cc
index b89d38b..99affc52 100644
--- a/ui/ozone/platform/scenic/scenic_window.cc
+++ b/ui/ozone/platform/scenic/scenic_window.cc
@@ -102,6 +102,11 @@
   delegate_->OnClosed();
 }
 
+bool ScenicWindow::IsVisible() const {
+  NOTIMPLEMENTED_LOG_ONCE();
+  return true;
+}
+
 void ScenicWindow::PrepareForShutdown() {
   NOTIMPLEMENTED();
 }
diff --git a/ui/ozone/platform/scenic/scenic_window.h b/ui/ozone/platform/scenic/scenic_window.h
index 9376a08..97f66da2 100644
--- a/ui/ozone/platform/scenic/scenic_window.h
+++ b/ui/ozone/platform/scenic/scenic_window.h
@@ -53,6 +53,7 @@
   void Show() override;
   void Hide() override;
   void Close() override;
+  bool IsVisible() const override;
   void PrepareForShutdown() override;
   void SetCapture() override;
   void ReleaseCapture() override;
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
index 5d48ba8..babf798 100644
--- a/ui/ozone/platform/wayland/BUILD.gn
+++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -185,8 +185,6 @@
     "test/mock_xdg_shell.h",
     "test/mock_xdg_surface.cc",
     "test/mock_xdg_surface.h",
-    "test/mock_zwp_linux_buffer_params.cc",
-    "test/mock_zwp_linux_buffer_params.h",
     "test/mock_zwp_linux_dmabuf.cc",
     "test/mock_zwp_linux_dmabuf.h",
     "test/mock_zwp_text_input.cc",
@@ -217,6 +215,8 @@
     "test/test_touch.h",
     "test/test_wayland_server_thread.cc",
     "test/test_wayland_server_thread.h",
+    "test/test_zwp_linux_buffer_params.cc",
+    "test/test_zwp_linux_buffer_params.h",
     "test/test_zwp_text_input_manager.cc",
     "test/test_zwp_text_input_manager.h",
   ]
@@ -275,6 +275,7 @@
     "//ui/events/ozone:events_ozone_layout",
     "//ui/ozone:platform",
     "//ui/ozone:test_support",
+    "//ui/ozone/common/linux:drm",
     "//ui/ozone/common/linux:gbm",
   ]
 
diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
index 2e1fe20..1444816 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
@@ -71,8 +71,9 @@
   }
 
   const uint32_t fourcc_format = GetFourCCFormatFromBufferFormat(format);
-  gbm_bo_ =
-      buffer_manager_->gbm_device()->CreateBuffer(fourcc_format, size, flags);
+  auto modifiers = buffer_manager_->GetModifiersForBufferFormat(format);
+  gbm_bo_ = buffer_manager_->gbm_device()->CreateBufferWithModifiers(
+      fourcc_format, size, flags, modifiers);
   if (!gbm_bo_) {
     LOG(ERROR) << "Cannot create bo with format= "
                << gfx::BufferFormatToString(format) << " and usage "
diff --git a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
index 84eda0a..43bbb47 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
@@ -16,28 +16,27 @@
 
 namespace ui {
 
-WaylandBufferManagerGpu::WaylandBufferManagerGpu()
-    : associated_binding_(this) {}
-
+WaylandBufferManagerGpu::WaylandBufferManagerGpu() = default;
 WaylandBufferManagerGpu::~WaylandBufferManagerGpu() = default;
 
-void WaylandBufferManagerGpu::SetWaylandBufferManagerHost(
-    BufferManagerHostPtr buffer_manager_host_ptr) {
-  // This is an IO child thread meant for IPC. Bind interface in this thread and
-  // do all the mojo calls on the same thread.
-  BindHostInterface(std::move(buffer_manager_host_ptr));
+void WaylandBufferManagerGpu::Initialize(
+    mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host,
+    const base::flat_map<::gfx::BufferFormat, std::vector<uint64_t>>&
+        buffer_formats_with_modifiers,
+    bool supports_dma_buf) {
+  DCHECK(supported_buffer_formats_with_modifiers_.empty());
+  supported_buffer_formats_with_modifiers_ = buffer_formats_with_modifiers;
+
+#if defined(WAYLAND_GBM)
+  if (!supports_dma_buf)
+    set_gbm_device(nullptr);
+#endif
+
+  BindHostInterface(std::move(remote_host));
 
   io_thread_runner_ = base::ThreadTaskRunnerHandle::Get();
 }
 
-void WaylandBufferManagerGpu::ResetGbmDevice() {
-#if defined(WAYLAND_GBM)
-  gbm_device_.reset();
-#else
-  NOTREACHED();
-#endif
-}
-
 void WaylandBufferManagerGpu::OnSubmission(gfx::AcceleratedWidget widget,
                                            uint32_t buffer_id,
                                            gfx::SwapResult swap_result) {
@@ -146,8 +145,19 @@
 }
 
 void WaylandBufferManagerGpu::AddBindingWaylandBufferManagerGpu(
-    ozone::mojom::WaylandBufferManagerGpuRequest request) {
-  bindings_.AddBinding(this, std::move(request));
+    mojo::PendingReceiver<ozone::mojom::WaylandBufferManagerGpu> receiver) {
+  receiver_.Bind(std::move(receiver));
+}
+
+const std::vector<uint64_t>&
+WaylandBufferManagerGpu::GetModifiersForBufferFormat(
+    gfx::BufferFormat buffer_format) const {
+  auto it = supported_buffer_formats_with_modifiers_.find(buffer_format);
+  if (it != supported_buffer_formats_with_modifiers_.end()) {
+    return it->second;
+  }
+  static std::vector<uint64_t> dummy;
+  return dummy;
 }
 
 void WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal(
@@ -161,8 +171,8 @@
     uint32_t planes_count,
     uint32_t buffer_id) {
   DCHECK(io_thread_runner_->BelongsToCurrentThread());
-  DCHECK(buffer_manager_host_ptr_);
-  buffer_manager_host_ptr_->CreateDmabufBasedBuffer(
+  DCHECK(remote_host_);
+  remote_host_->CreateDmabufBasedBuffer(
       widget,
       mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(dmabuf_fd))),
       size, strides, offsets, modifiers, current_format, planes_count,
@@ -176,8 +186,8 @@
     gfx::Size size,
     uint32_t buffer_id) {
   DCHECK(io_thread_runner_->BelongsToCurrentThread());
-  DCHECK(buffer_manager_host_ptr_);
-  buffer_manager_host_ptr_->CreateShmBasedBuffer(
+  DCHECK(remote_host_);
+  remote_host_->CreateShmBasedBuffer(
       widget, mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(shm_fd))),
       length, size, buffer_id);
 }
@@ -187,31 +197,30 @@
     uint32_t buffer_id,
     const gfx::Rect& damage_region) {
   DCHECK(io_thread_runner_->BelongsToCurrentThread());
-  DCHECK(buffer_manager_host_ptr_);
+  DCHECK(remote_host_);
 
-  buffer_manager_host_ptr_->CommitBuffer(widget, buffer_id, damage_region);
+  remote_host_->CommitBuffer(widget, buffer_id, damage_region);
 }
 
 void WaylandBufferManagerGpu::DestroyBufferInternal(
     gfx::AcceleratedWidget widget,
     uint32_t buffer_id) {
   DCHECK(io_thread_runner_->BelongsToCurrentThread());
-  DCHECK(buffer_manager_host_ptr_);
+  DCHECK(remote_host_);
 
-  buffer_manager_host_ptr_->DestroyBuffer(widget, buffer_id);
+  remote_host_->DestroyBuffer(widget, buffer_id);
 }
 
 void WaylandBufferManagerGpu::BindHostInterface(
-    BufferManagerHostPtr buffer_manager_host_ptr) {
-  buffer_manager_host_ptr_.Bind(buffer_manager_host_ptr.PassInterface());
+    mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host) {
+  remote_host_.Bind(std::move(remote_host));
 
   // Setup associated interface.
-  ozone::mojom::WaylandBufferManagerGpuAssociatedPtrInfo client_ptr_info;
-  auto request = MakeRequest(&client_ptr_info);
-  DCHECK(buffer_manager_host_ptr_);
-  buffer_manager_host_ptr_->SetWaylandBufferManagerGpuPtr(
-      std::move(client_ptr_info));
-  associated_binding_.Bind(std::move(request));
+  mojo::PendingAssociatedRemote<ozone::mojom::WaylandBufferManagerGpu>
+      client_remote;
+  associated_receiver_.Bind(client_remote.InitWithNewEndpointAndPassReceiver());
+  DCHECK(remote_host_);
+  remote_host_->SetWaylandBufferManagerGpu(std::move(client_remote));
 }
 
 void WaylandBufferManagerGpu::SubmitSwapResultOnOriginThread(
diff --git a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
index 3445aac..dffb43a 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
+++ b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
@@ -11,8 +11,9 @@
 #include "base/synchronization/lock.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_checker.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom.h"
@@ -45,10 +46,11 @@
   ~WaylandBufferManagerGpu() override;
 
   // WaylandBufferManagerGpu overrides:
-  void SetWaylandBufferManagerHost(
-      BufferManagerHostPtr buffer_manager_host_ptr) override;
-
-  void ResetGbmDevice() override;
+  void Initialize(
+      mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host,
+      const base::flat_map<::gfx::BufferFormat, std::vector<uint64_t>>&
+          buffer_formats_with_modifiers,
+      bool supports_dma_buf) override;
 
   // These two calls get the surface, which backs the |widget| and notifies it
   // about the submission and the presentation. After the surface receives the
@@ -119,7 +121,11 @@
 
   // Adds a WaylandBufferManagerGpu binding.
   void AddBindingWaylandBufferManagerGpu(
-      ozone::mojom::WaylandBufferManagerGpuRequest request);
+      mojo::PendingReceiver<ozone::mojom::WaylandBufferManagerGpu> receiver);
+
+  // Returns supported modifiers for the supplied |buffer_format|.
+  const std::vector<uint64_t>& GetModifiersForBufferFormat(
+      gfx::BufferFormat buffer_format) const;
 
  private:
   void CreateDmabufBasedBufferInternal(gfx::AcceleratedWidget widget,
@@ -141,7 +147,8 @@
                             const gfx::Rect& damage_region);
   void DestroyBufferInternal(gfx::AcceleratedWidget widget, uint32_t buffer_id);
 
-  void BindHostInterface(BufferManagerHostPtr buffer_manager_host_ptr);
+  void BindHostInterface(
+      mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host);
 
   // Provides the WaylandSurfaceGpu, which backs the |widget|, with swap and
   // presentation results.
@@ -158,18 +165,24 @@
   std::unique_ptr<GbmDevice> gbm_device_;
 #endif
 
-  mojo::BindingSet<ozone::mojom::WaylandBufferManagerGpu> bindings_;
+  mojo::Receiver<ozone::mojom::WaylandBufferManagerGpu> receiver_{this};
 
   // A pointer to a WaylandBufferManagerHost object, which always lives on a
   // browser process side. It's used for a multi-process mode.
-  BufferManagerHostPtr buffer_manager_host_ptr_;
+  mojo::Remote<ozone::mojom::WaylandBufferManagerHost> remote_host_;
 
-  mojo::AssociatedBinding<ozone::mojom::WaylandBufferManagerGpu>
-      associated_binding_;
+  mojo::AssociatedReceiver<ozone::mojom::WaylandBufferManagerGpu>
+      associated_receiver_{this};
 
   std::map<gfx::AcceleratedWidget, WaylandSurfaceGpu*>
       widget_to_surface_map_;  // Guarded by |lock_|.
 
+  // Supported buffer formats and modifiers sent by the Wayland compositor to
+  // the client. Corresponds to the map stored in WaylandZwpLinuxDmabuf and
+  // passed from it during initialization of this gpu host.
+  base::flat_map<gfx::BufferFormat, std::vector<uint64_t>>
+      supported_buffer_formats_with_modifiers_;
+
   // This task runner can be used to pass messages back to the same thread,
   // where the commit buffer request came from. For example, swap requests come
   // from the GpuMainThread, but rerouted to the IOChildThread and then mojo
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
index 821b673..a52cdc8 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
@@ -97,7 +97,7 @@
     WaylandTest::SetUp();
 
     auto manager_ptr = connection_->buffer_manager_host()->BindInterface();
-    buffer_manager_gpu_->SetWaylandBufferManagerHost(std::move(manager_ptr));
+    buffer_manager_gpu_->Initialize(std::move(manager_ptr), {}, false);
 
     // Wait until initialization and mojo calls go through.
     base::RunLoop().RunUntilIdle();
@@ -198,7 +198,7 @@
 
   // Reset gbm now. WaylandConnectionProxy can reset it when zwp is not
   // available. And factory must behave the same way as previously.
-  buffer_manager_gpu_->ResetGbmDevice();
+  buffer_manager_gpu_->set_gbm_device(nullptr);
   gl_surface = gl_ozone->CreateSurfacelessViewGLSurface(widget_);
   EXPECT_FALSE(gl_surface);
 }
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc
index 409adc5..2702f30 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc
@@ -7,6 +7,8 @@
 #include "base/bind.h"
 #include "base/task_runner_util.h"
 #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
+#include "ui/ozone/platform/wayland/host/wayland_connection.h"
+#include "ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h"
 
 namespace ui {
 
@@ -23,17 +25,18 @@
 }
 
 template <typename Interface>
-void BindInterfaceInGpuProcess(mojo::InterfaceRequest<Interface> request,
+void BindInterfaceInGpuProcess(mojo::PendingReceiver<Interface> request,
                                const BinderCallback& binder_callback) {
-  BindInterfaceInGpuProcess(
-      Interface::Name_, std::move(request.PassMessagePipe()), binder_callback);
+  BindInterfaceInGpuProcess(Interface::Name_, std::move(request.PassPipe()),
+                            binder_callback);
 }
 
 }  // namespace
 
 WaylandBufferManagerConnector::WaylandBufferManagerConnector(
-    WaylandBufferManagerHost* buffer_manager)
-    : buffer_manager_(buffer_manager) {}
+    WaylandConnection* wayland_connection)
+    : buffer_manager_(wayland_connection->buffer_manager_host()),
+      wayland_connection_(wayland_connection) {}
 
 WaylandBufferManagerConnector::~WaylandBufferManagerConnector() = default;
 
@@ -78,20 +81,27 @@
 }
 
 void WaylandBufferManagerConnector::OnBufferManagerHostPtrBinded(
-    ozone::mojom::WaylandBufferManagerHostPtr buffer_manager_host_ptr) const {
-  ozone::mojom::WaylandBufferManagerGpuPtr buffer_manager_gpu_ptr;
-  auto request = mojo::MakeRequest(&buffer_manager_gpu_ptr);
-  BindInterfaceInGpuProcess(std::move(request), binder_);
-  DCHECK(buffer_manager_host_ptr);
-  buffer_manager_gpu_ptr->SetWaylandBufferManagerHost(
-      std::move(buffer_manager_host_ptr));
+    mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost>
+        buffer_manager_host) const {
+  mojo::Remote<ozone::mojom::WaylandBufferManagerGpu> buffer_manager_gpu;
+  auto receiver = buffer_manager_gpu.BindNewPipeAndPassReceiver();
+  BindInterfaceInGpuProcess(std::move(receiver), binder_);
+  DCHECK(buffer_manager_gpu);
 
+  WaylandZwpLinuxDmabuf::BufferFormatsWithModifiersMap
+      buffer_formats_with_modifiers;
+  bool supports_dma_buf = false;
 #if defined(WAYLAND_GBM)
-  if (!buffer_manager_->CanCreateDmabufBasedBuffer()) {
-    LOG(WARNING) << "zwp_linux_dmabuf is not available.";
-    buffer_manager_gpu_ptr->ResetGbmDevice();
+  auto* zwp_linux_dmabuf = wayland_connection_->zwp_dmabuf();
+  if (zwp_linux_dmabuf) {
+    supports_dma_buf = true;
+    buffer_formats_with_modifiers =
+        zwp_linux_dmabuf->supported_buffer_formats();
   }
 #endif
+  buffer_manager_gpu->Initialize(std::move(buffer_manager_host),
+                                 buffer_formats_with_modifiers,
+                                 supports_dma_buf);
 }
 
 void WaylandBufferManagerConnector::OnTerminateGpuProcess(std::string message) {
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h b/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h
index 53fb400c..a67623f 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h
@@ -7,19 +7,20 @@
 
 #include "ui/ozone/public/gpu_platform_support_host.h"
 
+#include "mojo/public/cpp/bindings/remote.h"
 #include "ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom.h"
 
 namespace ui {
 
 class WaylandBufferManagerHost;
+class WaylandConnection;
 
 // A connector class which instantiates a connection between
 // WaylandBufferManagerGpu on the GPU side and the WaylandBufferManagerHost
 // object on the browser process side.
 class WaylandBufferManagerConnector : public GpuPlatformSupportHost {
  public:
-  explicit WaylandBufferManagerConnector(
-      WaylandBufferManagerHost* buffer_manager);
+  explicit WaylandBufferManagerConnector(WaylandConnection* wayland_connection);
   ~WaylandBufferManagerConnector() override;
 
   // GpuPlatformSupportHost:
@@ -39,14 +40,18 @@
 
  private:
   void OnBufferManagerHostPtrBinded(
-      ozone::mojom::WaylandBufferManagerHostPtr buffer_manager_host_ptr) const;
+      mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost>
+          buffer_manager_host) const;
 
   void OnTerminateGpuProcess(std::string message);
 
-  // Non-owning pointer, which is used to bind a mojo pointer to the
+  // Non-owned pointer, which is used to bind a mojo pointer to the
   // WaylandBufferManagerHost.
   WaylandBufferManagerHost* const buffer_manager_;
 
+  // Non-owned.
+  WaylandConnection* const wayland_connection_;
+
   GpuHostBindInterfaceCallback binder_;
   GpuHostTerminateCallback terminate_callback_;
 
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
index f360f91..12e3d46 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
@@ -513,8 +513,8 @@
   // surface it backed to avoid its contents shown on screen. However, it
   // means that the Wayland compositor no longer sends new buffer release events
   // as long as there has not been buffer attached and no submission callback is
-  // sent. To avoid this, |contents_reset_| can be used as an identification of a
-  // need to call submission callback manually.
+  // sent. To avoid this, |contents_reset_| can be used as an identification of
+  // a need to call submission callback manually.
   bool contents_reset_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(Surface);
@@ -528,7 +528,7 @@
 
 WaylandBufferManagerHost::WaylandBufferManagerHost(
     WaylandConnection* connection)
-    : connection_(connection), binding_(this), weak_factory_(this) {
+    : connection_(connection), receiver_(this), weak_factory_(this) {
   connection_->wayland_window_manager()->AddObserver(this);
 }
 
@@ -552,31 +552,27 @@
   terminate_gpu_cb_ = std::move(terminate_callback);
 }
 
-ozone::mojom::WaylandBufferManagerHostPtr
+mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost>
 WaylandBufferManagerHost::BindInterface() {
-  DCHECK(!binding_.is_bound());
-  ozone::mojom::WaylandBufferManagerHostPtr buffer_manager_host_ptr;
-  binding_.Bind(MakeRequest(&buffer_manager_host_ptr));
-  return buffer_manager_host_ptr;
+  DCHECK(!receiver_.is_bound());
+  mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost>
+      buffer_manager_host;
+  receiver_.Bind(buffer_manager_host.InitWithNewPipeAndPassReceiver());
+  return buffer_manager_host;
 }
 
 void WaylandBufferManagerHost::OnChannelDestroyed() {
-  buffer_manager_gpu_associated_ptr_.reset();
-  binding_.Close();
+  buffer_manager_gpu_associated_.reset();
+  receiver_.reset();
 
   for (auto& surface_pair : surfaces_)
     surface_pair.second->ClearState();
 }
 
-bool WaylandBufferManagerHost::CanCreateDmabufBasedBuffer() const {
-  return !!connection_->zwp_dmabuf();
-}
-
-void WaylandBufferManagerHost::SetWaylandBufferManagerGpuPtr(
-    ozone::mojom::WaylandBufferManagerGpuAssociatedPtrInfo
-        buffer_manager_gpu_associated_ptr) {
-  buffer_manager_gpu_associated_ptr_.Bind(
-      std::move(buffer_manager_gpu_associated_ptr));
+void WaylandBufferManagerHost::SetWaylandBufferManagerGpu(
+    mojo::PendingAssociatedRemote<ozone::mojom::WaylandBufferManagerGpu>
+        buffer_manager_gpu_associated) {
+  buffer_manager_gpu_associated_.Bind(std::move(buffer_manager_gpu_associated));
 }
 
 void WaylandBufferManagerHost::CreateDmabufBasedBuffer(
@@ -826,9 +822,8 @@
     const gfx::SwapResult& swap_result) {
   DCHECK(base::MessageLoopCurrentForUI::IsSet());
 
-  DCHECK(buffer_manager_gpu_associated_ptr_);
-  buffer_manager_gpu_associated_ptr_->OnSubmission(widget, buffer_id,
-                                                   swap_result);
+  DCHECK(buffer_manager_gpu_associated_);
+  buffer_manager_gpu_associated_->OnSubmission(widget, buffer_id, swap_result);
 }
 
 void WaylandBufferManagerHost::OnPresentation(
@@ -837,9 +832,8 @@
     const gfx::PresentationFeedback& feedback) {
   DCHECK(base::MessageLoopCurrentForUI::IsSet());
 
-  DCHECK(buffer_manager_gpu_associated_ptr_);
-  buffer_manager_gpu_associated_ptr_->OnPresentation(widget, buffer_id,
-                                                     feedback);
+  DCHECK(buffer_manager_gpu_associated_);
+  buffer_manager_gpu_associated_->OnPresentation(widget, buffer_id, feedback);
 }
 
 void WaylandBufferManagerHost::TerminateGpuProcess() {
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
index 700fcf9..116c9bd 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
@@ -14,7 +14,9 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/presentation_feedback.h"
@@ -47,24 +49,20 @@
       base::OnceCallback<void(std::string)> terminate_gpu_cb);
 
   // Returns bound pointer to own mojo interface.
-  ozone::mojom::WaylandBufferManagerHostPtr BindInterface();
+  mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> BindInterface();
 
   // Unbinds the interface and clears the state of the |buffer_manager_|. Used
   // only when the GPU channel, which uses the mojo pipe to this interface, is
   // destroyed.
   void OnChannelDestroyed();
 
-  // Says if zwp_linux_dmabuf interface is available, and the manager is able to
-  // create dmabuf based buffers.
-  bool CanCreateDmabufBasedBuffer() const;
-
   // ozone::mojom::WaylandBufferManagerHost overrides:
   //
   // These overridden methods below are invoked by the GPU when hardware
   // accelerated rendering is used.
-  void SetWaylandBufferManagerGpuPtr(
-      ozone::mojom::WaylandBufferManagerGpuAssociatedPtrInfo
-          buffer_manager_gpu_associated_ptr) override;
+  void SetWaylandBufferManagerGpu(
+      mojo::PendingAssociatedRemote<ozone::mojom::WaylandBufferManagerGpu>
+          buffer_manager_gpu_associated) override;
   //
   // Called by the GPU and asks to import a wl_buffer based on a gbm file
   // descriptor using zwp_linux_dmabuf protocol. Check comments in the
@@ -160,9 +158,9 @@
   // Non-owned pointer to the main connection.
   WaylandConnection* const connection_;
 
-  ozone::mojom::WaylandBufferManagerGpuAssociatedPtr
-      buffer_manager_gpu_associated_ptr_;
-  mojo::Binding<ozone::mojom::WaylandBufferManagerHost> binding_;
+  mojo::AssociatedRemote<ozone::mojom::WaylandBufferManagerGpu>
+      buffer_manager_gpu_associated_;
+  mojo::Receiver<ozone::mojom::WaylandBufferManagerHost> receiver_;
 
   // A callback, which is used to terminate a GPU process in case of invalid
   // data sent by the GPU to the browser process.
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
index 267a64c..9d92366f7 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -144,12 +144,6 @@
   return modifiers;
 }
 
-std::vector<gfx::BufferFormat> WaylandConnection::GetSupportedBufferFormats() {
-  if (zwp_dmabuf_)
-    return zwp_dmabuf_->supported_buffer_formats();
-  return std::vector<gfx::BufferFormat>();
-}
-
 void WaylandConnection::StartDrag(const ui::OSExchangeData& data,
                                   int operation) {
   if (!dragdrop_data_source_)
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h
index 1492bd2..fb843b5 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.h
+++ b/ui/ozone/platform/wayland/host/wayland_connection.h
@@ -100,8 +100,6 @@
     return &wayland_window_manager_;
   }
 
-  std::vector<gfx::BufferFormat> GetSupportedBufferFormats();
-
   // Starts drag with |data| to be delivered, |operation| supported by the
   // source side initiated the dragging.
   void StartDrag(const ui::OSExchangeData& data, int operation);
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc
index dd68beb..01e056a 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -374,6 +374,12 @@
   delegate_->OnClosed();
 }
 
+bool WaylandWindow::IsVisible() const {
+  // X and Windows return true if the window is minimized. For consistency, do
+  // the same.
+  return (!!xdg_surface_ || !!xdg_popup_) || IsMinimized();
+}
+
 void WaylandWindow::PrepareForShutdown() {}
 
 void WaylandWindow::SetBounds(const gfx::Rect& bounds_px) {
diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h
index ad65623..55c50c2 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.h
+++ b/ui/ozone/platform/wayland/host/wayland_window.h
@@ -116,6 +116,7 @@
   void Show() override;
   void Hide() override;
   void Close() override;
+  bool IsVisible() const override;
   void PrepareForShutdown() override;
   void SetBounds(const gfx::Rect& bounds) override;
   gfx::Rect GetBounds() override;
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
index ce4cf934..c5fc7a3 100644
--- a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
@@ -50,18 +50,9 @@
       zwp_linux_dmabuf_v1_create_params(zwp_linux_dmabuf_.get());
 
   for (size_t i = 0; i < planes_count; i++) {
-    uint32_t modifier_lo = 0;
-    uint32_t modifier_hi = 0;
-    if (modifiers[i] != DRM_FORMAT_MOD_INVALID) {
-      modifier_lo = modifiers[i] & UINT32_MAX;
-      modifier_hi = modifiers[i] >> 32;
-    } else {
-      DCHECK_EQ(planes_count, 1u) << "Invalid modifier may be passed only in "
-                                     "case of single plane format being used";
-    }
     zwp_linux_buffer_params_v1_add(params, fd.get(), i /* plane id */,
-                                   offsets[i], strides[i], modifier_hi,
-                                   modifier_lo);
+                                   offsets[i], strides[i], modifiers[i] >> 32,
+                                   modifiers[i] & UINT32_MAX);
   }
 
   // It's possible to avoid waiting until the buffer is created and have it
@@ -83,19 +74,30 @@
   connection_->ScheduleFlush();
 }
 
-void WaylandZwpLinuxDmabuf::AddSupportedFourCCFormat(uint32_t fourcc_format) {
-  // Return on not the supported fourcc format.
+void WaylandZwpLinuxDmabuf::AddSupportedFourCCFormatAndModifier(
+    uint32_t fourcc_format,
+    base::Optional<uint64_t> modifier) {
+  // Return on not supported fourcc formats.
   if (!IsValidBufferFormat(fourcc_format))
     return;
 
-  // It can happen that ::Format or ::Modifiers call can have already added
-  // such a format. Thus, we can ignore that format.
+  uint64_t format_modifier = modifier.value_or(DRM_FORMAT_MOD_INVALID);
+
+  // If the buffer format has already been stored, it must be another supported
+  // modifier sent by the Wayland compositor.
   gfx::BufferFormat format = GetBufferFormatFromFourCCFormat(fourcc_format);
-  auto it = std::find(supported_buffer_formats_.begin(),
-                      supported_buffer_formats_.end(), format);
-  if (it != supported_buffer_formats_.end())
+  auto it = supported_buffer_formats_with_modifiers_.find(format);
+  if (it != supported_buffer_formats_with_modifiers_.end()) {
+    if (format_modifier != DRM_FORMAT_MOD_INVALID)
+      it->second.emplace_back(format_modifier);
     return;
-  supported_buffer_formats_.push_back(format);
+  } else {
+    std::vector<uint64_t> modifiers;
+    if (format_modifier != DRM_FORMAT_MOD_INVALID)
+      modifiers.emplace_back(format_modifier);
+    supported_buffer_formats_with_modifiers_.emplace(format,
+                                                     std::move(modifiers));
+  }
 }
 
 void WaylandZwpLinuxDmabuf::NotifyRequestCreateBufferDone(
@@ -120,8 +122,10 @@
     uint32_t modifier_hi,
     uint32_t modifier_lo) {
   WaylandZwpLinuxDmabuf* self = static_cast<WaylandZwpLinuxDmabuf*>(data);
-  if (self)
-    self->AddSupportedFourCCFormat(format);
+  if (self) {
+    uint64_t modifier = static_cast<uint64_t>(modifier_hi) << 32 | modifier_lo;
+    self->AddSupportedFourCCFormatAndModifier(format, {modifier});
+  }
 }
 
 // static
@@ -130,7 +134,7 @@
                                    uint32_t format) {
   WaylandZwpLinuxDmabuf* self = static_cast<WaylandZwpLinuxDmabuf*>(data);
   if (self)
-    self->AddSupportedFourCCFormat(format);
+    self->AddSupportedFourCCFormatAndModifier(format, base::nullopt);
 }
 
 // static
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
index 0716d86..a4ed3a81 100644
--- a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
@@ -10,6 +10,7 @@
 #include "base/containers/flat_map.h"
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 
@@ -29,6 +30,9 @@
 // |wl_buffer|s backed by dmabuf |file| descriptor.
 class WaylandZwpLinuxDmabuf {
  public:
+  using BufferFormatsWithModifiersMap =
+      base::flat_map<gfx::BufferFormat, std::vector<uint64_t>>;
+
   WaylandZwpLinuxDmabuf(zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
                         WaylandConnection* connection);
   ~WaylandZwpLinuxDmabuf();
@@ -46,15 +50,17 @@
                     wl::OnRequestBufferCallback callback);
 
   // Returns supported buffer formats received from the Wayland compositor.
-  std::vector<gfx::BufferFormat> supported_buffer_formats() const {
-    return supported_buffer_formats_;
+  BufferFormatsWithModifiersMap supported_buffer_formats() const {
+    return supported_buffer_formats_with_modifiers_;
   }
 
  private:
   // Receives supported |fourcc_format| from either ::Modifers or ::Format call
   // (depending on the protocol version), and stores it as gfx::BufferFormat to
-  // the |supported_buffer_formats_| container.
-  void AddSupportedFourCCFormat(uint32_t fourcc_format);
+  // the |supported_buffer_formats_| container. Modifiers can also be passed to
+  // this method to be stored as a map of the format and modifier.
+  void AddSupportedFourCCFormatAndModifier(uint32_t fourcc_format,
+                                           base::Optional<uint64_t> modifier);
 
   // Finds the stored callback corresponding to the |params| created in the
   // RequestBufferAsync call, and passes the wl_buffer to the client. The
@@ -79,14 +85,16 @@
   static void CreateFailed(void* data,
                            struct zwp_linux_buffer_params_v1* params);
 
-  // Holds pointer to the zwp_linux_dmabuf_v1 Wayland factory.
+  // Holds pointer to the
+  // zwp_linux_dmabuf_v1 Wayland
+  // factory.
   const wl::Object<zwp_linux_dmabuf_v1> zwp_linux_dmabuf_;
 
   // Non-owned.
   WaylandConnection* const connection_;
 
   // Holds supported DRM formats translated to gfx::BufferFormat.
-  std::vector<gfx::BufferFormat> supported_buffer_formats_;
+  BufferFormatsWithModifiersMap supported_buffer_formats_with_modifiers_;
 
   // Contains callbacks for requests to create |wl_buffer|s using
   // |zwp_linux_dmabuf_| factory.
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index 67f20ad..200bbc3 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -26,6 +26,7 @@
 #include "ui/ozone/platform/wayland/host/wayland_input_method_context_factory.h"
 #include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
 #include "ui/ozone/platform/wayland/host/wayland_window.h"
+#include "ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h"
 #include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
@@ -39,6 +40,8 @@
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #endif
 
+#include "ui/gfx/buffer_format_util.h"
+
 #if defined(WAYLAND_GBM)
 #include "ui/base/ui_base_features.h"
 #include "ui/ozone/common/linux/gbm_wrapper.h"
@@ -52,10 +55,11 @@
 constexpr OzonePlatform::PlatformProperties kWaylandPlatformProperties = {
     /*needs_view_token=*/false,
 
-    // Supporting server-side decorations requires a support of xdg-decorations.
-    // But this protocol has been accepted into the upstream recently, and it
-    // will take time before it is taken by compositors. For now, always use
-    // custom frames and disallow switching to server-side frames.
+    // Supporting server-side decorations requires a support of
+    // xdg-decorations. But this protocol has been accepted into the upstream
+    // recently, and it will take time before it is taken by compositors. For
+    // now, always use custom frames and disallow switching to server-side
+    // frames.
     // https://github.com/wayland-project/wayland-protocols/commit/76d1ae8c65739eff3434ef219c58a913ad34e988
     /*custom_frame_pref_default=*/true,
     /*use_system_title_bar=*/false,
@@ -113,8 +117,8 @@
   }
 
   std::unique_ptr<PlatformScreen> CreateScreen() override {
-    // The WaylandConnection and the WaylandOutputManager must be created before
-    // PlatformScreen.
+    // The WaylandConnection and the WaylandOutputManager must be created
+    // before PlatformScreen.
     DCHECK(connection_ && connection_->wayland_output_manager());
     return connection_->wayland_output_manager()->CreateWaylandScreen(
         connection_.get());
@@ -137,9 +141,8 @@
     if (path_finder_.GetDrmRenderNodePath().empty())
       return false;
 
-    if (std::find(supported_buffer_formats_.begin(),
-                  supported_buffer_formats_.end(),
-                  format) == supported_buffer_formats_.end()) {
+    if (supported_buffer_formats_.find(format) ==
+        supported_buffer_formats_.end()) {
       return false;
     }
 
@@ -159,13 +162,16 @@
     if (!connection_->Initialize())
       LOG(FATAL) << "Failed to initialize Wayland platform";
 
-    buffer_manager_connector_ = std::make_unique<WaylandBufferManagerConnector>(
-        connection_->buffer_manager_host());
+    buffer_manager_connector_ =
+        std::make_unique<WaylandBufferManagerConnector>(connection_.get());
     cursor_factory_ = std::make_unique<BitmapCursorFactoryOzone>();
     overlay_manager_ = std::make_unique<StubOverlayManager>();
     input_controller_ = CreateStubInputController();
     gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
-    supported_buffer_formats_ = connection_->GetSupportedBufferFormats();
+
+    auto* zwp_dmabuf = connection_->zwp_dmabuf();
+    if (zwp_dmabuf)
+      supported_buffer_formats_ = zwp_dmabuf->supported_buffer_formats();
 
     // Instantiate and set LinuxInputMethodContextFactory unless it is already
     // set (e.g: tests may have already set it).
@@ -212,8 +218,8 @@
   }
 
   void CreateWaylandBufferManagerGpuBinding(
-      ozone::mojom::WaylandBufferManagerGpuRequest request) {
-    buffer_manager_->AddBindingWaylandBufferManagerGpu(std::move(request));
+      mojo::PendingReceiver<ozone::mojom::WaylandBufferManagerGpu> receiver) {
+    buffer_manager_->AddBindingWaylandBufferManagerGpu(std::move(receiver));
   }
 
  private:
@@ -234,8 +240,10 @@
   // Objects, which solely live in the GPU process.
   std::unique_ptr<WaylandBufferManagerGpu> buffer_manager_;
 
-  // Provides supported buffer formats for native gpu memory buffers framework.
-  std::vector<gfx::BufferFormat> supported_buffer_formats_;
+  // Provides supported buffer formats for native gpu memory buffers
+  // framework.
+  WaylandZwpLinuxDmabuf::BufferFormatsWithModifiersMap
+      supported_buffer_formats_;
 
   // This is used both in the gpu and browser processes to find out if a drm
   // render node is available.
diff --git a/ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.h b/ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.h
deleted file mode 100644
index 7da794a..0000000
--- a/ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_ZWP_LINUX_BUFFER_PARAMS_H_
-#define UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_ZWP_LINUX_BUFFER_PARAMS_H_
-
-#include <linux-dmabuf-unstable-v1-server-protocol.h>
-
-#include "base/files/scoped_file.h"
-#include "base/macros.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "ui/ozone/platform/wayland/test/server_object.h"
-
-struct wl_client;
-struct wl_resource;
-
-namespace wl {
-
-extern const struct zwp_linux_buffer_params_v1_interface
-    kMockZwpLinuxBufferParamsV1Impl;
-
-class MockZwpLinuxDmabufV1;
-
-// Manage zwp_linux_buffer_params_v1
-class MockZwpLinuxBufferParamsV1 : public ServerObject {
- public:
-  MockZwpLinuxBufferParamsV1(wl_resource* resource);
-  ~MockZwpLinuxBufferParamsV1();
-
-  MOCK_METHOD2(Destroy, void(wl_client* client, wl_resource* resource));
-  MOCK_METHOD8(Add,
-               void(wl_client* client,
-                    wl_resource* resource,
-                    int32_t fd,
-                    uint32_t plane_idx,
-                    uint32_t offset,
-                    uint32_t stride,
-                    uint32_t modifier_hi,
-                    uint32_t modifier_lo));
-  MOCK_METHOD6(Create,
-               void(wl_client* client,
-                    wl_resource* resource,
-                    int32_t width,
-                    int32_t height,
-                    uint32_t format,
-                    uint32_t flags));
-  MOCK_METHOD7(CreateImmed,
-               void(wl_client* client,
-                    wl_resource* resource,
-                    uint32_t buffer_id,
-                    int32_t width,
-                    int32_t height,
-                    uint32_t format,
-                    uint32_t flags));
-
-  wl_resource* buffer_resource() const { return buffer_resource_; }
-
-  void SetZwpLinuxDmabuf(MockZwpLinuxDmabufV1* linux_dmabuf);
-
-  void SetBufferResource(wl_resource* resource);
-
-  std::vector<base::ScopedFD> fds_;
-
- private:
-  // Non-owned pointer to the linux dmabuf object, which created this params
-  // resource and holds a pointer to it. On destruction, must notify it about
-  // going out of scope.
-  MockZwpLinuxDmabufV1* linux_dmabuf_ = nullptr;
-
-  // A buffer resource, which is created on Create or CreateImmed call. Can be
-  // null if not created/failed to be created.
-  wl_resource* buffer_resource_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(MockZwpLinuxBufferParamsV1);
-};
-
-}  // namespace wl
-
-#endif  // UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_ZWP_LINUX_BUFFER_PARAMS_H_
diff --git a/ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.cc b/ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.cc
index 006d55ff..c296027 100644
--- a/ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.cc
+++ b/ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.cc
@@ -8,7 +8,7 @@
 #include <wayland-server-core.h>
 
 #include "ui/ozone/platform/wayland/test/mock_buffer.h"
-#include "ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.h"
+#include "ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.h"
 
 namespace wl {
 
@@ -18,14 +18,14 @@
 
 void CreateParams(wl_client* client, wl_resource* resource, uint32_t id) {
   wl_resource* params_resource =
-      CreateResourceWithImpl<::testing::NiceMock<MockZwpLinuxBufferParamsV1>>(
+      CreateResourceWithImpl<TestZwpLinuxBufferParamsV1>(
           client, &zwp_linux_buffer_params_v1_interface,
-          wl_resource_get_version(resource), &kMockZwpLinuxBufferParamsV1Impl,
+          wl_resource_get_version(resource), &kTestZwpLinuxBufferParamsV1Impl,
           id);
 
   auto* zwp_linux_dmabuf = GetUserDataAs<MockZwpLinuxDmabufV1>(resource);
   auto* buffer_params =
-      GetUserDataAs<MockZwpLinuxBufferParamsV1>(params_resource);
+      GetUserDataAs<TestZwpLinuxBufferParamsV1>(params_resource);
 
   DCHECK(buffer_params);
   zwp_linux_dmabuf->StoreBufferParams(buffer_params);
@@ -50,12 +50,12 @@
 }
 
 void MockZwpLinuxDmabufV1::StoreBufferParams(
-    MockZwpLinuxBufferParamsV1* params) {
+    TestZwpLinuxBufferParamsV1* params) {
   buffer_params_.push_back(params);
 }
 
 void MockZwpLinuxDmabufV1::OnBufferParamsDestroyed(
-    MockZwpLinuxBufferParamsV1* params) {
+    TestZwpLinuxBufferParamsV1* params) {
   auto it = std::find(buffer_params_.begin(), buffer_params_.end(), params);
   DCHECK(it != buffer_params_.end());
   buffer_params_.erase(it);
diff --git a/ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.h b/ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.h
index 9d2e107..811177a4 100644
--- a/ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.h
+++ b/ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.h
@@ -18,7 +18,7 @@
 
 extern const struct zwp_linux_dmabuf_v1_interface kMockZwpLinuxDmabufV1Impl;
 
-class MockZwpLinuxBufferParamsV1;
+class TestZwpLinuxBufferParamsV1;
 
 // Manage zwp_linux_dmabuf_v1 object.
 class MockZwpLinuxDmabufV1 : public GlobalObject {
@@ -32,16 +32,16 @@
                     wl_resource* resource,
                     uint32_t params_id));
 
-  const std::vector<MockZwpLinuxBufferParamsV1*>& buffer_params() const {
+  const std::vector<TestZwpLinuxBufferParamsV1*>& buffer_params() const {
     return buffer_params_;
   }
 
-  void StoreBufferParams(MockZwpLinuxBufferParamsV1* params);
+  void StoreBufferParams(TestZwpLinuxBufferParamsV1* params);
 
-  void OnBufferParamsDestroyed(MockZwpLinuxBufferParamsV1* params);
+  void OnBufferParamsDestroyed(TestZwpLinuxBufferParamsV1* params);
 
  private:
-  std::vector<MockZwpLinuxBufferParamsV1*> buffer_params_;
+  std::vector<TestZwpLinuxBufferParamsV1*> buffer_params_;
 
   DISALLOW_COPY_AND_ASSIGN(MockZwpLinuxDmabufV1);
 };
diff --git a/ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.cc b/ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.cc
similarity index 69%
rename from ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.cc
rename to ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.cc
index 8ebe4e6..f5df297 100644
--- a/ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.cc
+++ b/ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.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 "ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.h"
+#include "ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.h"
 
 #include "ui/ozone/platform/wayland/test/mock_buffer.h"
 #include "ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.h"
@@ -19,14 +19,14 @@
          uint32_t stride,
          uint32_t modifier_hi,
          uint32_t modifier_lo) {
-  auto* buffer_params = GetUserDataAs<MockZwpLinuxBufferParamsV1>(resource);
+  auto* buffer_params = GetUserDataAs<TestZwpLinuxBufferParamsV1>(resource);
 
   buffer_params->fds_.emplace_back(fd);
-  buffer_params->Add(client, resource, fd, plane_idx, offset, stride,
-                     modifier_hi, modifier_lo);
+  buffer_params->modifier_lo_ = modifier_lo;
+  buffer_params->modifier_hi_ = modifier_hi;
 }
 
-void CreateCommon(MockZwpLinuxBufferParamsV1* buffer_params,
+void CreateCommon(TestZwpLinuxBufferParamsV1* buffer_params,
                   wl_client* client,
                   int32_t width,
                   int32_t height,
@@ -47,10 +47,8 @@
             uint32_t format,
             uint32_t flags) {
   auto* buffer_params =
-      GetUserDataAs<MockZwpLinuxBufferParamsV1>(buffer_params_resource);
+      GetUserDataAs<TestZwpLinuxBufferParamsV1>(buffer_params_resource);
   CreateCommon(buffer_params, client, width, height, format, flags);
-  buffer_params->Create(client, buffer_params_resource, width, height, format,
-                        flags);
 }
 
 void CreateImmed(wl_client* client,
@@ -61,33 +59,31 @@
                  uint32_t format,
                  uint32_t flags) {
   auto* buffer_params =
-      GetUserDataAs<MockZwpLinuxBufferParamsV1>(buffer_params_resource);
+      GetUserDataAs<TestZwpLinuxBufferParamsV1>(buffer_params_resource);
   CreateCommon(buffer_params, client, width, height, format, flags);
-  buffer_params->CreateImmed(client, buffer_params_resource, buffer_id, width,
-                             height, format, flags);
 }
 
 }  // namespace
 
 const struct zwp_linux_buffer_params_v1_interface
-    kMockZwpLinuxBufferParamsV1Impl = {&DestroyResource, &Add, &Create,
+    kTestZwpLinuxBufferParamsV1Impl = {&DestroyResource, &Add, &Create,
                                        &CreateImmed};
 
-MockZwpLinuxBufferParamsV1::MockZwpLinuxBufferParamsV1(wl_resource* resource)
+TestZwpLinuxBufferParamsV1::TestZwpLinuxBufferParamsV1(wl_resource* resource)
     : ServerObject(resource) {}
 
-MockZwpLinuxBufferParamsV1::~MockZwpLinuxBufferParamsV1() {
+TestZwpLinuxBufferParamsV1::~TestZwpLinuxBufferParamsV1() {
   DCHECK(linux_dmabuf_);
   linux_dmabuf_->OnBufferParamsDestroyed(this);
 }
 
-void MockZwpLinuxBufferParamsV1::SetZwpLinuxDmabuf(
+void TestZwpLinuxBufferParamsV1::SetZwpLinuxDmabuf(
     MockZwpLinuxDmabufV1* linux_dmabuf) {
   DCHECK(!linux_dmabuf_);
   linux_dmabuf_ = linux_dmabuf;
 }
 
-void MockZwpLinuxBufferParamsV1::SetBufferResource(wl_resource* resource) {
+void TestZwpLinuxBufferParamsV1::SetBufferResource(wl_resource* resource) {
   DCHECK(!buffer_resource_);
   buffer_resource_ = resource;
 }
diff --git a/ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.h b/ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.h
new file mode 100644
index 0000000..43f64ae
--- /dev/null
+++ b/ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.h
@@ -0,0 +1,80 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZWP_LINUX_BUFFER_PARAMS_H_
+#define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZWP_LINUX_BUFFER_PARAMS_H_
+
+#include <linux-dmabuf-unstable-v1-server-protocol.h>
+
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/ozone/platform/wayland/test/server_object.h"
+
+struct wl_client;
+struct wl_resource;
+
+namespace wl {
+
+extern const struct zwp_linux_buffer_params_v1_interface
+    kTestZwpLinuxBufferParamsV1Impl;
+
+class MockZwpLinuxDmabufV1;
+
+// Manage zwp_linux_buffer_params_v1
+class TestZwpLinuxBufferParamsV1 : public ServerObject {
+ public:
+  explicit TestZwpLinuxBufferParamsV1(wl_resource* resource);
+  ~TestZwpLinuxBufferParamsV1() override;
+
+  void Destroy(wl_client* client, wl_resource* resource);
+  void Add(wl_client* client,
+           wl_resource* resource,
+           int32_t fd,
+           uint32_t plane_idx,
+           uint32_t offset,
+           uint32_t stride,
+           uint32_t modifier_hi,
+           uint32_t modifier_lo);
+  void Create(wl_client* client,
+              wl_resource* resource,
+              int32_t width,
+              int32_t height,
+              uint32_t format,
+              uint32_t flags);
+  void CreateImmed(wl_client* client,
+                   wl_resource* resource,
+                   uint32_t buffer_id,
+                   int32_t width,
+                   int32_t height,
+                   uint32_t format,
+                   uint32_t flags);
+
+  wl_resource* buffer_resource() const { return buffer_resource_; }
+
+  void SetZwpLinuxDmabuf(MockZwpLinuxDmabufV1* linux_dmabuf);
+
+  void SetBufferResource(wl_resource* resource);
+
+  std::vector<base::ScopedFD> fds_;
+
+  uint32_t modifier_hi_ = 0;
+  uint32_t modifier_lo_ = 0;
+
+ private:
+  // Non-owned pointer to the linux dmabuf object, which created this params
+  // resource and holds a pointer to it. On destruction, must notify it about
+  // going out of scope.
+  MockZwpLinuxDmabufV1* linux_dmabuf_ = nullptr;
+
+  // A buffer resource, which is created on Create or CreateImmed call. Can be
+  // null if not created/failed to be created.
+  wl_resource* buffer_resource_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(TestZwpLinuxBufferParamsV1);
+};
+
+}  // namespace wl
+
+#endif  // UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZWP_LINUX_BUFFER_PARAMS_H_
diff --git a/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc b/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
index 3908e2af..91c8abf 100644
--- a/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
+++ b/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
@@ -14,10 +14,13 @@
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/ozone/common/linux/drm_util_linux.h"
 #include "ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h"
+#include "ui/ozone/platform/wayland/host/wayland_connection.h"
+#include "ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h"
 #include "ui/ozone/platform/wayland/test/mock_surface.h"
-#include "ui/ozone/platform/wayland/test/mock_zwp_linux_buffer_params.h"
 #include "ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.h"
+#include "ui/ozone/platform/wayland/test/test_zwp_linux_buffer_params.h"
 #include "ui/ozone/platform/wayland/test/wayland_test.h"
 
 using testing::_;
@@ -81,7 +84,7 @@
     // callback and bind the interface again if the manager failed.
     manager_host_->SetTerminateGpuCallback(callback_.Get());
     auto interface_ptr = manager_host_->BindInterface();
-    buffer_manager_gpu_->SetWaylandBufferManagerHost(std::move(interface_ptr));
+    buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false);
   }
 
  protected:
@@ -109,11 +112,15 @@
           .Times(1)
           .WillRepeatedly(::testing::Invoke([this, callback](std::string) {
             manager_host_->OnChannelDestroyed();
+
             manager_host_->SetTerminateGpuCallback(callback->Get());
 
             auto interface_ptr = manager_host_->BindInterface();
-            buffer_manager_gpu_->SetWaylandBufferManagerHost(
-                std::move(interface_ptr));
+            // Recreate the gpu side manager (the production code does the
+            // same).
+            buffer_manager_gpu_ = std::make_unique<WaylandBufferManagerGpu>();
+            buffer_manager_gpu_->Initialize(std::move(interface_ptr), {},
+                                            false);
           }));
     }
   }
@@ -201,6 +208,54 @@
                                           false /*fail*/);
 }
 
+TEST_P(WaylandBufferManagerTest, VerifyModifiers) {
+  constexpr uint32_t kDmabufBufferId = 1;
+  constexpr uint32_t kFourccFormatR8 = DRM_FORMAT_R8;
+  constexpr uint64_t kFormatModiferLinear = DRM_FORMAT_MOD_LINEAR;
+
+  const std::vector<uint64_t> kFormatModifiers{DRM_FORMAT_MOD_INVALID,
+                                               kFormatModiferLinear};
+
+  // Tests that fourcc format is added, but invalid modifier is ignored first.
+  // Then, when valid modifier comes, it is stored.
+  for (const auto& modifier : kFormatModifiers) {
+    uint32_t modifier_hi = modifier >> 32;
+    uint32_t modifier_lo = modifier & UINT32_MAX;
+    zwp_linux_dmabuf_v1_send_modifier(server_.zwp_linux_dmabuf_v1()->resource(),
+                                      kFourccFormatR8, modifier_hi,
+                                      modifier_lo);
+
+    Sync();
+
+    auto buffer_formats = connection_->zwp_dmabuf()->supported_buffer_formats();
+    DCHECK_EQ(buffer_formats.size(), 1u);
+    DCHECK_EQ(buffer_formats.begin()->first,
+              GetBufferFormatFromFourCCFormat(kFourccFormatR8));
+
+    auto modifiers = buffer_formats.begin()->second;
+    if (modifier == DRM_FORMAT_MOD_INVALID) {
+      DCHECK_EQ(modifiers.size(), 0u);
+    } else {
+      DCHECK_EQ(modifiers.size(), 1u);
+      DCHECK_EQ(modifiers[0], modifier);
+    }
+  }
+
+  EXPECT_CALL(*server_.zwp_linux_dmabuf_v1(), CreateParams(_, _, _)).Times(1);
+  const gfx::AcceleratedWidget widget = window_->GetWidget();
+
+  CreateDmabufBasedBufferAndSetTerminateExpecation(
+      false /*fail*/, widget, kDmabufBufferId, base::ScopedFD(), kDefaultSize,
+      {1}, {2}, {kFormatModiferLinear}, kFourccFormatR8, 1);
+
+  Sync();
+
+  auto params_vector = server_.zwp_linux_dmabuf_v1()->buffer_params();
+  EXPECT_EQ(params_vector.size(), 1u);
+  EXPECT_EQ(params_vector[0]->modifier_hi_, kFormatModiferLinear >> 32);
+  EXPECT_EQ(params_vector[0]->modifier_lo_, kFormatModiferLinear & UINT32_MAX);
+}
+
 TEST_P(WaylandBufferManagerTest, CreateShmBasedBuffers) {
   constexpr uint32_t kShmBufferId = 1;
 
diff --git a/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom b/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom
index dc4c26b..9b5bf1a7 100644
--- a/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom
+++ b/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom
@@ -9,13 +9,15 @@
 import "ui/gfx/mojom/accelerated_widget.mojom";
 import "ui/gfx/mojom/presentation_feedback.mojom";
 import "ui/gfx/mojom/swap_result.mojom";
+import "ui/gfx/mojom/buffer_types.mojom";
 
 // Used by the GPU for communication with the WaylandBufferManagerHost in
 // the browser process.
 interface WaylandBufferManagerHost {
   // Sets up an associated pipe between the Gpu and Host.
-  SetWaylandBufferManagerGpuPtr(
-      associated WaylandBufferManagerGpu buffer_manager_gpu_associated_ptr);
+  SetWaylandBufferManagerGpu(
+      pending_associated_remote<WaylandBufferManagerGpu>
+        buffer_manager_gpu_associated);
 
   // The following two methods are used either for hardware accelerated
   // rendering or for the software rendering.
@@ -69,14 +71,20 @@
 
 
 interface WaylandBufferManagerGpu {
-  // Used by the browser process to provide the GPU process with a mojo ptr to a
-  // WaylandBufferManagerHost, which lives in the browser process.
-  SetWaylandBufferManagerHost(WaylandBufferManagerHost buffer_manager_host_ptr);
-
-  // The browser process may request the client to reset gbm device instance to
-  // avoid using zwp_linux_dmabuf protocol, which means using wl_egl_surface in
-  // a single process mode, and software rendering in a multiple process mode.
-  ResetGbmDevice();
+  // Initializes the gpu side buffer manager by passing the interface pointer of
+  // of the WaylandBufferManagerHost that lives in the browser process to it.
+  // Also supplies the gpu side manager with the supported buffer formats and
+  // modifiers so that gpu side clients could be aware of supported modifiers
+  // the Wayland compositor announces. The modifiers may be empty, which means
+  // modifiers are not supported.
+  // The browser process may also request the client to reset gbm device
+  // instance to avoid using zwp_linux_dmabuf protocol by setting
+  // |supports_dma_buf| to false, which results in using wl_egl_surface in a
+  // single process mode, and software rendering in a multiple process mode.
+  Initialize(pending_remote<WaylandBufferManagerHost> remote_host,
+             map<gfx.mojom.BufferFormat,
+                 array<uint64>> buffer_formats_with_modifiers,
+            bool supports_dma_buf);
 
   // Signals about swap completion.
   OnSubmission(gfx.mojom.AcceleratedWidget widget,
diff --git a/ui/platform_window/platform_window.h b/ui/platform_window/platform_window.h
index a195dee..d4ca974 100644
--- a/ui/platform_window/platform_window.h
+++ b/ui/platform_window/platform_window.h
@@ -34,6 +34,8 @@
   virtual void Hide() = 0;
   virtual void Close() = 0;
 
+  virtual bool IsVisible() const = 0;
+
   // Informs the window it is going to be destroyed sometime soon. This is only
   // called for specific code paths, for example by Ash, so it shouldn't be
   // assumed this will get called before destruction.
diff --git a/ui/platform_window/stub/stub_window.cc b/ui/platform_window/stub/stub_window.cc
index 82d28c8..e4fe9059 100644
--- a/ui/platform_window/stub/stub_window.cc
+++ b/ui/platform_window/stub/stub_window.cc
@@ -28,6 +28,11 @@
   delegate_->OnClosed();
 }
 
+bool StubWindow::IsVisible() const {
+  NOTIMPLEMENTED_LOG_ONCE();
+  return true;
+}
+
 void StubWindow::PrepareForShutdown() {}
 
 void StubWindow::SetBounds(const gfx::Rect& bounds) {
diff --git a/ui/platform_window/stub/stub_window.h b/ui/platform_window/stub/stub_window.h
index 0574b19..09d8138 100644
--- a/ui/platform_window/stub/stub_window.h
+++ b/ui/platform_window/stub/stub_window.h
@@ -31,6 +31,7 @@
   void Show() override;
   void Hide() override;
   void Close() override;
+  bool IsVisible() const override;
   void PrepareForShutdown() override;
   void SetBounds(const gfx::Rect& bounds) override;
   gfx::Rect GetBounds() override;
diff --git a/ui/platform_window/win/win_window.cc b/ui/platform_window/win/win_window.cc
index ddeb1c3..730a1ee8 100644
--- a/ui/platform_window/win/win_window.cc
+++ b/ui/platform_window/win/win_window.cc
@@ -75,6 +75,11 @@
   Destroy();
 }
 
+bool WinWindow::IsVisible() const {
+  NOTIMPLEMENTED_LOG_ONCE();
+  return true;
+}
+
 void WinWindow::PrepareForShutdown() {}
 
 void WinWindow::SetBounds(const gfx::Rect& bounds) {
diff --git a/ui/platform_window/win/win_window.h b/ui/platform_window/win/win_window.h
index dd139126..4152ecb 100644
--- a/ui/platform_window/win/win_window.h
+++ b/ui/platform_window/win/win_window.h
@@ -30,6 +30,7 @@
   void Show() override;
   void Hide() override;
   void Close() override;
+  bool IsVisible() const override;
   void PrepareForShutdown() override;
   void SetBounds(const gfx::Rect& bounds) override;
   gfx::Rect GetBounds() override;
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc
index 173f25d..a86ae7fa 100644
--- a/ui/platform_window/x11/x11_window.cc
+++ b/ui/platform_window/x11/x11_window.cc
@@ -113,6 +113,10 @@
   platform_window_delegate_->OnClosed();
 }
 
+bool X11Window::IsVisible() const {
+  return XWindow::IsXWindowVisible();
+}
+
 void X11Window::PrepareForShutdown() {
   PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
 }
diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h
index 4209c7b..1f52f50 100644
--- a/ui/platform_window/x11/x11_window.h
+++ b/ui/platform_window/x11/x11_window.h
@@ -49,6 +49,7 @@
   void Show() override;
   void Hide() override;
   void Close() override;
+  bool IsVisible() const override;
   void PrepareForShutdown() override;
   void SetBounds(const gfx::Rect& bounds) override;
   gfx::Rect GetBounds() override;
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
index 1709b54..cc0060610 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
@@ -33,6 +33,7 @@
   void Show() override {}
   void Hide() override {}
   void Close() override {}
+  bool IsVisible() const override { return true; }
   void PrepareForShutdown() override {}
   void SetBounds(const gfx::Rect& bounds) override {}
   gfx::Rect GetBounds() override { return gfx::Rect(); }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index e9af1b1..7335817c 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -277,9 +277,7 @@
 }
 
 bool DesktopWindowTreeHostPlatform::IsVisible() const {
-  // TODO: needs PlatformWindow support.
-  NOTIMPLEMENTED_LOG_ONCE();
-  return true;
+  return platform_window()->IsVisible();
 }
 
 void DesktopWindowTreeHostPlatform::SetSize(const gfx::Size& size) {
@@ -572,7 +570,7 @@
 
 gfx::Transform DesktopWindowTreeHostPlatform::GetRootTransform() const {
   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
-  if (IsVisible()) {
+  if (platform_window() && IsVisible()) {
     display = display::Screen::GetScreen()->GetDisplayNearestWindow(
         GetWidget()->GetNativeWindow());
   }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 2a8e8f36..22af8463 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -280,10 +280,6 @@
   content_window()->Show();
 }
 
-bool DesktopWindowTreeHostX11::IsVisible() const {
-  return platform_window() ? GetXWindow()->IsVisible() : false;
-}
-
 void DesktopWindowTreeHostX11::SetSize(const gfx::Size& requested_size) {
   gfx::Size size_in_pixels = ToPixelRect(gfx::Rect(requested_size)).size();
   size_in_pixels = AdjustSizeForDisplay(size_in_pixels);
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index ef00ef22..ffc520e 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -96,7 +96,6 @@
       DesktopNativeCursorManager* cursor_manager) override;
   void Show(ui::WindowShowState show_state,
             const gfx::Rect& restore_bounds) override;
-  bool IsVisible() const override;
   void SetSize(const gfx::Size& requested_size) override;
   void GetWindowPlacement(gfx::Rect* bounds,
                           ui::WindowShowState* show_state) const override;
diff --git a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html
index bc5c7e2..e8aefd0 100644
--- a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html
+++ b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html
@@ -21,6 +21,10 @@
         width: var(--cr-searchable-drop-down-width, 472px);
       }
 
+      cr-input {
+        --cr-input-padding-start: 8px;
+      }
+
       iron-dropdown {
         max-height: 270px;
       }
@@ -90,7 +94,7 @@
         color: var(--paper-grey-900);
         font: inherit;
         min-height: 32px;
-        padding: 0 24px;
+        padding: 0 8px;
         text-align: start;
         width: 100%;
       }