diff --git a/DEPS b/DEPS
index a23827e..396747c 100644
--- a/DEPS
+++ b/DEPS
@@ -116,11 +116,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': '0e50a38dcaee9f3061aa0ddd850322fec5998d78',
+  'skia_revision': '67f5c0ceac22fdc2094a9b6dfe92ff6ab848d6f8',
   # 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': '5597b278be66db344f354930db456ea445d75076',
+  'v8_revision': '8eba77ea385d962a216d336b18bf984ed5fac519',
   # 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.
@@ -180,7 +180,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
-  'libfuzzer_revision': 'a305a5eb85ed42edc5c965c14f308f576cb245ca',
+  'libfuzzer_revision': '2a53098584c48af50aec3fb51febe5e651489774',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-node-modules
   # and whatever else without interference from each other.
@@ -680,7 +680,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6d6e0a8009f275943e2661493d442d4959eadcf4',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4d2d5b4bbe385b37659efcdd7e7641622c05bd2a',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -946,7 +946,7 @@
 
   # Minizip library. Used on Chrome OS.
   'src/third_party/minizip/src': {
-      'url': Var('chromium_git') + '/external/github.com/nmoinvaz/minizip' + '@' + '43c01101bf09d473e3aff17fe665faa07ee742b7',
+      'url': Var('chromium_git') + '/external/github.com/nmoinvaz/minizip' + '@' + 'c47090678d687742eddc60d07c5430279af416d8',
       'condition': 'checkout_linux',
   },
 
@@ -1161,7 +1161,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '0d55c887e92b645f6effe753528323ab2ffd94c2',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'dc98b9b975fae15e31c11a5d3f3ec499f3d5c6d3',
+    Var('webrtc_git') + '/src.git' + '@' + '8770ce70746aec7190075b890eb8ffcaa48adfcd',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1192,7 +1192,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0ab40518b6d4ce37271f94b172a212c14f5d101c',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0fc9f7540077a460a1e36480896495cb749ff5fb',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/system/bluetooth/bluetooth_feature_pod_controller.cc b/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
index ff44665..adbc3ee 100644
--- a/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
+++ b/ash/system/bluetooth/bluetooth_feature_pod_controller.cc
@@ -131,11 +131,15 @@
       IDS_ASH_STATUS_TRAY_BLUETOOTH_SETTINGS_TOOLTIP, tooltip_state));
 }
 
-void BluetoothFeaturePodController::OnBluetoothRefresh() {
+void BluetoothFeaturePodController::OnBluetoothSystemStateChanged() {
   UpdateButton();
 }
 
-void BluetoothFeaturePodController::OnBluetoothDiscoveringChanged() {
+void BluetoothFeaturePodController::OnBluetoothScanStateChanged() {
+  UpdateButton();
+}
+
+void BluetoothFeaturePodController::OnBluetoothDeviceListChanged() {
   UpdateButton();
 }
 
diff --git a/ash/system/bluetooth/bluetooth_feature_pod_controller.h b/ash/system/bluetooth/bluetooth_feature_pod_controller.h
index 1bf2ddaf..7771f33b 100644
--- a/ash/system/bluetooth/bluetooth_feature_pod_controller.h
+++ b/ash/system/bluetooth/bluetooth_feature_pod_controller.h
@@ -32,8 +32,9 @@
   void SetTooltipState(const base::string16& tooltip_state);
 
   // BluetoothObserver:
-  void OnBluetoothRefresh() override;
-  void OnBluetoothDiscoveringChanged() override;
+  void OnBluetoothSystemStateChanged() override;
+  void OnBluetoothScanStateChanged() override;
+  void OnBluetoothDeviceListChanged() override;
 
   // Unowned.
   UnifiedSystemTrayController* const tray_controller_;
diff --git a/ash/system/bluetooth/bluetooth_observer.h b/ash/system/bluetooth/bluetooth_observer.h
index 1c1bf4f..20fba3e 100644
--- a/ash/system/bluetooth/bluetooth_observer.h
+++ b/ash/system/bluetooth/bluetooth_observer.h
@@ -11,8 +11,14 @@
  public:
   virtual ~BluetoothObserver() {}
 
-  virtual void OnBluetoothRefresh() = 0;
-  virtual void OnBluetoothDiscoveringChanged() = 0;
+  // Called when the state of Bluetooth in the system changes.
+  virtual void OnBluetoothSystemStateChanged() {}
+
+  // Called when a Bluetooth scan has started or stopped.
+  virtual void OnBluetoothScanStateChanged() {}
+
+  // Called when a device was added, removed, or changed.
+  virtual void OnBluetoothDeviceListChanged() {}
 };
 
 }  // namespace ash
diff --git a/ash/system/bluetooth/tray_bluetooth_helper_experimental.cc b/ash/system/bluetooth/tray_bluetooth_helper_experimental.cc
index d56bc28..d543dcc70 100644
--- a/ash/system/bluetooth/tray_bluetooth_helper_experimental.cc
+++ b/ash/system/bluetooth/tray_bluetooth_helper_experimental.cc
@@ -84,13 +84,13 @@
 void TrayBluetoothHelperExperimental::OnStateChanged(
     device::mojom::BluetoothSystem::State state) {
   cached_state_ = state;
-  Shell::Get()->system_tray_notifier()->NotifyRefreshBluetooth();
+  Shell::Get()->system_tray_notifier()->NotifyBluetoothSystemStateChanged();
 }
 
 void TrayBluetoothHelperExperimental::OnScanStateChanged(
     device::mojom::BluetoothSystem::ScanState state) {
   cached_scan_state_ = state;
-  Shell::Get()->system_tray_notifier()->NotifyBluetoothDiscoveringChanged();
+  Shell::Get()->system_tray_notifier()->NotifyBluetoothScanStateChanged();
 }
 
 }  // namespace ash
diff --git a/ash/system/bluetooth/tray_bluetooth_helper_legacy.cc b/ash/system/bluetooth/tray_bluetooth_helper_legacy.cc
index c068913..83d748d7 100644
--- a/ash/system/bluetooth/tray_bluetooth_helper_legacy.cc
+++ b/ash/system/bluetooth/tray_bluetooth_helper_legacy.cc
@@ -165,34 +165,34 @@
 void TrayBluetoothHelperLegacy::AdapterPresentChanged(
     device::BluetoothAdapter* adapter,
     bool present) {
-  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
+  GetSystemTrayNotifier()->NotifyBluetoothSystemStateChanged();
 }
 
 void TrayBluetoothHelperLegacy::AdapterPoweredChanged(
     device::BluetoothAdapter* adapter,
     bool powered) {
-  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
+  GetSystemTrayNotifier()->NotifyBluetoothSystemStateChanged();
 }
 
 void TrayBluetoothHelperLegacy::AdapterDiscoveringChanged(
     device::BluetoothAdapter* adapter,
     bool discovering) {
-  GetSystemTrayNotifier()->NotifyBluetoothDiscoveringChanged();
+  GetSystemTrayNotifier()->NotifyBluetoothScanStateChanged();
 }
 
 void TrayBluetoothHelperLegacy::DeviceAdded(device::BluetoothAdapter* adapter,
                                             device::BluetoothDevice* device) {
-  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
+  GetSystemTrayNotifier()->NotifyBluetoothDeviceListChanged();
 }
 
 void TrayBluetoothHelperLegacy::DeviceChanged(device::BluetoothAdapter* adapter,
                                               device::BluetoothDevice* device) {
-  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
+  GetSystemTrayNotifier()->NotifyBluetoothDeviceListChanged();
 }
 
 void TrayBluetoothHelperLegacy::DeviceRemoved(device::BluetoothAdapter* adapter,
                                               device::BluetoothDevice* device) {
-  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
+  GetSystemTrayNotifier()->NotifyBluetoothDeviceListChanged();
 }
 
 void TrayBluetoothHelperLegacy::OnStartDiscoverySession(
@@ -204,7 +204,7 @@
     return;
   VLOG(1) << "Claiming new Bluetooth device discovery session.";
   discovery_session_ = std::move(discovery_session);
-  GetSystemTrayNotifier()->NotifyBluetoothDiscoveringChanged();
+  GetSystemTrayNotifier()->NotifyBluetoothScanStateChanged();
 }
 
 }  // namespace ash
diff --git a/ash/system/bluetooth/unified_bluetooth_detailed_view_controller.cc b/ash/system/bluetooth/unified_bluetooth_detailed_view_controller.cc
index f56c7c4..ac7e2ca 100644
--- a/ash/system/bluetooth/unified_bluetooth_detailed_view_controller.cc
+++ b/ash/system/bluetooth/unified_bluetooth_detailed_view_controller.cc
@@ -4,6 +4,9 @@
 
 #include "ash/system/bluetooth/unified_bluetooth_detailed_view_controller.h"
 
+#include <set>
+#include <string>
+
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
 #include "ash/system/bluetooth/bluetooth_detailed_view.h"
@@ -63,7 +66,6 @@
   TrayBluetoothHelper* helper = Shell::Get()->tray_bluetooth_helper();
   if (helper && helper->HasBluetoothDiscoverySession()) {
     helper->StopBluetoothDiscovering();
-    view_->HideLoadingIndicator();
   }
 }
 
@@ -72,59 +74,69 @@
   view_ = new tray::BluetoothDetailedView(
       detailed_view_delegate_.get(),
       Shell::Get()->session_controller()->login_status());
-  Update();
+  OnBluetoothSystemStateChanged();
   return view_;
 }
 
-void UnifiedBluetoothDetailedViewController::OnBluetoothRefresh() {
-  Update();
-}
+void UnifiedBluetoothDetailedViewController::OnBluetoothSystemStateChanged() {
+  auto* helper = Shell::Get()->tray_bluetooth_helper();
+  const BluetoothSystem::State bluetooth_state = helper->GetBluetoothState();
 
-void UnifiedBluetoothDetailedViewController::OnBluetoothDiscoveringChanged() {
-  Update();
-}
-
-void UnifiedBluetoothDetailedViewController::Update() {
-  // Update immediately for initial device list and
-  // when bluetooth is disabled.
-  if (view_->IsDeviceScrollListEmpty() ||
-      Shell::Get()->tray_bluetooth_helper()->GetBluetoothState() !=
-          BluetoothSystem::State::kPoweredOn) {
+  if (bluetooth_state == BluetoothSystem::State::kPoweredOn) {
+    // If Bluetooth was just turned on, start discovering.
+    Shell::Get()->tray_bluetooth_helper()->StartBluetoothDiscovering();
+  } else {
+    // Otherwise stop updating the list of devices.
     timer_.Stop();
-    DoUpdate();
-    return;
   }
 
-  // Return here since an update is already queued.
-  if (timer_.IsRunning())
-    return;
-
-  // Update the detailed view after kUpdateFrequencyMs.
-  timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kUpdateFrequencyMs),
-               this, &UnifiedBluetoothDetailedViewController::DoUpdate);
+  UpdateDeviceListAndUI();
 }
 
-void UnifiedBluetoothDetailedViewController::DoUpdate() {
-  BluetoothStartDiscovering();
+void UnifiedBluetoothDetailedViewController::OnBluetoothScanStateChanged() {
+  // To avoid delaying showing devices, update the device list and UI
+  // immediately.
+  UpdateDeviceListAndUI();
+
+  if (Shell::Get()->tray_bluetooth_helper()->HasBluetoothDiscoverySession()) {
+    // Update the device list and UI every |kUpdateFrequencyMs|.
+    timer_.Start(
+        FROM_HERE, base::TimeDelta::FromMilliseconds(kUpdateFrequencyMs), this,
+        &UnifiedBluetoothDetailedViewController::UpdateDeviceListAndUI);
+    return;
+  }
+  timer_.Stop();
+}
+
+void UnifiedBluetoothDetailedViewController::UpdateDeviceListAndUI() {
   UpdateBluetoothDeviceList();
 
-  // Update UI
-  view_->SetToggleIsOn(
-      Shell::Get()->tray_bluetooth_helper()->GetBluetoothState() ==
-      BluetoothSystem::State::kPoweredOn);
-  UpdateDeviceScrollList();
-}
+  auto* helper = Shell::Get()->tray_bluetooth_helper();
+  bool bluetooth_on =
+      helper->GetBluetoothState() == BluetoothSystem::State::kPoweredOn;
 
-void UnifiedBluetoothDetailedViewController::BluetoothStartDiscovering() {
-  TrayBluetoothHelper* helper = Shell::Get()->tray_bluetooth_helper();
-  if (helper->HasBluetoothDiscoverySession()) {
+  // Update toggle.
+  view_->SetToggleIsOn(bluetooth_on);
+
+  // Update loading indicator.
+  if (helper->HasBluetoothDiscoverySession())
     view_->ShowLoadingIndicator();
+  else
+    view_->HideLoadingIndicator();
+
+  // Update scroll list or show "BT disabled" panel
+  if (bluetooth_on) {
+    view_->HideBluetoothDisabledPanel();
+    view_->UpdateDeviceScrollList(connected_devices_, connecting_devices_,
+                                  paired_not_connected_devices_,
+                                  discovered_not_paired_devices_);
+
     return;
   }
 
-  view_->HideLoadingIndicator();
-  if (helper->GetBluetoothState() == BluetoothSystem::State::kPoweredOn)
-    helper->StartBluetoothDiscovering();
+  // If Bluetooth is disabled, show a panel which only indicates that it is
+  // disabled, instead of the scroller with Bluetooth devices.
+  view_->ShowBluetoothDisabledPanel();
 }
 
 void UnifiedBluetoothDetailedViewController::UpdateBluetoothDeviceList() {
@@ -160,30 +172,4 @@
                                          new_discovered_not_paired_devices);
 }
 
-void UnifiedBluetoothDetailedViewController::UpdateDeviceScrollList() {
-  const BluetoothSystem::State bluetooth_state =
-      Shell::Get()->tray_bluetooth_helper()->GetBluetoothState();
-
-  switch (bluetooth_state) {
-    case BluetoothSystem::State::kUnsupported:
-      // Bluetooth is always supported on Chrome OS.
-      NOTREACHED();
-      return;
-    case BluetoothSystem::State::kUnavailable:
-    case BluetoothSystem::State::kPoweredOff:
-    case BluetoothSystem::State::kTransitioning:
-      // If Bluetooth is disabled, show a panel which only indicates that it is
-      // disabled, instead of the scroller with Bluetooth devices.
-      view_->ShowBluetoothDisabledPanel();
-      return;
-    case BluetoothSystem::State::kPoweredOn:
-      break;
-  }
-
-  view_->HideBluetoothDisabledPanel();
-  view_->UpdateDeviceScrollList(connected_devices_, connecting_devices_,
-                                paired_not_connected_devices_,
-                                discovered_not_paired_devices_);
-}
-
 }  // namespace ash
diff --git a/ash/system/bluetooth/unified_bluetooth_detailed_view_controller.h b/ash/system/bluetooth/unified_bluetooth_detailed_view_controller.h
index 08425b2..7a01d079 100644
--- a/ash/system/bluetooth/unified_bluetooth_detailed_view_controller.h
+++ b/ash/system/bluetooth/unified_bluetooth_detailed_view_controller.h
@@ -34,15 +34,12 @@
   views::View* CreateView() override;
 
   // BluetoothObserver:
-  void OnBluetoothRefresh() override;
-  void OnBluetoothDiscoveringChanged() override;
+  void OnBluetoothSystemStateChanged() override;
+  void OnBluetoothScanStateChanged() override;
 
  private:
-  void Update();
-  void DoUpdate();
-  void BluetoothStartDiscovering();
+  void UpdateDeviceListAndUI();
   void UpdateBluetoothDeviceList();
-  void UpdateDeviceScrollList();
 
   const std::unique_ptr<DetailedViewDelegate> detailed_view_delegate_;
 
@@ -54,7 +51,7 @@
   BluetoothDeviceList discovered_not_paired_devices_;
 
   // Timer used to limit the update frequency.
-  base::OneShotTimer timer_;
+  base::RepeatingTimer timer_;
 
   DISALLOW_COPY_AND_ASSIGN(UnifiedBluetoothDetailedViewController);
 };
diff --git a/ash/system/tray/system_tray_notifier.cc b/ash/system/tray/system_tray_notifier.cc
index 4afd8d5..c0832905 100644
--- a/ash/system/tray/system_tray_notifier.cc
+++ b/ash/system/tray/system_tray_notifier.cc
@@ -26,14 +26,19 @@
   bluetooth_observers_.RemoveObserver(observer);
 }
 
-void SystemTrayNotifier::NotifyRefreshBluetooth() {
+void SystemTrayNotifier::NotifyBluetoothSystemStateChanged() {
   for (auto& observer : bluetooth_observers_)
-    observer.OnBluetoothRefresh();
+    observer.OnBluetoothSystemStateChanged();
 }
 
-void SystemTrayNotifier::NotifyBluetoothDiscoveringChanged() {
+void SystemTrayNotifier::NotifyBluetoothScanStateChanged() {
   for (auto& observer : bluetooth_observers_)
-    observer.OnBluetoothDiscoveringChanged();
+    observer.OnBluetoothScanStateChanged();
+}
+
+void SystemTrayNotifier::NotifyBluetoothDeviceListChanged() {
+  for (auto& observer : bluetooth_observers_)
+    observer.OnBluetoothDeviceListChanged();
 }
 
 void SystemTrayNotifier::AddIMEObserver(IMEObserver* observer) {
diff --git a/ash/system/tray/system_tray_notifier.h b/ash/system/tray/system_tray_notifier.h
index de7d070..ad67439 100644
--- a/ash/system/tray/system_tray_notifier.h
+++ b/ash/system/tray/system_tray_notifier.h
@@ -37,8 +37,9 @@
   // Bluetooth.
   void AddBluetoothObserver(BluetoothObserver* observer);
   void RemoveBluetoothObserver(BluetoothObserver* observer);
-  void NotifyRefreshBluetooth();
-  void NotifyBluetoothDiscoveringChanged();
+  void NotifyBluetoothSystemStateChanged();
+  void NotifyBluetoothScanStateChanged();
+  void NotifyBluetoothDeviceListChanged();
 
   // Input methods.
   void AddIMEObserver(IMEObserver* observer);
diff --git a/base/base_switches.cc b/base/base_switches.cc
index c1650ea..166fbca 100644
--- a/base/base_switches.cc
+++ b/base/base_switches.cc
@@ -81,6 +81,11 @@
 // go to a default file name.
 const char kTraceToFileName[]               = "trace-to-file-name";
 
+// Starts the sampling based profiler for the browser process at startup. This
+// will only work if chrome has been built with the gn arg enable_profiling =
+// true. The output will go to the value of kProfilingFile.
+const char kProfilingAtStart[] = "profiling-at-start";
+
 // Specifies a location for profiling output. This will only work if chrome has
 // been built with the gyp variable profiling=1 or gn arg enable_profiling=true.
 //
@@ -91,6 +96,12 @@
 // for tests.
 const char kProfilingFile[] = "profiling-file";
 
+// Controls whether profile data is periodically flushed to a file. Normally
+// the data gets written on exit but cases exist where chromium doesn't exit
+// cleanly (especially when using single-process). A time in seconds can be
+// specified.
+const char kProfilingFlush[] = "profiling-flush";
+
 #if defined(OS_WIN)
 // Disables the USB keyboard detection for blocking the OSK on Win8+.
 const char kDisableUsbKeyboardDetect[]      = "disable-usb-keyboard-detect";
diff --git a/base/base_switches.h b/base/base_switches.h
index 4ef070d..a22cd29 100644
--- a/base/base_switches.h
+++ b/base/base_switches.h
@@ -21,7 +21,9 @@
 extern const char kForceFieldTrials[];
 extern const char kFullMemoryCrashReport[];
 extern const char kNoErrorDialogs[];
+extern const char kProfilingAtStart[];
 extern const char kProfilingFile[];
+extern const char kProfilingFlush[];
 extern const char kTestChildProcess[];
 extern const char kTestDoNotInitializeIcu[];
 extern const char kTraceToFile[];
diff --git a/base/containers/span_unittest.cc b/base/containers/span_unittest.cc
index ae73954..d1ea2e4 100644
--- a/base/containers/span_unittest.cc
+++ b/base/containers/span_unittest.cc
@@ -1183,4 +1183,18 @@
   EXPECT_EQ(kArray[size], item);
 }
 
+TEST(SpanTest, OutOfBoundsDeath) {
+  constexpr span<int, 0> kEmptySpan;
+
+  ASSERT_DEATH_IF_SUPPORTED(kEmptySpan[0], "");
+
+  ASSERT_DEATH_IF_SUPPORTED(kEmptySpan(0), "");
+
+  ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.first(1), "");
+
+  ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.last(1), "");
+
+  ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.subspan(1), "");
+}
+
 }  // namespace base
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
index 7ae651c..13dafa9 100644
--- a/base/files/file_util_unittest.cc
+++ b/base/files/file_util_unittest.cc
@@ -2913,7 +2913,8 @@
   return 0;
 }
 
-TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) {
+// Times out on Android. http://crbug.com/902674.
+TEST_F(FileUtilTest, DISABLED_ReadFileToStringWithNamedPipe) {
   FilePath pipe_path =
       temp_dir_.GetPath().Append(FILE_PATH_LITERAL("test_pipe"));
   ASSERT_EQ(0, mkfifo(pipe_path.value().c_str(), 0600));
diff --git a/base/memory/singleton.h b/base/memory/singleton.h
index 880ef0a5..1b601a6 100644
--- a/base/memory/singleton.h
+++ b/base/memory/singleton.h
@@ -222,11 +222,14 @@
   // Classes using the Singleton<T> pattern should declare a GetInstance()
   // method and call Singleton::get() from within that.
   friend Type* Type::GetInstance();
+  // Classes may also declare a GetInstanceIfExists() method to invoke
+  // Singleton::GetIfExists().
+  friend Type* Type::GetInstanceIfExists();
 
   // This class is safe to be constructed and copy-constructed since it has no
   // member.
 
-  // Return a pointer to the one true instance of the class.
+  // Returns a pointer to the one true instance of the class.
   static Type* get() {
 #if DCHECK_IS_ON()
     if (!Traits::kAllowedToAccessOnNonjoinableThread)
@@ -238,6 +241,22 @@
         Traits::kRegisterAtExit ? OnExit : nullptr, nullptr);
   }
 
+  // Returns the same result as get() if the instance exists but doesn't
+  // construct it (and returns null) if it doesn't.
+  static Type* GetIfExists() {
+#if DCHECK_IS_ON()
+    if (!Traits::kAllowedToAccessOnNonjoinableThread)
+      ThreadRestrictions::AssertSingletonAllowed();
+#endif
+
+    if (!subtle::NoBarrier_Load(&instance_))
+      return nullptr;
+
+    // Need to invoke get() nonetheless as some Traits return null after
+    // destruction (even though |instance_| still holds garbage).
+    return get();
+  }
+
   // Internal method used as an adaptor for GetOrCreateLazyPointer(). Do not use
   // outside of that use case.
   static Type* CreatorFunc(void* /* creator_arg*/) { return Traits::New(); }
diff --git a/base/message_loop/message_pump_default.cc b/base/message_loop/message_pump_default.cc
index 4104e73..1e97f6a 100644
--- a/base/message_loop/message_pump_default.cc
+++ b/base/message_loop/message_pump_default.cc
@@ -22,7 +22,9 @@
 MessagePumpDefault::MessagePumpDefault()
     : keep_running_(true),
       event_(WaitableEvent::ResetPolicy::AUTOMATIC,
-             WaitableEvent::InitialState::NOT_SIGNALED) {}
+             WaitableEvent::InitialState::NOT_SIGNALED) {
+  event_.declare_only_used_while_idle();
+}
 
 MessagePumpDefault::~MessagePumpDefault() = default;
 
diff --git a/base/synchronization/condition_variable.h b/base/synchronization/condition_variable.h
index dfcf813..c1fd97f0 100644
--- a/base/synchronization/condition_variable.h
+++ b/base/synchronization/condition_variable.h
@@ -102,6 +102,15 @@
   // Signal() revives one waiting thread.
   void Signal();
 
+  // Declares that this ConditionVariable will only ever be used by a thread
+  // that is idle at the bottom of its stack and waiting for work (in
+  // particular, it is not synchronously waiting on this ConditionVariable
+  // before resuming ongoing work). This is useful to avoid telling
+  // base-internals that this thread is "blocked" when it's merely idle and
+  // ready to do work. As such, this is only expected to be used by thread and
+  // thread pool impls.
+  void declare_only_used_while_idle() { waiting_is_blocking_ = false; }
+
  private:
 
 #if defined(OS_WIN)
@@ -116,6 +125,11 @@
   base::Lock* const user_lock_;  // Needed to adjust shadow lock state on wait.
 #endif
 
+  // Whether a thread invoking Wait() on this ConditionalVariable should be
+  // considered blocked as opposed to idle (and potentially replaced if part of
+  // a pool).
+  bool waiting_is_blocking_ = true;
+
   DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
 };
 
diff --git a/base/synchronization/condition_variable_posix.cc b/base/synchronization/condition_variable_posix.cc
index 0ae72f15..04fa253 100644
--- a/base/synchronization/condition_variable_posix.cc
+++ b/base/synchronization/condition_variable_posix.cc
@@ -8,6 +8,7 @@
 #include <stdint.h>
 #include <sys/time.h>
 
+#include "base/optional.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_restrictions.h"
@@ -63,8 +64,11 @@
 }
 
 void ConditionVariable::Wait() {
-  internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
-      BlockingType::MAY_BLOCK);
+  Optional<internal::ScopedBlockingCallWithBaseSyncPrimitives>
+      scoped_blocking_call;
+  if (waiting_is_blocking_)
+    scoped_blocking_call.emplace(BlockingType::MAY_BLOCK);
+
 #if DCHECK_IS_ON()
   user_lock_->CheckHeldAndUnmark();
 #endif
@@ -76,8 +80,11 @@
 }
 
 void ConditionVariable::TimedWait(const TimeDelta& max_time) {
-  internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
-      BlockingType::MAY_BLOCK);
+  Optional<internal::ScopedBlockingCallWithBaseSyncPrimitives>
+      scoped_blocking_call;
+  if (waiting_is_blocking_)
+    scoped_blocking_call.emplace(BlockingType::MAY_BLOCK);
+
   int64_t usecs = max_time.InMicroseconds();
   struct timespec relative_time;
   relative_time.tv_sec = usecs / Time::kMicrosecondsPerSecond;
diff --git a/base/synchronization/condition_variable_win.cc b/base/synchronization/condition_variable_win.cc
index 00662cd0..0993f17 100644
--- a/base/synchronization/condition_variable_win.cc
+++ b/base/synchronization/condition_variable_win.cc
@@ -4,6 +4,7 @@
 
 #include "base/synchronization/condition_variable.h"
 
+#include "base/optional.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_restrictions.h"
@@ -30,8 +31,11 @@
 }
 
 void ConditionVariable::TimedWait(const TimeDelta& max_time) {
-  internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
-      BlockingType::MAY_BLOCK);
+  Optional<internal::ScopedBlockingCallWithBaseSyncPrimitives>
+      scoped_blocking_call;
+  if (waiting_is_blocking_)
+    scoped_blocking_call.emplace(BlockingType::MAY_BLOCK);
+
   DWORD timeout = static_cast<DWORD>(max_time.InMilliseconds());
 
 #if DCHECK_IS_ON()
diff --git a/base/synchronization/waitable_event.h b/base/synchronization/waitable_event.h
index 836adc0..31a36aa 100644
--- a/base/synchronization/waitable_event.h
+++ b/base/synchronization/waitable_event.h
@@ -113,6 +113,14 @@
   HANDLE handle() const { return handle_.Get(); }
 #endif
 
+  // Declares that this WaitableEvent will only ever be used by a thread that is
+  // idle at the bottom of its stack and waiting for work (in particular, it is
+  // not synchronously waiting on this event before resuming ongoing work). This
+  // is useful to avoid telling base-internals that this thread is "blocked"
+  // when it's merely idle and ready to do work. As such, this is only expected
+  // to be used by thread and thread pool impls.
+  void declare_only_used_while_idle() { waiting_is_blocking_ = false; }
+
   // Wait, synchronously, on multiple events.
   //   waitables: an array of WaitableEvent pointers
   //   count: the number of elements in @waitables
@@ -276,6 +284,10 @@
   scoped_refptr<WaitableEventKernel> kernel_;
 #endif
 
+  // Whether a thread invoking Wait() on this WaitableEvent should be considered
+  // blocked as opposed to idle (and potentially replaced if part of a pool).
+  bool waiting_is_blocking_ = true;
+
   DISALLOW_COPY_AND_ASSIGN(WaitableEvent);
 };
 
diff --git a/base/synchronization/waitable_event_posix.cc b/base/synchronization/waitable_event_posix.cc
index eab8646..bbe1ed4 100644
--- a/base/synchronization/waitable_event_posix.cc
+++ b/base/synchronization/waitable_event_posix.cc
@@ -10,6 +10,7 @@
 
 #include "base/debug/activity_tracker.h"
 #include "base/logging.h"
+#include "base/optional.h"
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
@@ -162,10 +163,13 @@
 }
 
 bool WaitableEvent::TimedWaitUntil(const TimeTicks& end_time) {
-  internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
-      BlockingType::MAY_BLOCK);
+  Optional<internal::ScopedBlockingCallWithBaseSyncPrimitives>
+      scoped_blocking_call;
+  if (waiting_is_blocking_)
+    scoped_blocking_call.emplace(BlockingType::MAY_BLOCK);
+
   // Record the event that this thread is blocking upon (for hang diagnosis).
-  base::debug::ScopedEventWaitActivity event_activity(this);
+  debug::ScopedEventWaitActivity event_activity(this);
 
   const bool finite_time = !end_time.is_max();
 
@@ -241,7 +245,7 @@
   internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
       BlockingType::MAY_BLOCK);
   // Record an event (the first) that this thread is blocking upon.
-  base::debug::ScopedEventWaitActivity event_activity(raw_waitables[0]);
+  debug::ScopedEventWaitActivity event_activity(raw_waitables[0]);
 
   // We need to acquire the locks in a globally consistent order. Thus we sort
   // the array of waitables by address. We actually sort a pairs so that we can
diff --git a/base/synchronization/waitable_event_win.cc b/base/synchronization/waitable_event_win.cc
index 8edc639..abf1e2b 100644
--- a/base/synchronization/waitable_event_win.cc
+++ b/base/synchronization/waitable_event_win.cc
@@ -13,6 +13,7 @@
 #include "base/debug/activity_tracker.h"
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/optional.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
@@ -53,10 +54,16 @@
 }
 
 void WaitableEvent::Wait() {
-  internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
-      BlockingType::MAY_BLOCK);
-  // Record the event that this thread is blocking upon (for hang diagnosis).
-  base::debug::ScopedEventWaitActivity event_activity(this);
+  // Record the event that this thread is blocking upon (for hang diagnosis) and
+  // consider blocked for scheduling purposes. Ignore this for non-blocking
+  // WaitableEvents.
+  Optional<debug::ScopedEventWaitActivity> event_activity;
+  Optional<internal::ScopedBlockingCallWithBaseSyncPrimitives>
+      scoped_blocking_call;
+  if (waiting_is_blocking_) {
+    event_activity.emplace(this);
+    scoped_blocking_call.emplace(BlockingType::MAY_BLOCK);
+  }
 
   DWORD result = WaitForSingleObject(handle_.Get(), INFINITE);
   // It is most unexpected that this should ever fail.  Help consumers learn
@@ -69,9 +76,6 @@
 
 // Helper function called from TimedWait and TimedWaitUntil.
 bool WaitUntil(HANDLE handle, const TimeTicks& now, const TimeTicks& end_time) {
-  internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
-      BlockingType::MAY_BLOCK);
-
   TimeDelta delta = end_time - now;
   DCHECK_GT(delta, TimeDelta());
 
@@ -108,9 +112,16 @@
   if (wait_delta.is_zero())
     return IsSignaled();
 
-  internal::AssertBaseSyncPrimitivesAllowed();
-  // Record the event that this thread is blocking upon (for hang diagnosis).
-  base::debug::ScopedEventWaitActivity event_activity(this);
+  // Record the event that this thread is blocking upon (for hang diagnosis) and
+  // consider blocked for scheduling purposes. Ignore this for non-blocking
+  // WaitableEvents.
+  Optional<debug::ScopedEventWaitActivity> event_activity;
+  Optional<internal::ScopedBlockingCallWithBaseSyncPrimitives>
+      scoped_blocking_call;
+  if (waiting_is_blocking_) {
+    event_activity.emplace(this);
+    scoped_blocking_call.emplace(BlockingType::MAY_BLOCK);
+  }
 
   TimeTicks now(TimeTicks::Now());
   // TimeTicks takes care of overflow including the cases when wait_delta
@@ -122,9 +133,16 @@
   if (end_time.is_null())
     return IsSignaled();
 
-  internal::AssertBaseSyncPrimitivesAllowed();
-  // Record the event that this thread is blocking upon (for hang diagnosis).
-  base::debug::ScopedEventWaitActivity event_activity(this);
+  // Record the event that this thread is blocking upon (for hang diagnosis) and
+  // consider blocked for scheduling purposes. Ignore this for non-blocking
+  // WaitableEvents.
+  Optional<debug::ScopedEventWaitActivity> event_activity;
+  Optional<internal::ScopedBlockingCallWithBaseSyncPrimitives>
+      scoped_blocking_call;
+  if (waiting_is_blocking_) {
+    event_activity.emplace(this);
+    scoped_blocking_call.emplace(BlockingType::MAY_BLOCK);
+  }
 
   TimeTicks now(TimeTicks::Now());
   if (end_time <= now)
@@ -136,11 +154,10 @@
 // static
 size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) {
   DCHECK(count) << "Cannot wait on no events";
-
   internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
       BlockingType::MAY_BLOCK);
   // Record an event (the first) that this thread is blocking upon.
-  base::debug::ScopedEventWaitActivity event_activity(events[0]);
+  debug::ScopedEventWaitActivity event_activity(events[0]);
 
   HANDLE handles[MAXIMUM_WAIT_OBJECTS];
   CHECK_LE(count, static_cast<size_t>(MAXIMUM_WAIT_OBJECTS))
diff --git a/base/task/task_scheduler/scheduler_worker.cc b/base/task/task_scheduler/scheduler_worker.cc
index 0f9cb2d..8f680add 100644
--- a/base/task/task_scheduler/scheduler_worker.cc
+++ b/base/task/task_scheduler/scheduler_worker.cc
@@ -58,6 +58,7 @@
   DCHECK(task_tracker_);
   DCHECK(CanUseBackgroundPriorityForSchedulerWorker() ||
          priority_hint_ != ThreadPriority::BACKGROUND);
+  wake_up_event_.declare_only_used_while_idle();
 }
 
 bool SchedulerWorker::Start(
diff --git a/base/threading/scoped_blocking_call.cc b/base/threading/scoped_blocking_call.cc
index aba32a9..1734cbee 100644
--- a/base/threading/scoped_blocking_call.cc
+++ b/base/threading/scoped_blocking_call.cc
@@ -8,11 +8,24 @@
 #include "base/scoped_clear_last_error.h"
 #include "base/threading/thread_local.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
 
 namespace base {
 
 namespace {
 
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_64)
+// For a mysterious reason, enabling tracing in ScopedBlockingCall makes
+// telemetry_unittests's
+// telemetry.core.tracing_controller_unittest.
+//     StartupTracingTest.testCloseBrowserBeforeTracingIsStopped
+// timeout only on chromeos-amd64-generic-rel : https://crbug.com/902514.
+const bool kTraceScopedBlockingCall = false;
+#else
+const bool kTraceScopedBlockingCall = true;
+#endif
+
 LazyInstance<ThreadLocalPointer<internal::BlockingObserver>>::Leaky
     tls_blocking_observer = LAZY_INSTANCE_INITIALIZER;
 
@@ -20,6 +33,14 @@
 LazyInstance<ThreadLocalPointer<internal::UncheckedScopedBlockingCall>>::Leaky
     tls_last_scoped_blocking_call = LAZY_INSTANCE_INITIALIZER;
 
+#if DCHECK_IS_ON()
+// Used to verify that the trace events used in the constructor do not result in
+// instantiating a ScopedBlockingCall themselves (which would cause an infinite
+// reentrancy loop).
+LazyInstance<ThreadLocalBoolean>::Leaky tls_construction_in_progress =
+    LAZY_INSTANCE_INITIALIZER;
+#endif
+
 }  // namespace
 
 namespace internal {
@@ -57,7 +78,25 @@
 
 ScopedBlockingCall::ScopedBlockingCall(BlockingType blocking_type)
     : UncheckedScopedBlockingCall(blocking_type) {
+#if DCHECK_IS_ON()
+  DCHECK(!tls_construction_in_progress.Get().Get());
+  tls_construction_in_progress.Get().Set(true);
+#endif
+
   internal::AssertBlockingAllowed();
+  if (kTraceScopedBlockingCall) {
+    TRACE_EVENT_BEGIN1("base", "ScopedBlockingCall", "blocking_type",
+                       static_cast<int>(blocking_type));
+  }
+
+#if DCHECK_IS_ON()
+  tls_construction_in_progress.Get().Set(false);
+#endif
+}
+
+ScopedBlockingCall::~ScopedBlockingCall() {
+  if (kTraceScopedBlockingCall)
+    TRACE_EVENT_END0("base", "ScopedBlockingCall");
 }
 
 namespace internal {
@@ -65,7 +104,26 @@
 ScopedBlockingCallWithBaseSyncPrimitives::
     ScopedBlockingCallWithBaseSyncPrimitives(BlockingType blocking_type)
     : UncheckedScopedBlockingCall(blocking_type) {
+#if DCHECK_IS_ON()
+  DCHECK(!tls_construction_in_progress.Get().Get());
+  tls_construction_in_progress.Get().Set(true);
+#endif
+
   internal::AssertBaseSyncPrimitivesAllowed();
+  if (kTraceScopedBlockingCall) {
+    TRACE_EVENT_BEGIN1("base", "ScopedBlockingCallWithBaseSyncPrimitives",
+                       "blocking_type", static_cast<int>(blocking_type));
+  }
+
+#if DCHECK_IS_ON()
+  tls_construction_in_progress.Get().Set(false);
+#endif
+}
+
+ScopedBlockingCallWithBaseSyncPrimitives::
+    ~ScopedBlockingCallWithBaseSyncPrimitives() {
+  if (kTraceScopedBlockingCall)
+    TRACE_EVENT_END0("base", "ScopedBlockingCallWithBaseSyncPrimitives");
 }
 
 void SetBlockingObserverForCurrentThread(BlockingObserver* blocking_observer) {
diff --git a/base/threading/scoped_blocking_call.h b/base/threading/scoped_blocking_call.h
index 516ac0a..b8c08fcf 100644
--- a/base/threading/scoped_blocking_call.h
+++ b/base/threading/scoped_blocking_call.h
@@ -110,7 +110,7 @@
     : public internal::UncheckedScopedBlockingCall {
  public:
   ScopedBlockingCall(BlockingType blocking_type);
-  ~ScopedBlockingCall() = default;
+  ~ScopedBlockingCall();
 };
 
 namespace internal {
@@ -124,7 +124,7 @@
     : public UncheckedScopedBlockingCall {
  public:
   ScopedBlockingCallWithBaseSyncPrimitives(BlockingType blocking_type);
-  ~ScopedBlockingCallWithBaseSyncPrimitives() = default;
+  ~ScopedBlockingCallWithBaseSyncPrimitives();
 };
 
 // Interface for an observer to be informed when a thread enters or exits
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc
index e6d8107..89059da3 100644
--- a/base/trace_event/trace_event_etw_export_win.cc
+++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
@@ -32,6 +33,7 @@
 #include "base/trace_event/etw_manifest/chrome_events_win.h"  // NOLINT
 
 namespace {
+
 // |kFilteredEventGroupNames| contains the event categories that can be
 // exported individually. These categories can be enabled by passing the correct
 // keyword when starting the trace. A keyword is a 64-bit flag and we attribute
@@ -135,12 +137,6 @@
 }
 
 // static
-TraceEventETWExport* TraceEventETWExport::GetInstance() {
-  return Singleton<TraceEventETWExport,
-                   StaticMemorySingletonTraits<TraceEventETWExport>>::get();
-}
-
-// static
 void TraceEventETWExport::EnableETWExport() {
   auto* instance = GetInstance();
   if (instance && !instance->etw_export_enabled_) {
@@ -167,7 +163,7 @@
 
 // static
 bool TraceEventETWExport::IsETWExportEnabled() {
-  auto* instance = GetInstance();
+  auto* instance = GetInstanceIfExists();
   return (instance && instance->etw_export_enabled_);
 }
 
@@ -294,7 +290,7 @@
 bool TraceEventETWExport::IsCategoryGroupEnabled(
     StringPiece category_group_name) {
   DCHECK(!category_group_name.empty());
-  auto* instance = GetInstance();
+  auto* instance = GetInstanceIfExists();
   if (instance == nullptr)
     return false;
 
@@ -377,5 +373,19 @@
   DCHECK(instance);
   instance->UpdateEnabledCategories();
 }
+
+// static
+TraceEventETWExport* TraceEventETWExport::GetInstance() {
+  return Singleton<TraceEventETWExport,
+                   StaticMemorySingletonTraits<TraceEventETWExport>>::get();
+}
+
+// static
+TraceEventETWExport* TraceEventETWExport::GetInstanceIfExists() {
+  return Singleton<
+      TraceEventETWExport,
+      StaticMemorySingletonTraits<TraceEventETWExport>>::GetIfExists();
+}
+
 }  // namespace trace_event
 }  // namespace base
diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h
index 8a85b221..345e87b 100644
--- a/base/trace_event/trace_event_etw_export_win.h
+++ b/base/trace_event/trace_event_etw_export_win.h
@@ -30,6 +30,12 @@
   // Note that this may return NULL post-AtExit processing.
   static TraceEventETWExport* GetInstance();
 
+  // Retrieves the singleton iff it was previously instantiated by a
+  // GetInstance() call. Avoids creating the instance only to check that it
+  // wasn't disabled. Note that, like GetInstance(), this may also return NULL
+  // post-AtExit processing.
+  static TraceEventETWExport* GetInstanceIfExists();
+
   // Enables/disables exporting of events to ETW. If disabled,
   // AddEvent and AddCustomEvent will simply return when called.
   static void EnableETWExport();
@@ -61,6 +67,7 @@
  private:
   // Ensure only the provider can construct us.
   friend struct StaticMemorySingletonTraits<TraceEventETWExport>;
+
   // To have access to UpdateKeyword().
   class ETWKeywordUpdateThread;
   TraceEventETWExport();
diff --git a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
index e4d5e25a..d3652f0d 100644
--- a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
+++ b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -65,8 +65,8 @@
       image_settings->images_to_skip = {};
       image_settings->image_to_current_frame_index = {};
 
-      PlaybackImageProvider image_provider(
-          image_decode_cache, gfx::ColorSpace(), std::move(image_settings));
+      PlaybackImageProvider image_provider(image_decode_cache,
+                                           std::move(image_settings));
       RasterSource::PlaybackSettings settings;
       settings.image_provider = &image_provider;
 
diff --git a/cc/layers/recording_source_unittest.cc b/cc/layers/recording_source_unittest.cc
index 34f3508..dbdcaa1 100644
--- a/cc/layers/recording_source_unittest.cc
+++ b/cc/layers/recording_source_unittest.cc
@@ -16,10 +16,6 @@
 namespace cc {
 namespace {
 
-gfx::ColorSpace DefaultColorSpace() {
-  return gfx::ColorSpace::CreateSRGB();
-}
-
 std::unique_ptr<FakeRecordingSource> CreateRecordingSource(
     const gfx::Rect& viewport) {
   gfx::Rect layer_rect(viewport.right(), viewport.bottom());
@@ -110,8 +106,7 @@
     std::vector<const DrawImage*> images;
     raster_source->GetDiscardableImagesInRect(gfx::Rect(130, 0, 128, 128),
                                               &images);
-    DrawImage image(*images[0], scale, PaintImage::kDefaultFrameIndex,
-                    DefaultColorSpace());
+    DrawImage image(*images[0], scale, PaintImage::kDefaultFrameIndex);
     EXPECT_EQ(1u, images.size());
     EXPECT_FLOAT_EQ(scale, image.scale().width());
     EXPECT_FLOAT_EQ(scale, image.scale().height());
diff --git a/cc/paint/discardable_image_map_unittest.cc b/cc/paint/discardable_image_map_unittest.cc
index 0c88e50..32ec754 100644
--- a/cc/paint/discardable_image_map_unittest.cc
+++ b/cc/paint/discardable_image_map_unittest.cc
@@ -55,14 +55,11 @@
       const DiscardableImageMap& image_map,
       const gfx::Rect& rect) {
     std::vector<const DrawImage*> draw_image_ptrs;
-    // Choose a not-SRGB-and-not-invalid target color space to verify that it
-    // is passed correctly to the resulting DrawImages.
-    gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateXYZD50();
     image_map.GetDiscardableImagesInRect(rect, &draw_image_ptrs);
     std::vector<DrawImage> draw_images;
     for (const auto* image : draw_image_ptrs)
-      draw_images.push_back(DrawImage(
-          *image, 1.f, PaintImage::kDefaultFrameIndex, target_color_space));
+      draw_images.push_back(
+          DrawImage(*image, 1.f, PaintImage::kDefaultFrameIndex));
 
     std::vector<PositionScaleDrawImage> position_draw_images;
     std::vector<DrawImage> results;
@@ -79,7 +76,6 @@
     for (size_t i = 0; i < draw_images.size(); ++i) {
       EXPECT_TRUE(draw_images[i].paint_image() ==
                   position_draw_images[i].image);
-      EXPECT_EQ(draw_images[i].target_color_space(), target_color_space);
     }
     return position_draw_images;
   }
diff --git a/cc/paint/draw_image.cc b/cc/paint/draw_image.cc
index a1a78af..984ccd5c 100644
--- a/cc/paint/draw_image.cc
+++ b/cc/paint/draw_image.cc
@@ -32,28 +32,24 @@
                      const SkIRect& src_rect,
                      SkFilterQuality filter_quality,
                      const SkMatrix& matrix,
-                     base::Optional<size_t> frame_index,
-                     const base::Optional<gfx::ColorSpace>& color_space)
+                     base::Optional<size_t> frame_index)
     : paint_image_(std::move(image)),
       src_rect_(src_rect),
       filter_quality_(filter_quality),
-      frame_index_(frame_index),
-      target_color_space_(color_space) {
+      frame_index_(frame_index) {
   matrix_is_decomposable_ = ExtractScale(matrix, &scale_);
 }
 
 DrawImage::DrawImage(const DrawImage& other,
                      float scale_adjustment,
-                     size_t frame_index,
-                     const gfx::ColorSpace& color_space)
+                     size_t frame_index)
     : paint_image_(other.paint_image_),
       src_rect_(other.src_rect_),
       filter_quality_(other.filter_quality_),
       scale_(SkSize::Make(other.scale_.width() * scale_adjustment,
                           other.scale_.height() * scale_adjustment)),
       matrix_is_decomposable_(other.matrix_is_decomposable_),
-      frame_index_(frame_index),
-      target_color_space_(color_space) {}
+      frame_index_(frame_index) {}
 
 DrawImage::DrawImage(const DrawImage& other) = default;
 DrawImage::DrawImage(DrawImage&& other) = default;
@@ -65,8 +61,7 @@
 bool DrawImage::operator==(const DrawImage& other) const {
   return paint_image_ == other.paint_image_ && src_rect_ == other.src_rect_ &&
          filter_quality_ == other.filter_quality_ && scale_ == other.scale_ &&
-         matrix_is_decomposable_ == other.matrix_is_decomposable_ &&
-         target_color_space_ == other.target_color_space_;
+         matrix_is_decomposable_ == other.matrix_is_decomposable_;
 }
 
 }  // namespace cc
diff --git a/cc/paint/draw_image.h b/cc/paint/draw_image.h
index 4e8fe7f..615b25e 100644
--- a/cc/paint/draw_image.h
+++ b/cc/paint/draw_image.h
@@ -13,13 +13,12 @@
 #include "third_party/skia/include/core/SkMatrix.h"
 #include "third_party/skia/include/core/SkRect.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
-#include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/size_f.h"
 
 namespace cc {
 
 // A DrawImage is a logical snapshot in time and space of a PaintImage.  It
-// includes decisions about scaling, animation frame, final colorspace, etc.
+// includes decisions about scaling, animation frame, etc.
 // It has not been decoded yet.  DrawImage turns into DecodedDrawImage via
 // ImageDecodeCache::GetDecodedImageForDraw during playback.
 class CC_PAINT_EXPORT DrawImage {
@@ -29,14 +28,9 @@
             const SkIRect& src_rect,
             SkFilterQuality filter_quality,
             const SkMatrix& matrix,
-            base::Optional<size_t> frame_index = base::nullopt,
-            const base::Optional<gfx::ColorSpace>& color_space = base::nullopt);
-  // Constructs a DrawImage from |other| by adjusting its scale and setting a
-  // new color_space.
-  DrawImage(const DrawImage& other,
-            float scale_adjustment,
-            size_t frame_index,
-            const gfx::ColorSpace& color_space);
+            base::Optional<size_t> frame_index = base::nullopt);
+  // Constructs a DrawImage from |other| by adjusting its scale and frame.
+  DrawImage(const DrawImage& other, float scale_adjustment, size_t frame_index);
   DrawImage(const DrawImage& other);
   DrawImage(DrawImage&& other);
   ~DrawImage();
@@ -51,10 +45,6 @@
   const SkIRect& src_rect() const { return src_rect_; }
   SkFilterQuality filter_quality() const { return filter_quality_; }
   bool matrix_is_decomposable() const { return matrix_is_decomposable_; }
-  const gfx::ColorSpace& target_color_space() const {
-    DCHECK(target_color_space_.has_value());
-    return *target_color_space_;
-  }
   PaintImage::FrameKey frame_key() const {
     return paint_image_.GetKeyForFrame(frame_index());
   }
@@ -70,7 +60,6 @@
   SkSize scale_;
   bool matrix_is_decomposable_;
   base::Optional<size_t> frame_index_;
-  base::Optional<gfx::ColorSpace> target_color_space_;
 };
 
 }  // namespace cc
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc
index 96b02540..cce9065 100644
--- a/cc/paint/oop_pixeltest.cc
+++ b/cc/paint/oop_pixeltest.cc
@@ -76,22 +76,11 @@
 
   void SetUp() override {
     InitializeOOPContext();
-    const int raster_max_texture_size =
-        raster_context_provider_->ContextCapabilities().max_texture_size;
-
     gles2_context_provider_ =
         base::MakeRefCounted<TestInProcessContextProvider>(
             /*enable_oop_rasterization=*/false, /*support_locking=*/true);
     gpu::ContextResult result = gles2_context_provider_->BindToCurrentThread();
     DCHECK_EQ(result, gpu::ContextResult::kSuccess);
-    const int gles2_max_texture_size =
-        raster_context_provider_->ContextCapabilities().max_texture_size;
-    gpu_image_cache_.reset(new GpuImageDecodeCache(
-        gles2_context_provider_.get(), false, kRGBA_8888_SkColorType,
-        kWorkingSetSize, gles2_max_texture_size,
-        PaintImage::kDefaultGeneratorClientId));
-
-    ASSERT_EQ(raster_max_texture_size, gles2_max_texture_size);
   }
 
   // gpu::raster::GrShaderCache::Client implementation.
@@ -108,12 +97,24 @@
             &gr_shader_cache_, &activity_flags_);
     gpu::ContextResult result = raster_context_provider_->BindToCurrentThread();
     DCHECK_EQ(result, gpu::ContextResult::kSuccess);
+  }
+
+  void CreateGpuImageCache(const gfx::ColorSpace& color_space) {
+    const int gles2_max_texture_size =
+        raster_context_provider_->ContextCapabilities().max_texture_size;
+    gpu_image_cache_.reset(new GpuImageDecodeCache(
+        gles2_context_provider_.get(), false, kRGBA_8888_SkColorType,
+        kWorkingSetSize, gles2_max_texture_size,
+        PaintImage::kDefaultGeneratorClientId, color_space.ToSkColorSpace()));
+  }
+
+  void CreateOopImageCache(const gfx::ColorSpace& color_space) {
     const int raster_max_texture_size =
         raster_context_provider_->ContextCapabilities().max_texture_size;
     oop_image_cache_.reset(new GpuImageDecodeCache(
         raster_context_provider_.get(), true, kRGBA_8888_SkColorType,
         kWorkingSetSize, raster_max_texture_size,
-        PaintImage::kDefaultGeneratorClientId));
+        PaintImage::kDefaultGeneratorClientId, color_space.ToSkColorSpace()));
   }
 
   class RasterOptions {
@@ -153,12 +154,13 @@
 
   SkBitmap Raster(scoped_refptr<DisplayItemList> display_item_list,
                   const RasterOptions& options) {
+    CreateOopImageCache(options.color_space);
+
     GURL url("https://example.com/foo");
     TestInProcessContextProvider::ScopedRasterContextLock lock(
         raster_context_provider_.get(), url.possibly_invalid_spec().c_str());
 
     PlaybackImageProvider image_provider(oop_image_cache_.get(),
-                                         options.color_space,
                                          PlaybackImageProvider::Settings());
 
     gpu::gles2::GLES2Interface* gl = gles2_context_provider_->ContextGL();
@@ -258,6 +260,8 @@
   SkBitmap RasterExpectedBitmap(
       scoped_refptr<DisplayItemList> display_item_list,
       const RasterOptions& options) {
+    CreateGpuImageCache(options.color_space);
+
     TestInProcessContextProvider::ScopedRasterContextLock lock(
         gles2_context_provider_.get());
     gles2_context_provider_->GrContext()->resetContext();
@@ -279,7 +283,6 @@
       options.shader_with_animated_images->set_has_animated_images(true);
 
     PlaybackImageProvider image_provider(gpu_image_cache_.get(),
-                                         options.color_space,
                                          PlaybackImageProvider::Settings());
 
     auto raster_source = recording.CreateRasterSource();
diff --git a/cc/raster/playback_image_provider.cc b/cc/raster/playback_image_provider.cc
index 50305d1..7aef7601 100644
--- a/cc/raster/playback_image_provider.cc
+++ b/cc/raster/playback_image_provider.cc
@@ -18,10 +18,8 @@
 
 PlaybackImageProvider::PlaybackImageProvider(
     ImageDecodeCache* cache,
-    const gfx::ColorSpace& target_color_space,
     base::Optional<Settings>&& settings)
     : cache_(cache),
-      target_color_space_(target_color_space),
       settings_(std::move(settings)) {
   DCHECK(cache_);
 }
@@ -53,7 +51,7 @@
                            ? PaintImage::kDefaultFrameIndex
                            : it->second;
 
-  DrawImage adjusted_image(draw_image, 1.f, frame_index, target_color_space_);
+  DrawImage adjusted_image(draw_image, 1.f, frame_index);
   if (!cache_->UseCacheForDrawImage(adjusted_image)) {
     return ScopedDecodedDrawImage(DecodedDrawImage(
         paint_image.GetSkImage(), SkSize::Make(0, 0), SkSize::Make(1.f, 1.f),
diff --git a/cc/raster/playback_image_provider.h b/cc/raster/playback_image_provider.h
index a33092d..990835c0 100644
--- a/cc/raster/playback_image_provider.h
+++ b/cc/raster/playback_image_provider.h
@@ -35,7 +35,6 @@
 
   // If no settings are provided, all images are skipped during rasterization.
   PlaybackImageProvider(ImageDecodeCache* cache,
-                        const gfx::ColorSpace& target_color_space,
                         base::Optional<Settings>&& settings);
   ~PlaybackImageProvider() override;
 
@@ -48,7 +47,6 @@
 
  private:
   ImageDecodeCache* cache_;
-  gfx::ColorSpace target_color_space_;
   base::Optional<Settings> settings_;
 
   DISALLOW_COPY_AND_ASSIGN(PlaybackImageProvider);
diff --git a/cc/raster/playback_image_provider_unittest.cc b/cc/raster/playback_image_provider_unittest.cc
index dd4f6a4..dbc5ba0c 100644
--- a/cc/raster/playback_image_provider_unittest.cc
+++ b/cc/raster/playback_image_provider_unittest.cc
@@ -66,7 +66,7 @@
 
 TEST(PlaybackImageProviderTest, SkipsAllImages) {
   MockDecodeCache cache;
-  PlaybackImageProvider provider(&cache, gfx::ColorSpace(), base::nullopt);
+  PlaybackImageProvider provider(&cache, base::nullopt);
 
   SkIRect rect = SkIRect::MakeWH(10, 10);
   SkMatrix matrix = SkMatrix::I();
@@ -93,8 +93,7 @@
   settings.emplace();
   settings->images_to_skip = {skip_image.stable_id()};
 
-  PlaybackImageProvider provider(&cache, gfx::ColorSpace(),
-                                 std::move(settings));
+  PlaybackImageProvider provider(&cache, std::move(settings));
 
   SkIRect rect = SkIRect::MakeWH(10, 10);
   SkMatrix matrix = SkMatrix::I();
@@ -108,8 +107,7 @@
 
   base::Optional<PlaybackImageProvider::Settings> settings;
   settings.emplace();
-  PlaybackImageProvider provider(&cache, gfx::ColorSpace(),
-                                 std::move(settings));
+  PlaybackImageProvider provider(&cache, std::move(settings));
 
   {
     SkRect rect = SkRect::MakeWH(10, 10);
@@ -137,8 +135,7 @@
   settings.emplace();
   settings->image_to_current_frame_index = image_to_frame;
 
-  PlaybackImageProvider provider(&cache, gfx::ColorSpace(),
-                                 std::move(settings));
+  PlaybackImageProvider provider(&cache, std::move(settings));
 
   SkIRect rect = SkIRect::MakeWH(10, 10);
   SkMatrix matrix = SkMatrix::I();
@@ -154,8 +151,7 @@
 
   base::Optional<PlaybackImageProvider::Settings> settings;
   settings.emplace();
-  PlaybackImageProvider provider(&cache, gfx::ColorSpace(),
-                                 std::move(settings));
+  PlaybackImageProvider provider(&cache, std::move(settings));
 
   {
     SkIRect rect = SkIRect::MakeWH(10, 10);
@@ -176,8 +172,7 @@
   cache.set_use_cache_for_draw_image(false);
   base::Optional<PlaybackImageProvider::Settings> settings;
   settings.emplace();
-  PlaybackImageProvider provider(&cache, gfx::ColorSpace(),
-                                 std::move(settings));
+  PlaybackImageProvider provider(&cache, std::move(settings));
   {
     SkIRect rect = SkIRect::MakeWH(10, 10);
     SkMatrix matrix = SkMatrix::I();
diff --git a/cc/raster/raster_source_unittest.cc b/cc/raster/raster_source_unittest.cc
index 311cb5ee..b910052 100644
--- a/cc/raster/raster_source_unittest.cc
+++ b/cc/raster/raster_source_unittest.cc
@@ -211,25 +211,19 @@
 
   // Tile sized iterators. These should find only one pixel ref.
   {
-    gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
     std::vector<const DrawImage*> images;
     raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), &images);
     EXPECT_EQ(1u, images.size());
-    DrawImage image(*images[0], 1.f, PaintImage::kDefaultFrameIndex,
-                    target_color_space);
+    DrawImage image(*images[0], 1.f, PaintImage::kDefaultFrameIndex);
     EXPECT_EQ(discardable_image[0][0], images[0]->paint_image());
-    EXPECT_EQ(target_color_space, image.target_color_space());
   }
   // Shifted tile sized iterators. These should find only one pixel ref.
   {
-    gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateXYZD50();
     std::vector<const DrawImage*> images;
     raster->GetDiscardableImagesInRect(gfx::Rect(260, 260, 256, 256), &images);
     EXPECT_EQ(1u, images.size());
-    DrawImage image(*images[0], 1.f, PaintImage::kDefaultFrameIndex,
-                    target_color_space);
+    DrawImage image(*images[0], 1.f, PaintImage::kDefaultFrameIndex);
     EXPECT_EQ(discardable_image[1][1], images[0]->paint_image());
-    EXPECT_EQ(target_color_space, image.target_color_space());
   }
   // Ensure there's no discardable pixel refs in the empty cell
   {
diff --git a/cc/raster/single_thread_task_graph_runner.cc b/cc/raster/single_thread_task_graph_runner.cc
index e17ec83..c852155 100644
--- a/cc/raster/single_thread_task_graph_runner.cc
+++ b/cc/raster/single_thread_task_graph_runner.cc
@@ -18,7 +18,9 @@
     : lock_(),
       has_ready_to_run_tasks_cv_(&lock_),
       has_namespaces_with_finished_running_tasks_cv_(&lock_),
-      shutdown_(false) {}
+      shutdown_(false) {
+  has_ready_to_run_tasks_cv_.declare_only_used_while_idle();
+}
 
 SingleThreadTaskGraphRunner::~SingleThreadTaskGraphRunner() = default;
 
diff --git a/cc/test/fake_tile_manager.cc b/cc/test/fake_tile_manager.cc
index 9532c7f..c82d7bcc 100644
--- a/cc/test/fake_tile_manager.cc
+++ b/cc/test/fake_tile_manager.cc
@@ -43,7 +43,8 @@
       image_decode_cache_(
           kN32_SkColorType,
           LayerTreeSettings().decoded_image_working_set_budget_bytes,
-          PaintImage::kDefaultGeneratorClientId) {
+          PaintImage::kDefaultGeneratorClientId,
+          nullptr) {
   SetResources(resource_pool, &image_decode_cache_, GetGlobalTaskGraphRunner(),
                GetGlobalRasterBufferProvider(),
                false /* use_gpu_rasterization */);
diff --git a/cc/tiles/checker_image_tracker.cc b/cc/tiles/checker_image_tracker.cc
index 33385af..ce854bc7 100644
--- a/cc/tiles/checker_image_tracker.cc
+++ b/cc/tiles/checker_image_tracker.cc
@@ -387,7 +387,6 @@
       std::max(decode_state->scale.fHeight, draw_image.scale().fHeight));
   decode_state->filter_quality =
       std::max(decode_state->filter_quality, draw_image.filter_quality());
-  decode_state->color_space = draw_image.target_color_space();
   decode_state->frame_index = draw_image.frame_index();
 }
 
@@ -427,7 +426,7 @@
         it->second.filter_quality,
         SkMatrix::MakeScale(it->second.scale.width(),
                             it->second.scale.height()),
-        it->second.frame_index, it->second.color_space);
+        it->second.frame_index);
     outstanding_image_decode_.emplace(candidate);
     break;
   }
diff --git a/cc/tiles/checker_image_tracker.h b/cc/tiles/checker_image_tracker.h
index a8f850e..1a8229fe 100644
--- a/cc/tiles/checker_image_tracker.h
+++ b/cc/tiles/checker_image_tracker.h
@@ -136,7 +136,6 @@
     DecodePolicy policy = DecodePolicy::SYNC;
     SkFilterQuality filter_quality = kNone_SkFilterQuality;
     SkSize scale = SkSize::MakeEmpty();
-    gfx::ColorSpace color_space;
     size_t frame_index = PaintImage::kDefaultFrameIndex;
   };
 
diff --git a/cc/tiles/checker_image_tracker_unittest.cc b/cc/tiles/checker_image_tracker_unittest.cc
index 88c3f10c..c375a59 100644
--- a/cc/tiles/checker_image_tracker_unittest.cc
+++ b/cc/tiles/checker_image_tracker_unittest.cc
@@ -125,7 +125,7 @@
                          .TakePaintImage(),
                      SkIRect::MakeWH(dimension, dimension),
                      kNone_SkFilterQuality, SkMatrix::I(),
-                     PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
+                     PaintImage::kDefaultFrameIndex);
   }
 
   bool ShouldCheckerImage(const DrawImage& draw_image, WhichTree tree) {
@@ -433,8 +433,7 @@
           .set_paint_image_generator(CreatePaintImageGenerator(image_size))
           .TakePaintImage(),
       SkIRect::MakeWH(image_size.width(), image_size.height()),
-      kNone_SkFilterQuality, SkMatrix::I(), PaintImage::kDefaultFrameIndex,
-      gfx::ColorSpace());
+      kNone_SkFilterQuality, SkMatrix::I(), PaintImage::kDefaultFrameIndex);
   EXPECT_FALSE(
       ShouldCheckerImage(completed_paint_image, WhichTree::PENDING_TREE));
 }
@@ -461,12 +460,10 @@
   SetUpTracker(true);
 
   DrawImage image = CreateImage(ImageType::CHECKERABLE);
-  DrawImage scaled_image1(image, 0.5f, PaintImage::kDefaultFrameIndex,
-                          gfx::ColorSpace());
+  DrawImage scaled_image1(image, 0.5f, PaintImage::kDefaultFrameIndex);
   DrawImage scaled_image2 =
       DrawImage(image.paint_image(), image.src_rect(), kHigh_SkFilterQuality,
-                SkMatrix::MakeScale(1.8f), PaintImage::kDefaultFrameIndex,
-                gfx::ColorSpace());
+                SkMatrix::MakeScale(1.8f), PaintImage::kDefaultFrameIndex);
 
   std::vector<DrawImage> draw_images = {scaled_image1, scaled_image2};
   CheckerImageTracker::ImageDecodeQueue image_decode_queue =
@@ -541,7 +538,7 @@
   DrawImage image = CreateImage(ImageType::CHECKERABLE);
   image = DrawImage(image.paint_image(), SkIRect::MakeWH(200, 200),
                     image.filter_quality(), SkMatrix::I(),
-                    PaintImage::kDefaultFrameIndex, image.target_color_space());
+                    PaintImage::kDefaultFrameIndex);
   EXPECT_FALSE(ShouldCheckerImage(image, WhichTree::PENDING_TREE));
 }
 
diff --git a/cc/tiles/decoded_image_tracker.cc b/cc/tiles/decoded_image_tracker.cc
index 9f717c9..ad1b297c 100644
--- a/cc/tiles/decoded_image_tracker.cc
+++ b/cc/tiles/decoded_image_tracker.cc
@@ -38,7 +38,6 @@
 
 void DecodedImageTracker::QueueImageDecode(
     const PaintImage& image,
-    const gfx::ColorSpace& target_color_space,
     const base::Callback<void(bool)>& callback) {
   size_t frame_index = PaintImage::kDefaultFrameIndex;
   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
@@ -49,7 +48,7 @@
   // our own.
   auto image_bounds = SkIRect::MakeWH(image.width(), image.height());
   DrawImage draw_image(image, image_bounds, kNone_SkFilterQuality,
-                       SkMatrix::I(), frame_index, target_color_space);
+                       SkMatrix::I(), frame_index);
   image_controller_->QueueImageDecode(
       draw_image,
       base::Bind(&DecodedImageTracker::ImageDecodeFinished,
diff --git a/cc/tiles/decoded_image_tracker.h b/cc/tiles/decoded_image_tracker.h
index 36f6dc3..e16b614e 100644
--- a/cc/tiles/decoded_image_tracker.h
+++ b/cc/tiles/decoded_image_tracker.h
@@ -34,7 +34,6 @@
   // completion. The callback takes a bool indicating whether the decode was
   // successful or not.
   void QueueImageDecode(const PaintImage& image,
-                        const gfx::ColorSpace& target_color_space,
                         const base::Callback<void(bool)>& callback);
 
   // Unlock all locked images - used to respond to memory pressure or
diff --git a/cc/tiles/decoded_image_tracker_unittest.cc b/cc/tiles/decoded_image_tracker_unittest.cc
index a31f5a2..4049261 100644
--- a/cc/tiles/decoded_image_tracker_unittest.cc
+++ b/cc/tiles/decoded_image_tracker_unittest.cc
@@ -86,44 +86,18 @@
 TEST_F(DecodedImageTrackerTest, QueueImageLocksImages) {
   bool locked = false;
   decoded_image_tracker()->QueueImageDecode(
-      CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(),
+      CreateDiscardablePaintImage(gfx::Size(1, 1)),
       base::Bind([](bool* locked, bool success) { *locked = true; },
                  base::Unretained(&locked)));
   EXPECT_TRUE(locked);
   EXPECT_EQ(1u, image_controller()->num_locked_images());
 }
 
-TEST_F(DecodedImageTrackerTest, Colorspace) {
-  bool locked = false;
-  gfx::ColorSpace decoded_color_space(
-      gfx::ColorSpace::PrimaryID::XYZ_D50,
-      gfx::ColorSpace::TransferID::IEC61966_2_1);
-  gfx::ColorSpace srgb_color_space = gfx::ColorSpace::CreateSRGB();
-  auto paint_image = CreateDiscardablePaintImage(gfx::Size(1, 1));
-  decoded_image_tracker()->QueueImageDecode(
-      paint_image, decoded_color_space,
-      base::Bind([](bool* locked, bool success) { *locked = true; },
-                 base::Unretained(&locked)));
-
-  // Check that the decoded color space images are locked, but if the color
-  // space differs then that image is not locked. Note that we use the high
-  // filter quality here, since it shouldn't matter and the checks should
-  // succeed anyway.
-  DrawImage locked_draw_image(
-      paint_image, SkIRect::MakeWH(1, 1), kHigh_SkFilterQuality, SkMatrix::I(),
-      PaintImage::kDefaultFrameIndex, decoded_color_space);
-  EXPECT_TRUE(image_controller()->IsDrawImageLocked(locked_draw_image));
-  DrawImage srgb_draw_image(paint_image, SkIRect::MakeWH(1, 1),
-                            kHigh_SkFilterQuality, SkMatrix::I(),
-                            PaintImage::kDefaultFrameIndex, srgb_color_space);
-  EXPECT_FALSE(image_controller()->IsDrawImageLocked(srgb_draw_image));
-}
-
 TEST_F(DecodedImageTrackerTest, ImagesTimeOut) {
   // Add an image, this will start a 250ms timeout to release it.
   bool locked = false;
   decoded_image_tracker()->QueueImageDecode(
-      CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(),
+      CreateDiscardablePaintImage(gfx::Size(1, 1)),
       base::Bind([](bool* locked, bool success) { *locked = true; },
                  base::Unretained(&locked)));
   EXPECT_TRUE(locked);
@@ -135,7 +109,7 @@
 
   // Add an image, this will not start a new timeout, as one is pending.
   decoded_image_tracker()->QueueImageDecode(
-      CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(),
+      CreateDiscardablePaintImage(gfx::Size(1, 1)),
       base::Bind([](bool* locked, bool success) { *locked = true; },
                  base::Unretained(&locked)));
   EXPECT_TRUE(locked);
@@ -156,7 +130,7 @@
   bool locked = false;
   auto paint_image_1 = CreateDiscardablePaintImage(gfx::Size(1, 1));
   decoded_image_tracker()->QueueImageDecode(
-      paint_image_1, gfx::ColorSpace(),
+      paint_image_1,
       base::Bind([](bool* locked, bool success) { *locked = true; },
                  base::Unretained(&locked)));
   EXPECT_TRUE(locked);
@@ -164,7 +138,7 @@
 
   auto paint_image_2 = CreateDiscardablePaintImage(gfx::Size(1, 1));
   decoded_image_tracker()->QueueImageDecode(
-      paint_image_2, gfx::ColorSpace(),
+      paint_image_2,
       base::Bind([](bool* locked, bool success) { *locked = true; },
                  base::Unretained(&locked)));
   EXPECT_TRUE(locked);
@@ -172,11 +146,9 @@
 
   // Create dummy draw images for each:
   DrawImage draw_image_1(paint_image_1, SkIRect::MakeWH(1, 1),
-                         kHigh_SkFilterQuality, SkMatrix::I(), 0,
-                         gfx::ColorSpace());
+                         kHigh_SkFilterQuality, SkMatrix::I(), 0);
   DrawImage draw_image_2(paint_image_2, SkIRect::MakeWH(1, 1),
-                         kHigh_SkFilterQuality, SkMatrix::I(), 0,
-                         gfx::ColorSpace());
+                         kHigh_SkFilterQuality, SkMatrix::I(), 0);
 
   // Both should be in the cache:
   EXPECT_TRUE(image_controller()->IsDrawImageLocked(draw_image_1));
@@ -194,13 +166,13 @@
   // Insert two images:
   bool locked = false;
   decoded_image_tracker()->QueueImageDecode(
-      CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(),
+      CreateDiscardablePaintImage(gfx::Size(1, 1)),
       base::Bind([](bool* locked, bool success) { *locked = true; },
                  base::Unretained(&locked)));
   EXPECT_TRUE(locked);
   EXPECT_EQ(1u, image_controller()->num_locked_images());
   decoded_image_tracker()->QueueImageDecode(
-      CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(),
+      CreateDiscardablePaintImage(gfx::Size(1, 1)),
       base::Bind([](bool* locked, bool success) { *locked = true; },
                  base::Unretained(&locked)));
   EXPECT_TRUE(locked);
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
index 4bcab88e..6e3ae2b 100644
--- a/cc/tiles/gpu_image_decode_cache.cc
+++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -320,24 +320,20 @@
 GpuImageDecodeCache::InUseCacheKey::InUseCacheKey(const DrawImage& draw_image)
     : frame_key(draw_image.frame_key()),
       upload_scale_mip_level(CalculateUploadScaleMipLevel(draw_image)),
-      filter_quality(CalculateDesiredFilterQuality(draw_image)),
-      target_color_space(draw_image.target_color_space()) {}
+      filter_quality(CalculateDesiredFilterQuality(draw_image)) {}
 
 bool GpuImageDecodeCache::InUseCacheKey::operator==(
     const InUseCacheKey& other) const {
   return frame_key == other.frame_key &&
          upload_scale_mip_level == other.upload_scale_mip_level &&
-         filter_quality == other.filter_quality &&
-         target_color_space == other.target_color_space;
+         filter_quality == other.filter_quality;
 }
 
 size_t GpuImageDecodeCache::InUseCacheKeyHash::operator()(
     const InUseCacheKey& cache_key) const {
-  return base::HashInts(
-      cache_key.target_color_space.GetHash(),
-      base::HashInts(cache_key.frame_key.hash(),
-                     base::HashInts(cache_key.upload_scale_mip_level,
-                                    cache_key.filter_quality)));
+  return base::HashInts(cache_key.frame_key.hash(),
+                        base::HashInts(cache_key.upload_scale_mip_level,
+                                       cache_key.filter_quality));
 }
 
 GpuImageDecodeCache::InUseCacheEntry::InUseCacheEntry(
@@ -598,7 +594,6 @@
     PaintImage::Id paint_image_id,
     DecodedDataMode mode,
     size_t size,
-    const gfx::ColorSpace& target_color_space,
     SkFilterQuality quality,
     int upload_scale_mip_level,
     bool needs_mips,
@@ -606,7 +601,6 @@
     : paint_image_id(paint_image_id),
       mode(mode),
       size(size),
-      target_color_space(target_color_space),
       quality(quality),
       upload_scale_mip_level(upload_scale_mip_level),
       needs_mips(needs_mips),
@@ -668,7 +662,8 @@
     SkColorType color_type,
     size_t max_working_set_bytes,
     int max_texture_size,
-    PaintImage::GeneratorClientId generator_client_id)
+    PaintImage::GeneratorClientId generator_client_id,
+    sk_sp<SkColorSpace> target_color_space)
     : color_type_(color_type),
       use_transfer_cache_(use_transfer_cache),
       context_(context),
@@ -676,7 +671,8 @@
       generator_client_id_(generator_client_id),
       persistent_cache_(PersistentCache::NO_AUTO_EVICT),
       max_working_set_bytes_(max_working_set_bytes),
-      max_working_set_items_(kMaxItemsInWorkingSet) {
+      max_working_set_items_(kMaxItemsInWorkingSet),
+      target_color_space_(std::move(target_color_space)) {
   // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
   // Don't register a dump provider in these cases.
   if (base::ThreadTaskRunnerHandle::IsSet()) {
@@ -1531,15 +1527,12 @@
   DCHECK_GT(image_data->decode.ref_count, 0u);
   DCHECK_GT(image_data->upload.ref_count, 0u);
 
-  sk_sp<SkColorSpace> target_color_space =
-      SupportsColorSpaceConversion() &&
-              draw_image.target_color_space().IsValid()
-          ? draw_image.target_color_space().ToSkColorSpace()
-          : nullptr;
-  if (target_color_space &&
-      SkColorSpace::Equals(target_color_space.get(),
+  sk_sp<SkColorSpace> color_space =
+      SupportsColorSpaceConversion() ? target_color_space_ : nullptr;
+  if (color_space &&
+      SkColorSpace::Equals(color_space.get(),
                            image_data->decode.image()->colorSpace())) {
-    target_color_space = nullptr;
+    color_space = nullptr;
   }
 
   if (image_data->mode == DecodedDataMode::kTransferCache) {
@@ -1548,7 +1541,7 @@
     if (!image_data->decode.image()->peekPixels(&pixmap))
       return;
 
-    ClientImageTransferCacheEntry image_entry(&pixmap, target_color_space.get(),
+    ClientImageTransferCacheEntry image_entry(&pixmap, color_space.get(),
                                               image_data->needs_mips);
     size_t size = image_entry.SerializedSize();
     void* data = context_->ContextSupport()->MapTransferCacheEntry(size);
@@ -1583,7 +1576,7 @@
     DCHECK(!use_transfer_cache_);
     base::AutoUnlock unlock(lock_);
     uploaded_image = MakeTextureImage(
-        context_, std::move(uploaded_image), target_color_space,
+        context_, std::move(uploaded_image), color_space,
         image_data->needs_mips ? GrMipMapped::kYes : GrMipMapped::kNo);
   }
 
@@ -1662,7 +1655,6 @@
                                 !cache_color_conversion_on_cpu;
   return base::WrapRefCounted(
       new ImageData(draw_image.paint_image().stable_id(), mode, data_size,
-                    draw_image.target_color_space(),
                     CalculateDesiredFilterQuality(draw_image),
                     upload_scale_mip_level, needs_mips, is_bitmap_backed));
 }
@@ -1889,10 +1881,6 @@
                              image_data->upload_scale_mip_level;
   bool quality_is_compatible =
       CalculateDesiredFilterQuality(draw_image) <= image_data->quality;
-  bool color_is_compatible =
-      image_data->target_color_space == draw_image.target_color_space();
-  if (!color_is_compatible)
-    return false;
   if (is_scaled && (!scale_is_compatible || !quality_is_compatible))
     return false;
   return true;
@@ -1975,7 +1963,7 @@
     return nullptr;
 
   if (mode == DecodedDataMode::kCpu)
-    return image.target_color_space().ToSkColorSpace();
+    return target_color_space_;
 
   // For kGpu or kTransferCache images color conversion is handled during
   // upload, so keep the original colorspace here.
diff --git a/cc/tiles/gpu_image_decode_cache.h b/cc/tiles/gpu_image_decode_cache.h
index dd21622..a167341 100644
--- a/cc/tiles/gpu_image_decode_cache.h
+++ b/cc/tiles/gpu_image_decode_cache.h
@@ -106,7 +106,8 @@
                                SkColorType color_type,
                                size_t max_working_set_bytes,
                                int max_texture_size,
-                               PaintImage::GeneratorClientId client_id);
+                               PaintImage::GeneratorClientId client_id,
+                               sk_sp<SkColorSpace> target_color_space);
   ~GpuImageDecodeCache() override;
 
   // Returns the GL texture ID backing the given SkImage.
@@ -307,7 +308,6 @@
     ImageData(PaintImage::Id paint_image_id,
               DecodedDataMode mode,
               size_t size,
-              const gfx::ColorSpace& target_color_space,
               SkFilterQuality quality,
               int upload_scale_mip_level,
               bool needs_mips,
@@ -320,7 +320,6 @@
     const PaintImage::Id paint_image_id;
     const DecodedDataMode mode;
     const size_t size;
-    gfx::ColorSpace target_color_space;
     SkFilterQuality quality;
     int upload_scale_mip_level;
     bool needs_mips = false;
@@ -365,7 +364,6 @@
     PaintImage::FrameKey frame_key;
     int upload_scale_mip_level;
     SkFilterQuality filter_quality;
-    gfx::ColorSpace target_color_space;
   };
   struct InUseCacheKeyHash {
     size_t operator()(const InUseCacheKey&) const;
@@ -512,6 +510,7 @@
   std::vector<SkImage*> images_pending_complete_lock_;
   std::vector<SkImage*> images_pending_unlock_;
   std::vector<sk_sp<SkImage>> images_pending_deletion_;
+  const sk_sp<SkColorSpace> target_color_space_;
 
   std::vector<uint32_t> ids_pending_unlock_;
   std::vector<uint32_t> ids_pending_deletion_;
diff --git a/cc/tiles/gpu_image_decode_cache_perftest.cc b/cc/tiles/gpu_image_decode_cache_perftest.cc
index 85a7f16..11e0e09 100644
--- a/cc/tiles/gpu_image_decode_cache_perftest.cc
+++ b/cc/tiles/gpu_image_decode_cache_perftest.cc
@@ -47,19 +47,20 @@
                kTimeCheckInterval),
         context_provider_(base::MakeRefCounted<TestInProcessContextProvider>(
             UseTransferCache(),
-            false /* support_locking */)),
-        cache_(context_provider_.get(),
-               UseTransferCache(),
-               kRGBA_8888_SkColorType,
-               kCacheSize,
-               MaxTextureSize(),
-               PaintImage::kDefaultGeneratorClientId) {
+            false /* support_locking */)) {
     // Initializing context here is ok because image decode cache does not use
     // context provider in its constructor.
     gpu::ContextResult result = context_provider_->BindToCurrentThread();
     DCHECK_EQ(result, gpu::ContextResult::kSuccess);
   }
 
+  void CreateCache(sk_sp<SkColorSpace> color_space = nullptr) {
+    cache_ = std::make_unique<GpuImageDecodeCache>(
+        context_provider_.get(), UseTransferCache(), kRGBA_8888_SkColorType,
+        kCacheSize, MaxTextureSize(), PaintImage::kDefaultGeneratorClientId,
+        std::move(color_space));
+  }
+
  protected:
   size_t MaxTextureSize() const {
     switch (GetParam()) {
@@ -88,7 +89,7 @@
 
   LapTimer timer_;
   scoped_refptr<TestInProcessContextProvider> context_provider_;
-  GpuImageDecodeCache cache_;
+  std::unique_ptr<GpuImageDecodeCache> cache_;
 };
 
 INSTANTIATE_TEST_CASE_P(P,
@@ -98,6 +99,7 @@
                                         TestMode::kSw));
 
 TEST_P(GpuImageDecodeCachePerfTest, DecodeWithColorConversion) {
+  CreateCache(gfx::ColorSpace::CreateXYZD50().ToSkColorSpace());
   timer_.Reset();
   do {
     DrawImage image(
@@ -106,11 +108,10 @@
             .set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
             .TakePaintImage(),
         SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
-        CreateMatrix(SkSize::Make(1.0f, 1.0f)), 0u,
-        gfx::ColorSpace::CreateXYZD50());
+        CreateMatrix(SkSize::Make(1.0f, 1.0f)), 0u);
 
-    DecodedDrawImage decoded_image = cache_.GetDecodedImageForDraw(image);
-    cache_.DrawWithImageFinished(image, decoded_image);
+    DecodedDrawImage decoded_image = cache_->GetDecodedImageForDraw(image);
+    cache_->DrawWithImageFinished(image, decoded_image);
     timer_.NextLap();
   } while (!timer_.HasTimeLimitExpired());
 
@@ -131,6 +132,7 @@
       context_provider_->GrContext(), SkBudgeted::kNo,
       SkImageInfo::MakeN32Premul(2048, 2048));
 
+  CreateCache();
   timer_.Reset();
   do {
     DrawImage image(
@@ -139,9 +141,9 @@
             .set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
             .TakePaintImage(),
         SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
-        CreateMatrix(SkSize::Make(0.6f, 0.6f)), 0u, gfx::ColorSpace());
+        CreateMatrix(SkSize::Make(0.6f, 0.6f)), 0u);
 
-    DecodedDrawImage decoded_image = cache_.GetDecodedImageForDraw(image);
+    DecodedDrawImage decoded_image = cache_->GetDecodedImageForDraw(image);
 
     if (GetParam() == TestMode::kGpu) {
       SkPaint paint;
@@ -152,7 +154,7 @@
       surface->prepareForExternalIO();
     }
 
-    cache_.DrawWithImageFinished(image, decoded_image);
+    cache_->DrawWithImageFinished(image, decoded_image);
     timer_.NextLap();
   } while (!timer_.HasTimeLimitExpired());
 
@@ -162,21 +164,21 @@
 
 TEST_P(GpuImageDecodeCachePerfTest, AcquireExistingImages) {
   timer_.Reset();
+  CreateCache(gfx::ColorSpace::CreateXYZD50().ToSkColorSpace());
   DrawImage image(
       PaintImageBuilder::WithDefault()
           .set_id(PaintImage::GetNextId())
           .set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
           .TakePaintImage(),
       SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
-      CreateMatrix(SkSize::Make(1.0f, 1.0f)), 0u,
-      gfx::ColorSpace::CreateXYZD50());
+      CreateMatrix(SkSize::Make(1.0f, 1.0f)), 0u);
 
-  DecodedDrawImage decoded_image = cache_.GetDecodedImageForDraw(image);
-  cache_.DrawWithImageFinished(image, decoded_image);
+  DecodedDrawImage decoded_image = cache_->GetDecodedImageForDraw(image);
+  cache_->DrawWithImageFinished(image, decoded_image);
 
   do {
-    DecodedDrawImage decoded_image = cache_.GetDecodedImageForDraw(image);
-    cache_.DrawWithImageFinished(image, decoded_image);
+    DecodedDrawImage decoded_image = cache_->GetDecodedImageForDraw(image);
+    cache_->DrawWithImageFinished(image, decoded_image);
     timer_.NextLap();
   } while (!timer_.HasTimeLimitExpired());
 
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc
index 3ba15f4..526c1dd 100644
--- a/cc/tiles/gpu_image_decode_cache_unittest.cc
+++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -273,10 +273,15 @@
   }
 
   std::unique_ptr<GpuImageDecodeCache> CreateCache() {
+    return CreateCache(DefaultColorSpace());
+  }
+
+  std::unique_ptr<GpuImageDecodeCache> CreateCache(
+      const gfx::ColorSpace& color_space) {
     return std::make_unique<GpuImageDecodeCache>(
         context_provider_.get(), use_transfer_cache_, color_type_,
         kGpuMemoryLimitBytes, max_texture_size_,
-        PaintImage::kDefaultGeneratorClientId);
+        PaintImage::kDefaultGeneratorClientId, color_space.ToSkColorSpace());
   }
 
   PaintImage CreatePaintImageInternal(
@@ -363,7 +368,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -372,7 +377,7 @@
   DrawImage another_draw_image(
       image, SkIRect::MakeWH(image.width(), image.height()), quality,
       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult another_result = cache->GetTaskForImageAndRef(
       another_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(another_result.need_unref);
@@ -394,7 +399,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -403,7 +408,7 @@
   DrawImage another_draw_image(
       image, SkIRect::MakeWH(image.width(), image.height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult another_result = cache->GetTaskForImageAndRef(
       another_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(another_result.need_unref);
@@ -424,7 +429,7 @@
 
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        kHigh_SkFilterQuality, matrix,
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -432,8 +437,7 @@
 
   DrawImage another_draw_image(
       image, SkIRect::MakeWH(image.width(), image.height()),
-      kLow_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex,
-      DefaultColorSpace());
+      kLow_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult another_result = cache->GetTaskForImageAndRef(
       another_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(another_result.need_unref);
@@ -455,7 +459,7 @@
   DrawImage first_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(first_result.need_unref);
@@ -466,7 +470,7 @@
       second_image,
       SkIRect::MakeWH(second_image.width(), second_image.height()), quality,
       CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(second_result.need_unref);
@@ -491,7 +495,7 @@
   DrawImage first_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(first_result.need_unref);
@@ -505,7 +509,7 @@
   DrawImage second_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(second_result.need_unref);
@@ -515,7 +519,7 @@
   DrawImage third_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult third_result = cache->GetTaskForImageAndRef(
       third_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(third_result.need_unref);
@@ -537,7 +541,7 @@
   DrawImage first_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(first_result.need_unref);
@@ -546,7 +550,7 @@
   DrawImage second_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(second_result.need_unref);
@@ -556,7 +560,7 @@
   DrawImage third_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult third_result = cache->GetTaskForImageAndRef(
       third_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(third_result.need_unref);
@@ -580,8 +584,7 @@
   PaintImage first_image = CreatePaintImageInternal(gfx::Size(100, 100));
   DrawImage first_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
-      kLow_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex,
-      DefaultColorSpace());
+      kLow_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(first_result.need_unref);
@@ -594,8 +597,7 @@
 
   DrawImage second_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
-      kHigh_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex,
-      DefaultColorSpace());
+      kHigh_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(second_result.need_unref);
@@ -616,7 +618,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -658,7 +660,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -700,7 +702,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -731,7 +733,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -774,7 +776,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -821,7 +823,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -850,7 +852,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -880,7 +882,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -912,7 +914,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -948,7 +950,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -982,7 +984,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        kLow_SkFilterQuality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -994,7 +996,7 @@
   DrawImage larger_draw_image(
       image, SkIRect::MakeWH(image.width(), image.height()), quality,
       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult larger_result = cache->GetTaskForImageAndRef(
       larger_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(larger_result.need_unref);
@@ -1036,7 +1038,7 @@
   PaintImage image = CreatePaintImageInternal(gfx::Size(100, 100));
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        kLow_SkFilterQuality, matrix,
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1047,8 +1049,7 @@
 
   DrawImage higher_quality_draw_image(
       image, SkIRect::MakeWH(image.width(), image.height()),
-      kHigh_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex,
-      DefaultColorSpace());
+      kHigh_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult hq_result = cache->GetTaskForImageAndRef(
       higher_quality_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(hq_result.need_unref);
@@ -1090,7 +1091,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(-0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1124,7 +1125,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1166,7 +1167,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1207,7 +1208,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   // Must hold context lock before calling GetDecodedImageForDraw /
   // DrawWithImageFinished.
@@ -1244,7 +1245,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   // Must hold context lock before calling GetDecodedImageForDraw /
   // DrawWithImageFinished.
@@ -1281,7 +1282,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1307,7 +1308,7 @@
   DrawImage draw_image(
       image, SkIRect::MakeXYWH(150, 150, image.width(), image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1333,7 +1334,7 @@
   DrawImage draw_image(
       image, SkIRect::MakeXYWH(0, 0, image.width(), image.height()), quality,
       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1359,7 +1360,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   {
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
@@ -1421,7 +1422,7 @@
   DrawImage first_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(first_result.need_unref);
@@ -1436,7 +1437,7 @@
   DrawImage second_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(second_result.need_unref);
@@ -1469,7 +1470,7 @@
   DrawImage first_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(first_result.need_unref);
@@ -1488,7 +1489,7 @@
   DrawImage second_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(second_result.need_unref);
@@ -1512,10 +1513,9 @@
   SkMatrix matrix = CreateMatrix(SkSize::Make(0.4f, 0.4f), is_decomposable);
 
   // Create an image with kLow_FilterQuality.
-  DrawImage low_draw_image(image,
-                           SkIRect::MakeWH(image.width(), image.height()),
-                           kLow_SkFilterQuality, matrix,
-                           PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+  DrawImage low_draw_image(
+      image, SkIRect::MakeWH(image.width(), image.height()),
+      kLow_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult low_result = cache->GetTaskForImageAndRef(
       low_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(low_result.need_unref);
@@ -1525,8 +1525,7 @@
   // should get a new task/ref.
   DrawImage medium_draw_image(
       image, SkIRect::MakeWH(image.width(), image.height()),
-      kMedium_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex,
-      DefaultColorSpace());
+      kMedium_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult medium_result = cache->GetTaskForImageAndRef(
       medium_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(medium_result.need_unref);
@@ -1536,8 +1535,7 @@
   // Get the same image at kHigh_FilterQuality. We should re-use medium.
   DrawImage large_draw_image(
       image, SkIRect::MakeWH(image.width(), image.height()),
-      kHigh_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex,
-      DefaultColorSpace());
+      kHigh_SkFilterQuality, matrix, PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult large_result = cache->GetTaskForImageAndRef(
       large_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(large_result.need_unref);
@@ -1565,7 +1563,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1587,7 +1585,7 @@
   DrawImage draw_image_mips(
       image, SkIRect::MakeWH(image.width(), image.height()), quality,
       CreateMatrix(SkSize::Make(0.6f, 0.6f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   DecodedDrawImage decoded_draw_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image_mips));
   cache->DrawWithImageFinished(draw_image_mips, decoded_draw_image);
@@ -1601,7 +1599,7 @@
   SkMatrix matrix = CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable);
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        kLow_SkFilterQuality, matrix,
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache->GetOutOfRasterDecodeTaskForImageAndRef(draw_image);
@@ -1629,7 +1627,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1680,13 +1678,13 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   PaintImage image2 = CreatePaintImageInternal(gfx::Size(100, 100));
   DrawImage draw_image2(
       image2, SkIRect::MakeWH(image2.width(), image2.height()), quality,
       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   // Add an image to the cache and un-ref it.
   {
@@ -1763,7 +1761,7 @@
     DrawImage draw_image(
         image, SkIRect::MakeWH(image.width(), image.height()), quality,
         CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+        PaintImage::kDefaultFrameIndex);
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
     EXPECT_TRUE(result.need_unref);
@@ -1793,7 +1791,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1818,65 +1816,17 @@
   EXPECT_EQ(cache->GetNumCacheEntriesForTesting(), 0u);
 }
 
-TEST_P(GpuImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForLargeImage) {
   auto cache = CreateCache();
   bool is_decomposable = true;
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
-  gfx::ColorSpace color_space_a = gfx::ColorSpace::CreateSRGB();
-  gfx::ColorSpace color_space_b = gfx::ColorSpace::CreateXYZD50();
-
-  PaintImage first_image = CreatePaintImageInternal(gfx::Size(100, 100));
-  DrawImage first_draw_image(
-      first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, color_space_a);
-  ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
-      first_draw_image, ImageDecodeCache::TracingInfo());
-  EXPECT_TRUE(first_result.need_unref);
-  EXPECT_TRUE(first_result.task);
-
-  DrawImage second_draw_image(
-      first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, color_space_b);
-  ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
-      second_draw_image, ImageDecodeCache::TracingInfo());
-  EXPECT_TRUE(second_result.need_unref);
-  EXPECT_TRUE(second_result.task);
-  EXPECT_TRUE(first_result.task.get() != second_result.task.get());
-
-  DrawImage third_draw_image(
-      first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, color_space_a);
-  ImageDecodeCache::TaskResult third_result = cache->GetTaskForImageAndRef(
-      third_draw_image, ImageDecodeCache::TracingInfo());
-  EXPECT_TRUE(third_result.need_unref);
-  EXPECT_TRUE(third_result.task.get() == first_result.task.get());
-
-  TestTileTaskRunner::ProcessTask(first_result.task->dependencies()[0].get());
-  TestTileTaskRunner::ProcessTask(first_result.task.get());
-  TestTileTaskRunner::ProcessTask(second_result.task->dependencies()[0].get());
-  TestTileTaskRunner::ProcessTask(second_result.task.get());
-
-  cache->UnrefImage(first_draw_image);
-  cache->UnrefImage(second_draw_image);
-  cache->UnrefImage(third_draw_image);
-}
-
-TEST_P(GpuImageDecodeCacheTest, GetTaskForLargeImageNonSRGBColorSpace) {
-  auto cache = CreateCache();
-  bool is_decomposable = true;
-  SkFilterQuality quality = kHigh_SkFilterQuality;
-  gfx::ColorSpace color_space = gfx::ColorSpace::CreateXYZD50();
-
   // Create an image that's too large to cache.
   PaintImage image = CreatePaintImageInternal(gfx::Size(1, 24000));
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, color_space);
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1909,10 +1859,9 @@
 
   bool is_decomposable = true;
   SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality,
-                       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       1u, DefaultColorSpace());
+  DrawImage draw_image(
+      image, SkIRect::MakeWH(image.width(), image.height()), quality,
+      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 1u);
   auto decoded_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image));
   ASSERT_TRUE(decoded_image.image());
@@ -1922,8 +1871,7 @@
   cache->DrawWithImageFinished(draw_image, decoded_image);
 
   // Scaled.
-  DrawImage scaled_draw_image(draw_image, 0.5f, 2u,
-                              draw_image.target_color_space());
+  DrawImage scaled_draw_image(draw_image, 0.5f, 2u);
   decoded_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(scaled_draw_image));
   ASSERT_TRUE(decoded_image.image());
@@ -1935,8 +1883,7 @@
   // Subset.
   DrawImage subset_draw_image(
       image, SkIRect::MakeWH(5, 5), quality,
-      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 3u,
-      DefaultColorSpace());
+      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 3u);
   decoded_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(subset_draw_image));
   ASSERT_TRUE(decoded_image.image());
@@ -1956,7 +1903,7 @@
   DrawImage first_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(first_result.need_unref);
@@ -1970,7 +1917,7 @@
   DrawImage second_draw_image(
       first_image, SkIRect::MakeWH(first_image.width(), first_image.height()),
       quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(second_result.need_unref);
@@ -2014,7 +1961,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -2051,7 +1998,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   // The image counts against our budget.
   viz::ContextProvider::ScopedContextLock context_lock(context_provider());
@@ -2065,7 +2012,7 @@
       CreatePaintImageInternal(gfx::Size(100, 100)),
       SkIRect::MakeWH(image.width(), image.height()), quality,
       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   // Should be at raster.
   ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
@@ -2095,7 +2042,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   // The image counts against our budget.
   viz::ContextProvider::ScopedContextLock context_lock(context_provider());
@@ -2109,7 +2056,7 @@
       CreateDiscardablePaintImage(gfx::Size(100, 100)),
       SkIRect::MakeWH(image.width(), image.height()), quality,
       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   // Should be at raster.
   ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
@@ -2127,17 +2074,17 @@
 
 TEST_P(GpuImageDecodeCacheTest,
        ColorConversionDuringDecodeForLargeImageNonSRGBColorSpace) {
-  auto cache = CreateCache();
+  gfx::ColorSpace color_space = gfx::ColorSpace::CreateXYZD50();
+  auto cache = CreateCache(color_space);
   bool is_decomposable = true;
   SkFilterQuality quality = kHigh_SkFilterQuality;
-  gfx::ColorSpace color_space = gfx::ColorSpace::CreateXYZD50();
 
   // Create an image that's too large to upload.
   PaintImage image = CreatePaintImageInternal(gfx::Size(1, 24000));
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, color_space);
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -2182,16 +2129,16 @@
 
 TEST_P(GpuImageDecodeCacheTest,
        ColorConversionDuringUploadForSmallImageNonSRGBColorSpace) {
-  auto cache = CreateCache();
+  gfx::ColorSpace color_space = gfx::ColorSpace::CreateDisplayP3D65();
+  auto cache = CreateCache(color_space);
   bool is_decomposable = true;
   SkFilterQuality quality = kHigh_SkFilterQuality;
-  gfx::ColorSpace color_space = gfx::ColorSpace::CreateDisplayP3D65();
 
   PaintImage image = CreatePaintImageInternal(gfx::Size(11, 12));
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, color_space);
+                       PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -2239,7 +2186,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   viz::ContextProvider::ScopedContextLock context_lock(context_provider());
   DecodedDrawImage decoded_draw_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image));
@@ -2260,7 +2207,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   auto result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -2280,7 +2227,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   auto result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -2293,7 +2240,8 @@
 }
 
 TEST_P(GpuImageDecodeCacheTest, NonLazyImageLargeImageColorConverted) {
-  auto cache = CreateCache();
+  auto color_space = gfx::ColorSpace::CreateDisplayP3D65();
+  auto cache = CreateCache(color_space);
   const bool should_cache_sw_image =
       cache->SupportsColorSpaceConversion() && !use_transfer_cache_;
 
@@ -2301,10 +2249,10 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   PaintImage image = CreateBitmapImageInternal(gfx::Size(10, 24000));
-  DrawImage draw_image(
-      image, SkIRect::MakeWH(image.width(), image.height()), quality,
-      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, gfx::ColorSpace::CreateDisplayP3D65());
+  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
+                       quality,
+                       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+                       PaintImage::kDefaultFrameIndex);
   viz::ContextProvider::ScopedContextLock context_lock(context_provider());
   DecodedDrawImage decoded_draw_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image));
@@ -2316,9 +2264,8 @@
   auto sw_image = cache->GetSWImageDecodeForTesting(draw_image);
   ASSERT_EQ(!!sw_image, should_cache_sw_image);
   if (should_cache_sw_image) {
-    EXPECT_TRUE(SkColorSpace::Equals(
-        sw_image->colorSpace(),
-        gfx::ColorSpace::CreateDisplayP3D65().ToSkColorSpace().get()));
+    EXPECT_TRUE(SkColorSpace::Equals(sw_image->colorSpace(),
+                                     color_space.ToSkColorSpace().get()));
   }
 }
 
@@ -2331,7 +2278,7 @@
   DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                        quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   viz::ContextProvider::ScopedContextLock context_lock(context_provider());
   DecodedDrawImage decoded_draw_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image));
@@ -2362,7 +2309,7 @@
     DrawImage draw_image(
         image, SkIRect::MakeWH(image.width(), image.height()), quality,
         CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+        PaintImage::kDefaultFrameIndex);
     DecodedDrawImage decoded_draw_image =
         EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image));
 
@@ -2414,7 +2361,7 @@
   DrawImage draw_image1(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   DecodedDrawImage decoded_image1 =
       EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image1));
   ASSERT_TRUE(decoded_image1.image());
@@ -2451,7 +2398,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   DecodedDrawImage decoded_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image));
   ASSERT_TRUE(decoded_image.image());
@@ -2467,15 +2414,16 @@
 
 TEST_P(GpuImageDecodeCacheTest, BasicMips) {
   auto decode_and_check_mips = [this](SkFilterQuality filter_quality,
-                                      SkSize scale, gfx::ColorSpace color_space,
+                                      SkSize scale,
+                                      const gfx::ColorSpace& color_space,
                                       bool should_have_mips) {
-    auto cache = CreateCache();
+    auto cache = CreateCache(color_space);
     bool is_decomposable = true;
 
     PaintImage image = CreatePaintImageInternal(gfx::Size(100, 100));
     DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
                          filter_quality, CreateMatrix(scale, is_decomposable),
-                         PaintImage::kDefaultFrameIndex, color_space);
+                         PaintImage::kDefaultFrameIndex);
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
     EXPECT_TRUE(result.need_unref);
@@ -2536,7 +2484,7 @@
     DrawImage draw_image(
         image, SkIRect::MakeWH(image.width(), image.height()), filter_quality,
         CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+        PaintImage::kDefaultFrameIndex);
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
     EXPECT_TRUE(result.need_unref);
@@ -2573,7 +2521,7 @@
     DrawImage draw_image(
         image, SkIRect::MakeWH(image.width(), image.height()), filter_quality,
         CreateMatrix(SkSize::Make(0.6f, 0.6f), is_decomposable),
-        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+        PaintImage::kDefaultFrameIndex);
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
     EXPECT_TRUE(result.need_unref);
@@ -2622,7 +2570,7 @@
     DrawImage draw_image(
         image, SkIRect::MakeWH(image.width(), image.height()), filter_quality,
         CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+        PaintImage::kDefaultFrameIndex);
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
     EXPECT_TRUE(result.need_unref);
@@ -2653,7 +2601,7 @@
     DrawImage draw_image(
         image, SkIRect::MakeWH(image.width(), image.height()), filter_quality,
         CreateMatrix(SkSize::Make(0.6f, 0.6f), is_decomposable),
-        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+        PaintImage::kDefaultFrameIndex);
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
     EXPECT_TRUE(result.need_unref);
diff --git a/cc/tiles/image_controller_unittest.cc b/cc/tiles/image_controller_unittest.cc
index 74567679..9a52430 100644
--- a/cc/tiles/image_controller_unittest.cc
+++ b/cc/tiles/image_controller_unittest.cc
@@ -229,7 +229,7 @@
   return DrawImage(CreateDiscardablePaintImage(size),
                    SkIRect::MakeWH(size.width(), size.height()),
                    kNone_SkFilterQuality, SkMatrix::I(),
-                   PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
+                   PaintImage::kDefaultFrameIndex);
 }
 
 class ImageControllerTest : public testing::Test {
@@ -324,14 +324,13 @@
 
   SkBitmap bitmap;
   bitmap.allocN32Pixels(1, 1);
-  DrawImage image =
-      DrawImage(PaintImageBuilder::WithDefault()
-                    .set_id(PaintImage::GetNextId())
-                    .set_image(SkImage::MakeFromBitmap(bitmap),
-                               PaintImage::GetNextContentId())
-                    .TakePaintImage(),
-                SkIRect::MakeWH(1, 1), kNone_SkFilterQuality, SkMatrix::I(),
-                PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
+  DrawImage image = DrawImage(PaintImageBuilder::WithDefault()
+                                  .set_id(PaintImage::GetNextId())
+                                  .set_image(SkImage::MakeFromBitmap(bitmap),
+                                             PaintImage::GetNextContentId())
+                                  .TakePaintImage(),
+                              SkIRect::MakeWH(1, 1), kNone_SkFilterQuality,
+                              SkMatrix::I(), PaintImage::kDefaultFrameIndex);
 
   ImageController::ImageDecodeRequestId expected_id =
       controller()->QueueImageDecode(
diff --git a/cc/tiles/software_image_decode_cache.cc b/cc/tiles/software_image_decode_cache.cc
index d75e6e2..0dbd879 100644
--- a/cc/tiles/software_image_decode_cache.cc
+++ b/cc/tiles/software_image_decode_cache.cc
@@ -16,6 +16,7 @@
 #include "cc/base/histograms.h"
 #include "cc/raster/tile_task.h"
 #include "cc/tiles/mipmap_util.h"
+#include "ui/gfx/color_space.h"
 #include "ui/gfx/skia_util.h"
 
 using base::trace_event::MemoryAllocatorDump;
@@ -140,8 +141,10 @@
 SoftwareImageDecodeCache::SoftwareImageDecodeCache(
     SkColorType color_type,
     size_t locked_memory_limit_bytes,
-    PaintImage::GeneratorClientId generator_client_id)
+    PaintImage::GeneratorClientId generator_client_id,
+    sk_sp<SkColorSpace> target_color_space)
     : decoded_images_(ImageMRUCache::NO_AUTO_EVICT),
+      target_color_space_(std::move(target_color_space)),
       locked_images_budget_(locked_memory_limit_bytes),
       color_type_(color_type),
       generator_client_id_(generator_client_id),
@@ -362,8 +365,9 @@
   // If we can use the original decode, we'll definitely need a decode.
   if (key.type() == CacheKey::kOriginal) {
     base::AutoUnlock release(lock_);
-    local_cache_entry = Utils::DoDecodeImage(key, paint_image, color_type_,
-                                             generator_client_id_);
+    local_cache_entry =
+        Utils::DoDecodeImage(key, paint_image, color_type_, target_color_space_,
+                             generator_client_id_);
   } else {
     // Attempt to find a cached decode to generate a scaled/subrected decode
     // from.
@@ -390,8 +394,9 @@
     DCHECK(!should_decode_to_scale || !key.is_nearest_neighbor());
     if (should_decode_to_scale) {
       base::AutoUnlock release(lock_);
-      local_cache_entry = Utils::DoDecodeImage(key, paint_image, color_type_,
-                                               generator_client_id_);
+      local_cache_entry =
+          Utils::DoDecodeImage(key, paint_image, color_type_,
+                               target_color_space_, generator_client_id_);
     }
 
     // Couldn't decode to scale or find a cached candidate. Create the
@@ -416,9 +421,9 @@
           key.type() == CacheKey::kSubrectOriginal
               ? SkIRect::MakeWH(paint_image.width(), paint_image.height())
               : gfx::RectToSkIRect(key.src_rect());
-      DrawImage candidate_draw_image(
-          paint_image, src_rect, kNone_SkFilterQuality, SkMatrix::I(),
-          key.frame_key().frame_index(), key.target_color_space());
+      DrawImage candidate_draw_image(paint_image, src_rect,
+                                     kNone_SkFilterQuality, SkMatrix::I(),
+                                     key.frame_key().frame_index());
       candidate_key.emplace(
           CacheKey::FromDrawImage(candidate_draw_image, color_type_));
     }
@@ -519,9 +524,7 @@
   // Cache images that need to be converted to a non-sRGB color space.
   // TODO(ccameron): Consider caching when any color conversion is required.
   // https://crbug.com/791828
-  const gfx::ColorSpace& dst_color_space = draw_image.target_color_space();
-  if (dst_color_space.IsValid() &&
-      dst_color_space != gfx::ColorSpace::CreateSRGB()) {
+  if (target_color_space_ && !target_color_space_->isSRGB()) {
     return true;
   }
 
diff --git a/cc/tiles/software_image_decode_cache.h b/cc/tiles/software_image_decode_cache.h
index 30040d1..eb7cc16 100644
--- a/cc/tiles/software_image_decode_cache.h
+++ b/cc/tiles/software_image_decode_cache.h
@@ -34,7 +34,8 @@
 
   SoftwareImageDecodeCache(SkColorType color_type,
                            size_t locked_memory_limit_bytes,
-                           PaintImage::GeneratorClientId generator_client_id);
+                           PaintImage::GeneratorClientId generator_client_id,
+                           sk_sp<SkColorSpace> target_color_space);
   ~SoftwareImageDecodeCache() override;
 
   // ImageDecodeCache overrides.
@@ -150,6 +151,7 @@
                      PaintImage::FrameKeyHash>
       frame_key_to_image_keys_;
 
+  const sk_sp<SkColorSpace> target_color_space_;
   MemoryBudget locked_images_budget_;
 
   const SkColorType color_type_;
diff --git a/cc/tiles/software_image_decode_cache_perftest.cc b/cc/tiles/software_image_decode_cache_perftest.cc
index 64d7967..5f69317 100644
--- a/cc/tiles/software_image_decode_cache_perftest.cc
+++ b/cc/tiles/software_image_decode_cache_perftest.cc
@@ -63,8 +63,7 @@
                              PaintImage::GetNextContentId())
                   .TakePaintImage(),
               subrect, quality,
-              CreateMatrix(SkSize::Make(scale.first, scale.second)), 0u,
-              gfx::ColorSpace());
+              CreateMatrix(SkSize::Make(scale.first, scale.second)), 0u);
         }
       }
     }
diff --git a/cc/tiles/software_image_decode_cache_unittest.cc b/cc/tiles/software_image_decode_cache_unittest.cc
index abae6c6..ff2cdb6 100644
--- a/cc/tiles/software_image_decode_cache_unittest.cc
+++ b/cc/tiles/software_image_decode_cache_unittest.cc
@@ -23,9 +23,13 @@
 class TestSoftwareImageDecodeCache : public SoftwareImageDecodeCache {
  public:
   TestSoftwareImageDecodeCache()
+      : TestSoftwareImageDecodeCache(DefaultColorSpace()) {}
+
+  explicit TestSoftwareImageDecodeCache(const gfx::ColorSpace& color_space)
       : SoftwareImageDecodeCache(kN32_SkColorType,
                                  kLockedMemoryLimitBytes,
-                                 PaintImage::kDefaultGeneratorClientId) {}
+                                 PaintImage::kDefaultGeneratorClientId,
+                                 color_space.ToSkColorSpace()) {}
 };
 
 SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) {
@@ -54,7 +58,7 @@
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kNone_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -76,7 +80,7 @@
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kLow_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -94,7 +98,7 @@
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kMedium_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -113,7 +117,7 @@
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kLow_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kARGB_4444_SkColorType);
@@ -132,7 +136,7 @@
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kHigh_SkFilterQuality,
       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kARGB_4444_SkColorType);
@@ -151,7 +155,7 @@
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kLow_SkFilterQuality,
       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -171,7 +175,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.4f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -190,7 +194,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -210,7 +214,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -231,7 +235,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -252,7 +256,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -273,7 +277,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -294,7 +298,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -314,7 +318,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -334,7 +338,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -354,7 +358,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -373,7 +377,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -392,7 +396,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -411,7 +415,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -431,7 +435,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -450,7 +454,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -473,7 +477,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.45f, 0.45f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -493,7 +497,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -513,7 +517,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -534,7 +538,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -555,7 +559,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -575,7 +579,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -589,7 +593,7 @@
   DrawImage another_draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto another_key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       another_draw_image, kN32_SkColorType);
@@ -612,7 +616,7 @@
       paint_image,
       SkIRect::MakeXYWH(25, 35, paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -633,7 +637,7 @@
       paint_image,
       SkIRect::MakeXYWH(20, 30, paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
       draw_image, kN32_SkColorType);
@@ -654,7 +658,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -663,7 +667,7 @@
   DrawImage another_draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult another_result = cache.GetTaskForImageAndRef(
       another_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(another_result.need_unref);
@@ -684,7 +688,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -714,7 +718,7 @@
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kHigh_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult high_quality_result =
       cache.GetTaskForImageAndRef(high_quality_draw_image,
                                   ImageDecodeCache::TracingInfo());
@@ -725,7 +729,7 @@
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kNone_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult none_quality_result =
       cache.GetTaskForImageAndRef(none_quality_draw_image,
                                   ImageDecodeCache::TracingInfo());
@@ -749,7 +753,7 @@
   DrawImage half_size_draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult half_size_result = cache.GetTaskForImageAndRef(
       half_size_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(half_size_result.need_unref);
@@ -758,7 +762,7 @@
   DrawImage quarter_size_draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult quarter_size_result =
       cache.GetTaskForImageAndRef(quarter_size_draw_image,
                                   ImageDecodeCache::TracingInfo());
@@ -783,7 +787,7 @@
       first_paint_image,
       SkIRect::MakeWH(first_paint_image.width(), first_paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult first_result = cache.GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(first_result.need_unref);
@@ -794,7 +798,7 @@
       second_paint_image,
       SkIRect::MakeWH(second_paint_image.width(), second_paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult second_result = cache.GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(second_result.need_unref);
@@ -808,63 +812,6 @@
   cache.UnrefImage(second_draw_image);
 }
 
-// crbug.com/709341
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageDifferentColorSpace \
-  DISABLED_GetTaskForImageDifferentColorSpace
-#else
-#define MAYBE_GetTaskForImageDifferentColorSpace \
-  GetTaskForImageDifferentColorSpace
-#endif
-TEST(SoftwareImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentColorSpace) {
-  TestSoftwareImageDecodeCache cache;
-  bool is_decomposable = true;
-  SkFilterQuality quality = kHigh_SkFilterQuality;
-
-  gfx::ColorSpace color_space_a(gfx::ColorSpace::PrimaryID::XYZ_D50,
-                                gfx::ColorSpace::TransferID::IEC61966_2_1);
-  gfx::ColorSpace color_space_b(gfx::ColorSpace::PrimaryID::SMPTE170M,
-                                gfx::ColorSpace::TransferID::IEC61966_2_1);
-  gfx::ColorSpace color_space_c = gfx::ColorSpace::CreateSRGB();
-
-  PaintImage paint_image = CreatePaintImage(100, 100, color_space_a);
-  DrawImage first_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, color_space_b);
-  ImageDecodeCache::TaskResult first_result = cache.GetTaskForImageAndRef(
-      first_draw_image, ImageDecodeCache::TracingInfo());
-  EXPECT_TRUE(first_result.need_unref);
-  EXPECT_TRUE(first_result.task);
-
-  DrawImage second_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, color_space_c);
-  ImageDecodeCache::TaskResult second_result = cache.GetTaskForImageAndRef(
-      second_draw_image, ImageDecodeCache::TracingInfo());
-  EXPECT_TRUE(second_result.need_unref);
-  EXPECT_TRUE(second_result.task);
-  EXPECT_TRUE(first_result.task.get() != second_result.task.get());
-
-  DrawImage third_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, color_space_b);
-  ImageDecodeCache::TaskResult third_result = cache.GetTaskForImageAndRef(
-      third_draw_image, ImageDecodeCache::TracingInfo());
-  EXPECT_TRUE(third_result.need_unref);
-  EXPECT_TRUE(third_result.task);
-  EXPECT_TRUE(first_result.task.get() == third_result.task.get());
-
-  TestTileTaskRunner::ProcessTask(first_result.task.get());
-  TestTileTaskRunner::ProcessTask(second_result.task.get());
-
-  cache.UnrefImage(first_draw_image);
-  cache.UnrefImage(second_draw_image);
-  cache.UnrefImage(third_draw_image);
-}
-
 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyDecoded) {
   TestSoftwareImageDecodeCache cache;
   bool is_decomposable = true;
@@ -874,7 +821,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -903,7 +850,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -938,7 +885,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -979,7 +926,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1019,7 +966,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1052,7 +999,7 @@
       paint_image,
       SkIRect::MakeXYWH(20, 30, paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(result.need_unref);
@@ -1083,7 +1030,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   DecodedDrawImage decoded_draw_image =
       cache.GetDecodedImageForDraw(draw_image);
@@ -1108,7 +1055,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   DecodedDrawImage decoded_draw_image =
       cache.GetDecodedImageForDraw(draw_image);
@@ -1138,7 +1085,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1162,7 +1109,7 @@
       paint_image,
       SkIRect::MakeXYWH(150, 150, paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1185,7 +1132,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1213,7 +1160,7 @@
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(paint_image, SkIRect::MakeXYWH(10, 10, 80, 80), quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1246,7 +1193,7 @@
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(paint_image, SkIRect::MakeXYWH(10, 10, 80, 80), quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1277,7 +1224,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1308,7 +1255,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1339,7 +1286,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1370,7 +1317,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1401,7 +1348,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1432,7 +1379,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1463,7 +1410,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1494,7 +1441,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1518,11 +1465,11 @@
   DrawImage draw_image_50(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   DrawImage draw_image_49(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result_50 = cache.GetTaskForImageAndRef(
       draw_image_50, ImageDecodeCache::TracingInfo());
@@ -1569,7 +1516,7 @@
     DrawImage draw_image(
         paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
         quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+        PaintImage::kDefaultFrameIndex);
     ImageDecodeCache::TaskResult result = cache.GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
     EXPECT_TRUE(result.need_unref);
@@ -1604,10 +1551,9 @@
 
   bool is_decomposable = true;
   SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality,
-                       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
-                       1u, DefaultColorSpace());
+  DrawImage draw_image(
+      image, SkIRect::MakeWH(image.width(), image.height()), quality,
+      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 1u);
   auto decoded_image = cache.GetDecodedImageForDraw(draw_image);
   ASSERT_TRUE(decoded_image.image());
   ASSERT_EQ(generator->frames_decoded().size(), 1u);
@@ -1616,8 +1562,7 @@
   cache.DrawWithImageFinished(draw_image, decoded_image);
 
   // Scaled.
-  DrawImage scaled_draw_image(draw_image, 0.5f, 2u,
-                              draw_image.target_color_space());
+  DrawImage scaled_draw_image(draw_image, 0.5f, 2u);
   decoded_image = cache.GetDecodedImageForDraw(scaled_draw_image);
   ASSERT_TRUE(decoded_image.image());
   ASSERT_EQ(generator->frames_decoded().size(), 1u);
@@ -1628,8 +1573,7 @@
   // Subset.
   DrawImage subset_draw_image(
       image, SkIRect::MakeWH(5, 5), quality,
-      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 3u,
-      DefaultColorSpace());
+      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 3u);
   decoded_image = cache.GetDecodedImageForDraw(subset_draw_image);
   ASSERT_TRUE(decoded_image.image());
   ASSERT_EQ(generator->frames_decoded().size(), 1u);
@@ -1649,7 +1593,7 @@
                                   DefaultColorSpace().ToSkColorSpace(), false);
   DrawImage draw_image(paint_image, SkIRect::MakeXYWH(0, 0, 10, 10), quality,
                        CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
 
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1682,7 +1626,7 @@
       gfx::Size(100, 100), DefaultColorSpace().ToSkColorSpace());
   DrawImage draw_image(paint_image, SkIRect::MakeWH(100, 100), quality,
                        CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   DecodedDrawImage decoded_draw_image =
       cache.GetDecodedImageForDraw(draw_image);
   EXPECT_TRUE(decoded_draw_image.image());
@@ -1692,7 +1636,7 @@
   DrawImage empty_draw_image(
       paint_image, SkIRect::MakeEmpty(), quality,
       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   DecodedDrawImage empty_decoded_draw_image =
       cache.GetDecodedImageForDraw(empty_draw_image);
   EXPECT_FALSE(empty_decoded_draw_image.image());
@@ -1700,16 +1644,16 @@
 }
 
 TEST(SoftwareImageDecodeCacheTest, BitmapImageColorConverted) {
-  TestSoftwareImageDecodeCache cache;
+  gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateDisplayP3D65();
+  TestSoftwareImageDecodeCache cache(target_color_space);
   bool is_decomposable = true;
   SkFilterQuality quality = kHigh_SkFilterQuality;
-  gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateDisplayP3D65();
 
   PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, target_color_space);
+      PaintImage::kDefaultFrameIndex);
 
   DecodedDrawImage decoded_draw_image =
       cache.GetDecodedImageForDraw(draw_image);
@@ -1733,7 +1677,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
 
   // The cache should not support this image.
   EXPECT_FALSE(cache.UseCacheForDrawImage(draw_image));
@@ -1759,7 +1703,7 @@
           paint_image,
           SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
           CreateMatrix(SkSize::Make(scale, scale), is_decomposable),
-          PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+          PaintImage::kDefaultFrameIndex);
       DecodedDrawImage decoded_draw_image =
           cache.GetDecodedImageForDraw(draw_image);
       EXPECT_TRUE(decoded_draw_image.image());
@@ -1798,7 +1742,7 @@
   DrawImage draw_image1(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   DecodedDrawImage decoded_image1 = cache.GetDecodedImageForDraw(draw_image1);
   ASSERT_TRUE(decoded_image1.image());
   EXPECT_EQ(decoded_image1.image()->width(), 50);
@@ -1815,7 +1759,7 @@
   DrawImage draw_image2(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.25, 0.25), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   DecodedDrawImage decoded_image2 = cache.GetDecodedImageForDraw(draw_image2);
   ASSERT_TRUE(decoded_image2.image());
   EXPECT_EQ(decoded_image2.image()->width(), 25);
@@ -1855,7 +1799,7 @@
   // subrect vetoes decode to scale.
   DrawImage draw_image(paint_image, SkIRect::MakeWH(50, 50), quality,
                        CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
-                       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+                       PaintImage::kDefaultFrameIndex);
   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
   ASSERT_TRUE(decoded_image.image());
   EXPECT_EQ(decoded_image.image()->width(), 25);
@@ -1891,7 +1835,7 @@
   DrawImage draw_image(
       paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
-      PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+      PaintImage::kDefaultFrameIndex);
   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
   ASSERT_TRUE(decoded_image.image());
   EXPECT_EQ(decoded_image.image()->width(), 100);
diff --git a/cc/tiles/software_image_decode_cache_unittest_combinations.cc b/cc/tiles/software_image_decode_cache_unittest_combinations.cc
index 5052a2a..03d3e09e 100644
--- a/cc/tiles/software_image_decode_cache_unittest_combinations.cc
+++ b/cc/tiles/software_image_decode_cache_unittest_combinations.cc
@@ -50,7 +50,7 @@
             ? SkIRect::MakeWH(paint_image().width(), paint_image().height())
             : src_rect,
         kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(scale, scale), true),
-        PaintImage::kDefaultFrameIndex, GetColorSpace());
+        PaintImage::kDefaultFrameIndex);
   }
 
   SoftwareImageDecodeCache& cache() { return *cache_; }
@@ -80,7 +80,8 @@
   std::unique_ptr<SoftwareImageDecodeCache> CreateCache() override {
     return std::make_unique<SoftwareImageDecodeCache>(
         kN32_SkColorType, kLockedMemoryLimitBytes,
-        PaintImage::kDefaultGeneratorClientId);
+        PaintImage::kDefaultGeneratorClientId,
+        GetColorSpace().ToSkColorSpace());
   }
 };
 
@@ -89,7 +90,8 @@
   std::unique_ptr<SoftwareImageDecodeCache> CreateCache() override {
     return std::make_unique<SoftwareImageDecodeCache>(
         kARGB_4444_SkColorType, kLockedMemoryLimitBytes,
-        PaintImage::kDefaultGeneratorClientId);
+        PaintImage::kDefaultGeneratorClientId,
+        GetColorSpace().ToSkColorSpace());
   }
 };
 
@@ -98,7 +100,8 @@
   std::unique_ptr<SoftwareImageDecodeCache> CreateCache() override {
     return std::make_unique<SoftwareImageDecodeCache>(
         kRGBA_F16_SkColorType, kLockedMemoryLimitBytes,
-        PaintImage::kDefaultGeneratorClientId);
+        PaintImage::kDefaultGeneratorClientId,
+        GetColorSpace().ToSkColorSpace());
   }
 };
 
@@ -135,9 +138,6 @@
                          const DrawImage& draw_image,
                          const gfx::Size& expected_size) override {
     auto decoded = cache().GetDecodedImageForDraw(draw_image);
-    EXPECT_TRUE(SkColorSpace::Equals(
-        decoded.image()->colorSpace(),
-        draw_image.target_color_space().ToSkColorSpace().get()));
     SCOPED_TRACE(base::StringPrintf("Failure from line %d", line));
     EXPECT_EQ(decoded.image()->width(), expected_size.width());
     EXPECT_EQ(decoded.image()->height(), expected_size.height());
diff --git a/cc/tiles/software_image_decode_cache_utils.cc b/cc/tiles/software_image_decode_cache_utils.cc
index 58bf110..f803af8c 100644
--- a/cc/tiles/software_image_decode_cache_utils.cc
+++ b/cc/tiles/software_image_decode_cache_utils.cc
@@ -59,6 +59,7 @@
     const CacheKey& key,
     const PaintImage& paint_image,
     SkColorType color_type,
+    sk_sp<SkColorSpace> color_space,
     PaintImage::GeneratorClientId client_id) {
   SkISize target_size =
       SkISize::Make(key.target_size().width(), key.target_size().height());
@@ -74,7 +75,7 @@
                "SoftwareImageDecodeCacheUtils::DoDecodeImage - "
                "decode");
   bool result = paint_image.Decode(target_pixels->data(), &target_info,
-                                   key.target_color_space().ToSkColorSpace(),
+                                   std::move(color_space),
                                    key.frame_key().frame_index(), client_id);
   if (!result) {
     target_pixels->Unlock();
@@ -180,7 +181,7 @@
   // the filter quality doesn't matter. Early out instead.
   if (target_size.IsEmpty()) {
     return CacheKey(frame_key, stable_id, kSubrectAndScale, false, src_rect,
-                    target_size, image.target_color_space());
+                    target_size);
   }
 
   ProcessingType type = kOriginal;
@@ -240,7 +241,7 @@
   }
 
   return CacheKey(frame_key, stable_id, type, is_nearest_neighbor, src_rect,
-                  target_size, image.target_color_space());
+                  target_size);
 }
 
 SoftwareImageDecodeCacheUtils::CacheKey::CacheKey(
@@ -249,15 +250,13 @@
     ProcessingType type,
     bool is_nearest_neighbor,
     const gfx::Rect& src_rect,
-    const gfx::Size& target_size,
-    const gfx::ColorSpace& target_color_space)
+    const gfx::Size& target_size)
     : frame_key_(frame_key),
       stable_id_(stable_id),
       type_(type),
       is_nearest_neighbor_(is_nearest_neighbor),
       src_rect_(src_rect),
-      target_size_(target_size),
-      target_color_space_(target_color_space) {
+      target_size_(target_size) {
   if (type == kOriginal) {
     hash_ = frame_key_.hash();
   } else {
@@ -274,8 +273,6 @@
     hash_ = base::HashInts(base::HashInts(src_rect_hash, target_size_hash),
                            frame_key_.hash());
   }
-  // Include the target color space in the hash regardless of scaling.
-  hash_ = base::HashInts(hash_, target_color_space.GetHash());
 }
 
 SoftwareImageDecodeCacheUtils::CacheKey::CacheKey(const CacheKey& other) =
@@ -297,7 +294,6 @@
   }
   str << "]\nis_nearest_neightbor[" << is_nearest_neighbor_ << "]\nsrc_rect["
       << src_rect_.ToString() << "]\ntarget_size[" << target_size_.ToString()
-      << "]\ntarget_color_space[" << target_color_space_.ToString()
       << "]\nhash[" << hash_ << "]";
   return str.str();
 }
diff --git a/cc/tiles/software_image_decode_cache_utils.h b/cc/tiles/software_image_decode_cache_utils.h
index 835d68c..42d7b020 100644
--- a/cc/tiles/software_image_decode_cache_utils.h
+++ b/cc/tiles/software_image_decode_cache_utils.h
@@ -16,7 +16,6 @@
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
 #include "third_party/skia/include/core/SkSize.h"
-#include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -57,7 +56,6 @@
       // image.
       DCHECK(!is_nearest_neighbor_ || type_ == kOriginal);
       return frame_key_ == other.frame_key_ && type_ == other.type_ &&
-             target_color_space_ == other.target_color_space_ &&
              (type_ == kOriginal || (src_rect_ == other.src_rect_ &&
                                      target_size_ == other.target_size_));
     }
@@ -70,9 +68,6 @@
     bool is_nearest_neighbor() const { return is_nearest_neighbor_; }
     gfx::Rect src_rect() const { return src_rect_; }
     gfx::Size target_size() const { return target_size_; }
-    const gfx::ColorSpace& target_color_space() const {
-      return target_color_space_;
-    }
 
     size_t get_hash() const { return hash_; }
 
@@ -94,8 +89,7 @@
              ProcessingType type,
              bool is_nearest_neighbor,
              const gfx::Rect& src_rect,
-             const gfx::Size& size,
-             const gfx::ColorSpace& target_color_space);
+             const gfx::Size& size);
 
     PaintImage::FrameKey frame_key_;
     // The stable id is does not factor into the cache key's value for hashing
@@ -106,7 +100,6 @@
     bool is_nearest_neighbor_;
     gfx::Rect src_rect_;
     gfx::Size target_size_;
-    gfx::ColorSpace target_color_space_;
     size_t hash_;
   };
 
@@ -186,6 +179,7 @@
       const CacheKey& key,
       const PaintImage& image,
       SkColorType color_type,
+      sk_sp<SkColorSpace> color_space,
       PaintImage::GeneratorClientId client_id);
   static std::unique_ptr<CacheEntry> GenerateCacheEntryFromCandidate(
       const CacheKey& key,
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index b1ffd0b..a817087 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -682,8 +682,6 @@
   MemoryUsage memory_usage(resource_pool_->memory_usage_bytes(),
                            resource_pool_->resource_count());
 
-  RasterColorSpace raster_color_space = client_->GetRasterColorSpace();
-
   std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue(
       client_->BuildRasterQueue(global_state_.tree_priority,
                                 RasterTilePriorityQueue::Type::ALL));
@@ -736,8 +734,7 @@
       DCHECK(prioritized_tile.should_decode_checkered_images_for_tile());
 
       AddCheckeredImagesToDecodeQueue(
-          prioritized_tile, raster_color_space.color_space,
-          CheckerImageTracker::DecodeType::kRaster,
+          prioritized_tile, CheckerImageTracker::DecodeType::kRaster,
           &work_to_schedule.checker_image_decode_queue);
       continue;
     }
@@ -793,15 +790,13 @@
       if (tile->raster_task_scheduled_with_checker_images() &&
           prioritized_tile.should_decode_checkered_images_for_tile()) {
         AddCheckeredImagesToDecodeQueue(
-            prioritized_tile, raster_color_space.color_space,
-            CheckerImageTracker::DecodeType::kRaster,
+            prioritized_tile, CheckerImageTracker::DecodeType::kRaster,
             &work_to_schedule.checker_image_decode_queue);
       }
     } else {
       // Creating the raster task here will acquire resources, but
       // this resource usage has already been accounted for above.
-      auto raster_task = CreateRasterTask(
-          prioritized_tile, client_->GetRasterColorSpace(), &work_to_schedule);
+      auto raster_task = CreateRasterTask(prioritized_tile, &work_to_schedule);
       if (!raster_task) {
         continue;
       }
@@ -841,8 +836,7 @@
       if (tile->draw_info().is_checker_imaged() ||
           tile->raster_task_scheduled_with_checker_images()) {
         AddCheckeredImagesToDecodeQueue(
-            prioritized_tile, raster_color_space.color_space,
-            CheckerImageTracker::DecodeType::kRaster,
+            prioritized_tile, CheckerImageTracker::DecodeType::kRaster,
             &work_to_schedule.checker_image_decode_queue);
       }
     }
@@ -899,7 +893,6 @@
 
 void TileManager::PartitionImagesForCheckering(
     const PrioritizedTile& prioritized_tile,
-    const gfx::ColorSpace& raster_color_space,
     std::vector<DrawImage>* sync_decoded_images,
     std::vector<PaintImage>* checkered_images,
     const gfx::Rect* invalidated_rect,
@@ -922,7 +915,7 @@
       (*image_to_frame_index)[image.stable_id()] = frame_index;
 
     DrawImage draw_image(*original_draw_image, tile->raster_transform().scale(),
-                         frame_index, raster_color_space);
+                         frame_index);
     if (checker_image_tracker_.ShouldCheckerImage(draw_image, tree))
       checkered_images->push_back(draw_image.paint_image());
     else
@@ -932,7 +925,6 @@
 
 void TileManager::AddCheckeredImagesToDecodeQueue(
     const PrioritizedTile& prioritized_tile,
-    const gfx::ColorSpace& raster_color_space,
     CheckerImageTracker::DecodeType decode_type,
     CheckerImageTracker::ImageDecodeQueue* image_decode_queue) {
   Tile* tile = prioritized_tile.tile();
@@ -945,7 +937,7 @@
     size_t frame_index = client_->GetFrameIndexForImage(
         original_draw_image->paint_image(), tree);
     DrawImage draw_image(*original_draw_image, tile->raster_transform().scale(),
-                         frame_index, raster_color_space);
+                         frame_index);
     if (checker_image_tracker_.ShouldCheckerImage(draw_image, tree)) {
       image_decode_queue->emplace_back(draw_image.paint_image(), decode_type);
     }
@@ -981,9 +973,6 @@
 
   graph_.Reset();
 
-  gfx::ColorSpace raster_color_space =
-      client_->GetRasterColorSpace().color_space;
-
   scoped_refptr<TileTask> required_for_activation_done_task =
       CreateTaskSetFinishedTask(
           &TileManager::DidFinishRunningTileTasksRequiredForActivation);
@@ -1038,9 +1027,8 @@
   for (const PrioritizedTile& prioritized_tile : tiles_to_process_for_images) {
     std::vector<DrawImage> sync_decoded_images;
     std::vector<PaintImage> checkered_images;
-    PartitionImagesForCheckering(prioritized_tile, raster_color_space,
-                                 &sync_decoded_images, &checkered_images,
-                                 nullptr);
+    PartitionImagesForCheckering(prioritized_tile, &sync_decoded_images,
+                                 &checkered_images, nullptr);
 
     // Add the sync decoded images to |new_locked_images| so they can be added
     // to the task graph.
@@ -1132,7 +1120,6 @@
 
 scoped_refptr<TileTask> TileManager::CreateRasterTask(
     const PrioritizedTile& prioritized_tile,
-    const RasterColorSpace& raster_color_space,
     PrioritizedWorkToSchedule* work_to_schedule) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "TileManager::CreateRasterTask");
@@ -1149,7 +1136,7 @@
         tile->id(), tile->invalidated_content_rect(), tile->invalidated_id(),
         &invalidated_rect);
   }
-
+  const RasterColorSpace& raster_color_space = client_->GetRasterColorSpace();
   bool partial_tile_decode = false;
   if (resource) {
     resource_content_id = tile->invalidated_id();
@@ -1180,8 +1167,8 @@
   base::flat_map<PaintImage::Id, size_t> image_id_to_current_frame_index;
   if (!skip_images) {
     PartitionImagesForCheckering(
-        prioritized_tile, raster_color_space.color_space, &sync_decoded_images,
-        &checkered_images, partial_tile_decode ? &invalidated_rect : nullptr,
+        prioritized_tile, &sync_decoded_images, &checkered_images,
+        partial_tile_decode ? &invalidated_rect : nullptr,
         &image_id_to_current_frame_index);
   }
 
@@ -1243,7 +1230,6 @@
   }
 
   PlaybackImageProvider image_provider(image_controller_.cache(),
-                                       raster_color_space.color_space,
                                        std::move(settings));
 
   playback_settings.raster_color_space = raster_color_space;
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index 35efee34..87fabafd 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -347,7 +347,6 @@
   void FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(Tile* tile);
   scoped_refptr<TileTask> CreateRasterTask(
       const PrioritizedTile& prioritized_tile,
-      const RasterColorSpace& raster_color_space,
       PrioritizedWorkToSchedule* work_to_schedule);
 
   std::unique_ptr<EvictionTilePriorityQueue>
@@ -380,14 +379,12 @@
 
   void PartitionImagesForCheckering(
       const PrioritizedTile& prioritized_tile,
-      const gfx::ColorSpace& raster_color_space,
       std::vector<DrawImage>* sync_decoded_images,
       std::vector<PaintImage>* checkered_images,
       const gfx::Rect* invalidated_rect,
       base::flat_map<PaintImage::Id, size_t>* image_to_frame_index = nullptr);
   void AddCheckeredImagesToDecodeQueue(
       const PrioritizedTile& prioritized_tile,
-      const gfx::ColorSpace& raster_color_space,
       CheckerImageTracker::DecodeType decode_type,
       CheckerImageTracker::ImageDecodeQueue* image_decode_queue);
 
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index 52c0a974..7fbe4f3 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -3365,9 +3365,9 @@
 
   // Add the images to our decoded_image_tracker.
   host_impl()->tile_manager()->decoded_image_tracker().QueueImageDecode(
-      image1, gfx::ColorSpace(), base::DoNothing());
+      image1, base::DoNothing());
   host_impl()->tile_manager()->decoded_image_tracker().QueueImageDecode(
-      image2, gfx::ColorSpace(), base::DoNothing());
+      image2, base::DoNothing());
   EXPECT_EQ(0u, host_impl()
                     ->tile_manager()
                     ->decoded_image_tracker()
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index ef9f0b99b..223fa3b 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -457,7 +457,7 @@
 void LayerTreeHostImpl::UpdateSyncTreeAfterCommitOrImplSideInvalidation() {
   // LayerTreeHost may have changed the GPU rasterization flags state, which
   // may require an update of the tree resources.
-  UpdateTreeResourcesForGpuRasterizationIfNeeded();
+  UpdateTreeResourcesIfNeeded();
   sync_tree()->set_needs_update_draw_properties();
 
   // We need an update immediately post-commit to have the opportunity to create
@@ -2409,8 +2409,15 @@
   return true;
 }
 
-void LayerTreeHostImpl::UpdateTreeResourcesForGpuRasterizationIfNeeded() {
-  if (!UpdateGpuRasterizationStatus())
+void LayerTreeHostImpl::UpdateTreeResourcesIfNeeded() {
+  // For simplicity, clobber all resources when the color space changes.
+  // This is mostly to clear the image decode caches, which don't handle
+  // multiple color space at once.
+  int color_space_id = GetRasterColorSpace().color_space_id;
+  bool color_space_changed = last_color_space_id_ != color_space_id;
+  last_color_space_id_ = color_space_id;
+
+  if (!UpdateGpuRasterizationStatus() && !color_space_changed)
     return;
 
   // Clean up and replace existing tile manager with another one that uses
@@ -3066,13 +3073,15 @@
         viz::ResourceFormatToClosestSkColorType(/*gpu_compositing=*/true,
                                                 tile_format),
         settings_.decoded_image_working_set_budget_bytes, max_texture_size_,
-        paint_image_generator_client_id_);
+        paint_image_generator_client_id_,
+        GetRasterColorSpace().color_space.ToSkColorSpace());
   } else {
     bool gpu_compositing = !!layer_tree_frame_sink_->context_provider();
     image_decode_cache_ = std::make_unique<SoftwareImageDecodeCache>(
         viz::ResourceFormatToClosestSkColorType(gpu_compositing, tile_format),
         settings_.decoded_image_working_set_budget_bytes,
-        paint_image_generator_client_id_);
+        paint_image_generator_client_id_,
+        GetRasterColorSpace().color_space.ToSkColorSpace());
   }
 
   // Pass the single-threaded synchronous task graph runner to the worker pool
@@ -3172,9 +3181,8 @@
   // Optimistically specify the current raster color space, since we assume that
   // it won't change.
   tile_manager_.decoded_image_tracker().QueueImageDecode(
-      image, GetRasterColorSpace().color_space,
-      base::Bind(&LayerTreeHostImpl::ImageDecodeFinished,
-                 base::Unretained(this), request_id));
+      image, base::Bind(&LayerTreeHostImpl::ImageDecodeFinished,
+                        base::Unretained(this), request_id));
   tile_manager_.checker_image_tracker().DisallowCheckeringForImage(image);
 }
 
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index f879057..07d3792 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -778,7 +778,7 @@
 
   // Returns true if status changed.
   bool UpdateGpuRasterizationStatus();
-  void UpdateTreeResourcesForGpuRasterizationIfNeeded();
+  void UpdateTreeResourcesIfNeeded();
 
   Viewport* viewport() const { return viewport_.get(); }
 
@@ -1106,6 +1106,7 @@
   base::circular_deque<FrameTokenInfo> frame_token_infos_;
   ui::FrameMetrics frame_metrics_;
   ui::SkippedFrameTracker skipped_frame_tracker_;
+  int last_color_space_id_ = -1;
   bool is_animating_for_snap_;
 
   const PaintImage::GeneratorClientId paint_image_generator_client_id_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 48db654..846ad6bb1 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -9895,6 +9895,11 @@
   // RequiresHighResToDraw is set when new output surface is used.
   EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
 
+  // The first commit will also set RequiresHighResToDraw due to the
+  // raster color space changing.
+  host_impl_->ResetRequiresHighResToDraw();
+  host_impl_->CommitComplete();
+  EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
   host_impl_->ResetRequiresHighResToDraw();
 
   host_impl_->SetContentHasSlowPaths(false);
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index a7ab71ce8..a3eeff0 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -8322,8 +8322,7 @@
 
     image_ = DrawImage(CreateDiscardablePaintImage(gfx::Size(400, 400)),
                        SkIRect::MakeWH(400, 400), kNone_SkFilterQuality,
-                       SkMatrix::I(), PaintImage::kDefaultFrameIndex,
-                       gfx::ColorSpace());
+                       SkMatrix::I(), PaintImage::kDefaultFrameIndex);
     auto callback =
         base::Bind(&LayerTreeHostTestQueueImageDecode::ImageDecodeFinished,
                    base::Unretained(this));
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 4f0c551..9d3b70a6 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -818,13 +818,14 @@
     root_->AddChild(child_);
     child_->AddChild(grandchild_);
 
-    layer_tree_host()->SetRootLayer(root_);
     LayerTreeHostContextTest::SetupTree();
     client_.set_bounds(root_->bounds());
   }
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
+  void AttachTree() { layer_tree_host()->SetRootLayer(root_); }
+
   void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
     LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
 
@@ -842,6 +843,18 @@
     ++num_commits_;
     switch (num_commits_) {
       case 1:
+        // Because setting the colorspace on the first activation releases
+        // resources, don't attach the layers until the first activation.
+        // Because of single thread vs multi thread differences (i.e.
+        // commit to active tree), if this delay is not done, then the
+        // active tree layers will have a different number of resource
+        // releasing.
+        MainThreadTaskRunner()->PostTask(
+            FROM_HERE,
+            base::BindOnce(&LayerTreeHostContextTestLayersNotified::AttachTree,
+                           base::Unretained(this)));
+        break;
+      case 2:
         EXPECT_EQ(0u, root_picture->release_resources_count());
         EXPECT_EQ(0u, child_picture->release_resources_count());
         EXPECT_EQ(0u, grandchild_picture->release_resources_count());
@@ -850,7 +863,7 @@
         LoseContext();
         times_to_fail_create_ = 1;
         break;
-      case 2:
+      case 3:
         EXPECT_TRUE(root_picture->release_resources_count());
         EXPECT_TRUE(child_picture->release_resources_count());
         EXPECT_TRUE(grandchild_picture->release_resources_count());
diff --git a/chrome/VERSION b/chrome/VERSION
index 570b070..fac53b8 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=72
 MINOR=0
-BUILD=3604
+BUILD=3605
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
index 3786b32..aa0f68d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -10,6 +10,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
@@ -29,12 +30,14 @@
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Queue;
 
 /**
  * Bridge to native side autofill_assistant::UiControllerAndroid. It allows native side to control
@@ -57,6 +60,9 @@
     private static final String AUTH_TOKEN_TYPE =
             "oauth2:https://www.googleapis.com/auth/userinfo.profile";
 
+    /** Display the final message for that long before shutting everything down. */
+    private static final long GRACEFUL_SHUTDOWN_DELAY_MS = 5000;
+
     private static final String RFC_3339_FORMAT = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ";
 
     private final WebContents mWebContents;
@@ -139,17 +145,14 @@
             public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
                 currentTabModel.removeObserver(this);
 
-                // Assume newly selected tab is always different from the last one.
-                mUiDelegateHolder.shutdown();
-                // TODO(crbug.com/806868): May start a new Autofill Assistant instance for the newly
-                // selected Tab.
+                nativeGiveUp(mUiControllerAndroid);
             }
         });
     }
 
     @Override
     public void onDismiss() {
-        mUiDelegateHolder.showDismissSnackbar();
+        mUiDelegateHolder.dismiss();
     }
 
     @Override
@@ -246,6 +249,11 @@
     }
 
     @CalledByNative
+    private void onShutdownGracefully() {
+        mUiDelegateHolder.enterGracefulShutdownMode();
+    }
+
+    @CalledByNative
     private void onUpdateScripts(
             String[] scriptNames, String[] scriptPaths, boolean[] scriptsHighlightFlags) {
         assert scriptNames.length == scriptPaths.length;
@@ -350,9 +358,10 @@
 
         private boolean mShouldQueueUiOperations = false;
         private boolean mHasBeenShutdown = false;
+        private boolean mIsShuttingDown = false;
         private SnackbarManager.SnackbarController mDismissSnackbar;
-        private final ArrayList<Callback<AutofillAssistantUiDelegate>> mPendingUiOperations =
-                new ArrayList<>();
+        private final Queue<Callback<AutofillAssistantUiDelegate>> mPendingUiOperations =
+                new ArrayDeque<>();
 
         private UiDelegateHolder(AutofillAssistantUiDelegate uiDelegate) {
             mUiDelegate = uiDelegate;
@@ -365,7 +374,9 @@
          *  - never if Autofill Assistant is shut down.
          */
         public void performUiOperation(Callback<AutofillAssistantUiDelegate> operation) {
-            assert !mHasBeenShutdown;
+            if (mHasBeenShutdown || mIsShuttingDown) {
+                return;
+            }
 
             if (mShouldQueueUiOperations) {
                 mPendingUiOperations.add(operation);
@@ -376,12 +387,19 @@
         }
 
         /**
-         * Hides the UI, pauses UI operations and, unless undone within the time delay, eventually
-         * destroy everything.
+         * Handles the dismiss operation.
+         *
+         * In normal mode, hides the UI, pauses UI operations and, unless undone within the time
+         * delay, eventually destroy everything. In graceful shutdown mode, shutdown immediately.
          */
-        public void showDismissSnackbar() {
+        public void dismiss() {
             assert !mHasBeenShutdown;
 
+            if (mIsShuttingDown) {
+                shutdown();
+                return;
+            }
+
             pauseUiOperations();
             mUiDelegate.hide();
             mDismissSnackbar = new SnackbarManager.SnackbarController() {
@@ -401,7 +419,22 @@
             mUiDelegate.showAutofillAssistantStoppedSnackbar(mDismissSnackbar);
         }
 
-        /** Hides the UI and destroys everything. */
+        /** Enters graceful shutdown mode once we can again perform UI operations. */
+        public void enterGracefulShutdownMode() {
+            mUiDelegateHolder.performUiOperation(uiDelegate -> {
+                mIsShuttingDown = true;
+                mPendingUiOperations.clear();
+                uiDelegate.enterGracefulShutdownMode();
+                ThreadUtils.postOnUiThreadDelayed(this ::shutdown, GRACEFUL_SHUTDOWN_DELAY_MS);
+            });
+        }
+
+        /**
+         * Hides the UI and destroys everything.
+         *
+         * <p>Shutdown is final: After this call from the C++ side, as it's been deleted and no UI
+         * operation can run.
+         */
         public void shutdown() {
             if (mHasBeenShutdown) {
                 return;
@@ -430,10 +463,9 @@
          */
         private void unpauseUiOperations() {
             mShouldQueueUiOperations = false;
-            for (int i = 0; i < mPendingUiOperations.size(); i++) {
-                mPendingUiOperations.get(i).onResult(mUiDelegate);
+            while (!mPendingUiOperations.isEmpty()) {
+                mPendingUiOperations.remove().onResult(mUiDelegate);
             }
-            mPendingUiOperations.clear();
         }
     }
 
@@ -528,6 +560,7 @@
     private native long nativeInit(WebContents webContents, String[] parameterNames,
             String[] parameterValues, String initialUrl);
     private native void nativeDestroy(long nativeUiControllerAndroid);
+    private native void nativeGiveUp(long nativeUiControllerAndroid);
     private native void nativeOnScriptSelected(long nativeUiControllerAndroid, String scriptPath);
     private native void nativeOnAddressSelected(long nativeUiControllerAndroid, String guid);
     private native void nativeOnCardSelected(long nativeUiControllerAndroid, String guid);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
index 858f8d0..b444d54c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
@@ -377,6 +377,21 @@
         mActivity.getSnackbarManager().dismissSnackbars(controller);
     }
 
+    /**
+     * Enters a simplified pre-shutdown state, with only a goodbye message - the current status
+     * message - and a close button.
+     */
+    public void enterGracefulShutdownMode() {
+        // TODO(crbug.com/806868): Introduce a proper, separate shutdown dialog, with enough space
+        // to display longer messages. Setting the max lines and hiding the feedback button are
+        // hacks to give enough space to display long messages.
+        mStatusMessageView.setMaxLines(4);
+        mBottomBar.findViewById(R.id.feedback_button).setVisibility(View.GONE);
+        hideProgressBar();
+        hideDetails();
+        hideChipsViewContainer();
+    }
+
     /** Called to show overlay. */
     public void showOverlay() {
         mOverlay.setVisibility(View.VISIBLE);
@@ -519,6 +534,10 @@
 
     private void clearChipsViewContainer() {
         mChipsViewContainer.removeAllViews();
+        hideChipsViewContainer();
+    }
+
+    private void hideChipsViewContainer() {
         mChipsViewContainer.setVisibility(View.GONE);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
index c0c80db1..24fab23f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -347,7 +347,7 @@
             BookmarkUtils.setLastUsedUrl(mActivity, state.mUrl);
             // If a loading state is replaced by another loading state, do not notify this change.
             if (mNativePage != null) {
-                mNativePage.onStateChange(state.mUrl);
+                mNativePage.onStateChange(state.mUrl, false);
             }
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java
index 2c6ed15..6caf0c9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.customtabs.dynamicmodule;
 
+import android.os.Bundle;
 import android.os.RemoteException;
 
 /**
@@ -60,4 +61,17 @@
             assert false;
         }
     }
+
+
+    /**
+     * Introduced in API version 6.
+     */
+    public void onBundleReceived(Bundle bundle) {
+        if (getModuleVersion() < 6) return;
+        try {
+            mEntryPoint.onBundleReceived(ObjectWrapper.wrap(bundle));
+        } catch (RemoteException e) {
+            assert false;
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleLoader.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleLoader.java
index a8aaf06f..b993b40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleLoader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleLoader.java
@@ -9,6 +9,7 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Process;
 import android.support.annotation.Nullable;
@@ -25,6 +26,9 @@
 import org.chromium.chrome.browser.crash.CrashKeys;
 import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleMetrics.DestructionReason;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Dynamically loads a module from another apk.
  */
@@ -44,6 +48,7 @@
     private boolean mIsModuleLoading;
 
     private final ObserverList<Callback<ModuleEntryPoint>> mCallbacks = new ObserverList<>();
+    private final List<Bundle> mPendingBundles = new ArrayList<>();
 
     /**
      * The timestamp of the moment the module became unused. This is used to determine whether or
@@ -115,6 +120,19 @@
     }
 
     /**
+     * Loads the dynamic module if it is not loaded yet,
+     * and transfers the bundle to it regardless of the previous loaded state.
+     */
+    public void sendBundleToModule(Bundle bundle) {
+        if (mModuleEntryPoint != null) {
+            mModuleEntryPoint.onBundleReceived(bundle);
+            return;
+        }
+        mPendingBundles.add(bundle);
+        loadModule();
+    }
+
+    /**
      * Register a callback to receive a {@link ModuleEntryPoint} asynchronously.
      * If the module fails to load, the callback will receive null.
      * If the module was already loaded and a reference to it is still held,
@@ -202,6 +220,14 @@
         mCallbacks.clear();
     }
 
+    private void sendAllBundles() {
+        assert !mIsModuleLoading;
+        for (Bundle bundle: mPendingBundles) {
+            mModuleEntryPoint.onBundleReceived(bundle);
+        }
+        mPendingBundles.clear();
+    }
+
     /**
      * A task for loading the module entry point class on a background thread.
      */
@@ -280,10 +306,12 @@
                 long entryPointInitStartTime = ModuleMetrics.now();
                 entryPoint.init(moduleHost);
                 ModuleMetrics.recordEntryPointInitTime(entryPointInitStartTime);
+
                 ModuleMetrics.recordLoadResult(ModuleMetrics.LoadResult.SUCCESS_NEW);
                 mModuleEntryPoint = entryPoint;
                 mModuleUnusedTimeMs = ModuleMetrics.now();
                 runAndClearCallbacks();
+                sendAllBundles();
                 return;
             } catch (Exception e) {
                 // No multi-catch below API level 19 for reflection exceptions.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
index c878cc45..95b3088 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
@@ -11,10 +11,10 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.SnackbarActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.download.home.DownloadManagerCoordinator;
 import org.chromium.chrome.browser.download.home.DownloadManagerCoordinatorFactory;
 import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
+import org.chromium.chrome.browser.download.home.filter.Filters;
 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorNotificationBridgeUiFactory;
 import org.chromium.chrome.browser.download.ui.DownloadManagerUi;
 import org.chromium.chrome.browser.util.IntentUtils;
@@ -22,25 +22,25 @@
 import org.chromium.ui.base.AndroidPermissionDelegate;
 
 import java.lang.ref.WeakReference;
-import java.util.Deque;
-import java.util.LinkedList;
 
 /**
  * Activity for managing downloads handled through Chrome.
  */
 public class DownloadActivity extends SnackbarActivity {
+    private static final String BUNDLE_KEY_CURRENT_URL = "current_url";
+
     private DownloadManagerCoordinator mDownloadCoordinator;
     private boolean mIsOffTheRecord;
     private AndroidPermissionDelegate mPermissionDelegate;
 
-    /** Caches the stack of filters applied to let the user backtrack through their history. */
-    private final Deque<String> mBackStack = new LinkedList<>();
+    /** Caches the current URL for the filter being applied. */
+    private String mCurrentUrl;
 
     private final DownloadManagerCoordinator.Observer mUiObserver =
             new DownloadManagerCoordinator.Observer() {
                 @Override
                 public void onUrlChanged(String url) {
-                    if (!url.equals(mBackStack.peek())) mBackStack.push(url);
+                    mCurrentUrl = url;
                 }
             };
 
@@ -64,9 +64,21 @@
         setContentView(mDownloadCoordinator.getView());
         mIsOffTheRecord = isOffTheRecord;
         mDownloadCoordinator.addObserver(mUiObserver);
-        // Call updateForUrl() to align with how DownloadPage interacts with DownloadManagerUi.
-        mDownloadCoordinator.updateForUrl(UrlConstants.DOWNLOADS_URL);
-        if (showPrefetchContent) mDownloadCoordinator.showPrefetchSection();
+
+        if (savedInstanceState != null) {
+            mCurrentUrl = savedInstanceState.getString(BUNDLE_KEY_CURRENT_URL);
+        } else {
+            mCurrentUrl = Filters.toUrl(
+                    showPrefetchContent ? Filters.FilterType.PREFETCHED : Filters.FilterType.NONE);
+        }
+
+        mDownloadCoordinator.updateForUrl(mCurrentUrl);
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mCurrentUrl != null) outState.putString(BUNDLE_KEY_CURRENT_URL, mCurrentUrl);
     }
 
     @Override
@@ -78,16 +90,7 @@
     @Override
     public void onBackPressed() {
         if (mDownloadCoordinator.onBackPressed()) return;
-        // The top of the stack always represents the current filter. When back is pressed,
-        // the top is popped off and the new top indicates what filter to use. If there are
-        // no filters remaining, the Activity itself is closed.
-        if (mBackStack.size() > 1) {
-            mBackStack.pop();
-            mDownloadCoordinator.updateForUrl(mBackStack.peek());
-        } else {
-            if (!mBackStack.isEmpty()) mBackStack.pop();
-            super.onBackPressed();
-        }
+        super.onBackPressed();
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
index b4746d1..f1f1255 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
@@ -98,6 +98,10 @@
     // DownloadManagerCoordinator.Observer implementation.
     @Override
     public void onUrlChanged(String url) {
-        onStateChange(url);
+        // We want to squash consecutive download home URLs having different filters into the one
+        // having the latest filter. This will avoid requiring user to press back button too many
+        // times to exit download home. In the event, chrome gets killed or if user navigates away
+        // from download home, we still will be able to come back to the latest filter.
+        onStateChange(url, true);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
index 88f7c30c..1a7c713c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -418,7 +418,7 @@
         for (Observer observer : mObservers) observer.onUrlChanged(url);
 
         if (mNativePage != null) {
-            mNativePage.onStateChange(DownloadFilter.getUrlForFilter(filter));
+            mNativePage.onStateChange(DownloadFilter.getUrlForFilter(filter), true);
         }
 
         RecordHistogram.recordEnumeratedHistogram(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/BasicNativePage.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/BasicNativePage.java
index 2cb51ed..9f3bdf7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/BasicNativePage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/BasicNativePage.java
@@ -106,10 +106,14 @@
 
     /**
      * Tells the native page framework that the url should be changed.
+     * @param url The URL of the page.
+     * @param replaceLastUrl Whether the last navigation entry should be replaced with the new URL.
      */
-    public void onStateChange(String url) {
+    public void onStateChange(String url, boolean replaceLastUrl) {
         if (url.equals(mUrl)) return;
-        mHost.loadUrl(new LoadUrlParams(url), /* incognito = */ false);
+        LoadUrlParams params = new LoadUrlParams(url);
+        params.setShouldReplaceCurrentEntry(replaceLastUrl);
+        mHost.loadUrl(params, /* incognito = */ false);
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/jsdialog/VrBrowserJavaScriptModalDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/jsdialog/VrBrowserJavaScriptModalDialogTest.java
index 4332ad46..f2516f7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/jsdialog/VrBrowserJavaScriptModalDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/jsdialog/VrBrowserJavaScriptModalDialogTest.java
@@ -17,7 +17,6 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -80,7 +79,6 @@
     @Test
     @MediumTest
     @Feature({"Browser", "RenderTest"})
-    @DisabledTest
     public void testPromptModalDialog() throws ExecutionException, IOException {
         testModalDialogImpl(
                 "js_modal_view_vr_prompt", "prompt('Is the tree closed?', 'Hopefully not')");
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index aba9454..d40e6e9 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -36,7 +36,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/crash_keys.h"
 #include "chrome/common/logging_chrome.h"
-#include "chrome/common/profiling.h"
 #include "chrome/common/trace_event_args_whitelist.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/gpu/chrome_content_gpu_client.h"
@@ -55,6 +54,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/profiling.h"
 #include "content/public/common/service_names.mojom.h"
 #include "extensions/common/constants.h"
 #include "net/url_request/url_request.h"
@@ -352,7 +352,7 @@
 
 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
 void SIGTERMProfilingShutdown(int signal) {
-  Profiling::Stop();
+  content::Profiling::Stop();
   struct sigaction sigact;
   memset(&sigact, 0, sizeof(sigact));
   sigact.sa_handler = SIG_DFL;
@@ -556,7 +556,7 @@
   chrome::common::mac::EnableCFBundleBlocker();
 #endif
 
-  Profiling::ProcessStarted();
+  content::Profiling::ProcessStarted();
 
   base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
       base::Bind(&IsTraceEventArgsWhitelisted));
@@ -1055,8 +1055,8 @@
 }
 
 void ChromeMainDelegate::ZygoteForked() {
-  Profiling::ProcessStarted();
-  if (Profiling::BeingProfiled()) {
+  content::Profiling::ProcessStarted();
+  if (content::Profiling::BeingProfiled()) {
     base::debug::RestartProfilingAfterFork();
     SetUpProfilingShutdownHandler();
   }
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
index 66655e1f..6eb480d 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -112,6 +112,11 @@
       AttachCurrentThread(), java_autofill_assistant_ui_controller_);
 }
 
+void UiControllerAndroid::ShutdownGracefully() {
+  Java_AutofillAssistantUiController_onShutdownGracefully(
+      AttachCurrentThread(), java_autofill_assistant_ui_controller_);
+}
+
 void UiControllerAndroid::UpdateScripts(
     const std::vector<ScriptHandle>& scripts) {
   std::vector<std::string> script_paths;
@@ -356,6 +361,12 @@
   ui_delegate_->OnDestroy();
 }
 
+void UiControllerAndroid::GiveUp(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jcaller) {
+  ui_delegate_->OnGiveUp();
+}
+
 static jlong JNI_AutofillAssistantUiController_Init(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h
index df6451b..3245e52 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.h
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -40,6 +40,7 @@
   void ShowOverlay() override;
   void HideOverlay() override;
   void Shutdown() override;
+  void ShutdownGracefully() override;
   void UpdateScripts(const std::vector<ScriptHandle>& scripts) override;
   void ChooseAddress(
       base::OnceCallback<void(const std::string&)> callback) override;
@@ -69,6 +70,7 @@
 
   // Called by Java.
   void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void GiveUp(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
   void OnScriptSelected(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& jcaller,
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 71f95fc..d38b48a 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -120,7 +120,6 @@
 #include "chrome/common/media/media_resource_provider.h"
 #include "chrome/common/net/net_resource_provider.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/common/profiling.h"
 #include "chrome/common/stack_sampling_configuration.h"
 #include "chrome/common/thread_profiler.h"
 #include "chrome/grit/generated_resources.h"
@@ -176,6 +175,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
+#include "content/public/common/profiling.h"
 #include "content/public/common/service_manager_connection.h"
 #include "device/vr/buildflags/buildflags.h"
 #include "extensions/buildflags/buildflags.h"
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 15a2d2e..09c6ccba 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2114,9 +2114,6 @@
       switches::kPpapiFlashArgs,
       switches::kPpapiFlashPath,
       switches::kPpapiFlashVersion,
-      switches::kProfilingAtStart,
-      switches::kProfilingFile,
-      switches::kProfilingFlush,
       switches::kReaderModeHeuristics,
       translate::switches::kTranslateSecurityOrigin,
     };
@@ -2157,12 +2154,6 @@
     if (browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) &&
         !command_line->HasSwitch(switches::kDisableBreakpad))
       command_line->AppendSwitch(switches::kDisableBreakpad);
-    static const char* const kSwitchNames[] = {
-        switches::kProfilingAtStart, switches::kProfilingFile,
-        switches::kProfilingFlush,
-    };
-    command_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
-                                   base::size(kSwitchNames));
   }
 
   StackSamplingConfiguration::Get()->AppendCommandLineSwitchForChildProcess(
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 04d630b4..438e25d9 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -2200,6 +2200,7 @@
     "lock_screen_apps/state_controller_unittest.cc",
     "login/auth/cryptohome_authenticator_unittest.cc",
     "login/demo_mode/demo_extensions_external_loader_unittest.cc",
+    "login/demo_mode/demo_mode_detector_unittest.cc",
     "login/demo_mode/demo_mode_resources_remover_unittest.cc",
     "login/demo_mode/demo_session_unittest.cc",
     "login/demo_mode/demo_setup_controller_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/arc_optin_uma.cc b/chrome/browser/chromeos/arc/arc_optin_uma.cc
index 60c73d8..e6a8af1 100644
--- a/chrome/browser/chromeos/arc/arc_optin_uma.cc
+++ b/chrome/browser/chromeos/arc/arc_optin_uma.cc
@@ -89,6 +89,10 @@
       GetHistogramName("Arc.Provisioning.Result.", profile), result);
 }
 
+void UpdateSecondarySigninResultUMA(ProvisioningResult result) {
+  UMA_HISTOGRAM_ENUMERATION("Arc.Secondary.Signin.Result", result);
+}
+
 void UpdateProvisioningTiming(const base::TimeDelta& elapsed_time,
                               bool success,
                               const Profile* profile) {
@@ -148,6 +152,11 @@
                            static_cast<int>(state));
 }
 
+void UpdateSecondaryAccountSilentAuthCodeUMA(OptInSilentAuthCode state) {
+  base::UmaHistogramSparse("Arc.OptInSilentAuthCode.SecondaryAccount",
+                           static_cast<int>(state));
+}
+
 std::ostream& operator<<(std::ostream& os, const ProvisioningResult& result) {
 #define MAP_PROVISIONING_RESULT(name) \
   case ProvisioningResult::name:      \
diff --git a/chrome/browser/chromeos/arc/arc_optin_uma.h b/chrome/browser/chromeos/arc/arc_optin_uma.h
index 2542980..dbbffac7 100644
--- a/chrome/browser/chromeos/arc/arc_optin_uma.h
+++ b/chrome/browser/chromeos/arc/arc_optin_uma.h
@@ -218,6 +218,7 @@
 void UpdateEnabledStateByUserTypeUMA(bool enabled, const Profile* profile);
 void UpdateProvisioningResultUMA(ProvisioningResult result,
                                  const Profile* profile);
+void UpdateSecondarySigninResultUMA(ProvisioningResult result);
 void UpdateProvisioningTiming(const base::TimeDelta& elapsed_time,
                               bool success,
                               const Profile* profile);
@@ -229,6 +230,7 @@
 void UpdateSupervisionTransitionResultUMA(
     mojom::SupervisionChangeStatus result);
 void UpdateReauthorizationSilentAuthCodeUMA(OptInSilentAuthCode state);
+void UpdateSecondaryAccountSilentAuthCodeUMA(OptInSilentAuthCode state);
 void UpdateAuthTiming(const char* histogram_name, base::TimeDelta elapsed_time);
 void UpdateAuthCheckinAttempts(int32_t num_attempts);
 void UpdateAuthAccountCheckStatus(mojom::AccountCheckStatus status);
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
index 033054ff..8811125 100644
--- a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
@@ -159,6 +159,16 @@
   return chromeos::AccountMapperUtil::IsEqual(account_key, primary_account_id);
 }
 
+std::string GetGaiaIdFromAccountName(
+    const AccountTrackerService* account_tracker_service,
+    const std::string& account_name) {
+  std::string gaia_id =
+      account_tracker_service->FindAccountInfoByEmail(account_name).gaia;
+  DCHECK(!gaia_id.empty());
+
+  return gaia_id;
+}
+
 }  // namespace
 
 // static
@@ -221,28 +231,46 @@
   pending_token_requests_.clear();
 }
 
-void ArcAuthService::OnAuthorizationComplete(mojom::ArcSignInStatus status,
-                                             bool initial_signin) {
-  if (!initial_signin) {
-    // Note, UMA for initial signin is updated from ArcSessionManager.
-    DCHECK_NE(mojom::ArcSignInStatus::SUCCESS_ALREADY_PROVISIONED, status);
-    UpdateReauthorizationResultUMA(
-        ConvertArcSignInStatusToProvisioningResult(status), profile_);
+void ArcAuthService::OnAuthorizationComplete(
+    mojom::ArcSignInStatus status,
+    bool initial_signin,
+    const base::Optional<std::string>& account_name) {
+  if (initial_signin) {
+    DCHECK(!account_name.has_value());
+    // UMA for initial signin is updated from ArcSessionManager.
+    ArcSessionManager::Get()->OnProvisioningFinished(
+        ConvertArcSignInStatusToProvisioningResult(status));
     return;
   }
 
-  ArcSessionManager::Get()->OnProvisioningFinished(
-      ConvertArcSignInStatusToProvisioningResult(status));
+  if (!account_name.has_value() ||
+      IsPrimaryAccount(chromeos::AccountManager::AccountKey{
+          GetGaiaIdFromAccountName(account_tracker_service_,
+                                   account_name.value()),
+          chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA})) {
+    // Reauthorization for the Primary Account.
+    // The check for |!account_name.has_value()| is for backwards compatibility
+    // with older ARC versions, for which Mojo will set |account_name| to
+    // empty/null.
+    DCHECK_NE(mojom::ArcSignInStatus::SUCCESS_ALREADY_PROVISIONED, status);
+    UpdateReauthorizationResultUMA(
+        ConvertArcSignInStatusToProvisioningResult(status), profile_);
+  } else {
+    UpdateSecondarySigninResultUMA(
+        ConvertArcSignInStatusToProvisioningResult(status));
+  }
 }
 
 void ArcAuthService::OnSignInCompleteDeprecated() {
-  OnAuthorizationComplete(mojom::ArcSignInStatus::SUCCESS,
-                          true /* initial_signin */);
+  OnAuthorizationComplete(mojom::ArcSignInStatus::SUCCESS /* status */,
+                          true /* initial_signin */,
+                          base::nullopt /* account_name */);
 }
 
 void ArcAuthService::OnSignInFailedDeprecated(mojom::ArcSignInStatus reason) {
   DCHECK_NE(mojom::ArcSignInStatus::SUCCESS, reason);
-  OnAuthorizationComplete(reason, true /* initial_signin */);
+  OnAuthorizationComplete(reason /* status */, true /* initial_signin */,
+                          base::nullopt /* account_name */);
 }
 
 void ArcAuthService::ReportMetrics(mojom::MetricsType metrics_type,
@@ -332,13 +360,10 @@
   // This is the post provisioning flow.
   // This request could have come for re-authenticating an existing account in
   // ARC, or for signing in a new Secondary Account.
-  const std::string gaia_id =
-      account_tracker_service_->FindAccountInfoByEmail(account_name).gaia;
-  DCHECK(!gaia_id.empty());
 
   // Check if |account_name| points to a Secondary Account.
   if (!IsPrimaryAccount(chromeos::AccountManager::AccountKey{
-          gaia_id,
+          GetGaiaIdFromAccountName(account_tracker_service_, account_name),
           chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA})) {
     FetchSecondaryAccountInfo(account_name, std::move(callback));
     return;
@@ -628,7 +653,9 @@
     const std::string& account_id,
     bool initial_signin) {
   auto fetcher = std::make_unique<ArcBackgroundAuthCodeFetcher>(
-      url_loader_factory_, profile_, account_id, initial_signin);
+      url_loader_factory_, profile_, account_id, initial_signin,
+      IsPrimaryAccount(
+          account_mapper_util_.OAuthAccountIdToAccountKey(account_id)));
   if (skip_merge_session_for_testing_)
     fetcher->SkipMergeSessionForTesting();
 
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service.h b/chrome/browser/chromeos/arc/auth/arc_auth_service.h
index b46418c..2b8edaa4 100644
--- a/chrome/browser/chromeos/arc/auth/arc_auth_service.h
+++ b/chrome/browser/chromeos/arc/auth/arc_auth_service.h
@@ -62,8 +62,10 @@
   void OnConnectionClosed() override;
 
   // mojom::AuthHost:
-  void OnAuthorizationComplete(mojom::ArcSignInStatus status,
-                               bool initial_signin) override;
+  void OnAuthorizationComplete(
+      mojom::ArcSignInStatus status,
+      bool initial_signin,
+      const base::Optional<std::string>& account_name) override;
   void OnSignInCompleteDeprecated() override;
   void OnSignInFailedDeprecated(mojom::ArcSignInStatus reason) override;
   void RequestAccountInfoDeprecated(bool initial_signin) override;
diff --git a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
index 79f158f9..3d1c440 100644
--- a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
@@ -51,12 +51,14 @@
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     Profile* profile,
     const std::string& account_id,
-    bool initial_signin)
+    bool initial_signin,
+    bool is_primary_account)
     : OAuth2TokenService::Consumer(kConsumerName),
       url_loader_factory_(std::move(url_loader_factory)),
       profile_(profile),
       context_(profile_, account_id),
       initial_signin_(initial_signin),
+      is_primary_account_(is_primary_account),
       weak_ptr_factory_(this) {}
 
 ArcBackgroundAuthCodeFetcher::~ArcBackgroundAuthCodeFetcher() = default;
@@ -226,8 +228,11 @@
   if (initial_signin_) {
     UpdateSilentAuthCodeUMA(uma_status);
   } else {
-    // TODO(sinhak): Check if we need to migrate this / create a new metric.
-    UpdateReauthorizationSilentAuthCodeUMA(uma_status);
+    // Not the initial provisioning.
+    if (is_primary_account_)
+      UpdateReauthorizationSilentAuthCodeUMA(uma_status);
+    else
+      UpdateSecondaryAccountSilentAuthCodeUMA(uma_status);
   }
   std::move(callback_).Run(!auth_code.empty(), auth_code);
 }
diff --git a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.h b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.h
index 593522a..9be2089 100644
--- a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.h
+++ b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.h
@@ -43,7 +43,8 @@
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       Profile* profile,
       const std::string& account_id,
-      bool initial_signin);
+      bool initial_signin,
+      bool is_primary_account);
   ~ArcBackgroundAuthCodeFetcher() override;
 
   // ArcAuthCodeFetcher:
@@ -78,7 +79,11 @@
 
   // Keeps context of account code request. |initial_signin_| is true if request
   // is made for initial sign-in flow.
-  bool initial_signin_;
+  const bool initial_signin_;
+
+  // Is this fetcher being used to fetch auth codes for the Device/Primary
+  // Account on Chrome OS.
+  const bool is_primary_account_;
 
   base::WeakPtrFactory<ArcBackgroundAuthCodeFetcher> weak_ptr_factory_;
 
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index eec9b1f..f8b032b 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -451,6 +451,7 @@
     if (integration_service_->drivefs_holder_ &&
         integration_service_->remount_when_online_ && !is_offline) {
       integration_service_->remount_when_online_ = false;
+      integration_service_->mount_start_ = {};
       integration_service_->AddDriveMountPoint();
       return;
     }
@@ -761,6 +762,7 @@
     drivefs_total_failures_count_ = 0;
     drivefs_consecutive_failures_count_ = 0;
     mount_failed_ = false;
+    mount_start_ = {};
   }
 }
 
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index f8fdb24..c964eb96 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -253,14 +253,8 @@
                       TestCase("imageOpenGalleryOpenDrive").DisableDriveFs(),
                       TestCase("imageOpenGalleryOpenDrive").EnableDriveFs()));
 
-// NaCl fails to compile zip plugin.pexe too often on ASAN, crbug.com/867738
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_ZipFiles DISABLED_ZipFiles
-#else
-#define MAYBE_ZipFiles ZipFiles
-#endif
 WRAPPED_INSTANTIATE_TEST_CASE_P(
-    MAYBE_ZipFiles, /* zip_files.js */
+    ZipFiles, /* zip_files.js */
     FilesAppBrowserTest,
     ::testing::Values(ZipCase("zipFileOpenDownloads").InGuestMode(),
                       ZipCase("zipFileOpenDownloads"),
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
index c2edc4c..6390767 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -218,24 +218,12 @@
 
     TestEntryInfo(EntryType type,
                   const std::string& source_file_name,
-                  const std::string& target_path,
-                  const std::string& mime_type,
-                  const std::string& team_drive_name,
-                  const std::string& computer_name,
-                  SharedOption shared_option,
-                  const base::Time& last_modified_time,
-                  const EntryCapabilities& capabilities,
-                  bool pinned)
+                  const std::string& target_path)
         : type(type),
-          shared_option(shared_option),
+          shared_option(NONE),
           source_file_name(source_file_name),
           target_path(target_path),
-          team_drive_name(team_drive_name),
-          computer_name(computer_name),
-          mime_type(mime_type),
-          last_modified_time(last_modified_time),
-          capabilities(capabilities),
-          pinned(pinned) {}
+          last_modified_time(base::Time::Now()) {}
 
     EntryType type;                  // Entry type: file or directory.
     SharedOption shared_option;      // File entry sharing option.
@@ -249,6 +237,42 @@
     EntryCapabilities capabilities;  // Entry permissions.
     bool pinned = false;             // Whether the file should be pinned.
 
+    TestEntryInfo& SetSharedOption(SharedOption option) {
+      shared_option = option;
+      return *this;
+    }
+
+    TestEntryInfo& SetMimeType(const std::string& type) {
+      mime_type = type;
+      return *this;
+    }
+
+    TestEntryInfo& SetTeamDriveName(const std::string& name) {
+      team_drive_name = name;
+      return *this;
+    }
+
+    TestEntryInfo& SetComputerName(const std::string& name) {
+      computer_name = name;
+      return *this;
+    }
+
+    TestEntryInfo& SetLastModifiedTime(const base::Time& time) {
+      last_modified_time = time;
+      return *this;
+    }
+
+    TestEntryInfo& SetEntryCapabilities(
+        const EntryCapabilities& new_capabilities) {
+      capabilities = new_capabilities;
+      return *this;
+    }
+
+    TestEntryInfo& SetPinned(bool is_pinned) {
+      pinned = is_pinned;
+      return *this;
+    }
+
     // Registers the member information to the given converter.
     static void RegisterJSONConverter(
         base::JSONValueConverter<TestEntryInfo>* converter) {
@@ -589,14 +613,11 @@
 
     // Note: must be kept in sync with BASIC_FAKE_ENTRY_SET defined in the
     // integration_tests/file_manager JS code.
-    CreateEntry(AddEntriesMessage::TestEntryInfo(
-        AddEntriesMessage::FILE, "text.txt", "hello.txt", "text/plain",
-        std::string(), std::string(), AddEntriesMessage::SharedOption::NONE,
-        base::Time::Now(), AddEntriesMessage::EntryCapabilities(), false));
-    CreateEntry(AddEntriesMessage::TestEntryInfo(
-        AddEntriesMessage::DIRECTORY, std::string(), "A", std::string(),
-        std::string(), std::string(), AddEntriesMessage::SharedOption::NONE,
-        base::Time::Now(), AddEntriesMessage::EntryCapabilities(), false));
+    CreateEntry(AddEntriesMessage::TestEntryInfo(AddEntriesMessage::FILE,
+                                                 "text.txt", "hello.txt")
+                    .SetMimeType("text/plain"));
+    CreateEntry(AddEntriesMessage::TestEntryInfo(AddEntriesMessage::DIRECTORY,
+                                                 std::string(), "A"));
     base::RunLoop().RunUntilIdle();
     return true;
   }
@@ -605,22 +626,17 @@
     if (!CreateRootDirectory(profile))
       return false;
 
+    CreateEntry(AddEntriesMessage::TestEntryInfo(AddEntriesMessage::DIRECTORY,
+                                                 "", "DCIM"));
+    CreateEntry(AddEntriesMessage::TestEntryInfo(AddEntriesMessage::FILE,
+                                                 "image2.png", "image2.png")
+                    .SetMimeType("image/png"));
     CreateEntry(AddEntriesMessage::TestEntryInfo(
-        AddEntriesMessage::DIRECTORY, "", "DCIM", std::string(), std::string(),
-        "", AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
-        AddEntriesMessage::EntryCapabilities(), false));
-    CreateEntry(AddEntriesMessage::TestEntryInfo(
-        AddEntriesMessage::FILE, "image2.png", "image2.png", std::string(),
-        std::string(), "image/png", AddEntriesMessage::SharedOption::NONE,
-        base::Time::Now(), AddEntriesMessage::EntryCapabilities(), false));
-    CreateEntry(AddEntriesMessage::TestEntryInfo(
-        AddEntriesMessage::FILE, "image3.jpg", "DCIM/image3.jpg", std::string(),
-        std::string(), "image/jpeg", AddEntriesMessage::SharedOption::NONE,
-        base::Time::Now(), AddEntriesMessage::EntryCapabilities(), false));
-    CreateEntry(AddEntriesMessage::TestEntryInfo(
-        AddEntriesMessage::FILE, "text.txt", "DCIM/hello.txt", std::string(),
-        std::string(), "text/plain", AddEntriesMessage::SharedOption::NONE,
-        base::Time::Now(), AddEntriesMessage::EntryCapabilities(), false));
+                    AddEntriesMessage::FILE, "image3.jpg", "DCIM/image3.jpg")
+                    .SetMimeType("image/png"));
+    CreateEntry(AddEntriesMessage::TestEntryInfo(AddEntriesMessage::FILE,
+                                                 "text.txt", "DCIM/hello.txt")
+                    .SetMimeType("text/plain"));
     base::RunLoop().RunUntilIdle();
     return true;
   }
diff --git a/chrome/browser/chromeos/idle_detector.cc b/chrome/browser/chromeos/idle_detector.cc
index 8b9547f..d7144f67 100644
--- a/chrome/browser/chromeos/idle_detector.cc
+++ b/chrome/browser/chromeos/idle_detector.cc
@@ -4,14 +4,15 @@
 
 #include "chrome/browser/chromeos/idle_detector.h"
 
-#include "base/bind.h"
-#include "base/logging.h"
+#include "base/location.h"
+#include "base/time/default_tick_clock.h"
 #include "ui/base/user_activity/user_activity_detector.h"
 
 namespace chromeos {
 
-IdleDetector::IdleDetector(const base::Closure& on_idle_callback)
-    : idle_callback_(on_idle_callback) {}
+IdleDetector::IdleDetector(const base::RepeatingClosure& on_idle_callback,
+                           const base::TickClock* tick_clock)
+    : timer_(tick_clock), idle_callback_(on_idle_callback) {}
 
 IdleDetector::~IdleDetector() {
   ui::UserActivityDetector* user_activity_detector =
diff --git a/chrome/browser/chromeos/idle_detector.h b/chrome/browser/chromeos/idle_detector.h
index 68c964f..d18c2cf 100644
--- a/chrome/browser/chromeos/idle_detector.h
+++ b/chrome/browser/chromeos/idle_detector.h
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_CHROMEOS_IDLE_DETECTOR_H_
 
 #include "base/callback.h"
-#include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "ui/base/user_activity/user_activity_observer.h"
@@ -16,7 +16,9 @@
 
 class IdleDetector : public ui::UserActivityObserver {
  public:
-  explicit IdleDetector(const base::Closure& on_idle_callback);
+  IdleDetector(const base::RepeatingClosure& on_idle_callback,
+               const base::TickClock* tick_clock);
+
   ~IdleDetector() override;
 
   void Start(const base::TimeDelta& timeout);
@@ -30,7 +32,7 @@
 
   base::OneShotTimer timer_;
 
-  base::Closure idle_callback_;
+  base::RepeatingClosure idle_callback_;
 
   base::TimeDelta timeout_;
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_mode_detector.cc b/chrome/browser/chromeos/login/demo_mode/demo_mode_detector.cc
index 1e7ea817..b22ce143 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_mode_detector.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_mode_detector.cc
@@ -5,34 +5,45 @@
 #include "chrome/browser/chromeos/login/demo_mode/demo_mode_detector.h"
 
 #include "base/command_line.h"
+#include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/sys_info.h"
+#include "base/time/default_tick_clock.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/chromeos_switches.h"
+#include "chromeos/dbus/dbus_switches.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 
-namespace {
-const int kDerelectDetectionTimeoutSeconds = 8 * 60 * 60;  // 8 hours.
-const int kDerelectIdleTimeoutSeconds = 5 * 60;            // 5 minutes.
-const int kOobeTimerUpdateIntervalSeconds = 5 * 60;        // 5 minutes.
-}  // namespace
 
 namespace chromeos {
 
+const base::TimeDelta DemoModeDetector::kDerelictDetectionTimeout =
+    base::TimeDelta::FromHours(8);
+const base::TimeDelta DemoModeDetector::kDerelictIdleTimeout =
+    base::TimeDelta::FromMinutes(5);
+const base::TimeDelta DemoModeDetector::kOobeTimerUpdateInterval =
+    base::TimeDelta::FromMinutes(5);
+
 // static
 void DemoModeDetector::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterInt64Pref(prefs::kTimeOnOobe, 0);
 }
 
-DemoModeDetector::DemoModeDetector() : weak_ptr_factory_(this) {
+DemoModeDetector::DemoModeDetector()
+    : tick_clock_(base::DefaultTickClock::GetInstance()),
+      weak_ptr_factory_(this) {
   SetupTimeouts();
 }
 
 DemoModeDetector::~DemoModeDetector() {}
 
+void DemoModeDetector::SetTickClockForTest(const base::TickClock* test_clock) {
+  tick_clock_ = test_clock;
+}
+
 void DemoModeDetector::InitDetection() {
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableDemoMode))
@@ -44,6 +55,14 @@
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDerelictIdleTimeout);
 
+  // Devices in retail won't be in dev mode, and DUTs (devices under test) often
+  // sit unused at OOBE for a while.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kSystemDevMode) &&
+      !has_derelict_switch) {
+    return;
+  }
+
   if (base::SysInfo::IsRunningOnChromeOS() && !has_derelict_switch) {
     std::string track;
     // We're running on an actual device; if we cannot find our release track
@@ -66,8 +85,9 @@
 
 void DemoModeDetector::StartIdleDetection() {
   if (!idle_detector_) {
-    idle_detector_.reset(new IdleDetector(
-        base::Bind(&DemoModeDetector::OnIdle, weak_ptr_factory_.GetWeakPtr())));
+    auto callback = base::BindRepeating(&DemoModeDetector::OnIdle,
+                                        weak_ptr_factory_.GetWeakPtr());
+    idle_detector_ = std::make_unique<IdleDetector>(callback, tick_clock_);
   }
   idle_detector_->Start(derelict_idle_timeout_);
 }
@@ -107,33 +127,37 @@
       base::TimeDelta::FromSeconds(prefs->GetInt64(prefs::kTimeOnOobe));
 
   int derelict_detection_timeout;
-  if (!cmdline->HasSwitch(switches::kDerelictDetectionTimeout) ||
-      !base::StringToInt(
+  if (cmdline->HasSwitch(switches::kDerelictDetectionTimeout) &&
+      base::StringToInt(
           cmdline->GetSwitchValueASCII(switches::kDerelictDetectionTimeout),
           &derelict_detection_timeout)) {
-    derelict_detection_timeout = kDerelectDetectionTimeoutSeconds;
+    derelict_detection_timeout_ =
+        base::TimeDelta::FromSeconds(derelict_detection_timeout);
+  } else {
+    derelict_detection_timeout_ = kDerelictDetectionTimeout;
   }
-  derelict_detection_timeout_ =
-      base::TimeDelta::FromSeconds(derelict_detection_timeout);
 
   int derelict_idle_timeout;
-  if (!cmdline->HasSwitch(switches::kDerelictIdleTimeout) ||
-      !base::StringToInt(
+  if (cmdline->HasSwitch(switches::kDerelictIdleTimeout) &&
+      base::StringToInt(
           cmdline->GetSwitchValueASCII(switches::kDerelictIdleTimeout),
           &derelict_idle_timeout)) {
-    derelict_idle_timeout = kDerelectIdleTimeoutSeconds;
+    derelict_idle_timeout_ =
+        base::TimeDelta::FromSeconds(derelict_idle_timeout);
+  } else {
+    derelict_idle_timeout_ = kDerelictIdleTimeout;
   }
-  derelict_idle_timeout_ = base::TimeDelta::FromSeconds(derelict_idle_timeout);
 
   int oobe_timer_update_interval;
-  if (!cmdline->HasSwitch(switches::kOobeTimerInterval) ||
-      !base::StringToInt(
+  if (cmdline->HasSwitch(switches::kOobeTimerInterval) &&
+      base::StringToInt(
           cmdline->GetSwitchValueASCII(switches::kOobeTimerInterval),
           &oobe_timer_update_interval)) {
-    oobe_timer_update_interval = kOobeTimerUpdateIntervalSeconds;
+    oobe_timer_update_interval_ =
+        base::TimeDelta::FromSeconds(oobe_timer_update_interval);
+  } else {
+    oobe_timer_update_interval_ = kOobeTimerUpdateInterval;
   }
-  oobe_timer_update_interval_ =
-      base::TimeDelta::FromSeconds(oobe_timer_update_interval);
 
   // In case we'd be derelict before our timer is set to trigger, reduce
   // the interval so we check again when we're scheduled to go derelict.
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_mode_detector.h b/chrome/browser/chromeos/login/demo_mode/demo_mode_detector.h
index 27bb68a..913a012 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_mode_detector.h
+++ b/chrome/browser/chromeos/login/demo_mode/demo_mode_detector.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/idle_detector.h"
@@ -31,6 +32,13 @@
   // Registers the preference for derelict state.
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
+  // Sets an alternative clock for testing purposes.
+  void SetTickClockForTest(const base::TickClock* test_clock);
+
+  static const base::TimeDelta kDerelictDetectionTimeout;
+  static const base::TimeDelta kDerelictIdleTimeout;
+  static const base::TimeDelta kOobeTimerUpdateInterval;
+
  private:
   void StartIdleDetection();
   void StartOobeTimer();
@@ -57,6 +65,8 @@
 
   bool demo_launched_ = false;
 
+  const base::TickClock* tick_clock_;
+
   base::WeakPtrFactory<DemoModeDetector> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DemoModeDetector);
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_mode_detector_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_mode_detector_unittest.cc
new file mode 100644
index 0000000..4740dce5
--- /dev/null
+++ b/chrome/browser/chromeos/login/demo_mode/demo_mode_detector_unittest.cc
@@ -0,0 +1,228 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/demo_mode/demo_mode_detector.h"
+
+#include <memory>
+
+#include "base/memory/ref_counted.h"
+#include "base/test/scoped_command_line.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/login/ui/mock_login_display_host.h"
+#include "chrome/browser/chromeos/scoped_set_running_on_chromeos_for_testing.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/dbus/dbus_switches.h"
+#include "components/prefs/testing_pref_service.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/user_activity/user_activity_detector.h"
+#include "ui/events/base_event_utils.h"
+
+namespace chromeos {
+
+class DemoModeDetectorTest : public testing::Test {
+ protected:
+  DemoModeDetectorTest();
+  ~DemoModeDetectorTest() override;
+
+  void StartDemoModeDetection();
+  void ExpectDemoModeWillLaunch();
+  void ExpectDemoModeWillNotLaunch();
+  void SetTimeOnOobePref(base::TimeDelta time_on_oobe);
+  base::TimeDelta GetTimeOnOobePref();
+  void DestroyDemoModeDetector();
+  void SimulateUserActivity();
+  scoped_refptr<base::TestMockTimeTaskRunner> runner_;
+
+ private:
+  TestingPrefServiceSimple local_state_;
+  MockLoginDisplayHost login_display_host_;
+  ui::UserActivityDetector user_activity_detector_;
+  std::unique_ptr<DemoModeDetector> demo_mode_detector_;
+  std::unique_ptr<base::ThreadTaskRunnerHandle> runner_handle_;
+};
+
+DemoModeDetectorTest::DemoModeDetectorTest() {
+  TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
+  DemoModeDetector::RegisterPrefs(local_state_.registry());
+  runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+  // If we don't register the TestMockTimeTaskRunner with a
+  // ThreadTaskRunnerHandle, the timers in the test fail
+  // to initialize, saying they need a SequencedContext.
+  runner_handle_ = std::make_unique<base::ThreadTaskRunnerHandle>(runner_);
+}
+
+DemoModeDetectorTest::~DemoModeDetectorTest() {
+  demo_mode_detector_.reset();
+  runner_handle_.reset();
+  TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
+}
+
+void DemoModeDetectorTest::ExpectDemoModeWillLaunch() {
+  EXPECT_CALL(login_display_host_, StartDemoAppLaunch());
+}
+
+void DemoModeDetectorTest::ExpectDemoModeWillNotLaunch() {
+  EXPECT_CALL(login_display_host_, StartDemoAppLaunch()).Times(0);
+}
+
+void DemoModeDetectorTest::StartDemoModeDetection() {
+  demo_mode_detector_ = std::make_unique<DemoModeDetector>();
+  demo_mode_detector_->SetTickClockForTest(runner_->GetMockTickClock());
+  demo_mode_detector_->InitDetection();
+}
+
+void DemoModeDetectorTest::SetTimeOnOobePref(base::TimeDelta time_on_oobe) {
+  local_state_.SetUserPref(prefs::kTimeOnOobe,
+                           std::make_unique<base::Value>(
+                               base::Int64ToString(time_on_oobe.InSeconds())));
+}
+
+base::TimeDelta DemoModeDetectorTest::GetTimeOnOobePref() {
+  return base::TimeDelta::FromSeconds(
+      local_state_.GetInt64(prefs::kTimeOnOobe));
+}
+
+void DemoModeDetectorTest::SimulateUserActivity() {
+  user_activity_detector_.HandleExternalUserActivity();
+}
+
+// Tests follow.
+
+// Test to ensure that Demo mode isn't launched before the detector
+// has entered the derelict state.
+TEST_F(DemoModeDetectorTest, DemoModeWillNotLaunchBeforeDerelict) {
+  ExpectDemoModeWillNotLaunch();
+
+  StartDemoModeDetection();
+  // Run for half the timeout.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictDetectionTimeout -
+                         DemoModeDetector::kDerelictDetectionTimeout / 2);
+}
+
+// Test to ensure that Demo mode isn't launched after the detector
+// has entered the derelict state but before the idle timeout.
+TEST_F(DemoModeDetectorTest,
+       DemoModeWillNotLaunchAfterDerelictAndBeforeIdleTimeout) {
+  ExpectDemoModeWillNotLaunch();
+
+  StartDemoModeDetection();
+  // Run through the derelict threshold.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictDetectionTimeout);
+  // Run for 1 minute less than the idle threshold.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictIdleTimeout -
+                         base::TimeDelta::FromMinutes(1));
+}
+
+// Test to ensure that Demo mode isn't launched after the detector
+// has entered the derelict state but user activity is preventing the idle
+// timeout.
+TEST_F(DemoModeDetectorTest,
+       DemoModeWillNotLaunchAfterDerelictWithUserActivity) {
+  ExpectDemoModeWillNotLaunch();
+
+  StartDemoModeDetection();
+
+  // Run for through the derelict threshold.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictIdleTimeout);
+
+  // Run for 2 more minutes (less than the idle threshold).
+  runner_->FastForwardBy(base::TimeDelta::FromMinutes(2));
+
+  // Simulate a user activity event.
+  SimulateUserActivity();
+
+  // Run for 3 more minutes (more than the idle threshold).
+  runner_->FastForwardBy(base::TimeDelta::FromMinutes(3));
+
+  // Simulate a user activity event.
+  SimulateUserActivity();
+}
+
+// Test to ensure that Demo mode is launched after the detector
+// has entered the derelict state and after the idle timeout.
+TEST_F(DemoModeDetectorTest, DemoModeWillLaunchAfterDerelictAndIdleTimeout) {
+  ExpectDemoModeWillLaunch();
+
+  StartDemoModeDetection();
+  // Run for long enough for all thresholds to be exceeded.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictDetectionTimeout +
+                         DemoModeDetector::kDerelictIdleTimeout);
+}
+
+// Test to ensure that a device in dev mode disables the demo mode.
+TEST_F(DemoModeDetectorTest, DemoModeWillNotLaunchInDevMode) {
+  // Set the command line dev mode switch.
+  auto command_line_ = std::make_unique<base::test::ScopedCommandLine>();
+  command_line_->GetProcessCommandLine()->AppendSwitch(
+      switches::kSystemDevMode);
+
+  ExpectDemoModeWillNotLaunch();
+
+  StartDemoModeDetection();
+
+  // Run through the derelict threshold.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictDetectionTimeout);
+}
+
+// Test to ensure that the --disable-demo-mode switch disables demo mode.
+TEST_F(DemoModeDetectorTest, DemoModeWillNotLaunchWhenDisabledBySwitch) {
+  // Set the command line dev mode switch.
+  auto command_line_ = std::make_unique<base::test::ScopedCommandLine>();
+  command_line_->GetProcessCommandLine()->AppendSwitch(
+      switches::kDisableDemoMode);
+
+  ExpectDemoModeWillNotLaunch();
+
+  StartDemoModeDetection();
+  // Run through the derelict threshold.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictDetectionTimeout);
+}
+
+// Test to ensure that demo mode is disabled on "testimage" LsbRelease
+// CHROMEOS_RELEASE_TRACK values.
+TEST_F(DemoModeDetectorTest, DemoModeWillNotLaunchWhenTestimageInLsbRelease) {
+  std::string lsb_release =
+      "CHROMEOS_RELEASE_NAME=Chromium OS\n"
+      "CHROMEOS_RELEASE_TRACK=testimage\n";
+
+  base::Time release_time;
+  EXPECT_TRUE(
+      base::Time::FromString("Wed, 24 Oct 2018 12:00:00 PDT", &release_time));
+
+  ScopedSetRunningOnChromeOSForTesting version_info(lsb_release, release_time);
+
+  ExpectDemoModeWillNotLaunch();
+
+  StartDemoModeDetection();
+  // Run through the derelict threshold.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictDetectionTimeout);
+}
+
+// Test to ensure that Demo mode is launched after the detector
+// has resumed (i.e. after shutdown/reboot).
+TEST_F(DemoModeDetectorTest,
+       DemoModeWillLaunchAfterResumedAndDerelictAndIdleTimeout) {
+  ExpectDemoModeWillLaunch();
+
+  // Simulate 1 hour less than the threshold elapsed by setting pref.
+  const auto elapsed_time = DemoModeDetector::kDerelictDetectionTimeout -
+                            base::TimeDelta::FromHours(1);
+  SetTimeOnOobePref(elapsed_time);
+  EXPECT_EQ(GetTimeOnOobePref(), elapsed_time);
+
+  StartDemoModeDetection();
+
+  // Run another hour to hit the threshold.
+  runner_->FastForwardBy(base::TimeDelta::FromHours(1));
+
+  // Run through the idle timeout.
+  runner_->FastForwardBy(DemoModeDetector::kDerelictIdleTimeout);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/preloaded_web_view.cc b/chrome/browser/chromeos/login/ui/preloaded_web_view.cc
index 9ff4fb9d3..d9deb17b 100644
--- a/chrome/browser/chromeos/login/ui/preloaded_web_view.cc
+++ b/chrome/browser/chromeos/login/ui/preloaded_web_view.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/login/ui/preloaded_web_view.h"
 
 #include "base/callback_helpers.h"
+#include "base/time/default_tick_clock.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/idle_detector.h"
 #include "chrome/browser/profiles/profile.h"
@@ -35,7 +36,9 @@
 void PreloadedWebView::PreloadOnIdle(PreloadCallback preload) {
   preload_function_ = std::move(preload);
   idle_detector_ = std::make_unique<chromeos::IdleDetector>(
-      base::Bind(&PreloadedWebView::RunPreloader, weak_factory_.GetWeakPtr()));
+      base::BindRepeating(&PreloadedWebView::RunPreloader,
+                          weak_factory_.GetWeakPtr()),
+      base::DefaultTickClock::GetInstance());
   idle_detector_->Start(
       base::TimeDelta::FromSeconds(kIdleSecondsBeforePreloadingLockScreen));
 }
diff --git a/chrome/browser/extensions/user_script_listener_browsertest.cc b/chrome/browser/extensions/user_script_listener_browsertest.cc
index 7fb616c..2d1df834 100644
--- a/chrome/browser/extensions/user_script_listener_browsertest.cc
+++ b/chrome/browser/extensions/user_script_listener_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "build/build_config.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/user_script_listener.h"
 #include "chrome/test/base/testing_profile.h"
@@ -41,9 +42,17 @@
 
 using UserScriptListenerTest = ExtensionBrowserTest;
 
+#if defined(OS_WIN)
+#define MAYBE_NavigationWaitsForContentScriptsToLoad \
+  DISABLED_NavigationWaitsForContentScriptsToLoad
+#else
+#define MAYBE_NavigationWaitsForContentScriptsToLoad \
+  NavigationWaitsForContentScriptsToLoad
+#endif
+
 // Test that navigations block while waiting for content scripts to load.
 IN_PROC_BROWSER_TEST_F(UserScriptListenerTest,
-                       NavigationWaitsForContentScriptsToLoad) {
+                       MAYBE_NavigationWaitsForContentScriptsToLoad) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   TestingProfile profile;
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index deb5840..bc8e44c 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3251,8 +3251,8 @@
 
 const char kEnableMyFilesVolumeName[] = "Enable MyFiles as Volume";
 const char kEnableMyFilesVolumeDescription[] =
-    "Enables use of the MyFiles as a read/write volume. This should be only "
-    "used for testing or for trying to restore previous Downloads content.";
+    "Enables use of MyFiles as a read/write volume. This should be only "
+    "used for testing or for trying to restore the previous Downloads content.";
 
 const char kEnableEhvInputName[] =
     "Emoji, handwriting and voice input on opt-in IME menu";
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index f308b91..9e78907 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -379,6 +379,7 @@
 
 // Deprecated 11/2018.
 const char kNetworkQualities[] = "net.network_qualities";
+const char kForceSessionSync[] = "settings.history_recorded";
 
 // Register prefs used only for migration (clearing or moving to a new key).
 void RegisterProfilePrefsForMigration(
@@ -407,6 +408,7 @@
   registry->RegisterBooleanPref(kReverseAutologinEnabled, true);
 
   registry->RegisterDictionaryPref(kNetworkQualities, PrefRegistry::LOSSY_PREF);
+  registry->RegisterBooleanPref(kForceSessionSync, false);
 }
 
 }  // namespace
@@ -868,4 +870,5 @@
 
   // Added 11/2018.
   profile_prefs->ClearPref(kNetworkQualities);
+  profile_prefs->ClearPref(kForceSessionSync);
 }
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 392ce35..111e2e801 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -379,7 +379,6 @@
   registry->RegisterBooleanPref(prefs::kForceGoogleSafeSearch, false);
   registry->RegisterIntegerPref(prefs::kForceYouTubeRestrict,
                                 safe_search_util::YOUTUBE_RESTRICT_OFF);
-  registry->RegisterBooleanPref(prefs::kForceSessionSync, false);
   registry->RegisterStringPref(prefs::kAllowedDomainsForApps, std::string());
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h
index 3d9bd62..4cab3ddd 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h
@@ -75,9 +75,6 @@
   // The minizip stream used to read the archive file.
   std::unique_ptr<MinizipStream> stream_;
 
-  // The minizip correspondent archive object.
-  ScopedMzZip zip_file_;
-
   // We use two kinds of cache strategies here: dynamic and static.
   // Dynamic cache is a common cache strategy used in most of IO streams such as
   // fread. When a file chunk is requested and if the size of the requested
@@ -154,6 +151,11 @@
 
   // The password cache to access password protected files.
   base::Optional<std::string> password_cache_;
+
+  // The minizip correspondent archive object.
+  // This must be destroyed before the archive stream and any of its buffers
+  // because AES encryption in minizip will try to read the file on close.
+  ScopedMzZip zip_file_;
 };
 
 #endif  // CHROME_BROWSER_RESOURCES_CHROMEOS_ZIP_ARCHIVER_CPP_VOLUME_ARCHIVE_MINIZIP_H_
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
index f3cb15c..534bb90a 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h"
 
+#include <stdlib.h>
+#include <time.h>
+
 #include <map>
 #include <memory>
 #include <string>
@@ -26,6 +29,34 @@
 
 constexpr char kEncryptedZipPassphrase[] = "test123";
 
+struct FileInfo {
+  int64_t size;
+  bool is_directory;
+  time_t mod_time;
+  const char* md5_sum;
+};
+using FileInfoMap = std::map<std::string, FileInfo>;
+const FileInfoMap kSmallZipFiles = {
+    {"file1", {15, false, 1407920154, "b4d9b82bb1cd97aa6191843149df18e6"}},
+    {"file2", {33, false, 1407920174, "b864e9456deb246b018c49ef831f7ca7"}},
+    {"dir/", {0, true, 1407920220, nullptr}},
+    {"dir/file3", {56, false, 1407920220, "bffbca4992b32db8ed72bfc2c88e7f11"}},
+};
+
+const FileInfoMap kPkEncryptedZipFiles = {
+    {"file1", {15, false, 1407920154, "b4d9b82bb1cd97aa6191843149df18e6"}},
+    {"file2", {33, false, 1407920174, "b864e9456deb246b018c49ef831f7ca7"}},
+    {"dir/", {0, true, 1407920220, nullptr}},
+    {"dir/file3", {56, false, 1407920220, "bffbca4992b32db8ed72bfc2c88e7f11"}},
+};
+
+const FileInfoMap kAesEncryptedZipFiles = {
+    {"file1", {15, false, 1528178134, "b4d9b82bb1cd97aa6191843149df18e6"}},
+    {"file2", {33, false, 1528178134, "b864e9456deb246b018c49ef831f7ca7"}},
+    {"dir/", {0, true, 1528178134, nullptr}},
+    {"dir/file3", {56, false, 1528178134, "bffbca4992b32db8ed72bfc2c88e7f11"}},
+};
+
 class TestVolumeReader : public VolumeReader {
  public:
   explicit TestVolumeReader(base::FilePath path)
@@ -74,34 +105,57 @@
     return full_path;
   }
 
-  void SetUp() override {}
+  void SetUp() override {
+    // Zip files are stored as local time, but minizip will do some timezone
+    // conversion internally. Fix the time zone (to Perth, Australia) so make
+    // this test deterministic wherever it is run.
+    // NOTE: Perth is +8, but is set as -8 because of how POSIX defines the TZ
+    // variable.
+    setenv("TZ", "UTC-8", 1);
+    tzset();
+  }
 
-  void TearDown() override {}
+  void CheckFileInfo(VolumeArchiveMinizip* archive, const FileInfo& file_info) {
+    std::string file_path;
+    bool is_utf8 = false;
+    int64_t size = -1;
+    bool is_directory = false;
+    time_t mod_time = 0;
+    auto result = archive->GetCurrentFileInfo(&file_path, &is_utf8, &size,
+                                              &is_directory, &mod_time);
+    EXPECT_EQ(result, VolumeArchive::RESULT_SUCCESS);
+    EXPECT_EQ(size, file_info.size);
+    EXPECT_EQ(is_directory, file_info.is_directory);
+    EXPECT_EQ(mod_time, file_info.mod_time);
+  }
+
+  void CheckFileContents(VolumeArchiveMinizip* archive,
+                         const FileInfo& file_info) {
+    base::MD5Context ctx;
+    base::MD5Init(&ctx);
+    const char* buffer = nullptr;
+    int64_t offset = 0;
+    while (offset < file_info.size) {
+      int64_t read =
+          archive->ReadData(offset, file_info.size - offset, &buffer);
+      ASSERT_GT(read, 0);
+      EXPECT_LE(read, file_info.size - offset);
+      base::MD5Update(&ctx, base::StringPiece(buffer, read));
+      offset += read;
+    }
+    EXPECT_EQ(file_info.size, offset);
+    EXPECT_EQ(0, archive->ReadData(offset, 1, &buffer));
+
+    base::MD5Digest digest;
+    base::MD5Final(&digest, &ctx);
+    std::string md5_sum = base::MD5DigestToBase16(digest);
+    EXPECT_EQ(md5_sum, file_info.md5_sum);
+  }
 
  private:
   std::unique_ptr<VolumeArchiveMinizip> archive_;
 };
 
-struct FileInfo {
-  int64_t size;
-  bool is_directory;
-  time_t mod_time;
-  const char* md5_sum;
-};
-const std::map<std::string, FileInfo> kSmallZipFiles = {
-    {"file1", {15, false, 1407912954, "b4d9b82bb1cd97aa6191843149df18e6"}},
-    {"file2", {33, false, 1407912974, "b864e9456deb246b018c49ef831f7ca7"}},
-    {"dir/", {0, true, 1407913020, nullptr}},
-    {"dir/file3", {56, false, 1407913020, "bffbca4992b32db8ed72bfc2c88e7f11"}},
-};
-
-const std::map<std::string, FileInfo> kEncryptedZipFiles = {
-    {"file1", {15, false, 1407912954, "b4d9b82bb1cd97aa6191843149df18e6"}},
-    {"file2", {33, false, 1407912974, "b864e9456deb246b018c49ef831f7ca7"}},
-    {"dir/", {0, true, 1407913020, nullptr}},
-    {"dir/file3", {56, false, 1407913020, "bffbca4992b32db8ed72bfc2c88e7f11"}},
-};
-
 TEST_F(VolumeArchiveMinizipTest, Basic) {
   std::unique_ptr<TestVolumeReader> reader =
       std::make_unique<TestVolumeReader>(GetTestZipPath("small_zip.zip"));
@@ -140,19 +194,7 @@
 
   for (auto it : kSmallZipFiles) {
     EXPECT_TRUE(archive.SeekHeader(it.first));
-
-    std::string file_path;
-    bool is_utf8 = false;
-    int64_t size = -1;
-    bool is_directory = false;
-    time_t mod_time = 0;
-    auto result = archive.GetCurrentFileInfo(&file_path, &is_utf8, &size,
-                                             &is_directory, &mod_time);
-    EXPECT_EQ(result, VolumeArchive::RESULT_SUCCESS);
-    EXPECT_EQ(file_path, it.first);
-    EXPECT_EQ(size, it.second.size);
-    EXPECT_EQ(is_directory, it.second.is_directory);
-    EXPECT_EQ(mod_time, it.second.mod_time);
+    CheckFileInfo(&archive, it.second);
   }
 }
 
@@ -178,28 +220,11 @@
     if (it.second.is_directory)
       continue;
 
-    base::MD5Context ctx;
-    base::MD5Init(&ctx);
-    const char* buffer = nullptr;
-    int64_t offset = 0;
-    while (offset < it.second.size) {
-      int64_t read = archive.ReadData(offset, it.second.size - offset, &buffer);
-      ASSERT_GT(read, 0);
-      EXPECT_LE(read, it.second.size - offset);
-      base::MD5Update(&ctx, base::StringPiece(buffer, read));
-      offset += read;
-    }
-    EXPECT_EQ(it.second.size, offset);
-    EXPECT_EQ(0, archive.ReadData(offset, 1, &buffer));
-
-    base::MD5Digest digest;
-    base::MD5Final(&digest, &ctx);
-    std::string md5_sum = base::MD5DigestToBase16(digest);
-    EXPECT_EQ(md5_sum, it.second.md5_sum);
+    CheckFileContents(&archive, it.second);
   }
 }
 
-TEST_F(VolumeArchiveMinizipTest, Encrypted) {
+TEST_F(VolumeArchiveMinizipTest, Encrypted_PkCrypt) {
   std::unique_ptr<TestVolumeReader> reader =
       std::make_unique<TestVolumeReader>(GetTestZipPath("encrypted.zip"));
   reader->set_passphrase(
@@ -207,42 +232,33 @@
   VolumeArchiveMinizip archive(std::move(reader));
   ASSERT_TRUE(archive.Init(""));
 
-  for (auto it : kEncryptedZipFiles) {
+  for (auto it : kPkEncryptedZipFiles) {
     EXPECT_TRUE(archive.SeekHeader(it.first));
-    std::string file_path;
-    bool is_utf8 = false;
-    int64_t size = -1;
-    bool is_directory = false;
-    time_t mod_time = 0;
-    auto result = archive.GetCurrentFileInfo(&file_path, &is_utf8, &size,
-                                             &is_directory, &mod_time);
-    EXPECT_EQ(result, VolumeArchive::RESULT_SUCCESS);
-    EXPECT_EQ(file_path, it.first);
-    EXPECT_EQ(size, it.second.size);
-    EXPECT_EQ(is_directory, it.second.is_directory);
-    EXPECT_EQ(mod_time, it.second.mod_time);
+    CheckFileInfo(&archive, it.second);
 
     if (it.second.is_directory)
       continue;
 
-    base::MD5Context ctx;
-    base::MD5Init(&ctx);
-    const char* buffer = nullptr;
-    int64_t offset = 0;
-    while (offset < it.second.size) {
-      int64_t read = archive.ReadData(offset, it.second.size - offset, &buffer);
-      ASSERT_GT(read, 0);
-      EXPECT_LE(read, it.second.size - offset);
-      base::MD5Update(&ctx, base::StringPiece(buffer, read));
-      offset += read;
-    }
-    EXPECT_EQ(it.second.size, offset);
-    EXPECT_EQ(0, archive.ReadData(offset, 1, &buffer));
+    CheckFileContents(&archive, it.second);
+  }
+}
 
-    base::MD5Digest digest;
-    base::MD5Final(&digest, &ctx);
-    std::string md5_sum = base::MD5DigestToBase16(digest);
-    EXPECT_EQ(md5_sum, it.second.md5_sum);
+TEST_F(VolumeArchiveMinizipTest, Encrypted_AES) {
+  std::unique_ptr<TestVolumeReader> reader =
+      std::make_unique<TestVolumeReader>(GetTestZipPath("encrypted_aes.zip"));
+  reader->set_passphrase(
+      base::make_optional<std::string>(kEncryptedZipPassphrase));
+  VolumeArchiveMinizip archive(std::move(reader));
+  ASSERT_TRUE(archive.Init(""));
+
+  for (auto it : kAesEncryptedZipFiles) {
+    EXPECT_TRUE(archive.SeekHeader(it.first));
+    CheckFileInfo(&archive, it.second);
+
+    if (it.second.is_directory)
+      continue;
+
+    CheckFileContents(&archive, it.second);
   }
 }
 
diff --git a/chrome/browser/resources/chromeos/zip_archiver/test/data/encrypted_aes.zip b/chrome/browser/resources/chromeos/zip_archiver/test/data/encrypted_aes.zip
new file mode 100644
index 0000000..258b5dd
--- /dev/null
+++ b/chrome/browser/resources/chromeos/zip_archiver/test/data/encrypted_aes.zip
Binary files differ
diff --git a/chrome/browser/resources/gaia_auth_host/saml_handler.js b/chrome/browser/resources/gaia_auth_host/saml_handler.js
index f994064b..d713fff7 100644
--- a/chrome/browser/resources/gaia_auth_host/saml_handler.js
+++ b/chrome/browser/resources/gaia_auth_host/saml_handler.js
@@ -338,7 +338,7 @@
         }
       }
 
-      return details;
+      return {};
     },
 
     /**
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
index 3074e77..3e3e35c 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -169,10 +169,6 @@
     SupervisedUserSettingsService* settings_service =
         SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
 
-    settings_service->SetLocalSetting(
-        supervised_users::kRecordHistoryIncludesSessionSync,
-        std::make_unique<base::Value>(false));
-
     // In contrast to legacy SUs, child account SUs must sign in.
     settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
                                       std::make_unique<base::Value>(true));
@@ -215,8 +211,6 @@
   } else {
     SupervisedUserSettingsService* settings_service =
         SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
-    settings_service->SetLocalSetting(
-        supervised_users::kRecordHistoryIncludesSessionSync, nullptr);
     settings_service->SetLocalSetting(supervised_users::kSigninAllowed,
                                       nullptr);
     settings_service->SetLocalSetting(supervised_users::kCookiesAlwaysAllowed,
diff --git a/chrome/browser/supervised_user/supervised_user_constants.cc b/chrome/browser/supervised_user/supervised_user_constants.cc
index f6902f2..04befe66 100644
--- a/chrome/browser/supervised_user/supervised_user_constants.cc
+++ b/chrome/browser/supervised_user/supervised_user_constants.cc
@@ -21,8 +21,6 @@
 const char kForceSafeSearch[] = "ForceSafeSearch";
 const char kGeolocationDisabled[] = "GeolocationDisabled";
 const char kRecordHistory[] = "RecordHistory";
-const char kRecordHistoryIncludesSessionSync[] =
-    "RecordHistoryIncludesSessionSync";
 const char kSafeSitesEnabled[] = "SafeSites";
 const char kSigninAllowed[] = "SigninAllowed";
 const char kUserName[] = "UserName";
diff --git a/chrome/browser/supervised_user/supervised_user_constants.h b/chrome/browser/supervised_user/supervised_user_constants.h
index 222e849..aaa1799 100644
--- a/chrome/browser/supervised_user/supervised_user_constants.h
+++ b/chrome/browser/supervised_user/supervised_user_constants.h
@@ -22,7 +22,6 @@
 extern const char kForceSafeSearch[];
 extern const char kGeolocationDisabled[];
 extern const char kRecordHistory[];
-extern const char kRecordHistoryIncludesSessionSync[];
 extern const char kSafeSitesEnabled[];
 extern const char kSigninAllowed[];
 extern const char kUserName[];
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store.cc b/chrome/browser/supervised_user/supervised_user_pref_store.cc
index 5e063cf..4f659625 100644
--- a/chrome/browser/supervised_user/supervised_user_pref_store.cc
+++ b/chrome/browser/supervised_user/supervised_user_pref_store.cc
@@ -148,13 +148,6 @@
       prefs_->SetInteger(prefs::kIncognitoModeAvailability,
                          record_history ? IncognitoModePrefs::DISABLED
                                         : IncognitoModePrefs::ENABLED);
-
-      bool record_history_includes_session_sync = true;
-      settings->GetBoolean(supervised_users::kRecordHistoryIncludesSessionSync,
-                           &record_history_includes_session_sync);
-      prefs_->SetBoolean(
-          prefs::kForceSessionSync,
-          record_history && record_history_includes_session_sync);
     }
 
     {
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index 9bdd315..4a961df 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -163,10 +163,6 @@
       prefs::kSupervisedUserId,
       base::Bind(&SupervisedUserService::OnSupervisedUserIdChanged,
           base::Unretained(this)));
-  pref_change_registrar_.Add(
-      prefs::kForceSessionSync,
-      base::Bind(&SupervisedUserService::OnForceSessionSyncChanged,
-                 base::Unretained(this)));
 
   browser_sync::ProfileSyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile_);
@@ -353,13 +349,8 @@
   url_reporter_ = std::move(reporter);
 }
 
-bool SupervisedUserService::IncludesSyncSessionsType() const {
-  return includes_sync_sessions_type_;
-}
-
 SupervisedUserService::SupervisedUserService(Profile* profile)
-    : includes_sync_sessions_type_(true),
-      profile_(profile),
+    : profile_(profile),
       active_(false),
       delegate_(NULL),
       is_profile_active_(false),
@@ -719,13 +710,6 @@
     observer.OnURLFilterChanged();
 }
 
-void SupervisedUserService::OnForceSessionSyncChanged() {
-  includes_sync_sessions_type_ =
-      profile_->GetPrefs()->GetBoolean(prefs::kForceSessionSync);
-  ProfileSyncServiceFactory::GetForProfile(profile_)
-      ->ReconfigureDatatypeManager(/*bypass_setup_in_progress_check=*/false);
-}
-
 void SupervisedUserService::Shutdown() {
   if (!did_init_)
     return;
@@ -1004,8 +988,6 @@
     return syncer::ModelTypeSet();
 
   syncer::ModelTypeSet result;
-  if (IncludesSyncSessionsType())
-    result.Put(syncer::SESSIONS);
   result.Put(syncer::EXTENSIONS);
   result.Put(syncer::EXTENSION_SETTINGS);
   result.Put(syncer::APPS);
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h
index 5efa226..da7ef07 100644
--- a/chrome/browser/supervised_user/supervised_user_service.h
+++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -170,10 +170,6 @@
   void SetSafeSearchURLReporter(
       std::unique_ptr<SafeSearchURLReporter> reporter);
 
-  // Returns true if the syncer::SESSIONS type should be included in Sync.
-  // Public for testing.
-  bool IncludesSyncSessionsType() const;
-
   // ProfileKeyedService override:
   void Shutdown() override;
 
@@ -308,16 +304,6 @@
   // corresponding preference is changed.
   void UpdateManualURLs();
 
-  // Subscribes to the SupervisedUserPrefStore, refreshes
-  // |includes_sync_sessions_type_| and triggers reconfiguring the
-  // ProfileSyncService.
-  void OnForceSessionSyncChanged();
-
-  // The option a custodian sets to either record or prevent recording the
-  // supervised user's history. Set by |FetchNewSessionSyncState()| and
-  // defaults to true.
-  bool includes_sync_sessions_type_;
-
   // Owns us via the KeyedService mechanism.
   Profile* profile_;
 
diff --git a/chrome/browser/supervised_user/supervised_user_service_unittest.cc b/chrome/browser/supervised_user/supervised_user_service_unittest.cc
index 4c83e6d7..e2bc1f3d 100644
--- a/chrome/browser/supervised_user/supervised_user_service_unittest.cc
+++ b/chrome/browser/supervised_user/supervised_user_service_unittest.cc
@@ -214,13 +214,6 @@
 
 }  // namespace
 
-TEST_F(SupervisedUserServiceTest, ChangesIncludedSessionOnChangedSettings) {
-  supervised_user_service_->Init();
-  EXPECT_TRUE(supervised_user_service_->IncludesSyncSessionsType());
-  profile_->GetPrefs()->SetBoolean(prefs::kForceSessionSync, false);
-  EXPECT_FALSE(supervised_user_service_->IncludesSyncSessionsType());
-}
-
 #if !defined(OS_ANDROID)
 // Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no
 // DCHECK is hit when the service is destroyed, this test passed.
diff --git a/chrome/browser/sync/test/integration/single_client_autofill_profile_sync_test.cc b/chrome/browser/sync/test/integration/single_client_autofill_profile_sync_test.cc
new file mode 100644
index 0000000..da2e0bcc
--- /dev/null
+++ b/chrome/browser/sync/test/integration/single_client_autofill_profile_sync_test.cc
@@ -0,0 +1,87 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "chrome/browser/sync/test/integration/autofill_helper.h"
+#include "chrome/browser/sync/test/integration/feature_toggler.h"
+#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
+#include "chrome/browser/sync/test/integration/sync_test.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/browser_sync/profile_sync_service.h"
+#include "components/prefs/pref_service.h"
+#include "components/sync/base/model_type.h"
+#include "components/sync/driver/sync_driver_switches.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class AutofillProfileDisabledChecker : public SingleClientStatusChangeChecker {
+ public:
+  explicit AutofillProfileDisabledChecker(
+      browser_sync::ProfileSyncService* service)
+      : SingleClientStatusChangeChecker(service) {}
+  ~AutofillProfileDisabledChecker() override = default;
+
+  // SingleClientStatusChangeChecker implementation.
+  bool IsExitConditionSatisfied() override {
+    return service()->GetTransportState() ==
+               syncer::SyncService::TransportState::ACTIVE &&
+           !service()->GetActiveDataTypes().Has(syncer::AUTOFILL_PROFILE);
+  }
+  std::string GetDebugMessage() const override {
+    return "Waiting for AUTOFILL_PROFILE to get disabled";
+  }
+};
+
+class SingleClientAutofillProfileSyncTest : public FeatureToggler,
+                                            public SyncTest {
+ public:
+  SingleClientAutofillProfileSyncTest()
+      : FeatureToggler(switches::kSyncUSSAutofillProfile),
+        SyncTest(SINGLE_CLIENT) {}
+  ~SingleClientAutofillProfileSyncTest() override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SingleClientAutofillProfileSyncTest);
+};
+
+IN_PROC_BROWSER_TEST_P(SingleClientAutofillProfileSyncTest,
+                       DisablingAutofillAlsoDisablesSyncing) {
+  ASSERT_TRUE(SetupSync());
+  ASSERT_TRUE(GetClient(0)->service()->GetActiveDataTypes().Has(
+      syncer::AUTOFILL_PROFILE));
+
+  // Add an autofill profile.
+  autofill_helper::AddProfile(0, autofill_helper::CreateAutofillProfile(
+                                     autofill_helper::PROFILE_HOMER));
+  autofill::PersonalDataManager* pdm =
+      autofill_helper::GetPersonalDataManager(0);
+  ASSERT_EQ(1uL, pdm->GetProfiles().size());
+
+  // Disable autofill (e.g. via chrome://settings).
+  autofill::prefs::SetProfileAutofillEnabled(GetProfile(0)->GetPrefs(), false);
+
+  // Wait for Sync to get reconfigured.
+  AutofillProfileDisabledChecker(GetClient(0)->service()).Wait();
+
+  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+            GetClient(0)->service()->GetTransportState());
+
+  // This should also disable syncing of autofill profiles.
+  EXPECT_FALSE(GetClient(0)->service()->GetActiveDataTypes().Has(
+      syncer::AUTOFILL_PROFILE));
+  // The autofill profile itself should still be there though.
+  EXPECT_EQ(1uL, pdm->GetProfiles().size());
+}
+
+INSTANTIATE_TEST_CASE_P(USS,
+                        SingleClientAutofillProfileSyncTest,
+                        ::testing::Values(false, true));
+
+}  // namespace
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 982a57f39..2c7657d 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1233,6 +1233,7 @@
       "//components/keep_alive_registry",
       "//components/network_session_configurator/common",
       "//components/ui_metrics",
+      "//components/url_formatter",
       "//components/vector_icons",
       "//components/web_modal",
       "//components/zoom",
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
index f53a4d8..675adc64 100644
--- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
@@ -85,6 +85,7 @@
     AutofillMetrics::LogSaveCardPromptMetric(
         AutofillMetrics::SAVE_CARD_PROMPT_SHOW_REQUESTED, is_upload_save_,
         is_reshow_, should_request_name_from_user_,
+        should_request_expiration_date_from_user_,
         pref_service_->GetInteger(
             prefs::kAutofillAcceptSaveCreditCardPromptState),
         GetSecurityLevel());
@@ -120,6 +121,7 @@
     AutofillMetrics::LogSaveCardPromptMetric(
         AutofillMetrics::SAVE_CARD_PROMPT_SHOW_REQUESTED, is_upload_save_,
         is_reshow_, should_request_name_from_user_,
+        should_request_expiration_date_from_user_,
         pref_service_->GetInteger(
             prefs::kAutofillAcceptSaveCreditCardPromptState),
         GetSecurityLevel());
@@ -130,6 +132,7 @@
     AutofillMetrics::LogSaveCardPromptMetric(
         AutofillMetrics::SAVE_CARD_PROMPT_END_INVALID_LEGAL_MESSAGE,
         is_upload_save_, is_reshow_, should_request_name_from_user_,
+        should_request_expiration_date_from_user_,
         pref_service_->GetInteger(
             prefs::kAutofillAcceptSaveCreditCardPromptState),
         GetSecurityLevel());
@@ -186,6 +189,7 @@
     AutofillMetrics::LogSaveCardPromptMetric(
         AutofillMetrics::SAVE_CARD_PROMPT_SHOW_REQUESTED, is_upload_save_,
         is_reshow_, should_request_name_from_user_,
+        should_request_expiration_date_from_user_,
         pref_service_->GetInteger(
             prefs::kAutofillAcceptSaveCreditCardPromptState),
         GetSecurityLevel());
@@ -359,6 +363,7 @@
     AutofillMetrics::LogSaveCardPromptMetric(
         AutofillMetrics::SAVE_CARD_PROMPT_END_ACCEPTED, is_upload_save_,
         is_reshow_, should_request_name_from_user_,
+        should_request_expiration_date_from_user_,
         pref_service_->GetInteger(
             prefs::kAutofillAcceptSaveCreditCardPromptState),
         GetSecurityLevel());
@@ -381,6 +386,7 @@
     AutofillMetrics::LogSaveCardPromptMetric(
         AutofillMetrics::SAVE_CARD_PROMPT_END_DENIED, is_upload_save_,
         is_reshow_, should_request_name_from_user_,
+        should_request_expiration_date_from_user_,
         pref_service_->GetInteger(
             prefs::kAutofillAcceptSaveCreditCardPromptState),
         GetSecurityLevel());
@@ -408,6 +414,7 @@
   AutofillMetrics::LogSaveCardPromptMetric(
       AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE,
       is_upload_save_, is_reshow_, should_request_name_from_user_,
+      should_request_expiration_date_from_user_,
       pref_service_->GetInteger(
           prefs::kAutofillAcceptSaveCreditCardPromptState),
       GetSecurityLevel());
@@ -504,6 +511,7 @@
             ? AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING
             : AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_HIDDEN,
         is_upload_save_, is_reshow_, should_request_name_from_user_,
+        should_request_expiration_date_from_user_,
         pref_service_->GetInteger(
             prefs::kAutofillAcceptSaveCreditCardPromptState),
         GetSecurityLevel());
@@ -588,6 +596,7 @@
       AutofillMetrics::LogSaveCardPromptMetric(
           AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, is_upload_save_, is_reshow_,
           should_request_name_from_user_,
+          should_request_expiration_date_from_user_,
           pref_service_->GetInteger(
               prefs::kAutofillAcceptSaveCreditCardPromptState),
           GetSecurityLevel());
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc
index 12159655..81ce530 100644
--- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc
+++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc
@@ -244,6 +244,19 @@
                   Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, 1)));
 }
 
+TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_FirstShow_RequestingExpirationDate_ShowBubble) {
+  base::HistogramTester histogram_tester;
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Autofill.SaveCreditCardPrompt.Upload."
+                                     "FirstShow.RequestingExpirationDate"),
+      ElementsAre(Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOW_REQUESTED, 1),
+                  Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, 1)));
+}
+
 TEST_F(SaveCardBubbleControllerImplTest, Metrics_Upload_Reshows_ShowBubble) {
   ShowUploadBubble();
 
@@ -271,6 +284,20 @@
                   Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, 1)));
 }
 
+TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_Reshows_RequestingExpirationDate_ShowBubble) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  base::HistogramTester histogram_tester;
+  CloseAndReshowBubble();
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Autofill.SaveCreditCardPrompt.Upload."
+                                     "Reshows.RequestingExpirationDate"),
+      ElementsAre(Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOW_REQUESTED, 1),
+                  Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, 1)));
+}
+
 TEST_F(SaveCardBubbleControllerImplTest, Metrics_Local_FirstShow_SaveButton) {
   ShowLocalBubble();
 
@@ -310,6 +337,19 @@
 }
 
 TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_FirstShow_RequestingExpirationDate_SaveButton) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  base::HistogramTester histogram_tester;
+  ClickSaveButton();
+  controller()->OnBubbleClosed();
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.FirstShow.RequestingExpirationDate",
+      AutofillMetrics::SAVE_CARD_PROMPT_END_ACCEPTED, 1);
+}
+
+TEST_F(SaveCardBubbleControllerImplTest,
        Metrics_Upload_Reshows_RequestingCardholderName_SaveButton) {
   ShowUploadBubble(/*should_request_name_from_user=*/true);
   CloseAndReshowBubble();
@@ -323,6 +363,21 @@
       AutofillMetrics::SAVE_CARD_PROMPT_END_ACCEPTED, 1);
 }
 
+TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_Reshows_RequestingExpirationDate_SaveButton) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  CloseAndReshowBubble();
+
+  base::HistogramTester histogram_tester;
+  ClickSaveButton();
+  controller()->OnBubbleClosed();
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.Reshows.RequestingExpirationDate",
+      AutofillMetrics::SAVE_CARD_PROMPT_END_ACCEPTED, 1);
+}
+
 TEST_F(SaveCardBubbleControllerImplTest, Metrics_Local_FirstShow_CancelButton) {
   ShowLocalBubble();
 
@@ -591,6 +646,32 @@
 }
 
 TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_FirstShow_RequestingExpirationDate_NavigateWhileShowing) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  base::HistogramTester histogram_tester;
+  // The bubble should still stick around for up to
+  // kCardBubbleSurviveNavigationTime (5 seconds) regardless of
+  // navigation.
+  test_clock_.Advance(base::TimeDelta::FromSeconds(3));
+
+  controller()->SimulateNavigation();
+
+  histogram_tester.ExpectTotalCount(
+      "Autofill.SaveCreditCardPrompt.Upload.FirstShow.RequestingExpirationDate",
+      0);
+
+  // Wait 3 more seconds (6 total); bubble should go away on next navigation.
+  test_clock_.Advance(base::TimeDelta::FromSeconds(3));
+
+  controller()->SimulateNavigation();
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.FirstShow.RequestingExpirationDate",
+      AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING, 1);
+}
+
+TEST_F(SaveCardBubbleControllerImplTest,
        Metrics_Upload_Reshows_NavigateWhileShowing) {
   ShowUploadBubble();
   CloseAndReshowBubble();
@@ -644,6 +725,34 @@
 }
 
 TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_Reshows_RequestingExpirationDate_NavigateWhileShowing) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  CloseAndReshowBubble();
+
+  base::HistogramTester histogram_tester;
+  // The bubble should still stick around for up to
+  // kCardBubbleSurviveNavigationTime (5 seconds) regardless of
+  // navigation.
+  test_clock_.Advance(base::TimeDelta::FromSeconds(3));
+
+  controller()->SimulateNavigation();
+
+  histogram_tester.ExpectTotalCount(
+      "Autofill.SaveCreditCardPrompt.Upload.Reshows.RequestingExpirationDate",
+      0);
+
+  // Wait 3 more seconds (6 total); bubble should go away on next navigation.
+  test_clock_.Advance(base::TimeDelta::FromSeconds(3));
+
+  controller()->SimulateNavigation();
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.Reshows.RequestingExpirationDate",
+      AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING, 1);
+}
+
+TEST_F(SaveCardBubbleControllerImplTest,
        Metrics_Local_FirstShow_NavigateWhileHidden) {
   ShowLocalBubble();
 
@@ -705,6 +814,21 @@
 }
 
 TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_FirstShow_RequestingExpirationDate_NavigateWhileHidden) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  base::HistogramTester histogram_tester;
+  controller()->OnBubbleClosed();
+  // Fake-navigate after bubble has been visible for a long time.
+  test_clock_.Advance(base::TimeDelta::FromMinutes(1));
+  controller()->SimulateNavigation();
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.FirstShow.RequestingExpirationDate",
+      AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_HIDDEN, 1);
+}
+
+TEST_F(SaveCardBubbleControllerImplTest,
        Metrics_Upload_Reshows_NavigateWhileHidden) {
   ShowUploadBubble();
   CloseAndReshowBubble();
@@ -737,6 +861,23 @@
 }
 
 TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_Reshows_RequestingExpirationDate_NavigateWhileHidden) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  CloseAndReshowBubble();
+
+  base::HistogramTester histogram_tester;
+  controller()->OnBubbleClosed();
+  // Fake-navigate after bubble has been visible for a long time.
+  test_clock_.Advance(base::TimeDelta::FromMinutes(1));
+  controller()->SimulateNavigation();
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.Reshows.RequestingExpirationDate",
+      AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_HIDDEN, 1);
+}
+
+TEST_F(SaveCardBubbleControllerImplTest,
        Metrics_Upload_FirstShow_LegalMessageLink) {
   ShowUploadBubble();
 
@@ -761,6 +902,18 @@
 }
 
 TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_FirstShow_RequestingExpirationDate_LegalMessageLink) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  base::HistogramTester histogram_tester;
+  controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com"));
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.FirstShow.RequestingExpirationDate",
+      AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1);
+}
+
+TEST_F(SaveCardBubbleControllerImplTest,
        Metrics_Upload_Reshows_LegalMessageLink) {
   ShowUploadBubble();
   CloseAndReshowBubble();
@@ -786,6 +939,20 @@
       AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1);
 }
 
+TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_Reshows_RequestingExpirationDate_LegalMessageLink) {
+  ShowUploadBubble(/*should_request_name_from_user=*/false,
+                   /*should_request_expiration_date_from_user=*/true);
+  CloseAndReshowBubble();
+
+  base::HistogramTester histogram_tester;
+  controller()->OnLegalMessageLinkClicked(GURL("http://www.example.com"));
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveCreditCardPrompt.Upload.Reshows.RequestingExpirationDate",
+      AutofillMetrics::SAVE_CARD_PROMPT_DISMISS_CLICK_LEGAL_MESSAGE, 1);
+}
+
 // SAVE_CARD_PROMPT_END_INVALID_LEGAL_MESSAGE is only possible for
 // Upload.FirstShow.
 TEST_F(SaveCardBubbleControllerImplTest,
@@ -839,6 +1006,34 @@
                  1)));
 }
 
+// SAVE_CARD_PROMPT_END_INVALID_LEGAL_MESSAGE is only possible for
+// Upload.FirstShow.
+TEST_F(SaveCardBubbleControllerImplTest,
+       Metrics_Upload_FirstShow_RequestingExpirationDate_InvalidLegalMessage) {
+  base::HistogramTester histogram_tester;
+
+  // Legal message is invalid because it's missing the url.
+  SetLegalMessage(
+      "{"
+      "  \"line\" : [ {"
+      "     \"template\": \"Panda {0}.\","
+      "     \"template_parameter\": [ {"
+      "        \"display_text\": \"bear\""
+      "     } ]"
+      "  } ]"
+      "}",
+      /*should_request_name_from_user=*/false,
+      /*should_request_expiration_date_from_user=*/true);
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Autofill.SaveCreditCardPrompt.Upload."
+                                     "FirstShow.RequestingExpirationDate"),
+      ElementsAre(
+          Bucket(AutofillMetrics::SAVE_CARD_PROMPT_SHOW_REQUESTED, 1),
+          Bucket(AutofillMetrics::SAVE_CARD_PROMPT_END_INVALID_LEGAL_MESSAGE,
+                 1)));
+}
+
 TEST_F(SaveCardBubbleControllerImplTest, OnlyOneActiveBubble_RepeatedLocal) {
   base::HistogramTester histogram_tester;
   ShowLocalBubble();
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 6a7f9b7..78436a32 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -153,7 +153,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/custom_handlers/protocol_handler.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/common/profiling.h"
 #include "chrome/common/ssl_insecure_content.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
@@ -200,6 +199,7 @@
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/page_zoom.h"
+#include "content/public/common/profiling.h"
 #include "content/public/common/renderer_preferences.h"
 #include "content/public/common/webplugininfo.h"
 #include "extensions/browser/extension_prefs.h"
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index 8ac63042..2c61e20 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -44,7 +44,6 @@
 #include "chrome/browser/ui/webui/inspect_ui.h"
 #include "chrome/common/content_restriction.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/common/profiling.h"
 #include "chrome/common/url_constants.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/dom_distiller/core/dom_distiller_switches.h"
@@ -58,6 +57,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/profiling.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/url_constants.h"
 #include "extensions/browser/extension_system.h"
@@ -608,7 +608,7 @@
       ToggleBookmarkBar(browser_);
       break;
     case IDC_PROFILING_ENABLED:
-      Profiling::Toggle();
+      content::Profiling::Toggle();
       break;
 
     case IDC_SHOW_BOOKMARK_MANAGER:
diff --git a/chrome/browser/ui/media_router/media_router_ui_base.cc b/chrome/browser/ui/media_router/media_router_ui_base.cc
index af4f9375..791971f 100644
--- a/chrome/browser/ui/media_router/media_router_ui_base.cc
+++ b/chrome/browser/ui/media_router/media_router_ui_base.cc
@@ -33,6 +33,7 @@
 #include "chrome/common/media_router/route_request_result.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/url_formatter/elide_url.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/common/fullscreen_video_element.mojom.h"
 #include "extensions/browser/extension_registry.h"
@@ -46,15 +47,6 @@
 namespace media_router {
 namespace {
 
-std::string TruncateHost(const std::string& host) {
-  const std::string truncated =
-      net::registry_controlled_domains::GetDomainAndRegistry(
-          host, net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
-  // The truncation will be empty in some scenarios (e.g. host is
-  // simply an IP address). Fail gracefully.
-  return truncated.empty() ? host : truncated;
-}
-
 // Returns the first source in |sources| that can be connected to, or an empty
 // source if there is none.  This is used by the Media Router to find such a
 // matching route if it exists.
@@ -306,14 +298,17 @@
   return enabled_sinks;
 }
 
-std::string MediaRouterUIBase::GetTruncatedPresentationRequestSourceName()
-    const {
+base::string16 MediaRouterUIBase::GetPresentationRequestSourceName() const {
   GURL gurl = GetFrameURL();
   CHECK(initiator_);
+  // Presentation URLs are only possible on https: and other secure contexts,
+  // so we can omit http/https schemes here.
   return gurl.SchemeIs(extensions::kExtensionScheme)
-             ? GetExtensionName(gurl, extensions::ExtensionRegistry::Get(
-                                          initiator_->GetBrowserContext()))
-             : TruncateHost(GetHostFromURL(gurl));
+             ? base::UTF8ToUTF16(
+                   GetExtensionName(gurl, extensions::ExtensionRegistry::Get(
+                                              initiator_->GetBrowserContext())))
+             : url_formatter::FormatUrlForSecurityDisplay(
+                   gurl, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
 }
 
 void MediaRouterUIBase::AddIssue(const IssueInfo& issue) {
@@ -552,10 +547,10 @@
   //     treat subsequent route requests from a Presentation API-initiated
   //     dialogs as browser-initiated.
   // TODO(https://crbug.com/868186): Close the Views dialog in case (2).
-  params.route_result_callbacks.push_back(base::BindOnce(
-      &MediaRouterUIBase::OnRouteResponseReceived, weak_factory_.GetWeakPtr(),
-      current_route_request_->id, sink_id, cast_mode,
-      base::UTF8ToUTF16(GetTruncatedPresentationRequestSourceName())));
+  params.route_result_callbacks.push_back(
+      base::BindOnce(&MediaRouterUIBase::OnRouteResponseReceived,
+                     weak_factory_.GetWeakPtr(), current_route_request_->id,
+                     sink_id, cast_mode, GetPresentationRequestSourceName()));
   if (for_presentation_source) {
     if (start_presentation_context_) {
       // |start_presentation_context_| will be nullptr after this call, as the
@@ -691,7 +686,7 @@
   params.route_result_callbacks.push_back(base::BindOnce(
       &MediaRouterUIBase::OnRouteResponseReceived, weak_factory_.GetWeakPtr(),
       request_id, sink_id, MediaCastMode::LOCAL_FILE,
-      base::UTF8ToUTF16(GetTruncatedPresentationRequestSourceName())));
+      GetPresentationRequestSourceName()));
 
   params.route_result_callbacks.push_back(
       base::BindOnce(&MediaRouterUIBase::MaybeReportCastingSource,
diff --git a/chrome/browser/ui/media_router/media_router_ui_base.h b/chrome/browser/ui/media_router/media_router_ui_base.h
index 424c3a0..954c46b 100644
--- a/chrome/browser/ui/media_router/media_router_ui_base.h
+++ b/chrome/browser/ui/media_router/media_router_ui_base.h
@@ -14,6 +14,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "chrome/browser/media/router/issues_observer.h"
 #include "chrome/browser/media/router/media_router_dialog_controller.h"
@@ -110,8 +111,8 @@
   // excludes the wired display that the initiator WebContents is on.
   virtual std::vector<MediaSinkWithCastModes> GetEnabledSinks() const;
 
-  // Returns a source name that can be shown in the dialog.
-  std::string GetTruncatedPresentationRequestSourceName() const;
+  // Returns a PresentationRequest source name that can be shown in the dialog.
+  base::string16 GetPresentationRequestSourceName() const;
 
   // Calls MediaRouter to add the given issue.
   void AddIssue(const IssueInfo& issue);
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index dccb467f..380a008 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -45,7 +45,6 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/common/profiling.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
@@ -63,6 +62,7 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/profiling.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/layout.h"
 #include "ui/base/models/button_menu_item_model.h"
@@ -629,7 +629,7 @@
         bookmarks::prefs::kShowBookmarkBar);
   }
   if (command_id == IDC_PROFILING_ENABLED)
-    return Profiling::BeingProfiled();
+    return content::Profiling::BeingProfiled();
   if (command_id == IDC_TOGGLE_REQUEST_TABLET_SITE)
     return chrome::IsRequestingTabletSite(browser_);
 
diff --git a/chrome/browser/ui/views/media_router/media_router_views_ui.cc b/chrome/browser/ui/views/media_router/media_router_views_ui.cc
index 7b43c94..fd7bdf0 100644
--- a/chrome/browser/ui/views/media_router/media_router_views_ui.cc
+++ b/chrome/browser/ui/views/media_router/media_router_views_ui.cc
@@ -4,6 +4,10 @@
 
 #include "chrome/browser/ui/views/media_router/media_router_views_ui.h"
 
+#include <string>
+#include <utility>
+#include <vector>
+
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -179,12 +183,12 @@
 }
 
 void MediaRouterViewsUI::UpdateModelHeader() {
-  const std::string source_name = GetTruncatedPresentationRequestSourceName();
+  const base::string16 source_name = GetPresentationRequestSourceName();
   const base::string16 header_text =
       source_name.empty()
           ? l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_CAST_DIALOG_TITLE)
           : l10n_util::GetStringFUTF16(IDS_MEDIA_ROUTER_PRESENTATION_CAST_MODE,
-                                       base::UTF8ToUTF16(source_name));
+                                       source_name);
   model_.set_dialog_header(header_text);
   for (CastDialogController::Observer& observer : observers_)
     observer.OnModelUpdated(model_);
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest_base.h b/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
index 09dfb02..e4aa356 100644
--- a/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
+++ b/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
@@ -21,8 +21,8 @@
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/autofill/core/browser/test_event_waiter.h"
-#include "components/autofill/core/browser/test_sync_service.h"
 #include "components/payments/content/payment_request.h"
+#include "components/sync/driver/test_sync_service.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -269,7 +269,7 @@
   std::unique_ptr<net::EmbeddedTestServer> https_server_;
   // Weak, owned by the PaymentRequest object.
   TestChromePaymentRequestDelegate* delegate_;
-  autofill::TestSyncService sync_service_;
+  syncer::TestSyncService sync_service_;
   sync_preferences::TestingPrefServiceSyncable prefs_;
   bool is_incognito_;
   bool is_valid_ssl_;
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index c6de8a2..c7b41bf 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -8,8 +8,13 @@
 
 source_set("web_applications") {
   sources = [
+    "abstract_web_app_database.h",
     "web_app.cc",
     "web_app.h",
+    "web_app_database.cc",
+    "web_app_database.h",
+    "web_app_database_factory.cc",
+    "web_app_database_factory.h",
     "web_app_install_manager.cc",
     "web_app_install_manager.h",
     "web_app_registrar.cc",
@@ -22,9 +27,14 @@
     ":web_app_group",
     "//chrome/browser/web_applications/components",
     "//chrome/common",
+    "//components/sync",
     "//content/public/browser",
     "//skia",
   ]
+
+  public_deps = [
+    "//chrome/browser/web_applications/proto",
+  ]
 }
 
 source_set("web_applications_test_support") {
@@ -33,6 +43,10 @@
   sources = [
     "test/test_data_retriever.cc",
     "test/test_data_retriever.h",
+    "test/test_web_app_database.cc",
+    "test/test_web_app_database.h",
+    "test/test_web_app_database_factory.cc",
+    "test/test_web_app_database_factory.h",
     "test/web_app_test.cc",
     "test/web_app_test.h",
   ]
@@ -42,6 +56,7 @@
     ":web_applications",
     "//chrome/browser/web_applications/components",
     "//chrome/test:test_support",
+    "//components/sync:test_support_model",
     "//testing/gtest",
   ]
 }
@@ -50,6 +65,7 @@
   testonly = true
 
   sources = [
+    "web_app_database_unittest.cc",
     "web_app_install_manager_unittest.cc",
     "web_app_registrar_unittest.cc",
   ]
diff --git a/chrome/browser/web_applications/abstract_web_app_database.h b/chrome/browser/web_applications/abstract_web_app_database.h
new file mode 100644
index 0000000..a7228db
--- /dev/null
+++ b/chrome/browser/web_applications/abstract_web_app_database.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_ABSTRACT_WEB_APP_DATABASE_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_ABSTRACT_WEB_APP_DATABASE_H_
+
+#include <map>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
+
+namespace web_app {
+
+class WebApp;
+
+using Registry = std::map<AppId, std::unique_ptr<WebApp>>;
+
+// An abstract database for the registry persistence.
+// Exclusively used from the UI thread.
+class AbstractWebAppDatabase {
+ public:
+  virtual ~AbstractWebAppDatabase() = default;
+
+  using OnceRegistryOpenedCallback =
+      base::OnceCallback<void(Registry registry)>;
+  // Open existing or create new DB. Read all data and return it via callback.
+  virtual void OpenDatabase(OnceRegistryOpenedCallback callback) = 0;
+
+  // |OpenDatabase| must have been called and completed before using any other
+  // methods. Otherwise, it fails with DCHECK.
+  virtual void WriteWebApp(const WebApp& web_app) = 0;
+  virtual void DeleteWebApps(std::vector<AppId> app_ids) = 0;
+};
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_ABSTRACT_WEB_APP_DATABASE_H_
diff --git a/chrome/browser/web_applications/components/web_app_constants.h b/chrome/browser/web_applications/components/web_app_constants.h
index 62d64d1..f3c0b08 100644
--- a/chrome/browser/web_applications/components/web_app_constants.h
+++ b/chrome/browser/web_applications/components/web_app_constants.h
@@ -33,7 +33,8 @@
   kFailedUnknownReason = 2,
   kGetWebApplicationInfoFailed = 3,
   kPreviouslyUninstalled = 4,
-  kMaxValue = kPreviouslyUninstalled,
+  kWebContentsDestroyed = 5,
+  kMaxValue = kWebContentsDestroyed,
 };
 
 // Where an app was installed from. This affects what flags will be used when
diff --git a/chrome/browser/web_applications/proto/BUILD.gn b/chrome/browser/web_applications/proto/BUILD.gn
new file mode 100644
index 0000000..58fc6fd
--- /dev/null
+++ b/chrome/browser/web_applications/proto/BUILD.gn
@@ -0,0 +1,14 @@
+# 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.
+
+import("//third_party/protobuf/proto_library.gni")
+
+proto_library("proto") {
+  sources = [
+    "web_app.proto",
+  ]
+  deps = [
+    "//components/sync/protocol",
+  ]
+}
diff --git a/chrome/browser/web_applications/proto/web_app.proto b/chrome/browser/web_applications/proto/web_app.proto
new file mode 100644
index 0000000..77dd32d
--- /dev/null
+++ b/chrome/browser/web_applications/proto/web_app.proto
@@ -0,0 +1,20 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package web_app;
+
+// WebApp class data.
+// TODO(loyso): Consider moving this proto to components/sync/protocol/
+// crbug.com/902214.
+message WebAppProto {
+  // app_id is the client tag for sync system.
+  optional string app_id = 1;
+  optional string name = 2;
+  optional string description = 3;
+  optional string launch_url = 4;
+}
diff --git a/chrome/browser/web_applications/test/test_web_app_database.cc b/chrome/browser/web_applications/test/test_web_app_database.cc
new file mode 100644
index 0000000..731bef6e
--- /dev/null
+++ b/chrome/browser/web_applications/test/test_web_app_database.cc
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/test/test_web_app_database.h"
+
+#include "chrome/browser/web_applications/web_app.h"
+
+namespace web_app {
+
+TestWebAppDatabase::TestWebAppDatabase() {}
+
+TestWebAppDatabase::~TestWebAppDatabase() {}
+
+void TestWebAppDatabase::OpenDatabase(OnceRegistryOpenedCallback callback) {
+  open_database_callback_ = std::move(callback);
+}
+
+void TestWebAppDatabase::WriteWebApp(const WebApp& web_app) {
+  write_web_app_id_ = web_app.app_id();
+}
+
+void TestWebAppDatabase::DeleteWebApps(std::vector<AppId> app_ids) {
+  delete_web_app_ids_ = std::move(app_ids);
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/test/test_web_app_database.h b/chrome/browser/web_applications/test/test_web_app_database.h
new file mode 100644
index 0000000..19d53fa
--- /dev/null
+++ b/chrome/browser/web_applications/test/test_web_app_database.h
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_WEB_APP_DATABASE_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_WEB_APP_DATABASE_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "chrome/browser/web_applications/abstract_web_app_database.h"
+
+namespace web_app {
+
+class TestWebAppDatabase : public AbstractWebAppDatabase {
+ public:
+  TestWebAppDatabase();
+  ~TestWebAppDatabase() override;
+
+  // AbstractWebAppDatabase:
+  void OpenDatabase(OnceRegistryOpenedCallback callback) override;
+  void WriteWebApp(const WebApp& web_app) override;
+  void DeleteWebApps(std::vector<AppId> app_ids) override;
+
+  OnceRegistryOpenedCallback TakeOpenDatabaseCallback() {
+    return std::move(open_database_callback_);
+  }
+  const AppId& write_web_app_id() const { return write_web_app_id_; }
+  const std::vector<AppId>& delete_web_app_ids() const {
+    return delete_web_app_ids_;
+  }
+
+ private:
+  OnceRegistryOpenedCallback open_database_callback_;
+  AppId write_web_app_id_;
+  std::vector<AppId> delete_web_app_ids_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestWebAppDatabase);
+};
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_WEB_APP_DATABASE_H_
diff --git a/chrome/browser/web_applications/test/test_web_app_database_factory.cc b/chrome/browser/web_applications/test/test_web_app_database_factory.cc
new file mode 100644
index 0000000..e8b101f
--- /dev/null
+++ b/chrome/browser/web_applications/test/test_web_app_database_factory.cc
@@ -0,0 +1,23 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/test/test_web_app_database_factory.h"
+
+#include "components/sync/model/model_type_store_test_util.h"
+
+namespace web_app {
+
+TestWebAppDatabaseFactory::TestWebAppDatabaseFactory() {
+  // InMemoryStore must be created after message_loop_.
+  store_ = syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest();
+}
+
+TestWebAppDatabaseFactory::~TestWebAppDatabaseFactory() {}
+
+syncer::OnceModelTypeStoreFactory TestWebAppDatabaseFactory::GetStoreFactory() {
+  return syncer::ModelTypeStoreTestUtil::FactoryForForwardingStore(
+      store_.get());
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/test/test_web_app_database_factory.h b/chrome/browser/web_applications/test/test_web_app_database_factory.h
new file mode 100644
index 0000000..ddefbf3
--- /dev/null
+++ b/chrome/browser/web_applications/test/test_web_app_database_factory.h
@@ -0,0 +1,38 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_WEB_APP_DATABASE_FACTORY_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_WEB_APP_DATABASE_FACTORY_H_
+
+#include "base/macros.h"
+#include "chrome/browser/web_applications/web_app_database_factory.h"
+
+namespace syncer {
+class ModelTypeStore;
+}  // namespace syncer
+
+namespace web_app {
+
+// Requires base::MessageLoop message_loop_ in test fixture. Reason:
+// InMemoryStore needs a SequencedTaskRunner.
+// MessageLoop ctor calls MessageLoop::SetThreadTaskRunnerHandle().
+class TestWebAppDatabaseFactory : public AbstractWebAppDatabaseFactory {
+ public:
+  TestWebAppDatabaseFactory();
+  ~TestWebAppDatabaseFactory() override;
+
+  // AbstractWebAppDatabaseFactory interface implementation.
+  syncer::OnceModelTypeStoreFactory GetStoreFactory() override;
+
+  syncer::ModelTypeStore* store() { return store_.get(); }
+
+ private:
+  std::unique_ptr<syncer::ModelTypeStore> store_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestWebAppDatabaseFactory);
+};
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_WEB_APP_DATABASE_FACTORY_H_
diff --git a/chrome/browser/web_applications/test/web_app_test.cc b/chrome/browser/web_applications/test/web_app_test.cc
index d1c0140..2378d3b 100644
--- a/chrome/browser/web_applications/test/web_app_test.cc
+++ b/chrome/browser/web_applications/test/web_app_test.cc
@@ -4,10 +4,17 @@
 
 #include "chrome/browser/web_applications/test/web_app_test.h"
 
+#include "content/public/test/web_contents_tester.h"
+
 namespace web_app {
 
 WebAppTest::WebAppTest() = default;
 
 WebAppTest::~WebAppTest() = default;
 
+void WebAppTest::SetUp() {
+  ChromeRenderViewHostTestHarness::SetUp();
+  SetContents(CreateTestWebContents());
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/test/web_app_test.h b/chrome/browser/web_applications/test/web_app_test.h
index d96606f..90ffd88 100644
--- a/chrome/browser/web_applications/test/web_app_test.h
+++ b/chrome/browser/web_applications/test/web_app_test.h
@@ -15,6 +15,8 @@
   WebAppTest();
   ~WebAppTest() override;
 
+  void SetUp() override;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(WebAppTest);
 };
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc
new file mode 100644
index 0000000..f232ec5
--- /dev/null
+++ b/chrome/browser/web_applications/web_app_database.cc
@@ -0,0 +1,179 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/web_app_database.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "chrome/browser/web_applications/proto/web_app.pb.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_database_factory.h"
+#include "components/sync/base/model_type.h"
+#include "components/sync/model/model_error.h"
+
+namespace web_app {
+
+WebAppDatabase::WebAppDatabase(AbstractWebAppDatabaseFactory* database_factory)
+    : database_factory_(database_factory) {
+  DCHECK(database_factory_);
+}
+
+WebAppDatabase::~WebAppDatabase() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void WebAppDatabase::OpenDatabase(OnceRegistryOpenedCallback callback) {
+  DCHECK(!store_);
+
+  syncer::OnceModelTypeStoreFactory store_factory =
+      database_factory_->GetStoreFactory();
+
+  // CreateStore then ReadRegistry.
+  CreateStore(
+      std::move(store_factory),
+      base::BindOnce(&WebAppDatabase::ReadRegistry,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void WebAppDatabase::WriteWebApp(const WebApp& web_app) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(opened_);
+
+  BeginTransaction();
+
+  auto proto = CreateWebAppProto(web_app);
+  write_batch_->WriteData(proto->app_id(), proto->SerializeAsString());
+
+  CommitTransaction();
+}
+
+void WebAppDatabase::DeleteWebApps(std::vector<AppId> app_ids) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(opened_);
+
+  BeginTransaction();
+  for (auto& app_id : app_ids)
+    write_batch_->DeleteData(app_id);
+  CommitTransaction();
+}
+
+// static
+std::unique_ptr<WebAppProto> WebAppDatabase::CreateWebAppProto(
+    const WebApp& web_app) {
+  auto proto = std::make_unique<WebAppProto>();
+
+  proto->set_app_id(web_app.app_id());
+  proto->set_name(web_app.name());
+  proto->set_description(web_app.description());
+  proto->set_launch_url(web_app.launch_url());
+
+  return proto;
+}
+
+// static
+std::unique_ptr<WebApp> WebAppDatabase::CreateWebApp(const WebAppProto& proto) {
+  auto web_app = std::make_unique<WebApp>(proto.app_id());
+
+  web_app->SetName(proto.name());
+  web_app->SetDescription(proto.description());
+  web_app->SetLaunchUrl(proto.launch_url());
+
+  return web_app;
+}
+
+void WebAppDatabase::ReadRegistry(OnceRegistryOpenedCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(store_);
+  store_->ReadAllData(base::BindOnce(&WebAppDatabase::OnAllDataRead,
+                                     weak_ptr_factory_.GetWeakPtr(),
+                                     std::move(callback)));
+}
+
+void WebAppDatabase::CreateStore(
+    syncer::OnceModelTypeStoreFactory store_factory,
+    base::OnceClosure closure) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // For now we use syncer:APPS prefix within local isolated LevelDB, no sync.
+  // TODO(loyso): Create separate ModelType::WEB_APPS before implementing sync.
+  // Otherwise it may interfere with existing APPS data.
+  std::move(store_factory)
+      .Run(syncer::APPS,
+           base::BindOnce(&WebAppDatabase::OnStoreCreated,
+                          weak_ptr_factory_.GetWeakPtr(), std::move(closure)));
+}
+
+void WebAppDatabase::OnStoreCreated(
+    base::OnceClosure closure,
+    const base::Optional<syncer::ModelError>& error,
+    std::unique_ptr<syncer::ModelTypeStore> store) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (error) {
+    LOG(ERROR) << "WebApps LevelDB opening error: " << error->ToString();
+    return;
+  }
+
+  store_ = std::move(store);
+  std::move(closure).Run();
+}
+
+void WebAppDatabase::OnAllDataRead(
+    OnceRegistryOpenedCallback callback,
+    const base::Optional<syncer::ModelError>& error,
+    std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (error) {
+    LOG(ERROR) << "WebApps LevelDB read error: " << error->ToString();
+    return;
+  }
+
+  Registry registry;
+  for (const syncer::ModelTypeStore::Record& record : *data_records) {
+    const AppId app_id = record.id;
+    std::unique_ptr<WebApp> web_app = ParseWebApp(app_id, record.value);
+    if (web_app)
+      registry.emplace(app_id, std::move(web_app));
+  }
+
+  std::move(callback).Run(std::move(registry));
+  opened_ = true;
+}
+
+void WebAppDatabase::OnDataWritten(
+    const base::Optional<syncer::ModelError>& error) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (error)
+    LOG(ERROR) << "WebApps LevelDB write error: " << error->ToString();
+}
+
+// static
+std::unique_ptr<WebApp> WebAppDatabase::ParseWebApp(const AppId& app_id,
+                                                    const std::string& value) {
+  WebAppProto proto;
+  const bool parsed = proto.ParseFromString(value);
+  if (!parsed || proto.app_id() != app_id) {
+    LOG(ERROR) << "WebApps LevelDB parse error (unknown).";
+    return nullptr;
+  }
+
+  return CreateWebApp(proto);
+}
+
+void WebAppDatabase::BeginTransaction() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!write_batch_);
+  write_batch_ = store_->CreateWriteBatch();
+}
+
+void WebAppDatabase::CommitTransaction() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(write_batch_);
+
+  store_->CommitWriteBatch(std::move(write_batch_),
+                           base::BindOnce(&WebAppDatabase::OnDataWritten,
+                                          weak_ptr_factory_.GetWeakPtr()));
+  write_batch_.reset();
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_database.h b/chrome/browser/web_applications/web_app_database.h
new file mode 100644
index 0000000..8ef472b
--- /dev/null
+++ b/chrome/browser/web_applications/web_app_database.h
@@ -0,0 +1,83 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_DATABASE_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_DATABASE_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "chrome/browser/web_applications/abstract_web_app_database.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "components/sync/model/model_type_store.h"
+
+namespace syncer {
+class ModelError;
+}  // namespace syncer
+
+namespace web_app {
+
+class AbstractWebAppDatabaseFactory;
+class WebApp;
+class WebAppProto;
+
+// Exclusively used from the UI thread.
+class WebAppDatabase : public AbstractWebAppDatabase {
+ public:
+  explicit WebAppDatabase(AbstractWebAppDatabaseFactory* database_factory);
+  ~WebAppDatabase() override;
+
+  // AbstractWebAppDatabase:
+  void OpenDatabase(OnceRegistryOpenedCallback callback) override;
+  void WriteWebApp(const WebApp& web_app) override;
+  void DeleteWebApps(std::vector<AppId> app_ids) override;
+
+  // Exposed for testing.
+  static std::unique_ptr<WebAppProto> CreateWebAppProto(const WebApp& web_app);
+  // Exposed for testing.
+  static std::unique_ptr<WebApp> CreateWebApp(const WebAppProto& proto);
+  // Exposed for testing.
+  void ReadRegistry(OnceRegistryOpenedCallback callback);
+
+ private:
+  void CreateStore(syncer::OnceModelTypeStoreFactory store_factory,
+                   base::OnceClosure closure);
+  void OnStoreCreated(base::OnceClosure closure,
+                      const base::Optional<syncer::ModelError>& error,
+                      std::unique_ptr<syncer::ModelTypeStore> store);
+
+  void OnAllDataRead(
+      OnceRegistryOpenedCallback callback,
+      const base::Optional<syncer::ModelError>& error,
+      std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records);
+
+  void OnDataWritten(const base::Optional<syncer::ModelError>& error);
+
+  static std::unique_ptr<WebApp> ParseWebApp(const AppId& app_id,
+                                             const std::string& value);
+
+  void BeginTransaction();
+  void CommitTransaction();
+
+  std::unique_ptr<syncer::ModelTypeStore> store_;
+  std::unique_ptr<syncer::ModelTypeStore::WriteBatch> write_batch_;
+  AbstractWebAppDatabaseFactory* database_factory_;
+
+  // Database is opened if store is created and all data read.
+  bool opened_ = false;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  base::WeakPtrFactory<WebAppDatabase> weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(WebAppDatabase);
+};
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_DATABASE_H_
diff --git a/chrome/browser/web_applications/web_app_database_factory.cc b/chrome/browser/web_applications/web_app_database_factory.cc
new file mode 100644
index 0000000..6254a80
--- /dev/null
+++ b/chrome/browser/web_applications/web_app_database_factory.cc
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/web_app_database_factory.h"
+
+#include "base/files/file_path.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/sync/model_impl/model_type_store_service_impl.h"
+
+namespace web_app {
+
+constexpr base::FilePath::CharType kWebAppsFolderName[] =
+    FILE_PATH_LITERAL("WebApps");
+
+WebAppDatabaseFactory::WebAppDatabaseFactory(Profile* profile)
+    : model_type_store_service_(
+          std::make_unique<syncer::ModelTypeStoreServiceImpl>(
+              profile->GetPath().Append(base::FilePath(kWebAppsFolderName)))) {}
+
+WebAppDatabaseFactory::~WebAppDatabaseFactory() {}
+
+syncer::OnceModelTypeStoreFactory WebAppDatabaseFactory::GetStoreFactory() {
+  return model_type_store_service_->GetStoreFactory();
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_database_factory.h b/chrome/browser/web_applications/web_app_database_factory.h
new file mode 100644
index 0000000..33ac124
--- /dev/null
+++ b/chrome/browser/web_applications/web_app_database_factory.h
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_DATABASE_FACTORY_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_DATABASE_FACTORY_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/sync/model/model_type_store.h"
+
+class Profile;
+
+namespace syncer {
+class ModelTypeStoreService;
+}  // namespace syncer
+
+namespace web_app {
+
+class AbstractWebAppDatabaseFactory {
+ public:
+  virtual ~AbstractWebAppDatabaseFactory() = default;
+  virtual syncer::OnceModelTypeStoreFactory GetStoreFactory() = 0;
+};
+
+class WebAppDatabaseFactory : public AbstractWebAppDatabaseFactory {
+ public:
+  explicit WebAppDatabaseFactory(Profile* profile);
+  ~WebAppDatabaseFactory() override;
+
+  // AbstractWebAppDatabaseFactory implementation.
+  syncer::OnceModelTypeStoreFactory GetStoreFactory() override;
+
+ private:
+  // TODO(loyso): Consider using shared ModelTypeStoreService from profile.
+  // crbug.com/902214.
+  std::unique_ptr<syncer::ModelTypeStoreService> model_type_store_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebAppDatabaseFactory);
+};
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_DATABASE_FACTORY_H_
diff --git a/chrome/browser/web_applications/web_app_database_unittest.cc b/chrome/browser/web_applications/web_app_database_unittest.cc
new file mode 100644
index 0000000..8955cd4
--- /dev/null
+++ b/chrome/browser/web_applications/web_app_database_unittest.cc
@@ -0,0 +1,181 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/web_app_database.h"
+
+#include <memory>
+#include <tuple>
+
+#include "base/bind_helpers.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/proto/web_app.pb.h"
+#include "chrome/browser/web_applications/test/test_web_app_database_factory.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
+#include "components/sync/model/model_type_store.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace web_app {
+
+namespace {
+
+bool operator==(const WebApp& web_app, const WebApp& web_app2) {
+  return std::tie(web_app.app_id(), web_app.name(), web_app.launch_url(),
+                  web_app.description()) ==
+         std::tie(web_app2.app_id(), web_app2.name(), web_app2.launch_url(),
+                  web_app2.description());
+}
+
+bool operator!=(const WebApp& web_app, const WebApp& web_app2) {
+  return !operator==(web_app, web_app2);
+}
+
+bool IsRegistryEqual(const Registry& registry, const Registry& registry2) {
+  if (registry.size() != registry2.size())
+    return false;
+
+  for (auto& kv : registry) {
+    const WebApp* web_app = kv.second.get();
+    const WebApp* web_app2 = registry2.at(web_app->app_id()).get();
+    if (*web_app != *web_app2)
+      return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+class WebAppDatabaseTest : public testing::Test {
+ public:
+  WebAppDatabaseTest() {
+    database_factory_ = std::make_unique<TestWebAppDatabaseFactory>();
+    database_ = std::make_unique<WebAppDatabase>(database_factory_.get());
+    registrar_ = std::make_unique<WebAppRegistrar>(database_.get());
+  }
+
+  void InitRegistrar() {
+    base::RunLoop run_loop;
+
+    registrar_->Init(base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
+
+    run_loop.Run();
+  }
+
+  static std::unique_ptr<WebApp> CreateWebApp(const std::string& base_url,
+                                              int suffix) {
+    const auto launch_url = base_url + base::IntToString(suffix);
+    const AppId app_id = GenerateAppIdFromURL(GURL(launch_url));
+    const std::string name = "Name" + base::IntToString(suffix);
+    const std::string description = "Description" + base::IntToString(suffix);
+
+    auto app = std::make_unique<WebApp>(app_id);
+
+    app->SetName(name);
+    app->SetDescription(description);
+    app->SetLaunchUrl(launch_url);
+
+    return app;
+  }
+
+  Registry ReadRegistry() {
+    Registry registry;
+    base::RunLoop run_loop;
+
+    database_->ReadRegistry(base::BindLambdaForTesting([&](Registry r) {
+      registry = std::move(r);
+      run_loop.Quit();
+    }));
+
+    run_loop.Run();
+    return registry;
+  }
+
+  bool IsDatabaseRegistryEqualToRegistrar() {
+    Registry registry = ReadRegistry();
+    return IsRegistryEqual(registrar_->registry(), registry);
+  }
+
+  void WriteBatch(
+      std::unique_ptr<syncer::ModelTypeStore::WriteBatch> write_batch) {
+    base::RunLoop run_loop;
+
+    database_factory_->store()->CommitWriteBatch(
+        std::move(write_batch),
+        base::BindLambdaForTesting(
+            [&](const base::Optional<syncer::ModelError>& error) {
+              EXPECT_FALSE(error);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+
+  Registry WriteWebApps(const std::string& base_url, int num_apps) {
+    Registry registry;
+
+    auto write_batch = database_factory_->store()->CreateWriteBatch();
+
+    for (int i = 0; i < num_apps; ++i) {
+      auto app = CreateWebApp(base_url, i);
+      auto proto = WebAppDatabase::CreateWebAppProto(*app);
+      const auto app_id = app->app_id();
+
+      write_batch->WriteData(app_id, proto->SerializeAsString());
+
+      registry.emplace(app_id, std::move(app));
+    }
+
+    WriteBatch(std::move(write_batch));
+
+    return registry;
+  }
+
+ protected:
+  // Must be created before TestWebAppDatabaseFactory.
+  base::MessageLoop message_loop_;
+
+  std::unique_ptr<TestWebAppDatabaseFactory> database_factory_;
+  std::unique_ptr<WebAppDatabase> database_;
+  std::unique_ptr<WebAppRegistrar> registrar_;
+};
+
+TEST_F(WebAppDatabaseTest, WriteAndReadRegistry) {
+  InitRegistrar();
+  EXPECT_TRUE(registrar_->is_empty());
+
+  const int num_apps = 100;
+  const std::string base_url = "https://example.com/path";
+
+  auto app = CreateWebApp(base_url, 0);
+  auto app_id = app->app_id();
+  registrar_->RegisterApp(std::move(app));
+  EXPECT_TRUE(IsDatabaseRegistryEqualToRegistrar());
+
+  for (int i = 1; i <= num_apps; ++i) {
+    auto extra_app = CreateWebApp(base_url, i);
+    registrar_->RegisterApp(std::move(extra_app));
+  }
+  EXPECT_TRUE(IsDatabaseRegistryEqualToRegistrar());
+
+  registrar_->UnregisterApp(app_id);
+  EXPECT_TRUE(IsDatabaseRegistryEqualToRegistrar());
+
+  registrar_->UnregisterAll();
+  EXPECT_TRUE(IsDatabaseRegistryEqualToRegistrar());
+}
+
+TEST_F(WebAppDatabaseTest, OpenDatabaseAndReadRegistry) {
+  Registry registry = WriteWebApps("https://example.com/path", 100);
+
+  InitRegistrar();
+  EXPECT_TRUE(IsRegistryEqual(registrar_->registry(), registry));
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc
index 8ef74a4..267144fd 100644
--- a/chrome/browser/web_applications/web_app_install_manager.cc
+++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -7,9 +7,12 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/installable/installable_data.h"
+#include "chrome/browser/installable/installable_manager.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/components/web_app_data_retriever.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/components/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
@@ -34,18 +37,26 @@
   return IsValidWebAppUrl(web_contents->GetURL());
 }
 
-void WebAppInstallManager::InstallWebApp(content::WebContents* web_contents,
+void WebAppInstallManager::InstallWebApp(content::WebContents* contents,
                                          bool force_shortcut_app,
                                          OnceInstallCallback install_callback) {
-  // TODO(loyso): Use force_shortcut_app flag during installation.
-
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  // No parrallel installations support.
+  DCHECK(!web_contents());
+
+  force_shortcut_app_ = force_shortcut_app;
+  install_callback_ = std::move(install_callback);
+  Observe(contents);
+
   data_retriever_->GetWebApplicationInfo(
-      web_contents,
+      web_contents(),
       base::BindOnce(&WebAppInstallManager::OnGetWebApplicationInfo,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     std::move(install_callback)));
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void WebAppInstallManager::WebContentsDestroyed() {
+  ReturnError(InstallResultCode::kWebContentsDestroyed);
 }
 
 void WebAppInstallManager::SetDataRetrieverForTesting(
@@ -53,34 +64,94 @@
   data_retriever_ = std::move(data_retriever);
 }
 
+void WebAppInstallManager::ResetInstallProcessArguments() {
+  Observe(nullptr);
+  force_shortcut_app_ = false;
+  web_app_info_.reset();
+}
+
+void WebAppInstallManager::CallInstallCallback(const AppId& app_id,
+                                               InstallResultCode code) {
+  ResetInstallProcessArguments();
+
+  DCHECK(install_callback_);
+  std::move(install_callback_).Run(app_id, code);
+}
+
+void WebAppInstallManager::ReturnError(InstallResultCode code) {
+  CallInstallCallback(AppId(), code);
+}
+
+bool WebAppInstallManager::InstallInterrupted() const {
+  // Interrupt early if WebContents is being destroyed.
+  // WebContentsDestroyed will get called eventually and the callback will be
+  // invoked at that point.
+  if (!web_contents() || web_contents()->IsBeingDestroyed())
+    return true;
+
+  return false;
+}
+
 void WebAppInstallManager::OnGetWebApplicationInfo(
-    OnceInstallCallback install_callback,
     std::unique_ptr<WebApplicationInfo> web_app_info) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  if (!web_app_info) {
-    std::move(install_callback)
-        .Run(AppId(), InstallResultCode::kGetWebApplicationInfoFailed);
+  // If interrupted, install_callback_ is already invoked or may invoke later.
+  if (InstallInterrupted())
     return;
-  }
+
+  if (!web_app_info)
+    return ReturnError(InstallResultCode::kGetWebApplicationInfoFailed);
+
+  web_app_info_ = std::move(web_app_info);
+
+  // TODO(loyso): Consider to merge InstallableManager into WebAppDataRetriever.
+  InstallableManager* installable_manager =
+      InstallableManager::FromWebContents(web_contents());
+  DCHECK(installable_manager);
+
+  // TODO(crbug.com/829232) Unify with other calls to GetData.
+  InstallableParams params;
+  params.check_eligibility = true;
+  params.valid_primary_icon = true;
+  params.valid_manifest = true;
+  params.has_worker = true;
+  // Do not wait_for_worker. OnDidPerformInstallableCheck is always invoked.
+  installable_manager->GetData(
+      params,
+      base::BindRepeating(&WebAppInstallManager::OnDidPerformInstallableCheck,
+                          weak_ptr_factory_.GetWeakPtr()));
+}
+
+void WebAppInstallManager::OnDidPerformInstallableCheck(
+    const InstallableData& data) {
+  DCHECK(data.manifest_url.is_valid() || data.manifest->IsEmpty());
+  // If interrupted, install_callback_ is already invoked or may invoke later.
+  if (InstallInterrupted())
+    return;
+
+  const ForInstallableSite for_installable_site =
+      data.error_code == NO_ERROR_DETECTED && !force_shortcut_app_
+          ? ForInstallableSite::kYes
+          : ForInstallableSite::kNo;
+
+  UpdateWebAppInfoFromManifest(*data.manifest, web_app_info_.get(),
+                               for_installable_site);
 
   // TODO(loyso): Implement installation logic from BookmarkAppHelper:
-  // - InstallableManager to get InstallableData.
-  // - UpdateWebAppInfoFromManifest.
   // - UpdateShareTargetInPrefs.
   // - WebAppIconDownloader.
   // etc
 
-  const AppId app_id = GenerateAppIdFromURL(web_app_info->app_url);
+  const AppId app_id = GenerateAppIdFromURL(web_app_info_->app_url);
   auto web_app = std::make_unique<WebApp>(app_id);
 
-  web_app->SetName(base::UTF16ToUTF8(web_app_info->title));
-  web_app->SetDescription(base::UTF16ToUTF8(web_app_info->description));
-  web_app->SetLaunchUrl(web_app_info->app_url.spec());
+  web_app->SetName(base::UTF16ToUTF8(web_app_info_->title));
+  web_app->SetDescription(base::UTF16ToUTF8(web_app_info_->description));
+  web_app->SetLaunchUrl(web_app_info_->app_url.spec());
 
   registrar_->RegisterApp(std::move(web_app));
 
-  std::move(install_callback).Run(app_id, InstallResultCode::kSuccess);
+  CallInstallCallback(app_id, InstallResultCode::kSuccess);
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h
index f52884d1..6df2031 100644
--- a/chrome/browser/web_applications/web_app_install_manager.h
+++ b/chrome/browser/web_applications/web_app_install_manager.h
@@ -5,35 +5,63 @@
 #ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_INSTALL_MANAGER_H_
 #define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_INSTALL_MANAGER_H_
 
+#include <memory>
+
+#include "base/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/web_applications/components/install_manager.h"
+#include "content/public/browser/web_contents_observer.h"
 
 class Profile;
+struct InstallableData;
 struct WebApplicationInfo;
 
+namespace content {
+class WebContents;
+}
+
 namespace web_app {
 
 class WebAppDataRetriever;
 class WebAppRegistrar;
 
-class WebAppInstallManager final : public InstallManager {
+class WebAppInstallManager final : public InstallManager,
+                                   content::WebContentsObserver {
  public:
   WebAppInstallManager(Profile* profile, WebAppRegistrar* registrar);
   ~WebAppInstallManager() override;
 
-  // InstallManager interface implementation.
+  // InstallManager:
   bool CanInstallWebApp(const content::WebContents* web_contents) override;
-  void InstallWebApp(content::WebContents* web_contents,
+  void InstallWebApp(content::WebContents* contents,
                      bool force_shortcut_app,
                      OnceInstallCallback callback) override;
 
+  // WebContentsObserver:
+  void WebContentsDestroyed() override;
+
   void SetDataRetrieverForTesting(
       std::unique_ptr<WebAppDataRetriever> data_retriever);
 
  private:
+  void ResetInstallProcessArguments();
+  void CallInstallCallback(const AppId& app_id, InstallResultCode code);
+  void ReturnError(InstallResultCode code);
+
+  // Checks typical errors like WebContents destroyed.
+  bool InstallInterrupted() const;
+
   void OnGetWebApplicationInfo(
-      OnceInstallCallback install_callback,
       std::unique_ptr<WebApplicationInfo> web_app_info);
+  void OnDidPerformInstallableCheck(const InstallableData& data);
+
+  // Forces the creation of a shortcut app instead of a PWA even if installation
+  // is available.
+  bool force_shortcut_app_ = false;
+
+  // Arguments, valid during installation process:
+  OnceInstallCallback install_callback_;
+  std::unique_ptr<WebApplicationInfo> web_app_info_;
 
   Profile* profile_;
   WebAppRegistrar* registrar_;
diff --git a/chrome/browser/web_applications/web_app_install_manager_unittest.cc b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
index 454b44e..0cb7922e 100644
--- a/chrome/browser/web_applications/web_app_install_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
@@ -4,12 +4,19 @@
 
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 
+#include <memory>
+
 #include "base/callback.h"
 #include "base/run_loop.h"
+#include "base/strings/nullable_string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
+#include "chrome/browser/installable/installable_data.h"
+#include "chrome/browser/installable/installable_manager.h"
+#include "chrome/browser/ssl/security_state_tab_helper.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/test/test_data_retriever.h"
+#include "chrome/browser/web_applications/test/test_web_app_database.h"
 #include "chrome/browser/web_applications/test/web_app_test.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -20,48 +27,120 @@
 
 namespace web_app {
 
-class WebAppInstallManagerTest : public WebAppTest {};
+class TestInstallableManager : public InstallableManager {
+ public:
+  explicit TestInstallableManager(content::WebContents* web_contents)
+      : InstallableManager(web_contents) {}
+
+  static TestInstallableManager* CreateForWebContents(
+      content::WebContents* web_contents) {
+    auto manager = std::make_unique<TestInstallableManager>(web_contents);
+    TestInstallableManager* result = manager.get();
+    web_contents->SetUserData(UserDataKey(), std::move(manager));
+    return result;
+  }
+
+  void SetData(std::unique_ptr<InstallableData> data) {
+    data_ = std::move(data);
+  }
+
+  void GetData(const InstallableParams& params,
+               const InstallableCallback& callback) override {
+    callback.Run(*std::move(data_));
+  }
+
+  std::unique_ptr<InstallableData> data_;
+};
+
+class WebAppInstallManagerTest : public WebAppTest {
+ public:
+  void SetUp() override {
+    WebAppTest::SetUp();
+
+    database_ = std::make_unique<TestWebAppDatabase>();
+    registrar_ = std::make_unique<WebAppRegistrar>(database_.get());
+    install_manager_ =
+        std::make_unique<WebAppInstallManager>(profile(), registrar_.get());
+  }
+
+  void CreateRendererAppInfo(const GURL& url,
+                             const std::string name,
+                             const std::string description) {
+    auto web_app_info = std::make_unique<WebApplicationInfo>();
+
+    web_app_info->app_url = url;
+    web_app_info->title = base::UTF8ToUTF16(name);
+    web_app_info->description = base::UTF8ToUTF16(description);
+
+    install_manager_->SetDataRetrieverForTesting(
+        std::make_unique<TestDataRetriever>(std::move(web_app_info)));
+  }
+
+  void CreateDefaultInstallableManager() {
+    InstallableManager::CreateForWebContents(web_contents());
+    // Required by InstallableManager.
+    // Causes eligibility check to return NOT_FROM_SECURE_ORIGIN for GetData.
+    SecurityStateTabHelper::CreateForWebContents(web_contents());
+  }
+
+  void CreateTestInstallableManager(const GURL& manifest_url,
+                                    blink::Manifest* manifest) {
+    const InstallableStatusCode installable_code = NO_ERROR_DETECTED;
+    const bool valid_manifest = true;
+    const bool has_worker = true;
+
+    // Not used in WebAppInstallManager:
+    const GURL icon_url;
+    const std::unique_ptr<SkBitmap> icon;
+
+    auto installable_data = std::make_unique<InstallableData>(
+        installable_code, manifest_url, manifest, icon_url, icon.get(),
+        icon_url, icon.get(), valid_manifest, has_worker);
+
+    TestInstallableManager* installable_manager =
+        TestInstallableManager::CreateForWebContents(web_contents());
+    installable_manager->SetData(std::move(installable_data));
+  }
+
+  static base::NullableString16 ToNullableUTF16(const std::string& str) {
+    return base::NullableString16(base::UTF8ToUTF16(str), false);
+  }
+
+ protected:
+  std::unique_ptr<TestWebAppDatabase> database_;
+  std::unique_ptr<WebAppRegistrar> registrar_;
+  std::unique_ptr<WebAppInstallManager> install_manager_;
+};
 
 TEST_F(WebAppInstallManagerTest, InstallFromWebContents) {
   EXPECT_EQ(true, AllowWebAppInstallation(profile()));
 
-  auto registrar = std::make_unique<WebAppRegistrar>();
-  auto manager =
-      std::make_unique<WebAppInstallManager>(profile(), registrar.get());
-
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
-
   const GURL url = GURL("https://example.com/path");
   const std::string name = "Name";
   const std::string description = "Description";
-
   const AppId app_id = GenerateAppIdFromURL(url);
 
-  web_app_info->app_url = url;
-  web_app_info->title = base::UTF8ToUTF16(name);
-  web_app_info->description = base::UTF8ToUTF16(description);
-  manager->SetDataRetrieverForTesting(
-      std::make_unique<TestDataRetriever>(std::move(web_app_info)));
+  CreateRendererAppInfo(url, name, description);
+  CreateDefaultInstallableManager();
 
   base::RunLoop run_loop;
   bool callback_called = false;
   const bool force_shortcut_app = false;
 
-  manager->InstallWebApp(
+  install_manager_->InstallWebApp(
       web_contents(), force_shortcut_app,
       base::BindLambdaForTesting(
           [&](const AppId& installed_app_id, InstallResultCode code) {
             EXPECT_EQ(InstallResultCode::kSuccess, code);
             EXPECT_EQ(app_id, installed_app_id);
             callback_called = true;
-            base::ThreadTaskRunnerHandle::Get()->PostTask(
-                FROM_HERE, run_loop.QuitClosure());
+            run_loop.Quit();
           }));
   run_loop.Run();
 
   EXPECT_TRUE(callback_called);
 
-  WebApp* web_app = registrar->GetAppById(app_id);
+  WebApp* web_app = registrar_->GetAppById(app_id);
   EXPECT_NE(nullptr, web_app);
 
   EXPECT_EQ(app_id, web_app->app_id());
@@ -71,30 +150,99 @@
 }
 
 TEST_F(WebAppInstallManagerTest, GetWebApplicationInfoFailed) {
-  auto registrar = std::make_unique<WebAppRegistrar>();
-  auto manager =
-      std::make_unique<WebAppInstallManager>(profile(), registrar.get());
+  install_manager_->SetDataRetrieverForTesting(
+      std::make_unique<TestDataRetriever>(
+          std::unique_ptr<WebApplicationInfo>()));
 
-  manager->SetDataRetrieverForTesting(std::make_unique<TestDataRetriever>(
-      std::unique_ptr<WebApplicationInfo>()));
+  CreateDefaultInstallableManager();
 
   base::RunLoop run_loop;
   bool callback_called = false;
   const bool force_shortcut_app = false;
 
-  manager->InstallWebApp(
+  install_manager_->InstallWebApp(
       web_contents(), force_shortcut_app,
       base::BindLambdaForTesting(
           [&](const AppId& installed_app_id, InstallResultCode code) {
             EXPECT_EQ(InstallResultCode::kGetWebApplicationInfoFailed, code);
             EXPECT_EQ(AppId(), installed_app_id);
             callback_called = true;
-            base::ThreadTaskRunnerHandle::Get()->PostTask(
-                FROM_HERE, run_loop.QuitClosure());
+            run_loop.Quit();
           }));
   run_loop.Run();
 
   EXPECT_TRUE(callback_called);
 }
 
+TEST_F(WebAppInstallManagerTest, WebContentsDestroyed) {
+  CreateRendererAppInfo(GURL("https://example.com/path"), "Name",
+                        "Description");
+  CreateDefaultInstallableManager();
+
+  base::RunLoop run_loop;
+  bool callback_called = false;
+  const bool force_shortcut_app = false;
+
+  install_manager_->InstallWebApp(
+      web_contents(), force_shortcut_app,
+      base::BindLambdaForTesting(
+          [&](const AppId& installed_app_id, InstallResultCode code) {
+            EXPECT_EQ(InstallResultCode::kWebContentsDestroyed, code);
+            EXPECT_EQ(AppId(), installed_app_id);
+            callback_called = true;
+            run_loop.Quit();
+          }));
+
+  // Destroy WebContents.
+  DeleteContents();
+  EXPECT_EQ(nullptr, web_contents());
+
+  run_loop.Run();
+
+  EXPECT_TRUE(callback_called);
+}
+
+// TODO(loyso): Convert more tests from bookmark_app_helper_unittest.cc
+TEST_F(WebAppInstallManagerTest, InstallableCheck) {
+  const std::string renderer_description = "RendererDescription";
+  CreateRendererAppInfo(GURL("https://example.com/path"), "RendererName",
+                        renderer_description);
+
+  const GURL manifest_start_url = GURL("https://example.com/start");
+  const AppId app_id = GenerateAppIdFromURL(manifest_start_url);
+  const std::string manifest_name = "Name from Manifest";
+
+  blink::Manifest manifest;
+  manifest.short_name = ToNullableUTF16("Short Name from Manifest");
+  manifest.name = ToNullableUTF16(manifest_name);
+  manifest.start_url = GURL(manifest_start_url);
+
+  CreateTestInstallableManager(GURL("https://example.com/manifest"), &manifest);
+
+  base::RunLoop run_loop;
+  bool callback_called = false;
+  const bool force_shortcut_app = false;
+
+  install_manager_->InstallWebApp(
+      web_contents(), force_shortcut_app,
+      base::BindLambdaForTesting(
+          [&](const AppId& installed_app_id, InstallResultCode code) {
+            EXPECT_EQ(InstallResultCode::kSuccess, code);
+            EXPECT_EQ(app_id, installed_app_id);
+            callback_called = true;
+            run_loop.Quit();
+          }));
+  run_loop.Run();
+
+  EXPECT_TRUE(callback_called);
+
+  WebApp* web_app = registrar_->GetAppById(app_id);
+  EXPECT_NE(nullptr, web_app);
+
+  EXPECT_EQ(app_id, web_app->app_id());
+  EXPECT_EQ(manifest_name, web_app->name());
+  EXPECT_EQ(manifest_start_url.spec(), web_app->launch_url());
+  EXPECT_EQ(renderer_description, web_app->description());
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc
index d74b049..9188038 100644
--- a/chrome/browser/web_applications/web_app_provider.cc
+++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -19,6 +19,8 @@
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
 #include "chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h"
 #include "chrome/browser/web_applications/extensions/web_app_extension_ids_map.h"
+#include "chrome/browser/web_applications/web_app_database.h"
+#include "chrome/browser/web_applications/web_app_database_factory.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_provider_factory.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -56,9 +58,13 @@
   if (!AllowWebAppInstallation(profile))
     return;
 
-  registrar_ = std::make_unique<WebAppRegistrar>();
+  database_factory_ = std::make_unique<WebAppDatabaseFactory>(profile);
+  database_ = std::make_unique<WebAppDatabase>(database_factory_.get());
+  registrar_ = std::make_unique<WebAppRegistrar>(database_.get());
   install_manager_ =
       std::make_unique<WebAppInstallManager>(profile, registrar_.get());
+
+  registrar_->Init(base::DoNothing());
 }
 
 void WebAppProvider::CreateBookmarkAppsSubsystems(Profile* profile) {
@@ -123,6 +129,8 @@
 
   install_manager_.reset();
   registrar_.reset();
+  database_.reset();
+  database_factory_.reset();
 }
 
 void WebAppProvider::Observe(int type,
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h
index 9c5ef7d..65ed8c4 100644
--- a/chrome/browser/web_applications/web_app_provider.h
+++ b/chrome/browser/web_applications/web_app_provider.h
@@ -32,6 +32,8 @@
 class InstallManager;
 
 // Forward declarations for new extension-independent subsystems.
+class WebAppDatabase;
+class WebAppDatabaseFactory;
 class WebAppRegistrar;
 
 // Forward declarations for legacy extension-based subsystems.
@@ -82,6 +84,8 @@
       std::vector<web_app::PendingAppManager::AppInfo>);
 
   // New extension-independent subsystems:
+  std::unique_ptr<WebAppDatabaseFactory> database_factory_;
+  std::unique_ptr<WebAppDatabase> database_;
   std::unique_ptr<WebAppRegistrar> registrar_;
 
   // New generalized subsystems:
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc
index 61a0c49..cd1832a 100644
--- a/chrome/browser/web_applications/web_app_registrar.cc
+++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -4,12 +4,18 @@
 
 #include "chrome/browser/web_applications/web_app_registrar.h"
 
+#include "base/bind.h"
+#include "base/callback.h"
 #include "base/logging.h"
+#include "chrome/browser/web_applications/abstract_web_app_database.h"
 #include "chrome/browser/web_applications/web_app.h"
 
 namespace web_app {
 
-WebAppRegistrar::WebAppRegistrar() {}
+WebAppRegistrar::WebAppRegistrar(AbstractWebAppDatabase* database)
+    : database_(database) {
+  DCHECK(database_);
+}
 
 WebAppRegistrar::~WebAppRegistrar() = default;
 
@@ -18,12 +24,16 @@
   DCHECK(!app_id.empty());
   DCHECK(!GetAppById(app_id));
 
-  registry_.emplace(std::make_pair(app_id, std::move(web_app)));
+  database_->WriteWebApp(*web_app);
+
+  registry_.emplace(app_id, std::move(web_app));
 }
 
 std::unique_ptr<WebApp> WebAppRegistrar::UnregisterApp(const AppId& app_id) {
   DCHECK(!app_id.empty());
 
+  database_->DeleteWebApps({app_id});
+
   auto kv = registry_.find(app_id);
   DCHECK(kv != registry_.end());
 
@@ -38,7 +48,27 @@
 }
 
 void WebAppRegistrar::UnregisterAll() {
+  std::vector<AppId> app_ids;
+  for (auto& kv : registry()) {
+    const AppId& app_id = kv.first;
+    app_ids.push_back(app_id);
+  }
+  database_->DeleteWebApps(std::move(app_ids));
+
   registry_.clear();
 }
 
+void WebAppRegistrar::Init(base::OnceClosure closure) {
+  database_->OpenDatabase(base::BindOnce(&WebAppRegistrar::OnDatabaseOpened,
+                                         weak_ptr_factory_.GetWeakPtr(),
+                                         std::move(closure)));
+}
+
+void WebAppRegistrar::OnDatabaseOpened(base::OnceClosure closure,
+                                       Registry registry) {
+  DCHECK(is_empty());
+  registry_ = std::move(registry);
+  std::move(closure).Run();
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h
index cf26c9d9..d76e046 100644
--- a/chrome/browser/web_applications/web_app_registrar.h
+++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -5,10 +5,12 @@
 #ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_REGISTRAR_H_
 #define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_REGISTRAR_H_
 
-#include <map>
 #include <memory>
 
+#include "base/callback_forward.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/web_applications/abstract_web_app_database.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
 
 namespace web_app {
@@ -17,7 +19,7 @@
 
 class WebAppRegistrar {
  public:
-  WebAppRegistrar();
+  explicit WebAppRegistrar(AbstractWebAppDatabase* database);
   ~WebAppRegistrar();
 
   void RegisterApp(std::unique_ptr<WebApp> web_app);
@@ -25,7 +27,6 @@
 
   WebApp* GetAppById(const AppId& app_id);
 
-  using Registry = std::map<AppId, std::unique_ptr<WebApp>>;
   const Registry& registry() const { return registry_; }
 
   bool is_empty() const { return registry_.empty(); }
@@ -33,9 +34,18 @@
   // Clears registry.
   void UnregisterAll();
 
+  void Init(base::OnceClosure closure);
+
  private:
+  void OnDatabaseOpened(base::OnceClosure closure, Registry registry);
+
   Registry registry_;
 
+  // An abstract database, not owned by this registrar.
+  AbstractWebAppDatabase* database_;
+
+  base::WeakPtrFactory<WebAppRegistrar> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(WebAppRegistrar);
 };
 
diff --git a/chrome/browser/web_applications/web_app_registrar_unittest.cc b/chrome/browser/web_applications/web_app_registrar_unittest.cc
index f296f5b..390ff342 100644
--- a/chrome/browser/web_applications/web_app_registrar_unittest.cc
+++ b/chrome/browser/web_applications/web_app_registrar_unittest.cc
@@ -6,8 +6,10 @@
 
 #include <set>
 
+#include "base/bind_helpers.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/test/test_web_app_database.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -16,18 +18,26 @@
 
 namespace {
 
-std::set<AppId> RegisterAppsForTesting(const std::string& base_url,
-                                       int num_apps,
-                                       WebAppRegistrar* registrar) {
-  std::set<AppId> ids;
+Registry CreateRegistryForTesting(const std::string& base_url, int num_apps) {
+  Registry registry;
 
   for (int i = 0; i < num_apps; ++i) {
     const auto url = base_url + base::IntToString(i);
     const AppId app_id = GenerateAppIdFromURL(GURL(url));
     auto web_app = std::make_unique<WebApp>(app_id);
-    registrar->RegisterApp(std::move(web_app));
+    registry.emplace(app_id, std::move(web_app));
+  }
 
-    ids.insert(app_id);
+  return registry;
+}
+
+std::set<AppId> RegisterAppsForTesting(WebAppRegistrar* registrar,
+                                       Registry&& registry) {
+  std::set<AppId> ids;
+
+  for (auto& kv : registry) {
+    ids.insert(kv.first);
+    registrar->RegisterApp(std::move(kv.second));
   }
 
   return ids;
@@ -36,7 +46,9 @@
 }  // namespace
 
 TEST(WebAppRegistrar, CreateRegisterUnregister) {
-  auto registrar = std::make_unique<WebAppRegistrar>();
+  auto database = std::make_unique<TestWebAppDatabase>();
+  auto registrar = std::make_unique<WebAppRegistrar>(database.get());
+
   EXPECT_EQ(nullptr, registrar->GetAppById(AppId()));
 
   const GURL launch_url = GURL("https://example.com/path");
@@ -88,7 +100,8 @@
 }
 
 TEST(WebAppRegistrar, DestroyRegistrarOwningRegisteredApps) {
-  auto registrar = std::make_unique<WebAppRegistrar>();
+  auto database = std::make_unique<TestWebAppDatabase>();
+  auto registrar = std::make_unique<WebAppRegistrar>(database.get());
 
   const AppId app_id = GenerateAppIdFromURL(GURL("https://example.com/path"));
   const AppId app_id2 = GenerateAppIdFromURL(GURL("https://example.com/path2"));
@@ -103,10 +116,11 @@
 }
 
 TEST(WebAppRegistrar, ForEachAndUnregisterAll) {
-  auto registrar = std::make_unique<WebAppRegistrar>();
+  auto database = std::make_unique<TestWebAppDatabase>();
+  auto registrar = std::make_unique<WebAppRegistrar>(database.get());
 
-  auto ids =
-      RegisterAppsForTesting("https://example.com/path", 100, registrar.get());
+  Registry registry = CreateRegistryForTesting("https://example.com/path", 100);
+  auto ids = RegisterAppsForTesting(registrar.get(), std::move(registry));
   EXPECT_EQ(100UL, ids.size());
 
   for (auto& kv : registrar->registry()) {
@@ -121,4 +135,43 @@
   EXPECT_TRUE(registrar->is_empty());
 }
 
+TEST(WebAppRegistrar, AbstractWebAppDatabase) {
+  auto database = std::make_unique<TestWebAppDatabase>();
+  auto registrar = std::make_unique<WebAppRegistrar>(database.get());
+
+  registrar->Init(base::DoNothing());
+  EXPECT_TRUE(registrar->is_empty());
+
+  // Load 100 apps.
+  Registry registry = CreateRegistryForTesting("https://example.com/path", 100);
+  // Copy their ids.
+  std::set<AppId> ids;
+  for (auto& kv : registry)
+    ids.insert(kv.first);
+  EXPECT_EQ(100UL, ids.size());
+
+  database->TakeOpenDatabaseCallback().Run(std::move(registry));
+
+  // Add 1 app after opening.
+  const AppId app_id = GenerateAppIdFromURL(GURL("https://example.com/path"));
+  auto web_app = std::make_unique<WebApp>(app_id);
+  registrar->RegisterApp(std::move(web_app));
+  EXPECT_EQ(app_id, database->write_web_app_id());
+  EXPECT_EQ(101UL, registrar->registry().size());
+
+  // Remove 1 app after opening.
+  registrar->UnregisterApp(app_id);
+  EXPECT_EQ(100UL, registrar->registry().size());
+  EXPECT_EQ(1UL, database->delete_web_app_ids().size());
+  EXPECT_EQ(app_id, database->delete_web_app_ids()[0]);
+
+  // Remove 100 apps after opening.
+  registrar->UnregisterAll();
+  for (auto& app_id : database->delete_web_app_ids())
+    ids.erase(app_id);
+
+  EXPECT_TRUE(ids.empty());
+  EXPECT_TRUE(registrar->is_empty());
+}
+
 }  // namespace web_app
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 3c5f821..c6840e7 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -175,8 +175,6 @@
     "prerender_url_loader_throttle.h",
     "prerender_util.cc",
     "prerender_util.h",
-    "profiling.cc",
-    "profiling.h",
     "ref_counted_util.h",
     "render_messages.h",
     "search/instant_types.cc",
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index acf3421..937949a 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -550,17 +550,6 @@
 // Selects directory of profile to associate with the first browser launched.
 const char kProfileDirectory[]              = "profile-directory";
 
-// Starts the sampling based profiler for the browser process at startup. This
-// will only work if chrome has been built with the gyp variable profiling=1.
-// The output will go to the value of kProfilingFile.
-const char kProfilingAtStart[]              = "profiling-at-start";
-
-// Controls whether profile data is periodically flushed to a file. Normally
-// the data gets written on exit but cases exist where chrome doesn't exit
-// cleanly (especially when using single-process). A time in seconds can be
-// specified.
-const char kProfilingFlush[]                = "profiling-flush";
-
 // Forces proxy auto-detection.
 const char kProxyAutoDetect[]               = "proxy-auto-detect";
 
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index beaeb052..ab31517 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -164,8 +164,6 @@
 extern const char kPrivetIPv6Only[];
 extern const char kProductVersion[];
 extern const char kProfileDirectory[];
-extern const char kProfilingAtStart[];
-extern const char kProfilingFlush[];
 extern const char kProxyAutoDetect[];
 extern const char kProxyBypassList[];
 extern const char kProxyPacUrl[];
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 7cd0512..c0d8216 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -914,10 +914,6 @@
 // YouTube. See |safe_search_util::YouTubeRestrictMode| for possible values.
 const char kForceYouTubeRestrict[] = "settings.force_youtube_restrict";
 
-// Boolean controlling whether history is recorded via Session Sync
-// (for supervised users).
-const char kForceSessionSync[] = "settings.history_recorded";
-
 // Comma separated list of domain names (e.g. "google.com,school.edu").
 // When this pref is set, the user will be able to access Google Apps
 // only using an account that belongs to one of the domains from this pref.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index f33408b..e7045f5 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -293,7 +293,6 @@
 #endif
 extern const char kForceGoogleSafeSearch[];
 extern const char kForceYouTubeRestrict[];
-extern const char kForceSessionSync[];
 extern const char kAllowedDomainsForApps[];
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
 extern const char kUsesSystemTheme[];
diff --git a/chrome/common/trace_event_args_whitelist.cc b/chrome/common/trace_event_args_whitelist.cc
index 9a50d01..48bb67f9 100644
--- a/chrome/common/trace_event_args_whitelist.cc
+++ b/chrome/common/trace_event_args_whitelist.cc
@@ -23,6 +23,7 @@
 const char* const kMemoryDumpAllowedArgs[] = {"dumps", nullptr};
 
 const WhitelistEntry kEventArgsWhitelist[] = {
+    {"browser", "KeyedServiceFactory::GetServiceForContext", nullptr},
     {"__metadata", "thread_name", nullptr},
     {"__metadata", "process_name", nullptr},
     {"__metadata", "process_uptime_seconds", nullptr},
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc
index c9f1eb82..c353e128 100644
--- a/chrome/renderer/extensions/cast_streaming_native_handler.cc
+++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -43,6 +43,7 @@
 #include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/web/web_dom_media_stream_track.h"
+#include "third_party/blink/public/web/web_local_frame.h"
 #include "url/gurl.h"
 
 using content::V8ValueConverter;
@@ -440,11 +441,14 @@
 
   create_callback_.Reset(isolate, args[2].As<v8::Function>());
 
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&CastStreamingNativeHandler::CallCreateCallback,
-                 weak_factory_.GetWeakPtr(), base::Passed(&stream1),
-                 base::Passed(&stream2), base::Passed(&udp_transport)));
+  context()
+      ->web_frame()
+      ->GetTaskRunner(blink::TaskType::kInternalMedia)
+      ->PostTask(
+          FROM_HERE,
+          base::BindOnce(&CastStreamingNativeHandler::CallCreateCallback,
+                         weak_factory_.GetWeakPtr(), base::Passed(&stream1),
+                         base::Passed(&stream2), base::Passed(&udp_transport)));
 }
 
 void CastStreamingNativeHandler::CallCreateCallback(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c4fec94..649289a 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -5330,6 +5330,7 @@
       "../browser/sync/test/integration/migration_test.cc",
       "../browser/sync/test/integration/single_client_app_list_sync_test.cc",
       "../browser/sync/test/integration/single_client_apps_sync_test.cc",
+      "../browser/sync/test/integration/single_client_autofill_profile_sync_test.cc",
       "../browser/sync/test/integration/single_client_bookmarks_sync_test.cc",
       "../browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc",
       "../browser/sync/test/integration/single_client_dictionary_sync_test.cc",
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index c632b82..1e12540 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-11230.0.0
\ No newline at end of file
+11235.0.0
\ No newline at end of file
diff --git a/chromeos/components/drivefs/mojom/drivefs.mojom b/chromeos/components/drivefs/mojom/drivefs.mojom
index 73cb133f..c0c97c6 100644
--- a/chromeos/components/drivefs/mojom/drivefs.mojom
+++ b/chromeos/components/drivefs/mojom/drivefs.mojom
@@ -152,6 +152,7 @@
   mojo_base.mojom.FilePath path;
 };
 
+// Next MinVersion: 2
 struct FileMetadata {
   enum Type {
     // A regular file.
@@ -193,6 +194,8 @@
   array<uint8>? deprecated_thumbnail;
 
   Capabilities capabilities;
+
+  [MinVersion=1] FolderFeature? folder_feature;
 };
 
 struct ImageMetadata {
@@ -213,6 +216,20 @@
   bool can_add_children = true;
 };
 
+// Set on Drive Uploader roots and optionally on select sub-folders.
+struct FolderFeature {
+  // Identifies a root directory of a machine sync, used for the backup and
+  // restore feature.
+  bool is_machine_root = false;
+
+  // Identifies a sync folder.
+  bool is_arbitary_sync_folder = false;
+
+  // Identifies an external media folder, that contains one time only uploads
+  // for USB devices, SD cards etc.
+  bool is_external_media = false;
+};
+
 struct ItemEvent {
   enum State {
     kQueued,
diff --git a/chromeos/services/ime/public/cpp/rulebased/engine.cc b/chromeos/services/ime/public/cpp/rulebased/engine.cc
index 78f5330..dcd8777 100644
--- a/chromeos/services/ime/public/cpp/rulebased/engine.cc
+++ b/chromeos/services/ime/public/cpp/rulebased/engine.cc
@@ -44,16 +44,17 @@
   ProcessKeyResult res;
   // The fallback result should commit the existing composition text.
   res.commit_text = context_;
-  if (!current_data_)
+  if (!current_data_ || modifier_state > 7) {
+    Reset();
     return res;
-  if (modifier_state > 7)
-    return res;
+  }
 
   const KeyMap* key_map = current_data_->GetKeyMapByModifiers(modifier_state);
   auto it = key_map->find(code);
   if (it == key_map->end()) {
     if (code == "Backspace" && !context_.empty())
       return ProcessBackspace();
+    Reset();
     return res;
   }
 
diff --git a/chromeos/services/ime/public/cpp/rulebased/rules_data.cc b/chromeos/services/ime/public/cpp/rulebased/rules_data.cc
index b648603..0ccc1c3 100644
--- a/chromeos/services/ime/public/cpp/rulebased/rules_data.cc
+++ b/chromeos/services/ime/public/cpp/rulebased/rules_data.cc
@@ -327,6 +327,14 @@
   auto& re = *(std::get<0>(rule));
   const std::string& repl = std::get<1>(rule);
 
+  // Don't transform if matching happens in the middle of |appended| string.
+  if (re.Match(str, 0, str.length(), re2::RE2::Anchor::UNANCHORED,
+               matches.get(), nmatch)) {
+    size_t match_start = matches[0].data() - str.data();
+    if (match_start > str.length() - appended.length())
+      return false;
+  }
+
   re2::RE2::Replace(&str, re, repl);
   re2::RE2::Replace(&str, "\u001d", "");
   *transformed = str;
diff --git a/chromeos/services/multidevice_setup/host_status_provider_impl.cc b/chromeos/services/multidevice_setup/host_status_provider_impl.cc
index 916a1d9..9259745 100644
--- a/chromeos/services/multidevice_setup/host_status_provider_impl.cc
+++ b/chromeos/services/multidevice_setup/host_status_provider_impl.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "chromeos/components/proximity_auth/logging/logging.h"
 #include "chromeos/services/multidevice_setup/eligible_host_devices_provider.h"
@@ -63,6 +64,8 @@
   device_sync_client_->AddObserver(this);
 
   CheckForUpdatedStatusAndNotifyIfChanged();
+  UMA_HISTOGRAM_ENUMERATION("MultiDevice.Setup.HostStatus",
+                            current_status_and_device_.host_status());
 }
 
 HostStatusProviderImpl::~HostStatusProviderImpl() {
diff --git a/components/arc/common/auth.mojom b/components/arc/common/auth.mojom
index 098b0e5f..773ce46 100644
--- a/components/arc/common/auth.mojom
+++ b/components/arc/common/auth.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Next MinVersion: 18
+// Next MinVersion: 19
 
 module arc.mojom;
 
@@ -209,8 +209,12 @@
   // Notifies Chrome that the authorization flow is completed and provides
   // resulting |status|. If |initial_signin| is true then this indicates that
   // authorization happened for initial device provisioning.
-  [MinVersion=11] OnAuthorizationComplete@10(ArcSignInStatus status,
-                                             bool initial_signin);
+  // If |account_name| is not present, it is assumed to be the Primary/Device
+  // account. It cannot/must not be supplied when |initial_signin| is true.
+  [MinVersion=11] OnAuthorizationComplete@10(
+      ArcSignInStatus status,
+      bool initial_signin,
+      [MinVersion=18] string? account_name);
 
   // Notifies Chrome that the sign-in is completed successfully.
   [MinVersion=2] OnSignInCompleteDeprecated@2();
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index f6b65645..fe45230a 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -355,8 +355,6 @@
     "test_region_data_loader.h",
     "test_strike_database.cc",
     "test_strike_database.h",
-    "test_sync_service.cc",
-    "test_sync_service.h",
     "webdata/autofill_sync_bridge_test_util.cc",
     "webdata/autofill_sync_bridge_test_util.h",
     "webdata/mock_autofill_webdata_backend.cc",
diff --git a/components/autofill/core/browser/autofill_experiments_unittest.cc b/components/autofill/core/browser/autofill_experiments_unittest.cc
index 724db579..91e6e95 100644
--- a/components/autofill/core/browser/autofill_experiments_unittest.cc
+++ b/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -5,11 +5,12 @@
 #include "components/autofill/core/browser/autofill_experiments.h"
 
 #include "base/test/scoped_feature_list.h"
-#include "components/autofill/core/browser/test_sync_service.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
+#include "components/sync/driver/test_sync_service.h"
+#include "google_apis/gaia/google_service_auth_error.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace autofill {
@@ -35,7 +36,7 @@
 
   base::test::ScopedFeatureList scoped_feature_list_;
   TestingPrefServiceSimple pref_service_;
-  TestSyncService sync_service_;
+  syncer::TestSyncService sync_service_;
 };
 
 TEST_F(AutofillExperimentsTest, DenyUpload_FeatureEnabled) {
@@ -57,26 +58,29 @@
 
 TEST_F(AutofillExperimentsTest, DenyUpload_AuthError) {
   scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
-  sync_service_.SetInAuthError(true);
+  sync_service_.SetAuthError(
+      GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
   EXPECT_FALSE(IsCreditCardUploadEnabled());
 }
 
 TEST_F(AutofillExperimentsTest,
        DenyUpload_SyncServiceDoesNotHaveAutofillProfilePreferredDataType) {
   scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
-  sync_service_.SetDataTypes(syncer::ModelTypeSet());
+  sync_service_.SetPreferredDataTypes(syncer::ModelTypeSet());
+  sync_service_.SetActiveDataTypes(syncer::ModelTypeSet());
   EXPECT_FALSE(IsCreditCardUploadEnabled());
 }
 
 TEST_F(AutofillExperimentsTest, DenyUpload_SyncCycleNotComplete) {
   scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
-  sync_service_.SetSyncCycleComplete(false);
+  sync_service_.SetLastCycleSnapshot(syncer::SyncCycleSnapshot());
   EXPECT_FALSE(IsCreditCardUploadEnabled());
 }
 
 TEST_F(AutofillExperimentsTest, DenyUpload_SyncConfigurationNotDone) {
   scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
-  sync_service_.SetConfigurationDone(false);
+  sync_service_.SetTransportState(
+      syncer::SyncService::TransportState::CONFIGURING);
   EXPECT_FALSE(IsCreditCardUploadEnabled());
 }
 
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc
index 125d8061..daed82e 100644
--- a/components/autofill/core/browser/autofill_metrics.cc
+++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -760,6 +760,7 @@
     bool is_uploading,
     bool is_reshow,
     bool is_requesting_cardholder_name,
+    bool is_requesting_expiration_date,
     int previous_save_credit_card_prompt_user_decision,
     security_state::SecurityLevel security_level) {
   DCHECK_LT(metric, NUM_SAVE_CARD_PROMPT_METRICS);
@@ -774,6 +775,11 @@
         metric_with_destination_and_show + ".RequestingCardholderName", metric,
         NUM_SAVE_CARD_PROMPT_METRICS);
   }
+  if (is_requesting_expiration_date) {
+    base::UmaHistogramEnumeration(
+        metric_with_destination_and_show + ".RequestingExpirationDate", metric,
+        NUM_SAVE_CARD_PROMPT_METRICS);
+  }
   base::UmaHistogramEnumeration(
       metric_with_destination_and_show +
           PreviousSaveCreditCardPromptUserDecisionToString(
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h
index d9b4104..4c40ddb 100644
--- a/components/autofill/core/browser/autofill_metrics.h
+++ b/components/autofill/core/browser/autofill_metrics.h
@@ -103,6 +103,9 @@
     // The Autofill StrikeDatabase decided not to allow offering to save for
     // this card. On mobile, that means no save prompt is shown at all.
     UPLOAD_NOT_OFFERED_MAX_STRIKES_ON_MOBILE = 1 << 13,
+    // A pair of dropdowns for the user to select expiration date was surfaced
+    // in the offer-to-save dialog.
+    USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE = 1 << 14,
     // Update |kNumCardUploadDecisionMetrics| when adding new enum here.
   };
 
@@ -908,6 +911,7 @@
       bool is_uploading,
       bool is_reshow,
       bool is_requesting_cardholder_name,
+      bool is_requesting_expiration_date_from_user,
       int previous_save_credit_card_prompt_user_decision,
       security_state::SecurityLevel security_level);
   static void LogSaveCardPromptMetricBySecurityLevel(
@@ -1278,7 +1282,7 @@
   };
 
  private:
-  static const int kNumCardUploadDecisionMetrics = 14;
+  static const int kNumCardUploadDecisionMetrics = 15;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(AutofillMetrics);
 };
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index 70e97fd..6a18b576 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -29,13 +29,13 @@
 #include "components/autofill/core/browser/test_autofill_manager.h"
 #include "components/autofill/core/browser/test_form_structure.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/browser/test_sync_service.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/prefs/pref_service.h"
+#include "components/sync/driver/test_sync_service.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "components/webdata/common/web_data_results.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
@@ -254,7 +254,7 @@
   base::test::ScopedTaskEnvironment scoped_task_environment_;
   ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
   MockAutofillClient autofill_client_;
-  TestSyncService sync_service_;
+  syncer::TestSyncService sync_service_;
   std::unique_ptr<TestAutofillDriver> autofill_driver_;
   std::unique_ptr<TestAutofillManager> autofill_manager_;
   std::unique_ptr<TestPersonalDataManager> personal_data_;
@@ -8083,6 +8083,7 @@
         AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING,
         /*is_uploading=*/true, /*is_reshow=*/false,
         /*is_requesting_cardholder_name=*/false,
+        /*is_requesting_expiration_date=*/false,
         /*previous_save_credit_card_prompt_user_decision=*/1,
         security_state::SecurityLevel::EV_SECURE);
     histogram_tester.ExpectBucketCount(
@@ -8095,6 +8096,7 @@
     AutofillMetrics::LogSaveCardPromptMetric(
         AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, /*is_uploading=*/false,
         /*is_reshow=*/true, /*is_requesting_cardholder_name=*/false,
+        /*is_requesting_expiration_date=*/false,
         /*previous_save_credit_card_prompt_user_decision=*/0,
         security_state::SecurityLevel::SECURE);
     histogram_tester.ExpectBucketCount(
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc
index 54010f82..39303f5 100644
--- a/components/autofill/core/browser/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -186,8 +186,8 @@
   should_request_expiration_date_from_user_ = false;
   if (upload_request_.detected_values &
       DetectedValue::USER_PROVIDED_EXPIRATION_DATE) {
-    // TODO(crbug.com/899057): Update |upload_decision_metrics_| with
-    //                         USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE.
+    upload_decision_metrics_ |=
+        AutofillMetrics::USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE;
     should_request_expiration_date_from_user_ = true;
   }
 
diff --git a/components/autofill/core/browser/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
index 9e929a06..173496c 100644
--- a/components/autofill/core/browser/credit_card_save_manager_unittest.cc
+++ b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -36,7 +36,6 @@
 #include "components/autofill/core/browser/test_credit_card_save_manager.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/autofill/core/browser/test_strike_database.h"
-#include "components/autofill/core/browser/test_sync_service.h"
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_clock.h"
@@ -45,6 +44,7 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/prefs/pref_service.h"
+#include "components/sync/driver/test_sync_service.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_test_util.h"
@@ -307,7 +307,7 @@
   std::unique_ptr<TestAutofillManager> autofill_manager_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_;
   TestPersonalDataManager personal_data_;
-  TestSyncService sync_service_;
+  syncer::TestSyncService sync_service_;
   base::test::ScopedFeatureList scoped_feature_list_;
   // Ends up getting owned (and destroyed) by TestFormDataImporter:
   TestCreditCardSaveManager* credit_card_save_manager_;
@@ -2441,7 +2441,13 @@
   credit_card_form.fields[3].value = ASCIIToUTF16("");
   credit_card_form.fields[4].value = ASCIIToUTF16("123");
 
+  base::HistogramTester histogram_tester;
   FormSubmitted(credit_card_form);
+  // Verify that the correct histogram entry and DetectedValue for "Expiration
+  // date explicitly requested" was logged.
+  ExpectCardUploadDecision(
+      histogram_tester,
+      AutofillMetrics::USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE);
   EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
   EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
   EXPECT_TRUE(
@@ -2473,7 +2479,13 @@
   credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
   credit_card_form.fields[4].value = ASCIIToUTF16("123");
 
+  base::HistogramTester histogram_tester;
   FormSubmitted(credit_card_form);
+  // Verify that the correct histogram entry and DetectedValue for "Expiration
+  // date explicitly requested" was logged.
+  ExpectCardUploadDecision(
+      histogram_tester,
+      AutofillMetrics::USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE);
   EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
   EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
   EXPECT_TRUE(
@@ -2505,7 +2517,13 @@
   credit_card_form.fields[3].value = ASCIIToUTF16("");
   credit_card_form.fields[4].value = ASCIIToUTF16("123");
 
+  base::HistogramTester histogram_tester;
   FormSubmitted(credit_card_form);
+  // Verify that the correct histogram entry and DetectedValue for "Expiration
+  // date explicitly requested" was logged.
+  ExpectCardUploadDecision(
+      histogram_tester,
+      AutofillMetrics::USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE);
   EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
   EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
   EXPECT_TRUE(
diff --git a/components/autofill/core/browser/local_card_migration_manager_unittest.cc b/components/autofill/core/browser/local_card_migration_manager_unittest.cc
index c0570b63..b412a91 100644
--- a/components/autofill/core/browser/local_card_migration_manager_unittest.cc
+++ b/components/autofill/core/browser/local_card_migration_manager_unittest.cc
@@ -35,7 +35,6 @@
 #include "components/autofill/core/browser/test_credit_card_save_manager.h"
 #include "components/autofill/core/browser/test_local_card_migration_manager.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/browser/test_sync_service.h"
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_clock.h"
@@ -44,6 +43,7 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/prefs/pref_service.h"
+#include "components/sync/driver/test_sync_service.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
@@ -164,7 +164,7 @@
   std::unique_ptr<TestAutofillManager> autofill_manager_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_;
   TestPersonalDataManager personal_data_;
-  TestSyncService sync_service_;
+  syncer::TestSyncService sync_service_;
   base::test::ScopedFeatureList scoped_feature_list_;
   // Ends up getting owned (and destroyed) by TestFormDataImporter:
   TestCreditCardSaveManager* credit_card_save_manager_;
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 23aeb83..3b57cd73 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -39,7 +39,6 @@
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/autofill/core/browser/test_autofill_clock.h"
 #include "components/autofill/core/browser/test_autofill_profile_validator.h"
-#include "components/autofill/core/browser/test_sync_service.h"
 #include "components/autofill/core/browser/webdata/autofill_table.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_clock.h"
@@ -51,9 +50,11 @@
 #include "components/os_crypt/os_crypt_mocker.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/driver/sync_service_utils.h"
+#include "components/sync/driver/test_sync_service.h"
 #include "components/version_info/version_info.h"
 #include "components/webdata/common/web_data_service_base.h"
 #include "components/webdata/common/web_database_service.h"
+#include "google_apis/gaia/google_service_auth_error.h"
 #include "services/identity/public/cpp/identity_test_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -402,7 +403,7 @@
   base::MessageLoopForUI message_loop_;
   std::unique_ptr<PrefService> prefs_;
   identity::IdentityTestEnvironment identity_test_env_;
-  TestSyncService sync_service_;
+  syncer::TestSyncService sync_service_;
   scoped_refptr<AutofillWebDataService> profile_database_service_;
   scoped_refptr<AutofillWebDataService> account_database_service_;
   scoped_refptr<WebDatabaseService> profile_web_database_;
@@ -5988,7 +5989,8 @@
 
 TEST_F(PersonalDataManagerTest, CreateDataForTest) {
   // Disable sync so the data gets created.
-  sync_service_.SetDataTypes(syncer::ModelTypeSet());
+  sync_service_.SetPreferredDataTypes(syncer::ModelTypeSet());
+  sync_service_.SetActiveDataTypes(syncer::ModelTypeSet());
 
   // By default, the creation of test data is disabled.
   ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -6108,12 +6110,14 @@
   SetUpThreeCardTypes();
 
   // Set an auth error and inform the personal data manager.
-  sync_service_.SetInAuthError(true);
+  sync_service_.SetAuthError(
+      GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
   personal_data_->OnStateChanged(&sync_service_);
   WaitForOnPersonalDataChanged();
 
   // Remove the auth error to be able to get the server cards.
-  sync_service_.SetInAuthError(false);
+  sync_service_.SetAuthError(
+      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
 
   // Check that cards were masked and other were untouched.
   EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
@@ -6163,15 +6167,17 @@
   SetUpThreeCardTypes();
 
   // Call OnSyncServiceInitialized with a sync service in auth error.
-  TestSyncService sync_service;
+  syncer::TestSyncService sync_service;
   sync_service.SetIsAuthenticatedAccountPrimary(
       /*is_authenticated_account_primary=*/false);
-  sync_service.SetInAuthError(true);
+  sync_service.SetAuthError(
+      GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
   personal_data_->OnSyncServiceInitialized(&sync_service);
   WaitForOnPersonalDataChanged();
 
   // Remove the auth error to be able to get the server cards.
-  sync_service.SetInAuthError(false);
+  sync_service.SetAuthError(
+      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
 
   // Check that cards were masked and other were untouched.
   EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
@@ -6195,7 +6201,8 @@
   SetUpThreeCardTypes();
 
   // Set a persistent auth error.
-  sync_service_.SetInAuthError(true);
+  sync_service_.SetAuthError(
+      GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
 
   // Check that no server cards are available for suggestion, but that the other
   // calls to get the credit cards are unaffected.
@@ -6204,8 +6211,9 @@
   EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
   EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
 
-  // Remove error
-  sync_service_.SetInAuthError(false);
+  // Remove error.
+  sync_service_.SetAuthError(
+      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
 
   // Check that all cards are available.
   EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
@@ -6452,7 +6460,8 @@
   // Turn off autofill profile sync.
   auto model_type_set = sync_service_.GetActiveDataTypes();
   model_type_set.Remove(syncer::AUTOFILL_PROFILE);
-  sync_service_.SetDataTypes(model_type_set);
+  sync_service_.SetPreferredDataTypes(model_type_set);
+  sync_service_.SetActiveDataTypes(model_type_set);
 
   // The data should still exist.
   ASSERT_EQ(1U, personal_data_->GetProfiles().size());
@@ -6484,7 +6493,8 @@
   auto model_type_set = sync_service_.GetActiveDataTypes();
   model_type_set.Remove(syncer::AUTOFILL_WALLET_DATA);
   model_type_set.Remove(syncer::AUTOFILL_WALLET_METADATA);
-  sync_service_.SetDataTypes(model_type_set);
+  sync_service_.SetPreferredDataTypes(model_type_set);
+  sync_service_.SetActiveDataTypes(model_type_set);
 
   // The credit card should still exist.
   ASSERT_EQ(1U, personal_data_->GetCreditCards().size());
diff --git a/components/autofill/core/browser/test_sync_service.cc b/components/autofill/core/browser/test_sync_service.cc
deleted file mode 100644
index 2f42009a..0000000
--- a/components/autofill/core/browser/test_sync_service.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/browser/test_sync_service.h"
-
-#include <vector>
-
-#include "components/sync/base/model_type.h"
-#include "components/sync/base/progress_marker_map.h"
-#include "components/sync/driver/sync_token_status.h"
-#include "components/sync/engine/cycle/model_neutral_state.h"
-#include "components/sync/engine/cycle/sync_cycle_snapshot.h"
-
-namespace autofill {
-
-TestSyncService::TestSyncService() : data_types_(syncer::ModelTypeSet::All()) {}
-
-TestSyncService::~TestSyncService() {}
-
-int TestSyncService::GetDisableReasons() const {
-  return disable_reasons_;
-}
-
-syncer::ModelTypeSet TestSyncService::GetPreferredDataTypes() const {
-  return data_types_;
-}
-
-syncer::ModelTypeSet TestSyncService::GetActiveDataTypes() const {
-  return data_types_;
-}
-
-bool TestSyncService::IsFirstSetupComplete() const {
-  return true;
-}
-
-bool TestSyncService::IsUsingSecondaryPassphrase() const {
-  return is_using_secondary_passphrase_;
-}
-
-bool TestSyncService::IsAuthenticatedAccountPrimary() const {
-  return is_authenticated_account_primary_;
-}
-
-const GoogleServiceAuthError& TestSyncService::GetAuthError() const {
-  return auth_error_;
-}
-
-syncer::SyncCycleSnapshot TestSyncService::GetLastCycleSnapshot() const {
-  if (sync_cycle_complete_) {
-    return syncer::SyncCycleSnapshot(
-        syncer::ModelNeutralState(), syncer::ProgressMarkerMap(), false, 5, 2,
-        7, false, 0, base::Time::Now(), base::Time::Now(),
-        std::vector<int>(syncer::MODEL_TYPE_COUNT, 0),
-        std::vector<int>(syncer::MODEL_TYPE_COUNT, 0),
-        sync_pb::SyncEnums::UNKNOWN_ORIGIN,
-        /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
-        /*long_poll_interval=*/base::TimeDelta::FromMinutes(180),
-        /*has_remaining_local_changes=*/false);
-  }
-  return syncer::SyncCycleSnapshot();
-}
-
-syncer::SyncTokenStatus TestSyncService::GetSyncTokenStatus() const {
-  syncer::SyncTokenStatus token;
-
-  if (is_in_auth_error_) {
-    token.connection_status = syncer::ConnectionStatus::CONNECTION_AUTH_ERROR;
-    token.last_get_token_error =
-        GoogleServiceAuthError::FromServiceError("error");
-  }
-
-  return token;
-}
-
-AccountInfo TestSyncService::GetAuthenticatedAccountInfo() const {
-  return account_info_;
-}
-
-void TestSyncService::SetInAuthError(bool is_in_auth_error) {
-  is_in_auth_error_ = is_in_auth_error;
-
-  if (is_in_auth_error) {
-    auth_error_ = GoogleServiceAuthError(
-        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-  } else {
-    auth_error_ = GoogleServiceAuthError(GoogleServiceAuthError::NONE);
-  }
-}
-
-}  // namespace autofill
diff --git a/components/autofill/core/browser/test_sync_service.h b/components/autofill/core/browser/test_sync_service.h
deleted file mode 100644
index cecf626..0000000
--- a/components/autofill/core/browser/test_sync_service.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_SYNC_SERVICE_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_SYNC_SERVICE_H_
-
-#include "components/sync/driver/fake_sync_service.h"
-#include "components/sync/driver/sync_service.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-
-namespace autofill {
-class TestSyncService : public syncer::FakeSyncService {
- public:
-  TestSyncService();
-  ~TestSyncService() override;
-
-  // FakeSyncService:
-  int GetDisableReasons() const override;
-  syncer::ModelTypeSet GetPreferredDataTypes() const override;
-  syncer::ModelTypeSet GetActiveDataTypes() const override;
-  bool IsFirstSetupComplete() const override;
-  bool IsUsingSecondaryPassphrase() const override;
-  syncer::SyncCycleSnapshot GetLastCycleSnapshot() const override;
-  const GoogleServiceAuthError& GetAuthError() const override;
-  syncer::SyncTokenStatus GetSyncTokenStatus() const override;
-  bool IsAuthenticatedAccountPrimary() const override;
-  AccountInfo GetAuthenticatedAccountInfo() const override;
-
-  void SetDisableReasons(int disable_reasons) {
-    disable_reasons_ = disable_reasons;
-  }
-
-  void SetIsAuthenticatedAccountPrimary(bool is_authenticated_account_primary) {
-    is_authenticated_account_primary_ = is_authenticated_account_primary;
-  }
-
-  void SetDataTypes(syncer::ModelTypeSet data_types) {
-    data_types_ = data_types;
-  }
-
-  void SetIsUsingSecondaryPassphrase(bool is_using_secondary_passphrase) {
-    is_using_secondary_passphrase_ = is_using_secondary_passphrase;
-  }
-
-  void SetSyncCycleComplete(bool complete) { sync_cycle_complete_ = complete; }
-
-  void SetInAuthError(bool is_in_auth_error);
-
-  void SetAuthenticatedAccountInfo(const AccountInfo& account_info) {
-    account_info_ = account_info;
-  }
-
- private:
-  int disable_reasons_ = DISABLE_REASON_NONE;
-  // Used as both "preferred" and "active" data types.
-  syncer::ModelTypeSet data_types_;
-  bool is_using_secondary_passphrase_ = false;
-  bool sync_cycle_complete_ = true;
-  GoogleServiceAuthError auth_error_;
-  bool is_in_auth_error_ = false;
-  bool is_authenticated_account_primary_ = true;
-  AccountInfo account_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestSyncService);
-};
-
-}  // namespace autofill
-
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_SYNC_SERVICE_H_
diff --git a/components/autofill_assistant/browser/batch_element_checker.cc b/components/autofill_assistant/browser/batch_element_checker.cc
index 99b56c3..182585d 100644
--- a/components/autofill_assistant/browser/batch_element_checker.cc
+++ b/components/autofill_assistant/browser/batch_element_checker.cc
@@ -23,7 +23,7 @@
     : web_controller_(web_controller),
       pending_checks_count_(0),
       all_found_(false),
-      stopped_(false),
+      started_(false),
       weak_ptr_factory_(this) {
   DCHECK(web_controller);
 }
@@ -34,7 +34,7 @@
     ElementCheckType check_type,
     const std::vector<std::string>& selectors,
     ElementCheckCallback callback) {
-  DCHECK(!try_done_callback_);
+  DCHECK(!started_);
 
   element_check_callbacks_[std::make_pair(check_type, selectors)].emplace_back(
       std::move(callback));
@@ -43,7 +43,7 @@
 void BatchElementChecker::AddFieldValueCheck(
     const std::vector<std::string>& selectors,
     GetFieldValueCallback callback) {
-  DCHECK(!try_done_callback_);
+  DCHECK(!started_);
 
   get_field_value_callbacks_[selectors].emplace_back(std::move(callback));
 }
@@ -51,6 +51,7 @@
 void BatchElementChecker::Run(const base::TimeDelta& duration,
                               base::RepeatingCallback<void()> try_done,
                               base::OnceCallback<void()> all_done) {
+  started_ = true;
   int64_t try_count = duration / kCheckPeriod;
   if (try_count <= 0) {
     try_count = 1;
@@ -62,13 +63,17 @@
       base::Unretained(this), try_count, try_done, std::move(all_done)));
 }
 
+bool BatchElementChecker::all_found() {
+  if (!started_) {
+    return element_check_callbacks_.empty() &&
+           get_field_value_callbacks_.empty();
+  }
+  return all_found_;
+}
+
 void BatchElementChecker::Try(base::OnceCallback<void()> try_done_callback) {
   DCHECK(!try_done_callback_);
 
-  if (stopped_) {
-    std::move(try_done_callback).Run();
-    return;
-  }
   try_done_callback_ = std::move(try_done_callback);
 
   DCHECK_EQ(pending_checks_count_, 0);
@@ -130,7 +135,7 @@
   }
 
   --remaining_attempts;
-  if (remaining_attempts <= 0 || stopped_) {
+  if (remaining_attempts <= 0) {
     // GiveUp is run before calling try_done, so its effects are visible right
     // away.
     GiveUp();
diff --git a/components/autofill_assistant/browser/batch_element_checker.h b/components/autofill_assistant/browser/batch_element_checker.h
index b33ec13..906c708 100644
--- a/components/autofill_assistant/browser/batch_element_checker.h
+++ b/components/autofill_assistant/browser/batch_element_checker.h
@@ -88,12 +88,9 @@
            base::RepeatingCallback<void()> try_done,
            base::OnceCallback<void()> all_done);
 
-  // Makes any pending Run stop after the end of the current try.
-  void StopTrying() { stopped_ = true; }
-
   // Returns true if all element that were asked for have been found. Can be
   // called while Run is progress or afterwards.
-  bool all_found() { return all_found_; }
+  bool all_found();
 
  private:
   // Tries running the checks, reporting only successes.
@@ -136,7 +133,9 @@
       get_field_value_callbacks_;
   int pending_checks_count_;
   bool all_found_;
-  bool stopped_;
+
+  // Run() was called. Checking elements might or might not have finished yet.
+  bool started_;
 
   // The callback built for Try(). It is kept around while going through the
   // maps and called once all selectors in that map have been looked up once,
diff --git a/components/autofill_assistant/browser/batch_element_checker_unittest.cc b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
index dbe6607..b3217f99 100644
--- a/components/autofill_assistant/browser/batch_element_checker_unittest.cc
+++ b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
@@ -101,6 +101,13 @@
   std::map<std::string, int> try_done_;
 };
 
+TEST_F(BatchElementCheckerTest, AllFoundIfEmpty) {
+  EXPECT_TRUE(checks_.all_found());
+  checks_.AddElementCheck(kExistenceCheck, {"exists"},
+                          ElementExistenceCallback("exists"));
+  EXPECT_FALSE(checks_.all_found());
+}
+
 TEST_F(BatchElementCheckerTest, OneElementFound) {
   EXPECT_CALL(mock_web_controller_,
               OnElementCheck(kExistenceCheck, ElementsAre("exists"), _))
@@ -351,26 +358,5 @@
   EXPECT_FALSE(checks_.all_found());
 }
 
-TEST_F(BatchElementCheckerTest, StopTrying) {
-  EXPECT_CALL(mock_web_controller_,
-              OnElementCheck(kExistenceCheck, ElementsAre("element"), _))
-      .WillRepeatedly(RunOnceCallback<2>(false));
-
-  checks_.AddElementCheck(kExistenceCheck, {"element"}, base::DoNothing());
-  checks_.Run(base::TimeDelta::FromSeconds(1), TryCallback("try"),
-              DoneCallback("all_done"));
-
-  // The first try does not fully succeed.
-  EXPECT_THAT(try_done_, Contains(Pair("try", 1)));
-  EXPECT_THAT(all_done_, Not(Contains("all_done")));
-
-  checks_.StopTrying();
-
-  // Give up on the second try, because of StopTrying.
-  AdvanceTime();
-  EXPECT_THAT(try_done_, Contains(Pair("try", 2)));
-  EXPECT_THAT(all_done_, Contains("all_done"));
-}
-
 }  // namespace
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index c16773e8..a77d5c34 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -13,6 +13,7 @@
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -184,6 +185,8 @@
     GetUiController()->HideOverlay();
     GetUiController()->ShowStatusMessage(
         l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR));
+    GetUiController()->ShutdownGracefully();
+    return;
   }
 
   periodic_script_check_count_--;
@@ -224,6 +227,7 @@
     LOG(ERROR) << "Failed to execute script " << script_path;
     GetUiController()->ShowStatusMessage(
         l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR));
+    GetUiController()->ShutdownGracefully();
     return;
   }
 
@@ -232,6 +236,10 @@
       GetUiController()->Shutdown();  // indirectly deletes this
       return;
 
+    case ScriptExecutor::SHUTDOWN_GRACEFULLY:
+      GetUiController()->ShutdownGracefully();
+      return;
+
     case ScriptExecutor::RESTART:
       script_tracker_ = std::make_unique<ScriptTracker>(/* delegate= */ this,
                                                         /* listener= */ this);
@@ -263,6 +271,7 @@
   // Runnable scripts will be checked and reported if necessary after executing
   // the script.
   script_tracker_->ClearRunnableScripts();
+  GetUiController()->UpdateScripts({});  // Clear scripts.
   allow_autostart_ = false;  // Only ever autostart the very first script.
   script_tracker_->ExecuteScript(
       script_path, base::BindOnce(&Controller::OnScriptExecuted,
@@ -274,6 +283,12 @@
   delete this;
 }
 
+void Controller::OnGiveUp() {
+  GetUiController()->ShowStatusMessage(
+      l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_GIVE_UP));
+  GetUiController()->ShutdownGracefully();
+}
+
 void Controller::DidAttachInterstitialPage() {
   GetUiController()->Shutdown();
 }
@@ -296,6 +311,20 @@
   }
 }
 
+void Controller::OnNoRunnableScriptsAnymore() {
+  if (script_tracker_->running())
+    return;
+
+  // We're on a page that has no scripts or the scripts have reached a state
+  // from which they cannot recover through a DOM change. This should never
+  // happen with a consistent set of scripts; there should always be an explicit
+  // end.
+  GetUiController()->ShowStatusMessage(
+      l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR));
+  GetUiController()->ShutdownGracefully();
+  return;
+}
+
 void Controller::OnRunnableScriptsChanged(
     const std::vector<ScriptHandle>& runnable_scripts) {
   // Script selection is disabled when a script is already running. We will
@@ -360,6 +389,26 @@
   GetOrCheckScripts(web_contents()->GetLastCommittedURL());
 }
 
+void Controller::DidStartNavigation(
+    content::NavigationHandle* navigation_handle) {
+  // The following types of navigations are allowed for the main frame:
+  //  - first-time URL load
+  //  - script-directed navigation, while a script is running
+  //  - server redirections, which might happen outside of a script, but
+  //    because of a load triggered by a previously-running script.
+  //  - same-document modifications, which might happen automatically
+  ///
+  // Everything else, such as clicking on a link, going back to a previous page,
+  // or refreshing the page is considered an end condition.
+  if (navigation_handle->IsInMainFrame() &&
+      web_contents()->GetLastCommittedURL().is_valid() &&
+      !script_tracker_->running() && !navigation_handle->WasServerRedirect() &&
+      !navigation_handle->IsSameDocument()) {
+    OnGiveUp();
+    return;
+  }
+}
+
 void Controller::RenderProcessGone(base::TerminationStatus status) {
   GetUiController()->Shutdown();
 }
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h
index 76682f0..0d1e304 100644
--- a/components/autofill_assistant/browser/controller.h
+++ b/components/autofill_assistant/browser/controller.h
@@ -83,9 +83,11 @@
   // Overrides content::UiDelegate:
   void OnClickOverlay() override;
   void OnDestroy() override;
+  void OnGiveUp() override;
   void OnScriptSelected(const std::string& script_path) override;
 
   // Overrides ScriptTracker::Listener:
+  void OnNoRunnableScriptsAnymore() override;
   void OnRunnableScriptsChanged(
       const std::vector<ScriptHandle>& runnable_scripts) override;
 
@@ -94,6 +96,8 @@
   void DidGetUserInteraction(const blink::WebInputEvent::Type type) override;
   void DidFinishLoad(content::RenderFrameHost* render_frame_host,
                      const GURL& validated_url) override;
+  void DidStartNavigation(
+      content::NavigationHandle* navigation_handle) override;
   void DocumentAvailableInMainFrame() override;
   void RenderProcessGone(base::TerminationStatus status) override;
   void WebContentsDestroyed() override;
diff --git a/components/autofill_assistant/browser/mock_ui_controller.h b/components/autofill_assistant/browser/mock_ui_controller.h
index 4703cb6f..c08e8b0f 100644
--- a/components/autofill_assistant/browser/mock_ui_controller.h
+++ b/components/autofill_assistant/browser/mock_ui_controller.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_UI_CONTROLLER_H_
 #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_UI_CONTROLLER_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -25,6 +26,7 @@
   MOCK_METHOD0(ShowOverlay, void());
   MOCK_METHOD0(HideOverlay, void());
   MOCK_METHOD0(Shutdown, void());
+  MOCK_METHOD0(ShutdownGracefully, void());
   MOCK_METHOD1(UpdateScripts, void(const std::vector<ScriptHandle>& scripts));
 
   void ChooseAddress(
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index e557658..67dc8fc8 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -40,6 +40,7 @@
       at_end_(CONTINUE),
       should_stop_script_(false),
       should_clean_contextual_ui_on_finish_(false),
+      previous_action_type_(ActionProto::ACTION_INFO_NOT_SET),
       weak_ptr_factory_(this) {
   DCHECK(delegate_);
 }
@@ -181,7 +182,14 @@
 }
 
 void ScriptExecutor::Shutdown() {
-  at_end_ = SHUTDOWN;
+  // The following handles the case where scripts end with tell + stop
+  // differently from just stop. TODO(b/806868): Make that difference explicit:
+  // add an optional message to stop and update the scripts to use that.
+  if (previous_action_type_ == ActionProto::kTell) {
+    at_end_ = SHUTDOWN_GRACEFULLY;
+  } else {
+    at_end_ = SHUTDOWN;
+  }
 }
 
 void ScriptExecutor::Restart() {
@@ -294,6 +302,7 @@
 
 void ScriptExecutor::OnProcessedAction(
     std::unique_ptr<ProcessedActionProto> processed_action_proto) {
+  previous_action_type_ = processed_action_proto->action().action_info_case();
   processed_actions_.emplace_back(*processed_action_proto);
   if (processed_actions_.back().status() !=
       ProcessedActionStatusProto::ACTION_APPLIED) {
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index 04b79bf..b473c61 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -49,6 +49,9 @@
     // Shut down Autofill Assistant.
     SHUTDOWN,
 
+    // Shut down Autofill Assistant after a delay.
+    SHUTDOWN_GRACEFULLY,
+
     // Reset all state and restart.
     RESTART
   };
@@ -136,6 +139,7 @@
   AtEnd at_end_;
   bool should_stop_script_;
   bool should_clean_contextual_ui_on_finish_;
+  ActionProto::ActionInfoCase previous_action_type_;
 
   base::WeakPtrFactory<ScriptExecutor> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(ScriptExecutor);
diff --git a/components/autofill_assistant/browser/script_tracker.cc b/components/autofill_assistant/browser/script_tracker.cc
index 8e1b4e74..0e803e2 100644
--- a/components/autofill_assistant/browser/script_tracker.cc
+++ b/components/autofill_assistant/browser/script_tracker.cc
@@ -17,6 +17,7 @@
                              ScriptTracker::Listener* listener)
     : delegate_(delegate),
       listener_(listener),
+      reported_runnable_scripts_(false),
       weak_ptr_factory_(this) {
   DCHECK(delegate_);
   DCHECK(listener_);
@@ -32,25 +33,9 @@
 }
 
 void ScriptTracker::CheckScripts(const base::TimeDelta& max_duration) {
-  if (batch_element_checker_) {
-    // It should be possible to just call batch_element_checker_.reset() to give
-    // up on all checks. This doesn't work, however, because it ends up running
-    // multiple checks in parallel, which fails.
-    //
-    // StopTrying() tells BatchElementChecker to give up early and call
-    // OnCheckDone as soon as possible, which is a safe point for deleting the
-    // checker and starting a new check.
-    //
-    // TODO(crbug.com/806868): Figure out why checks run in parallel don't work
-    // and simplify this logic.
-    batch_element_checker_->StopTrying();
+  // In case checks are still running, terminate them.
+  TerminatePendingChecks();
 
-    // TODO(crbug.com/806868): May stop recheck if there is a script pending to
-    // run.
-    must_recheck_ = base::BindOnce(&ScriptTracker::CheckScripts,
-                                   base::Unretained(this), max_duration);
-    return;
-  }
   DCHECK(pending_runnable_scripts_.empty());
 
   batch_element_checker_ =
@@ -63,6 +48,15 @@
         base::BindOnce(&ScriptTracker::OnPreconditionCheck,
                        weak_ptr_factory_.GetWeakPtr(), script));
   }
+  if (batch_element_checker_->all_found() &&
+      pending_runnable_scripts_.empty() && reported_runnable_scripts_) {
+    // There are no runnable scripts, even though we haven't checked the DOM
+    // yet. Report it all immediately.
+    UpdateRunnableScriptsIfNecessary();
+    listener_->OnNoRunnableScriptsAnymore();
+    OnCheckDone();
+    return;
+  }
   batch_element_checker_->Run(
       max_duration,
       /* try_done= */
@@ -91,30 +85,18 @@
   ScriptExecutor::RunScriptCallback run_script_callback = base::BindOnce(
       &ScriptTracker::OnScriptRun, weak_ptr_factory_.GetWeakPtr(), script_path,
       std::move(callback));
-  // Postpone running script until finishing the current round of preconditions
-  // check.
-  if (!batch_element_checker_ && !must_recheck_) {
-    executor_->Run(std::move(run_script_callback));
-  } else {
-    pending_run_script_callback_ = std::move(run_script_callback);
-    // Do not recheck and retry when there is a script pending to run. Note
-    // that |batch_element_checker_| may take a long time to wait on retrying
-    // unsatisfied preconditions check without stop trying.
-    must_recheck_.Reset();
-    batch_element_checker_->StopTrying();
-  }
+  TerminatePendingChecks();
+  executor_->Run(std::move(run_script_callback));
 }
 
 void ScriptTracker::ClearRunnableScripts() {
   runnable_scripts_.clear();
-  listener_->OnRunnableScriptsChanged(runnable_scripts_);
 }
 
 void ScriptTracker::OnScriptRun(
     const std::string& script_path,
     ScriptExecutor::RunScriptCallback original_callback,
     ScriptExecutor::Result result) {
-  DCHECK(!pending_run_script_callback_);
   executor_.reset();
   executed_scripts_[script_path] =
       result.success ? SCRIPT_STATUS_SUCCESS : SCRIPT_STATUS_FAILURE;
@@ -139,19 +121,12 @@
     runnable_scripts_.push_back(script->handle);
   }
 
+  reported_runnable_scripts_ = true;
   listener_->OnRunnableScriptsChanged(runnable_scripts_);
 }
 
 void ScriptTracker::OnCheckDone() {
   TerminatePendingChecks();
-  if (must_recheck_) {
-    std::move(must_recheck_).Run();
-    return;
-  }
-
-  // TODO(crbug.com/806868): Check whether the script is still runnable.
-  if (pending_run_script_callback_)
-    executor_->Run(std::move(pending_run_script_callback_));
 }
 
 void ScriptTracker::TerminatePendingChecks() {
diff --git a/components/autofill_assistant/browser/script_tracker.h b/components/autofill_assistant/browser/script_tracker.h
index 2de9d65..6f69f79f3 100644
--- a/components/autofill_assistant/browser/script_tracker.h
+++ b/components/autofill_assistant/browser/script_tracker.h
@@ -37,6 +37,15 @@
     // are the new runnable scripts. Runnable scripts are ordered by priority.
     virtual void OnRunnableScriptsChanged(
         const std::vector<ScriptHandle>& runnable_scripts) = 0;
+
+    // Called when there are no more runnable scripts anymore and there cannot
+    // be any without navigating to another page.
+    //
+    // This is not called if a DOM change could make some scripts runnable.
+    //
+    // This is not called until some scripts have been reported runnable to
+    // OnRunnableScriptsChanged at least once.
+    virtual void OnNoRunnableScriptsAnymore() = 0;
   };
 
   // |delegate| and |listener| should outlive this object and should not be
@@ -53,8 +62,8 @@
   // Run the preconditions on the current set of scripts, and possibly update
   // the set of runnable scripts.
   //
-  // Calling CheckScripts() while a check is in progress cleanly cancels the
-  // previously running check and starts a new one right afterwards.
+  // Calling CheckScripts() while a check is in progress cancels the previously
+  // running check and starts a new one right away.
   void CheckScripts(const base::TimeDelta& max_duration);
 
   // Runs a script and reports, when the script has ended, whether the run was
@@ -87,7 +96,9 @@
   // Overrides ScriptExecutor::Listener.
   void OnServerPayloadChanged(const std::string& server_payload) override;
 
-  // Cleans up any state use by pending checks. Stops running pending checks.
+  // Stops running pending checks and cleans up any state used by pending
+  // checks. This can safely be called at any time, including when no checks are
+  // running.
   void TerminatePendingChecks();
 
   // Returns true if |runnable_| should be updated.
@@ -108,6 +119,11 @@
   // the bottom bar.
   std::vector<ScriptHandle> runnable_scripts_;
 
+  // True if OnRunnableScriptsChanged was called at least once - necessarily
+  // with a non-empty set of scripts the first time, since the tracker starts
+  // with an empty set of scripts.
+  bool reported_runnable_scripts_;
+
   // Sets of available scripts. SetScripts resets this and interrupts
   // any pending check.
   AvailableScriptMap available_scripts_;
@@ -120,18 +136,10 @@
   // |batch_element_checker_|.
   std::vector<Script*> pending_runnable_scripts_;
 
-  // If a Check() was called while a check was in progress, run another one just
-  // afterwards, in case things have changed.
-  base::OnceCallback<void()> must_recheck_;
-
   // If a script is currently running, this is the script's executor. Otherwise,
   // this is nullptr.
   std::unique_ptr<ScriptExecutor> executor_;
 
-  // The callback of the pending run script. |executor_| must not be nullptr if
-  // |pending_run_script_callback_| is not nullptr.
-  ScriptExecutor::RunScriptCallback pending_run_script_callback_;
-
   std::string last_server_payload_;
 
   base::WeakPtrFactory<ScriptTracker> weak_ptr_factory_;
diff --git a/components/autofill_assistant/browser/script_tracker_unittest.cc b/components/autofill_assistant/browser/script_tracker_unittest.cc
index 40113704..c872175 100644
--- a/components/autofill_assistant/browser/script_tracker_unittest.cc
+++ b/components/autofill_assistant/browser/script_tracker_unittest.cc
@@ -46,7 +46,10 @@
   }
 
  protected:
-  ScriptTrackerTest() : runnable_scripts_changed_(0), tracker_(this, this) {}
+  ScriptTrackerTest()
+      : no_runnable_scripts_anymore_(0),
+        runnable_scripts_changed_(0),
+        tracker_(this, this) {}
 
   // Overrides ScriptTrackerDelegate
   Service* GetService() override { return &mock_service_; }
@@ -74,6 +77,8 @@
     runnable_scripts_ = runnable_scripts;
   }
 
+  void OnNoRunnableScriptsAnymore() override { no_runnable_scripts_anymore_++; }
+
   void SetAndCheckScripts(const SupportsScriptResponseProto& response) {
     std::string response_str;
     response.SerializeToString(&response_str);
@@ -90,10 +95,12 @@
     SupportedScriptProto* script = response->add_scripts();
     script->set_path(path);
     script->mutable_presentation()->set_name(name);
-    script->mutable_presentation()
-        ->mutable_precondition()
-        ->add_elements_exist()
-        ->add_selectors(selector);
+    if (!selector.empty()) {
+      script->mutable_presentation()
+          ->mutable_precondition()
+          ->add_elements_exist()
+          ->add_selectors(selector);
+    }
     ScriptStatusMatchProto dont_run_twice_precondition;
     dont_run_twice_precondition.set_script(path);
     dont_run_twice_precondition.set_comparator(ScriptStatusMatchProto::EQUAL);
@@ -129,6 +136,8 @@
   ClientMemory client_memory_;
   std::map<std::string, std::string> parameters_;
 
+  // Number of times NoRunnableScriptsAnymore was called.
+  int no_runnable_scripts_anymore_;
   // Number of times OnRunnableScriptsChanged was called.
   int runnable_scripts_changed_;
   std::vector<ScriptHandle> runnable_scripts_;
@@ -137,9 +146,10 @@
 
 TEST_F(ScriptTrackerTest, NoScripts) {
   tracker_.SetScripts({});
-  EXPECT_EQ(0, runnable_scripts_changed_);
   tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
   EXPECT_THAT(runnable_scripts(), IsEmpty());
+  EXPECT_EQ(0, runnable_scripts_changed_);
+  EXPECT_EQ(0, no_runnable_scripts_anymore_);
 }
 
 TEST_F(ScriptTrackerTest, SomeRunnableScripts) {
@@ -271,33 +281,4 @@
   ASSERT_THAT(runnable_script_paths(), ElementsAre("script path"));
 }
 
-TEST_F(ScriptTrackerTest, DuplicateCheckCalls) {
-  SupportsScriptResponseProto scripts;
-  AddScript(&scripts, "runnable name", "runnable path", "exists");
-
-  base::OnceCallback<void(bool)> captured_callback;
-  EXPECT_CALL(mock_web_controller_,
-              OnElementCheck(kExistenceCheck, ElementsAre("exists"), _))
-      .WillOnce(CaptureOnceCallback<2>(&captured_callback))
-      .WillOnce(RunOnceCallback<2>(false));
-  SetAndCheckScripts(scripts);
-
-  // At this point, since the callback hasn't been run, there's still a check in
-  // progress. The three calls to CheckScripts will trigger one call to
-  // CheckScript right after first_call has run.
-  for (int i = 0; i < 3; i++) {
-    tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
-  }
-
-  EXPECT_THAT(runnable_scripts(), IsEmpty());
-  ASSERT_TRUE(captured_callback);
-  std::move(captured_callback).Run(true);
-
-  // The second check is run right away, after the first check, say that the
-  // element doesn't exist anymore, and we end up again with an empty
-  // runnable_scripts.
-  EXPECT_THAT(runnable_scripts(), IsEmpty());
-  EXPECT_EQ(2, runnable_scripts_changed_);
-}
-
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/ui_controller.h b/components/autofill_assistant/browser/ui_controller.h
index 74af593..0b536b4 100644
--- a/components/autofill_assistant/browser/ui_controller.h
+++ b/components/autofill_assistant/browser/ui_controller.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_UI_CONTROLLER_H_
 #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_UI_CONTROLLER_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -40,6 +41,11 @@
   // Warning: this indirectly deletes the caller.
   virtual void Shutdown() = 0;
 
+  // Shuts down Autofill Assistant after a small delay.
+  //
+  // Warning: this indirectly deletes the caller.
+  virtual void ShutdownGracefully() = 0;
+
   // Update the list of scripts in the UI.
   virtual void UpdateScripts(const std::vector<ScriptHandle>& scripts) = 0;
 
diff --git a/components/autofill_assistant/browser/ui_delegate.h b/components/autofill_assistant/browser/ui_delegate.h
index d90f7a9..7e16d77 100644
--- a/components/autofill_assistant/browser/ui_delegate.h
+++ b/components/autofill_assistant/browser/ui_delegate.h
@@ -20,6 +20,11 @@
   // detached from the associated activity.
   virtual void OnDestroy() = 0;
 
+  // Called when the Autofill Assistant should display a message saying that
+  // it's shutting down and then shut down, because something happened that
+  // scripts cannot handle, such as a new window being opened.
+  virtual void OnGiveUp() = 0;
+
   // Called when a script was selected for execution.
   virtual void OnScriptSelected(const std::string& script_path) = 0;
 
diff --git a/components/autofill_assistant_strings.grdp b/components/autofill_assistant_strings.grdp
index 12a52b7..4520a73b 100644
--- a/components/autofill_assistant_strings.grdp
+++ b/components/autofill_assistant_strings.grdp
@@ -1,8 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
   <if expr="is_android">
-    <message name="IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR" desc="Text label that is shown when communication with server fails.">
-      Service is not available. Try again later.
+    <message name="IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR" desc="Text label that is shown when autofill assistant cannot help anymore, because something went wrong.">
+      Something happened! I cannot help anymore. You can continue directly on the website.
+    </message>
+    <message name="IDS_AUTOFILL_ASSISTANT_GIVE_UP" desc="Text label that is shown when autofill assistant cannot help anymore, because of a user action.">
+      It looks like you want to do this by yourself. It's ok to continue on without my help.
     </message>
     <message name="IDS_AUTOFILL_ASSISTANT_LOADING" desc="Text label that is shown during the loading of the first page, right after being triggered.">
       Opening <ph name="SITE_NAME">$1<ex>google.com</ex></ph>…
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index 361d04e..787d5b9 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -25,8 +25,8 @@
 #include "components/history/core/browser/sync/history_delete_directives_model_type_controller.h"
 #include "components/history/core/browser/sync/typed_url_model_type_controller.h"
 #include "components/password_manager/core/browser/password_data_type_controller.h"
-#include "components/password_manager/core/browser/password_model_type_controller.h"
 #include "components/password_manager/core/browser/password_store.h"
+#include "components/password_manager/core/browser/password_syncable_service_based_model_type_controller.h"
 #include "components/prefs/pref_service.h"
 #include "components/reading_list/features/reading_list_switches.h"
 #include "components/sync/base/report_unrecoverable_error.h"
@@ -321,7 +321,8 @@
   if (!disabled_types.Has(syncer::PASSWORDS)) {
     if (base::FeatureList::IsEnabled(switches::kSyncPseudoUSSPasswords)) {
       controllers.push_back(
-          std::make_unique<password_manager::PasswordModelTypeController>(
+          std::make_unique<password_manager::
+                               PasswordSyncableServiceBasedModelTypeController>(
               sync_client_->GetModelTypeStoreService()->GetStoreFactory(),
               dump_stack, password_store_, sync_client_));
     } else {
diff --git a/components/keyed_service/core/keyed_service_base_factory.cc b/components/keyed_service/core/keyed_service_base_factory.cc
index 773b1f9..19b7513 100644
--- a/components/keyed_service/core/keyed_service_base_factory.cc
+++ b/components/keyed_service/core/keyed_service_base_factory.cc
@@ -45,10 +45,7 @@
 
 KeyedServiceBaseFactory::KeyedServiceBaseFactory(const char* service_name,
                                                  DependencyManager* manager)
-    : dependency_manager_(manager) {
-#ifndef NDEBUG
-  service_name_ = service_name;
-#endif
+    : dependency_manager_(manager), service_name_(service_name) {
   dependency_manager_->AddComponent(this);
 }
 
diff --git a/components/keyed_service/core/keyed_service_base_factory.h b/components/keyed_service/core/keyed_service_base_factory.h
index 0c6d7c5..48c3ca2 100644
--- a/components/keyed_service/core/keyed_service_base_factory.h
+++ b/components/keyed_service/core/keyed_service_base_factory.h
@@ -30,10 +30,8 @@
 // direct subclasses react to lifecycle events and implement memory management.
 class KEYED_SERVICE_EXPORT KeyedServiceBaseFactory : public DependencyNode {
  public:
-#ifndef NDEBUG
-  // Returns our name. We don't keep track of this in release mode.
+  // Returns our name.
   const char* name() const { return service_name_; }
-#endif
 
  protected:
   KeyedServiceBaseFactory(const char* service_name, DependencyManager* manager);
@@ -135,12 +133,9 @@
   // Contexts that have this service's preferences registered on them.
   std::set<base::SupportsUserData*> registered_preferences_;
 
-#if !defined(NDEBUG)
   // A static string passed in to the constructor. Should be unique across all
-  // services. This is used only for debugging in debug mode. (Used to print
-  // pretty graphs with GraphViz.)
+  // services.
   const char* service_name_;
-#endif
 };
 
 #endif  // COMPONENTS_KEYED_SERVICE_CORE_KEYED_SERVICE_BASE_FACTORY_H_
diff --git a/components/keyed_service/core/keyed_service_factory.cc b/components/keyed_service/core/keyed_service_factory.cc
index eff4e3d2..5fbfc03 100644
--- a/components/keyed_service/core/keyed_service_factory.cc
+++ b/components/keyed_service/core/keyed_service_factory.cc
@@ -58,7 +58,8 @@
 KeyedService* KeyedServiceFactory::GetServiceForContext(
     base::SupportsUserData* context,
     bool create) {
-  TRACE_EVENT0("browser,startup", "KeyedServiceFactory::GetServiceForContext");
+  TRACE_EVENT1("browser,startup", "KeyedServiceFactory::GetServiceForContext",
+               "service_name", name());
   context = GetContextToUse(context);
   if (!context)
     return nullptr;
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 4941deb..cf11f46 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -134,8 +134,6 @@
     "password_manager_metrics_util.h",
     "password_manager_util.cc",
     "password_manager_util.h",
-    "password_model_type_controller.cc",
-    "password_model_type_controller.h",
     "password_model_worker.cc",
     "password_model_worker.h",
     "password_requirements_service.cc",
@@ -156,6 +154,8 @@
     "password_sync_util.h",
     "password_syncable_service.cc",
     "password_syncable_service.h",
+    "password_syncable_service_based_model_type_controller.cc",
+    "password_syncable_service_based_model_type_controller.h",
     "password_ui_utils.cc",
     "password_ui_utils.h",
     "psl_matching_helper.cc",
diff --git a/components/password_manager/core/browser/form_parsing/form_parser.cc b/components/password_manager/core/browser/form_parsing/form_parser.cc
index a30b697..acba64ea 100644
--- a/components/password_manager/core/browser/form_parsing/form_parser.cc
+++ b/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -178,25 +178,52 @@
   return nullptr;
 }
 
-// Tries to parse |processed_fields| based on server |predictions|.
+// Tries to parse |processed_fields| based on server |predictions|. Uses |mode|
+// to decide which of two username hints are relevant, if present.
 std::unique_ptr<SignificantFields> ParseUsingPredictions(
     const std::vector<ProcessedField>& processed_fields,
-    const FormPredictions& predictions) {
+    const FormPredictions& predictions,
+    FormDataParser::Mode mode) {
   auto result = std::make_unique<SignificantFields>();
-  // Note: The code does not check whether there is at most 1 username, 1
-  // current password and at most 2 new passwords. It is assumed that server
-  // side predictions are sane.
+
+  // Following the design from https://goo.gl/Mc2KRe, this code will attempt to
+  // understand the special case when there are two usernames hinted by the
+  // server. In that case, they are considered the sign-in and sign-up
+  // usernames, in the order in which the (only) current password and the first
+  // new-password come. If there is another amount of usernames, 0 or 2+ current
+  // password fields or no new password field, then the abort switch below is
+  // set and simply the first field of each kind is used.
+  bool prevent_handling_two_usernames = false;  // the abort switch
+  // Whether the first username is for sign-in.
+  bool sign_in_username_first = true;
+  // First username is stored in |result->username|.
+  const FormFieldData* second_username = nullptr;
   for (const auto& prediction : predictions) {
     switch (DeriveFromServerFieldType(prediction.second.type)) {
       case CredentialFieldType::kUsername:
-        result->username =
-            FindFieldWithUniqueRendererId(processed_fields, prediction.first);
+        if (!result->username) {
+          result->username =
+              FindFieldWithUniqueRendererId(processed_fields, prediction.first);
+        } else if (!second_username) {
+          second_username =
+              FindFieldWithUniqueRendererId(processed_fields, prediction.first);
+        } else {
+          prevent_handling_two_usernames = true;
+        }
         break;
       case CredentialFieldType::kCurrentPassword:
-        result->password =
-            FindFieldWithUniqueRendererId(processed_fields, prediction.first);
+        if (result->password) {
+          prevent_handling_two_usernames = true;
+        } else {
+          result->password =
+              FindFieldWithUniqueRendererId(processed_fields, prediction.first);
+        }
         break;
       case CredentialFieldType::kNewPassword:
+        // If any (and thus the first) new password comes before the current
+        // password, the first username is understood as sign-up, not sign-in.
+        if (!result->password)
+          sign_in_username_first = false;
         result->new_password =
             FindFieldWithUniqueRendererId(processed_fields, prediction.first);
         break;
@@ -208,6 +235,25 @@
         break;
     }
   }
+
+  if (!result->new_password || !result->password)
+    prevent_handling_two_usernames = true;
+
+  if (!prevent_handling_two_usernames && second_username) {
+    // Now that there are two usernames, |sign_in_username_first| determines
+    // which is sign-in and which sign-up.
+    const FormFieldData* sign_in = result->username;
+    const FormFieldData* sign_up = second_username;
+    if (!sign_in_username_first)
+      std::swap(sign_in, sign_up);
+    // For filling, the sign-in username is relevant, because Chrome should not
+    // fill where the credentials first need to be created. For saving, the
+    // sign-up username is relevant: if both have values, then the sign-up one
+    // was not filled and hence was typed by the user.
+    result->username =
+        mode == FormDataParser::Mode::kSaving ? sign_up : sign_in;
+  }
+
   // If the server suggests there is a confirmation field but no new password,
   // something went wrong. Sanitize the result.
   if (result->confirmation_password && !result->new_password)
@@ -733,7 +779,8 @@
 
   // (1) First, try to parse with server predictions.
   if (predictions_) {
-    significant_fields = ParseUsingPredictions(processed_fields, *predictions_);
+    significant_fields =
+        ParseUsingPredictions(processed_fields, *predictions_, mode);
     if (significant_fields && significant_fields->username) {
       username_detection_method =
           UsernameDetectionMethod::kServerSidePrediction;
diff --git a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
index a4f7618..d7fcb2b 100644
--- a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
+++ b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
@@ -1493,6 +1493,126 @@
   });
 }
 
+// Check that multiple usernames in server hints are handled properly.
+TEST(FormParserTest, MultipleUsernames) {
+  CheckTestData({
+      {
+          "More than two usernames are ignored.",
+          {
+              {.role = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role = ElementRole::CURRENT_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::PASSWORD}},
+              {.role = ElementRole::NEW_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}},
+          },
+      },
+      {
+          "No current passwod -> ignore additional usernames.",
+          {
+              {.role = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role = ElementRole::NEW_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}},
+          },
+      },
+      {
+          "2 current passwods -> ignore additional usernames.",
+          {
+              {.role = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role = ElementRole::CURRENT_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::PASSWORD}},
+              {.form_control_type = "password",
+               .prediction = {.type = autofill::PASSWORD}},
+          },
+      },
+      {
+          "No new passwod -> ignore additional usernames.",
+          {
+              {.role = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role = ElementRole::CURRENT_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::PASSWORD}},
+          },
+      },
+      {
+          "Two usernames in sign-in, sign-up order.",
+          {
+              {.role_filling = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role_saving = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role = ElementRole::CURRENT_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::PASSWORD}},
+              {.role = ElementRole::NEW_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}},
+          },
+      },
+      {
+          "Two usernames in sign-up, sign-in order.",
+          {
+              {.role_saving = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role_filling = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role = ElementRole::NEW_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}},
+              {.role = ElementRole::NEW_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}},
+              {.role = ElementRole::CURRENT_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::PASSWORD}},
+          },
+      },
+      {
+          "Two usernames in sign-in, sign-up order; sign-in is pre-filled.",
+          {
+              {.role_filling = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .properties_mask = FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD,
+               .prediction = {.type = autofill::USERNAME}},
+              {.role_saving = ElementRole::USERNAME,
+               .form_control_type = "text",
+               .prediction = {.type = autofill::USERNAME}},
+              {.role = ElementRole::CURRENT_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::PASSWORD}},
+              {.role = ElementRole::NEW_PASSWORD,
+               .form_control_type = "password",
+               .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}},
+          },
+      },
+  });
+}
+
 TEST(FormParserTest, HistogramsForUsernameDetectionMethod) {
   struct HistogramTestCase {
     FormParsingTestCase parsing_data;
diff --git a/components/password_manager/core/browser/password_model_type_controller.cc b/components/password_manager/core/browser/password_syncable_service_based_model_type_controller.cc
similarity index 83%
rename from components/password_manager/core/browser/password_model_type_controller.cc
rename to components/password_manager/core/browser/password_syncable_service_based_model_type_controller.cc
index e24a64a2..dfb11e13 100644
--- a/components/password_manager/core/browser/password_model_type_controller.cc
+++ b/components/password_manager/core/browser/password_syncable_service_based_model_type_controller.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/password_manager/core/browser/password_model_type_controller.h"
+#include "components/password_manager/core/browser/password_syncable_service_based_model_type_controller.h"
 
 #include <string>
 #include <utility>
@@ -81,7 +81,7 @@
 
 // Created and constructed on any thread, but otherwise used exclusively on a
 // single sequence (the model sequence).
-class PasswordModelTypeController::ModelCryptographerImpl
+class PasswordSyncableServiceBasedModelTypeController::ModelCryptographerImpl
     : public syncer::SyncableServiceBasedBridge::ModelCryptographer {
  public:
   ModelCryptographerImpl() { DETACH_FROM_SEQUENCE(sequence_checker_); }
@@ -156,21 +156,23 @@
   std::unique_ptr<syncer::Cryptographer> cryptographer_;
 };
 
-PasswordModelTypeController::PasswordModelTypeController(
-    syncer::OnceModelTypeStoreFactory store_factory,
-    const base::RepeatingClosure& dump_stack,
-    scoped_refptr<PasswordStore> password_store,
-    syncer::SyncClient* sync_client)
-    : PasswordModelTypeController(
+PasswordSyncableServiceBasedModelTypeController::
+    PasswordSyncableServiceBasedModelTypeController(
+        syncer::OnceModelTypeStoreFactory store_factory,
+        const base::RepeatingClosure& dump_stack,
+        scoped_refptr<PasswordStore> password_store,
+        syncer::SyncClient* sync_client)
+    : PasswordSyncableServiceBasedModelTypeController(
           std::move(store_factory),
           dump_stack,
           std::move(password_store),
           sync_client,
           base::MakeRefCounted<ModelCryptographerImpl>()) {}
 
-PasswordModelTypeController::~PasswordModelTypeController() = default;
+PasswordSyncableServiceBasedModelTypeController::
+    ~PasswordSyncableServiceBasedModelTypeController() = default;
 
-void PasswordModelTypeController::LoadModels(
+void PasswordSyncableServiceBasedModelTypeController::LoadModels(
     const syncer::ConfigureContext& configure_context,
     const ModelLoadCallback& model_load_callback) {
   DCHECK(CalledOnValidThread());
@@ -180,8 +182,9 @@
   sync_client_->GetPasswordStateChangedCallback().Run();
 }
 
-void PasswordModelTypeController::Stop(syncer::ShutdownReason shutdown_reason,
-                                       StopCallback callback) {
+void PasswordSyncableServiceBasedModelTypeController::Stop(
+    syncer::ShutdownReason shutdown_reason,
+    StopCallback callback) {
   DCHECK(CalledOnValidThread());
   sync_client_->GetSyncService()->RemoveObserver(this);
   NonUiSyncableServiceBasedModelTypeController::Stop(shutdown_reason,
@@ -190,7 +193,7 @@
 }
 
 std::unique_ptr<syncer::SyncEncryptionHandler::Observer>
-PasswordModelTypeController::GetEncryptionObserverProxy() {
+PasswordSyncableServiceBasedModelTypeController::GetEncryptionObserverProxy() {
   DCHECK(CalledOnValidThread());
   return std::make_unique<OnCryptographerStateChangedProxy>(
       background_task_runner_,
@@ -198,17 +201,19 @@
                           model_cryptographer_));
 }
 
-void PasswordModelTypeController::OnStateChanged(syncer::SyncService* sync) {
+void PasswordSyncableServiceBasedModelTypeController::OnStateChanged(
+    syncer::SyncService* sync) {
   DCHECK(CalledOnValidThread());
   sync_client_->GetPasswordStateChangedCallback().Run();
 }
 
-PasswordModelTypeController::PasswordModelTypeController(
-    syncer::OnceModelTypeStoreFactory store_factory,
-    const base::RepeatingClosure& dump_stack,
-    scoped_refptr<PasswordStore> password_store,
-    syncer::SyncClient* sync_client,
-    scoped_refptr<ModelCryptographerImpl> model_cryptographer)
+PasswordSyncableServiceBasedModelTypeController::
+    PasswordSyncableServiceBasedModelTypeController(
+        syncer::OnceModelTypeStoreFactory store_factory,
+        const base::RepeatingClosure& dump_stack,
+        scoped_refptr<PasswordStore> password_store,
+        syncer::SyncClient* sync_client,
+        scoped_refptr<ModelCryptographerImpl> model_cryptographer)
     : NonUiSyncableServiceBasedModelTypeController(
           syncer::PASSWORDS,
           std::move(store_factory),
diff --git a/components/password_manager/core/browser/password_model_type_controller.h b/components/password_manager/core/browser/password_syncable_service_based_model_type_controller.h
similarity index 71%
rename from components/password_manager/core/browser/password_model_type_controller.h
rename to components/password_manager/core/browser/password_syncable_service_based_model_type_controller.h
index 4c952119..1255068 100644
--- a/components/password_manager/core/browser/password_model_type_controller.h
+++ b/components/password_manager/core/browser/password_syncable_service_based_model_type_controller.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MODEL_TYPE_CONTROLLER_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MODEL_TYPE_CONTROLLER_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_SYNCABLE_SERVICE_BASED_MODEL_TYPE_CONTROLLER_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_SYNCABLE_SERVICE_BASED_MODEL_TYPE_CONTROLLER_H_
 
 #include <memory>
 
@@ -21,7 +21,7 @@
 class PasswordStore;
 
 // A class that manages the startup and shutdown of password sync.
-class PasswordModelTypeController
+class PasswordSyncableServiceBasedModelTypeController
     : public syncer::NonUiSyncableServiceBasedModelTypeController,
       public syncer::SyncServiceObserver {
  public:
@@ -29,11 +29,12 @@
   // copy of sync's data and metadata, sync-ed with |password_store|.
   // |dump_stack| is called when a unrecoverable error occurs. |sync_client|
   // must not be null.
-  PasswordModelTypeController(syncer::OnceModelTypeStoreFactory store_factory,
-                              const base::RepeatingClosure& dump_stack,
-                              scoped_refptr<PasswordStore> password_store,
-                              syncer::SyncClient* sync_client);
-  ~PasswordModelTypeController() override;
+  PasswordSyncableServiceBasedModelTypeController(
+      syncer::OnceModelTypeStoreFactory store_factory,
+      const base::RepeatingClosure& dump_stack,
+      scoped_refptr<PasswordStore> password_store,
+      syncer::SyncClient* sync_client);
+  ~PasswordSyncableServiceBasedModelTypeController() override;
 
   // DataTypeController overrides.
   void LoadModels(const syncer::ConfigureContext& configure_context,
@@ -51,7 +52,7 @@
 
   // Constructor overload to make sure |ModelCryptographerImpl| gets constructed
   // before the base class.
-  PasswordModelTypeController(
+  PasswordSyncableServiceBasedModelTypeController(
       syncer::OnceModelTypeStoreFactory store_factory,
       const base::RepeatingClosure& dump_stack,
       scoped_refptr<PasswordStore> password_store,
@@ -62,9 +63,9 @@
   const scoped_refptr<ModelCryptographerImpl> model_cryptographer_;
   syncer::SyncClient* const sync_client_;
 
-  DISALLOW_COPY_AND_ASSIGN(PasswordModelTypeController);
+  DISALLOW_COPY_AND_ASSIGN(PasswordSyncableServiceBasedModelTypeController);
 };
 
 }  // namespace password_manager
 
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MODEL_TYPE_CONTROLLER_H_
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_SYNCABLE_SERVICE_BASED_MODEL_TYPE_CONTROLLER_H_
diff --git a/components/signin/core/browser/test_signin_client.cc b/components/signin/core/browser/test_signin_client.cc
index 3a0cb77..c6b72c5 100644
--- a/components/signin/core/browser/test_signin_client.cc
+++ b/components/signin/core/browser/test_signin_client.cc
@@ -8,7 +8,6 @@
 
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/signin/core/browser/webdata/token_service_table.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index c6882f63..9379891 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -123,8 +123,10 @@
   if (dtc_iter->second->ReadyForStart()) {
     ForceReconfiguration();
   } else {
-    // Stop the datatype
-    model_association_manager_.StopDatatype(type, DISABLE_SYNC, SyncError());
+    model_association_manager_.StopDatatype(
+        type, DISABLE_SYNC,
+        SyncError(FROM_HERE, syncer::SyncError::UNREADY_ERROR,
+                  "Data type is unready.", type));
   }
 }
 
diff --git a/components/sync/driver/fake_sync_service.cc b/components/sync/driver/fake_sync_service.cc
index 110aac3..e9f8054 100644
--- a/components/sync/driver/fake_sync_service.cc
+++ b/components/sync/driver/fake_sync_service.cc
@@ -14,18 +14,6 @@
 
 namespace syncer {
 
-void FakeSyncService::SetAuthenticatedAccountInfo(
-    const AccountInfo& account_info) {
-  account_info_ = account_info;
-}
-AccountInfo FakeSyncService::GetAuthenticatedAccountInfo() const {
-  return account_info_;
-}
-
-void FakeSyncService::SetConfigurationDone(bool configuration_done) {
-  configuration_done_ = configuration_done;
-}
-
 // Dummy methods
 
 FakeSyncService::FakeSyncService()
@@ -52,12 +40,13 @@
   if (!IsFirstSetupComplete()) {
     return TransportState::PENDING_DESIRED_CONFIGURATION;
   }
-  if (!configuration_done_) {
-    return TransportState::CONFIGURING;
-  }
   return TransportState::ACTIVE;
 }
 
+AccountInfo FakeSyncService::GetAuthenticatedAccountInfo() const {
+  return AccountInfo();
+}
+
 bool FakeSyncService::IsAuthenticatedAccountPrimary() const {
   return true;
 }
diff --git a/components/sync/driver/fake_sync_service.h b/components/sync/driver/fake_sync_service.h
index 2440b4a..748d8af 100644
--- a/components/sync/driver/fake_sync_service.h
+++ b/components/sync/driver/fake_sync_service.h
@@ -25,22 +25,15 @@
   FakeSyncService();
   ~FakeSyncService() override;
 
-  // TODO(crbug.com/859874): Add setters for all the other state here, so that
-  // subclasses don't have to reimplement it N times.
-
   void set_auth_error(GoogleServiceAuthError error) {
     error_ = std::move(error);
   }
 
-  void SetAuthenticatedAccountInfo(const AccountInfo& account_info);
-  AccountInfo GetAuthenticatedAccountInfo() const override;
-
-  void SetConfigurationDone(bool configuration_done);
-
   // Dummy methods.
   // SyncService implementation.
   int GetDisableReasons() const override;
   TransportState GetTransportState() const override;
+  AccountInfo GetAuthenticatedAccountInfo() const override;
   bool IsAuthenticatedAccountPrimary() const override;
   bool IsFirstSetupComplete() const override;
   bool IsLocalSyncEnabled() const override;
@@ -100,10 +93,6 @@
   GURL sync_service_url_;
   std::string unrecoverable_error_message_;
   std::unique_ptr<UserShare> user_share_;
-
-  AccountInfo account_info_;
-
-  bool configuration_done_ = true;
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc
index 2b39e95b..7dd7e9e0 100644
--- a/components/sync/driver/model_association_manager.cc
+++ b/components/sync/driver/model_association_manager.cc
@@ -178,6 +178,7 @@
 void ModelAssociationManager::StopDatatype(ModelType type,
                                            ShutdownReason shutdown_reason,
                                            SyncError error) {
+  DCHECK(error.IsSet());
   DataTypeController* dtc = controllers_->find(type)->second.get();
   if (dtc->state() != DataTypeController::NOT_RUNNING &&
       dtc->state() != DataTypeController::STOPPING) {
diff --git a/components/sync/driver/model_association_manager.h b/components/sync/driver/model_association_manager.h
index 830413e..bbc2cee 100644
--- a/components/sync/driver/model_association_manager.h
+++ b/components/sync/driver/model_association_manager.h
@@ -101,7 +101,8 @@
   // When this is completed, |OnModelAssociationDone| will be invoked.
   void StartAssociationAsync(const ModelTypeSet& types_to_associate);
 
-  // Stops an individual datatype |type| for |shutdown_reason|.
+  // Stops an individual datatype |type| for |shutdown_reason|. |error| must be
+  // an actual error (i.e. not UNSET).
   void StopDatatype(ModelType type,
                     ShutdownReason shutdown_reason,
                     SyncError error);
diff --git a/components/sync/driver/model_association_manager_unittest.cc b/components/sync/driver/model_association_manager_unittest.cc
index ae04185..12b933aa 100644
--- a/components/sync/driver/model_association_manager_unittest.cc
+++ b/components/sync/driver/model_association_manager_unittest.cc
@@ -596,7 +596,10 @@
   ASSERT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::MODEL_LOADED);
 
-  model_association_manager.StopDatatype(BOOKMARKS, DISABLE_SYNC, SyncError());
+  model_association_manager.StopDatatype(
+      BOOKMARKS, DISABLE_SYNC,
+      SyncError(FROM_HERE, syncer::SyncError::UNREADY_ERROR,
+                "Data type is unready.", BOOKMARKS));
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::NOT_RUNNING);
@@ -612,7 +615,10 @@
   ASSERT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::NOT_RUNNING);
 
-  model_association_manager.StopDatatype(BOOKMARKS, DISABLE_SYNC, SyncError());
+  model_association_manager.StopDatatype(
+      BOOKMARKS, DISABLE_SYNC,
+      SyncError(FROM_HERE, syncer::SyncError::UNREADY_ERROR,
+                "Data type is unready.", BOOKMARKS));
 
   // The state should still be not running.
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
diff --git a/components/sync/driver/sync_service_utils_unittest.cc b/components/sync/driver/sync_service_utils_unittest.cc
index e3ed453..fd329314 100644
--- a/components/sync/driver/sync_service_utils_unittest.cc
+++ b/components/sync/driver/sync_service_utils_unittest.cc
@@ -4,31 +4,13 @@
 
 #include "components/sync/driver/sync_service_utils.h"
 
-#include <vector>
-
 #include "components/sync/base/model_type.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/test_sync_service.h"
-#include "components/sync/engine/cycle/sync_cycle_snapshot.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace syncer {
 
-namespace {
-
-static SyncCycleSnapshot MakeSyncCycleSnapshot() {
-  return SyncCycleSnapshot(
-      ModelNeutralState(), ProgressMarkerMap(), false, 5, 2, 7, false, 0,
-      base::Time::Now(), base::Time::Now(),
-      std::vector<int>(MODEL_TYPE_COUNT, 0),
-      std::vector<int>(MODEL_TYPE_COUNT, 0), sync_pb::SyncEnums::UNKNOWN_ORIGIN,
-      /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
-      /*long_poll_interval=*/base::TimeDelta::FromMinutes(180),
-      /*has_remaining_local_changes=*/false);
-}
-
-}  // namespace
-
 TEST(SyncServiceUtilsTest, UploadToGoogleDisabledIfSyncNotAllowed) {
   TestSyncService service;
 
@@ -62,6 +44,7 @@
       syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST);
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
+  service.SetEmptyLastCycleSnapshot();
 
   // By default, if sync isn't disabled, we should be INITIALIZING.
   EXPECT_EQ(UploadState::INITIALIZING,
@@ -73,7 +56,7 @@
             GetUploadToGoogleState(&service, syncer::BOOKMARKS));
 
   // Only after a sync cycle has been completed is upload actually ACTIVE.
-  service.SetLastCycleSnapshot(MakeSyncCycleSnapshot());
+  service.SetNonEmptyLastCycleSnapshot();
   EXPECT_EQ(UploadState::ACTIVE,
             GetUploadToGoogleState(&service, syncer::BOOKMARKS));
 }
@@ -82,7 +65,7 @@
   TestSyncService service;
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
   service.SetTransportState(syncer::SyncService::TransportState::ACTIVE);
-  service.SetLastCycleSnapshot(MakeSyncCycleSnapshot());
+  service.SetNonEmptyLastCycleSnapshot();
 
   // Sync is enabled only for a specific model type.
   service.SetPreferredDataTypes(ModelTypeSet(syncer::BOOKMARKS));
@@ -105,7 +88,7 @@
   TestSyncService service;
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
   service.SetTransportState(syncer::SyncService::TransportState::ACTIVE);
-  service.SetLastCycleSnapshot(MakeSyncCycleSnapshot());
+  service.SetNonEmptyLastCycleSnapshot();
 
   // Sync is enabled for some model types.
   service.SetPreferredDataTypes(
@@ -128,7 +111,7 @@
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
   service.SetTransportState(syncer::SyncService::TransportState::ACTIVE);
-  service.SetLastCycleSnapshot(MakeSyncCycleSnapshot());
+  service.SetNonEmptyLastCycleSnapshot();
 
   // Sanity check: Upload is active now.
   ASSERT_EQ(UploadState::ACTIVE,
@@ -148,7 +131,7 @@
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
   service.SetTransportState(syncer::SyncService::TransportState::ACTIVE);
-  service.SetLastCycleSnapshot(MakeSyncCycleSnapshot());
+  service.SetNonEmptyLastCycleSnapshot();
 
   // Sanity check: Upload is active now.
   ASSERT_EQ(UploadState::ACTIVE,
@@ -188,7 +171,7 @@
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
   service.SetTransportState(syncer::SyncService::TransportState::ACTIVE);
-  service.SetLastCycleSnapshot(MakeSyncCycleSnapshot());
+  service.SetNonEmptyLastCycleSnapshot();
 
   // Sanity check: Upload is ACTIVE, even for data types that are always
   // encrypted implicitly (PASSWORDS).
@@ -201,7 +184,7 @@
 
   // Once a custom passphrase is in use, upload should be considered disabled:
   // Even if we're technically still uploading, Google can't inspect the data.
-  service.SetCustomPassphraseEnabled(true);
+  service.SetIsUsingSecondaryPassphrase(true);
 
   EXPECT_EQ(UploadState::NOT_ACTIVE,
             GetUploadToGoogleState(&service, syncer::BOOKMARKS));
diff --git a/components/sync/driver/test_sync_service.cc b/components/sync/driver/test_sync_service.cc
index 143df22..63df42dd 100644
--- a/components/sync/driver/test_sync_service.cc
+++ b/components/sync/driver/test_sync_service.cc
@@ -4,13 +4,40 @@
 
 #include "components/sync/driver/test_sync_service.h"
 
+#include <vector>
+
 #include "base/time/time.h"
 #include "base/values.h"
+#include "components/sync/base/progress_marker_map.h"
 #include "components/sync/driver/sync_token_status.h"
+#include "components/sync/engine/cycle/model_neutral_state.h"
 
 namespace syncer {
 
-TestSyncService::TestSyncService() = default;
+namespace {
+
+SyncCycleSnapshot MakeDefaultCycleSnapshot() {
+  return SyncCycleSnapshot(
+      ModelNeutralState(), ProgressMarkerMap(), /*is_silenced-*/ false,
+      /*num_encryption_conflicts=*/5, /*num_hierarchy_conflicts=*/2,
+      /*num_server_conflicts=*/7, /*notifications_enabled=*/false,
+      /*num_entries=*/0, /*sync_start_time=*/base::Time::Now(),
+      /*poll_finish_time=*/base::Time::Now(),
+      /*num_entries_by_type=*/std::vector<int>(syncer::MODEL_TYPE_COUNT, 0),
+      /*num_to_delete_entries_by_type=*/
+      std::vector<int>(syncer::MODEL_TYPE_COUNT, 0),
+      /*get_updates_origin=*/sync_pb::SyncEnums::UNKNOWN_ORIGIN,
+      /*short_poll_interval=*/base::TimeDelta::FromMinutes(30),
+      /*long_poll_interval=*/base::TimeDelta::FromMinutes(180),
+      /*has_remaining_local_changes=*/false);
+}
+
+}  // namespace
+
+TestSyncService::TestSyncService()
+    : preferred_data_types_(ModelTypeSet::All()),
+      active_data_types_(ModelTypeSet::All()),
+      last_cycle_snapshot_(MakeDefaultCycleSnapshot()) {}
 
 TestSyncService::~TestSyncService() = default;
 
@@ -26,6 +53,15 @@
   local_sync_enabled_ = local_sync_enabled;
 }
 
+void TestSyncService::SetAuthenticatedAccountInfo(
+    const AccountInfo& account_info) {
+  account_info_ = account_info;
+}
+
+void TestSyncService::SetIsAuthenticatedAccountPrimary(bool is_primary) {
+  account_is_primary_ = is_primary;
+}
+
 void TestSyncService::SetAuthError(const GoogleServiceAuthError& auth_error) {
   auth_error_ = auth_error;
 }
@@ -38,14 +74,22 @@
   active_data_types_ = types;
 }
 
-void TestSyncService::SetCustomPassphraseEnabled(bool enabled) {
-  custom_passphrase_enabled_ = enabled;
+void TestSyncService::SetIsUsingSecondaryPassphrase(bool enabled) {
+  using_secondary_passphrase_ = enabled;
 }
 
 void TestSyncService::SetLastCycleSnapshot(const SyncCycleSnapshot& snapshot) {
   last_cycle_snapshot_ = snapshot;
 }
 
+void TestSyncService::SetEmptyLastCycleSnapshot() {
+  SetLastCycleSnapshot(SyncCycleSnapshot());
+}
+
+void TestSyncService::SetNonEmptyLastCycleSnapshot() {
+  SetLastCycleSnapshot(MakeDefaultCycleSnapshot());
+}
+
 int TestSyncService::GetDisableReasons() const {
   return disable_reasons_;
 }
@@ -63,7 +107,7 @@
 }
 
 bool TestSyncService::IsAuthenticatedAccountPrimary() const {
-  return true;
+  return account_is_primary_;
 }
 
 const GoogleServiceAuthError& TestSyncService::GetAuthError() const {
@@ -125,7 +169,7 @@
 }
 
 bool TestSyncService::IsUsingSecondaryPassphrase() const {
-  return custom_passphrase_enabled_;
+  return using_secondary_passphrase_;
 }
 
 void TestSyncService::EnableEncryptEverything() {}
@@ -153,7 +197,15 @@
 }
 
 syncer::SyncTokenStatus TestSyncService::GetSyncTokenStatus() const {
-  return syncer::SyncTokenStatus();
+  syncer::SyncTokenStatus token;
+
+  if (GetAuthError().state() != GoogleServiceAuthError::NONE) {
+    token.connection_status = syncer::ConnectionStatus::CONNECTION_AUTH_ERROR;
+    token.last_get_token_error =
+        GoogleServiceAuthError::FromServiceError("error");
+  }
+
+  return token;
 }
 
 bool TestSyncService::QueryDetailedSyncStatus(SyncStatus* result) const {
@@ -208,7 +260,7 @@
 }
 
 ModelTypeSet TestSyncService::GetEncryptedDataTypes() const {
-  if (!custom_passphrase_enabled_) {
+  if (!using_secondary_passphrase_) {
     // PASSWORDS are always encrypted.
     return ModelTypeSet(syncer::PASSWORDS);
   }
diff --git a/components/sync/driver/test_sync_service.h b/components/sync/driver/test_sync_service.h
index 4d62e082..5384125 100644
--- a/components/sync/driver/test_sync_service.h
+++ b/components/sync/driver/test_sync_service.h
@@ -17,6 +17,8 @@
 
 namespace syncer {
 
+// A simple test implementation of SyncService that allows direct control over
+// the returned state. By default, everything returns "enabled"/"active".
 class TestSyncService : public SyncService {
  public:
   TestSyncService();
@@ -25,11 +27,17 @@
   void SetDisableReasons(int disable_reasons);
   void SetTransportState(TransportState transport_state);
   void SetLocalSyncEnabled(bool local_sync_enabled);
+  void SetAuthenticatedAccountInfo(const AccountInfo& account_info);
+  void SetIsAuthenticatedAccountPrimary(bool is_primary);
   void SetAuthError(const GoogleServiceAuthError& auth_error);
   void SetPreferredDataTypes(const ModelTypeSet& types);
   void SetActiveDataTypes(const ModelTypeSet& types);
-  void SetCustomPassphraseEnabled(bool enabled);
+  void SetIsUsingSecondaryPassphrase(bool enabled);
   void SetLastCycleSnapshot(const SyncCycleSnapshot& snapshot);
+  // Convenience versions of the above, for when the caller doesn't care about
+  // the particular values in the snapshot, just whether there is one.
+  void SetEmptyLastCycleSnapshot();
+  void SetNonEmptyLastCycleSnapshot();
 
   // SyncService implementation.
   int GetDisableReasons() const override;
@@ -102,12 +110,13 @@
   TransportState transport_state_ = TransportState::ACTIVE;
   bool local_sync_enabled_ = false;
   AccountInfo account_info_;
+  bool account_is_primary_ = true;
   GoogleServiceAuthError auth_error_;
 
   ModelTypeSet preferred_data_types_;
   ModelTypeSet active_data_types_;
 
-  bool custom_passphrase_enabled_ = false;
+  bool using_secondary_passphrase_ = false;
 
   SyncCycleSnapshot last_cycle_snapshot_;
 
diff --git a/components/test/data/js_dialogs/render_tests/VrBrowserJavaScriptModalDialogTest.js_modal_view_vr_prompt.Pixel_XL-25.png b/components/test/data/js_dialogs/render_tests/VrBrowserJavaScriptModalDialogTest.js_modal_view_vr_prompt.Pixel_XL-25.png
index 50991cc..89e5df81 100644
--- a/components/test/data/js_dialogs/render_tests/VrBrowserJavaScriptModalDialogTest.js_modal_view_vr_prompt.Pixel_XL-25.png
+++ b/components/test/data/js_dialogs/render_tests/VrBrowserJavaScriptModalDialogTest.js_modal_view_vr_prompt.Pixel_XL-25.png
Binary files differ
diff --git a/components/test/data/js_dialogs/render_tests/VrBrowserJavaScriptModalDialogTest.js_modal_view_vr_prompt.Pixel_XL-26.png b/components/test/data/js_dialogs/render_tests/VrBrowserJavaScriptModalDialogTest.js_modal_view_vr_prompt.Pixel_XL-26.png
index 31ebcc2f..93c115b47 100644
--- a/components/test/data/js_dialogs/render_tests/VrBrowserJavaScriptModalDialogTest.js_modal_view_vr_prompt.Pixel_XL-26.png
+++ b/components/test/data/js_dialogs/render_tests/VrBrowserJavaScriptModalDialogTest.js_modal_view_vr_prompt.Pixel_XL-26.png
Binary files differ
diff --git a/content/app/DEPS b/content/app/DEPS
index cd56a2a..4a94233 100644
--- a/content/app/DEPS
+++ b/content/app/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
-  "+components/download",
   "+components/tracing",
   "+content",
   "+device/bluetooth",
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index a37944b5..d442aae7 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -39,7 +39,6 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
-#include "components/download/public/common/download_task_runner.h"
 #include "components/tracing/common/trace_startup.h"
 #include "content/app/mojo/mojo_init.h"
 #include "content/browser/browser_process_sub_thread.h"
@@ -154,10 +153,6 @@
 #include "services/service_manager/zygote/host/zygote_host_impl_linux.h"
 #endif
 
-#if defined(OS_ANDROID)
-#include "content/browser/android/browser_startup_controller.h"
-#endif
-
 namespace content {
 extern int GpuMain(const content::MainFunctionParams&);
 #if BUILDFLAG(ENABLE_PLUGINS)
@@ -172,11 +167,6 @@
 
 namespace {
 
-#if !defined(CHROME_MULTIPLE_DLL_CHILD)
-const char kAllowStartingServiceManagerOnly[] =
-    "allow-start-service-manager-only";
-#endif
-
 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) && defined(OS_ANDROID)
 #if defined __LP64__
 #define kV8SnapshotDataDescriptor kV8Snapshot64DataDescriptor
@@ -864,20 +854,13 @@
   RegisterMainThreadFactories();
 
 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
-  if (process_type.empty())
-    return RunServiceManager(main_params, start_service_manager_only);
-#endif  // !defined(CHROME_MULTIPLE_DLL_CHILD)
+  // The thread used to start the ServiceManager is handed-off to
+  // BrowserMain() which may elect to promote it (e.g. to BrowserThread::IO).
+  if (process_type.empty()) {
+    startup_data_ = std::make_unique<StartupDataImpl>();
+    startup_data_->thread = BrowserProcessSubThread::CreateIOThread();
+    main_params.startup_data = startup_data_.get();
 
-  return RunOtherNamedProcessTypeMain(process_type, main_params, delegate_);
-}
-
-#if !defined(CHROME_MULTIPLE_DLL_CHILD)
-int ContentMainRunnerImpl::RunServiceManager(MainFunctionParams& main_params,
-                                             bool start_service_manager_only) {
-  if (is_browser_main_loop_started_)
-    return -1;
-
-  if (!service_manager_context_) {
     if (GetContentClient()->browser()->ShouldCreateTaskScheduler()) {
       // Create and start the TaskScheduler early to allow upcoming code to use
       // the post_task.h API.
@@ -916,33 +899,13 @@
     // incorrect to post to a BrowserThread before this point.
     BrowserTaskExecutor::Create();
 
-    // The thread used to start the ServiceManager is handed-off to
-    // BrowserMain() which may elect to promote it (e.g. to BrowserThread::IO).
-    service_manager_thread_ = BrowserProcessSubThread::CreateIOThread();
-    service_manager_context_.reset(
-        new ServiceManagerContext(service_manager_thread_->task_runner()));
-    download::SetIOTaskRunner(service_manager_thread_->task_runner());
-#if defined(OS_ANDROID)
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&ServiceManagerStartupComplete));
-#endif
+    return RunBrowserProcessMain(main_params, delegate_);
   }
-
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          kAllowStartingServiceManagerOnly) &&
-      start_service_manager_only) {
-    return -1;
-  }
-
-  is_browser_main_loop_started_ = true;
-  startup_data_ = std::make_unique<StartupDataImpl>();
-  startup_data_->thread = std::move(service_manager_thread_);
-  startup_data_->service_manager_context = service_manager_context_.get();
-  main_params.startup_data = startup_data_.get();
-  return RunBrowserProcessMain(main_params, delegate_);
-}
 #endif  // !defined(CHROME_MULTIPLE_DLL_CHILD)
 
+  return RunOtherNamedProcessTypeMain(process_type, main_params, delegate_);
+}
+
 void ContentMainRunnerImpl::Shutdown() {
   DCHECK(is_initialized_);
   DCHECK(!is_shutdown_);
diff --git a/content/app/content_main_runner_impl.h b/content/app/content_main_runner_impl.h
index 29c9675f..c402da2 100644
--- a/content/app/content_main_runner_impl.h
+++ b/content/app/content_main_runner_impl.h
@@ -12,12 +12,10 @@
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "build/build_config.h"
-#include "content/browser/service_manager/service_manager_context.h"
 #include "content/browser/startup_data_impl.h"
 #include "content/public/app/content_main.h"
 #include "content/public/app/content_main_runner.h"
 #include "content/public/common/content_client.h"
-#include "content/public/common/main_function_params.h"
 
 #if defined(OS_WIN)
 #include "sandbox/win/src/sandbox_types.h"
@@ -48,20 +46,6 @@
   void Shutdown() override;
 
  private:
-#if !defined(CHROME_MULTIPLE_DLL_CHILD)
-  int RunServiceManager(MainFunctionParams& main_function_params,
-                        bool start_service_manager_only);
-
-  bool is_browser_main_loop_started_ = false;
-
-  std::unique_ptr<base::MessageLoop> main_message_loop_;
-
-  std::unique_ptr<StartupDataImpl> startup_data_;
-  std::unique_ptr<base::FieldTrialList> field_trial_list_;
-  std::unique_ptr<BrowserProcessSubThread> service_manager_thread_;
-  std::unique_ptr<ServiceManagerContext> service_manager_context_;
-#endif  // !defined(CHROME_MULTIPLE_DLL_CHILD)
-
   // True if the runner has been initialized.
   bool is_initialized_ = false;
 
@@ -89,6 +73,14 @@
 
   CreatedMainPartsClosure* created_main_parts_closure_ = nullptr;
 
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
+  std::unique_ptr<base::MessageLoop> main_message_loop_;
+
+  std::unique_ptr<StartupDataImpl> startup_data_;
+
+  std::unique_ptr<base::FieldTrialList> field_trial_list_;
+#endif  // !defined(CHROME_MULTIPLE_DLL_CHILD)
+
   DISALLOW_COPY_AND_ASSIGN(ContentMainRunnerImpl);
 };
 
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index c1e3b78..2c34b17 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -561,7 +561,6 @@
     // This is always invoked before |io_thread_| is initialized (i.e. never
     // resets it).
     io_thread_ = std::move(startup_data->thread);
-    service_manager_context_ = startup_data->service_manager_context;
   }
 
   parts_.reset(
@@ -1082,8 +1081,7 @@
     BrowserGpuChannelHostFactory::instance()->CloseChannel();
 
   // Shutdown the Service Manager and IPC.
-  service_manager_context_->ShutDown();
-  owned_service_manager_context_.reset();
+  service_manager_context_.reset();
   mojo_ipc_support_.reset();
 
   if (save_file_manager_)
@@ -1537,13 +1535,9 @@
       base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
       mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST));
 
-  if (!service_manager_context_) {
-    owned_service_manager_context_ =
-        std::make_unique<ServiceManagerContext>(io_thread_->task_runner());
-    service_manager_context_ = owned_service_manager_context_.get();
-  }
+  service_manager_context_.reset(
+      new ServiceManagerContext(io_thread_->task_runner()));
   ServiceManagerContext::StartBrowserConnection();
-
 #if defined(OS_MACOSX)
   mojo::core::SetMachPortProvider(MachBroker::GetInstance());
 #endif  // defined(OS_MACOSX)
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index b70af76..f9118502 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -351,10 +351,8 @@
       gpu_data_manager_visual_proxy_;
 #endif
 
-  ServiceManagerContext* service_manager_context_ = nullptr;
-  std::unique_ptr<ServiceManagerContext> owned_service_manager_context_;
-
   // Members initialized in |BrowserThreadsStarted()| --------------------------
+  std::unique_ptr<ServiceManagerContext> service_manager_context_;
   std::unique_ptr<mojo::core::ScopedIPCSupport> mojo_ipc_support_;
 
   // |user_input_monitor_| has to outlive |audio_manager_|, so declared first.
diff --git a/content/browser/browser_main_loop_unittest.cc b/content/browser/browser_main_loop_unittest.cc
index 7d73547..b5d345fc 100644
--- a/content/browser/browser_main_loop_unittest.cc
+++ b/content/browser/browser_main_loop_unittest.cc
@@ -37,7 +37,6 @@
     browser_main_loop.MainMessageLoopStart();
     browser_main_loop.Init();
     browser_main_loop.CreateThreads();
-    browser_main_loop.InitializeMojo();
     EXPECT_GE(base::TaskScheduler::GetInstance()
                   ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
                       {base::TaskPriority::USER_VISIBLE}),
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc
index fdfade9e..fdfa7d6 100644
--- a/content/browser/frame_host/navigation_controller_impl.cc
+++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -2496,6 +2496,20 @@
   if (!node)
     node = delegate_->GetFrameTree()->root();
 
+  // Compute the url_to_load to check that it doesn't change through the
+  // function.
+  // TODO(clamy): Remove this once the root cause behind
+  // https://crbug.com/896028 has been found.
+  GURL url_to_load;
+  GURL virtual_url;
+  if (node->IsMainFrame()) {
+    bool reverse_on_redirect = false;
+    RewriteUrlForNavigation(params.url, browser_context_, &url_to_load,
+                            &virtual_url, &reverse_on_redirect);
+  } else {
+    url_to_load = params.url;
+  }
+
   // Compute overrides to the LoadURLParams for |override_user_agent|,
   // |should_replace_current_entry| and |has_user_gesture| that will be used
   // both in the creation of the NavigationEntry and the NavigationRequest.
@@ -2530,8 +2544,10 @@
     entry = CreateNavigationEntryFromLoadParams(
         node, params, override_user_agent, should_replace_current_entry,
         has_user_gesture);
+    CHECK_EQ(url_to_load, entry->GetFrameEntry(node)->url());
     DiscardPendingEntry(false);
     SetPendingEntry(std::move(entry));
+    CHECK_EQ(url_to_load, pending_entry_->GetFrameEntry(node)->url());
   }
 
   // Renderer-debug URLs are sent to the renderer process immediately for
@@ -2570,6 +2586,7 @@
   DCHECK(node->IsMainFrame() || !params.navigation_ui_data);
 
   DCHECK(pending_entry_);
+  CHECK_EQ(url_to_load, pending_entry_->GetFrameEntry(node)->url());
   std::unique_ptr<NavigationRequest> request =
       CreateNavigationRequestFromLoadParams(
           node, params, override_user_agent, should_replace_current_entry,
@@ -2736,13 +2753,14 @@
     // TODO(clamy): In order to remove the pending NavigationEntry,
     // |virtual_url| and |reverse_on_redirect| should be stored in the
     // NavigationRequest.
+    CHECK(virtual_url == entry.GetVirtualURL());
+    CHECK_EQ(url_to_load, frame_entry->url());
   } else {
     url_to_load = params.url;
     virtual_url = params.url;
+    CHECK_EQ(url_to_load, frame_entry->url());
   }
 
-  CHECK(!node->IsMainFrame() || virtual_url == entry.GetVirtualURL());
-  CHECK_EQ(url_to_load, frame_entry->url());
 
   if (!IsValidURLForNavigation(node->IsMainFrame(), virtual_url, url_to_load))
     return nullptr;
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 5ff417c..76b0214 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -220,6 +220,9 @@
     switches::kLoggingLevel,
     switches::kEnableLowEndDeviceMode,
     switches::kDisableLowEndDeviceMode,
+    switches::kProfilingAtStart,
+    switches::kProfilingFile,
+    switches::kProfilingFlush,
     switches::kRunAllCompositorStagesBeforeDraw,
     switches::kSkiaFontCacheLimitMb,
     switches::kSkiaResourceCacheLimitMb,
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h
index 6aa9090..e2a499a 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -149,26 +149,18 @@
 
   // The state of |delegated_frame_host_| and |recyclable_compositor_| to
   // manage being visible, hidden, or drawn via a ui::Layer.
+  // The state of |recyclable_compositor_| and |parent_ui_layer_|.
   enum State {
-    // Effects:
-    // - |recyclable_compositor_| exists and is attached to
-    //   |delegated_frame_host_|.
-    // Happens when:
-    // - |render_widet_host_| is in the visible state.
-    HasAttachedCompositor,
-    // Effects:
-    // - |recyclable_compositor_| has been recycled and |delegated_frame_host_|
-    //   is hidden and detached from it.
-    // Happens when:
-    // - The |render_widget_host_| hidden or gone, and |cocoa_view_| is not
-    //   attached to an NSWindow.
-    // - This happens for backgrounded tabs.
+    // We are drawing using |recyclable_compositor_|. This happens when the
+    // renderer, but no parent ui::Layer has been specified. This is used by
+    // content shell, popup windows (time/date picker), and when tab capturing
+    // a backgrounded tab.
+    HasOwnCompositor,
+    // There is no compositor. This is true when the renderer is not visible
+    // and no parent ui::Layer is specified.
     HasNoCompositor,
-    // Effects:
-    // - |recyclable_compositor_| does not exist. |delegated_frame_host_| is
-    //   attached to |parent_ui_layer_|'s compositor.
-    // Happens when:
-    // - |parent_ui_layer_| is non-nullptr.
+    // We are drawing using |parent_ui_layer_|'s compositor. This happens
+    // whenever |parent_ui_layer_| is non-nullptr.
     UseParentLayerCompositor,
   };
   State state_ = HasNoCompositor;
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm
index c1cf09c..b132a00 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -216,7 +216,7 @@
 
   // If the host is visible and a compositor is required then create one.
   if (!render_widget_host_is_hidden_) {
-    TransitionToState(HasAttachedCompositor);
+    TransitionToState(HasOwnCompositor);
     return;
   }
 
@@ -225,26 +225,51 @@
 }
 
 void BrowserCompositorMac::TransitionToState(State new_state) {
-  // Note that the state enum values represent the other through which
-  // transitions must be done (see comments in State definition).
+  // Skip if there is no change to make.
+  bool is_no_op = false;
+  if (state_ == new_state) {
+    if (state_ == UseParentLayerCompositor)
+      is_no_op = parent_ui_layer_ == root_layer_->parent();
+    else
+      is_no_op = true;
+  }
+  if (is_no_op)
+    return;
 
-  // Transition UseParentLayerCompositor -> HasNoCompositor. Note that this
-  // transition will be made if we are already in UseParentLayerCompositor, but
-  // with a different parent layer.
-  if (state_ == UseParentLayerCompositor &&
-      (new_state != UseParentLayerCompositor ||
-       parent_ui_layer_ != root_layer_->parent())) {
+  // First, detach from the current compositor, if there is one.
+  delegated_frame_host_->DetachFromCompositor();
+  if (state_ == UseParentLayerCompositor) {
     DCHECK(root_layer_->parent());
     state_ = HasNoCompositor;
     root_layer_->parent()->RemoveObserver(this);
     root_layer_->parent()->Remove(root_layer_.get());
-    delegated_frame_host_->WasHidden();
-    delegated_frame_host_->DetachFromCompositor();
+  }
+  if (state_ == HasOwnCompositor) {
+    recyclable_compositor_->widget()->ResetNSView();
+    recyclable_compositor_->compositor()->SetRootLayer(nullptr);
+    recyclable_compositor_->InvalidateSurface();
+    ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor(
+        std::move(recyclable_compositor_));
   }
 
-  // Transition HasNoCompositor -> HasAttachedCompositor.
-  if (state_ == HasNoCompositor && new_state == HasAttachedCompositor) {
-    state_ = HasAttachedCompositor;
+  // The compositor is now detached. If this is the target state, we're done.
+  state_ = HasNoCompositor;
+  if (new_state == HasNoCompositor) {
+    // Don't transiently hide the DelegatedFrameHost because that can cause the
+    // current frame to be inappropriately evicted.
+    // https://crbug.com/897156
+    delegated_frame_host_->WasHidden();
+    return;
+  }
+
+  // Attach to the new compositor.
+  if (new_state == UseParentLayerCompositor) {
+    DCHECK(parent_ui_layer_);
+    parent_ui_layer_->Add(root_layer_.get());
+    parent_ui_layer_->AddObserver(this);
+    state_ = UseParentLayerCompositor;
+  }
+  if (new_state == HasOwnCompositor) {
     recyclable_compositor_ =
         ui::RecyclableCompositorMacFactory::Get()->CreateCompositor(
             content::GetContextFactory(), content::GetContextFactoryPrivate());
@@ -256,40 +281,13 @@
         dfh_display_.color_space());
     recyclable_compositor_->widget()->SetNSView(
         accelerated_widget_mac_ns_view_);
-    delegated_frame_host_->AttachToCompositor(
-        recyclable_compositor_->compositor());
-    delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
-                                    false /* record_presentation_time */);
     recyclable_compositor_->Unsuspend();
+    state_ = HasOwnCompositor;
   }
-
-  // Transition HasAttachedCompositor -> HasNoCompositor.
-  if (state_ == HasAttachedCompositor && new_state != HasAttachedCompositor) {
-    state_ = HasNoCompositor;
-    // Marking the DelegatedFrameHost as removed from the window hierarchy is
-    // necessary to remove all connections to its old ui::Compositor.
-    delegated_frame_host_->WasHidden();
-    delegated_frame_host_->DetachFromCompositor();
-    recyclable_compositor_->widget()->ResetNSView();
-    recyclable_compositor_->compositor()->SetRootLayer(nullptr);
-    recyclable_compositor_->InvalidateSurface();
-    ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor(
-        std::move(recyclable_compositor_));
-  }
-
-  // Transition HasNoCompositor -> UseParentLayerCompositor.
-  if (state_ == HasNoCompositor && new_state == UseParentLayerCompositor) {
-    DCHECK(parent_ui_layer_);
-    DCHECK(parent_ui_layer_->GetCompositor());
-    DCHECK(!root_layer_->parent());
-    state_ = UseParentLayerCompositor;
-    delegated_frame_host_->AttachToCompositor(
-        parent_ui_layer_->GetCompositor());
-    delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
-                                    false /* record_presentation_time */);
-    parent_ui_layer_->Add(root_layer_.get());
-    parent_ui_layer_->AddObserver(this);
-  }
+  DCHECK_EQ(state_, new_state);
+  delegated_frame_host_->AttachToCompositor(GetCompositor());
+  delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
+                                  false /* record_presentation_time */);
 }
 
 // static
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 6448e7c..5d919f54 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3048,6 +3048,9 @@
     switches::kOverridePluginPowerSaverForTesting,
     switches::kPassiveListenersDefault,
     switches::kPpapiInProcess,
+    switches::kProfilingAtStart,
+    switches::kProfilingFile,
+    switches::kProfilingFlush,
     switches::kReducedReferrerGranularity,
     switches::kRegisterPepperPlugins,
     switches::kRendererStartupDialog,
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index 881400f7..bedcfee2 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -796,10 +796,6 @@
 }
 
 ServiceManagerContext::~ServiceManagerContext() {
-  ShutDown();
-}
-
-void ServiceManagerContext::ShutDown() {
   // NOTE: The in-process ServiceManager MUST be destroyed before the browser
   // process-wide ServiceManagerConnection. Otherwise it's possible for the
   // ServiceManager to receive connection requests for service:content_browser
@@ -810,7 +806,6 @@
     ServiceManagerConnection::DestroyForProcess();
   service_manager_thread_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&DestroyConnectorOnIOThread));
-  packaged_services_connection_.reset();
 }
 
 // static
@@ -834,12 +829,22 @@
   RegisterCommonBrowserInterfaces(browser_connection);
   browser_connection->Start();
 
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService))
-    return;
-
-  // Create the in-process NetworkService object so that its getter is
-  // available on the IO thread.
-  GetNetworkService();
+  bool network_service_enabled =
+      base::FeatureList::IsEnabled(network::features::kNetworkService);
+  bool network_service_in_process =
+      base::FeatureList::IsEnabled(features::kNetworkServiceInProcess) ||
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kSingleProcess);
+  if (!network_service_enabled) {
+    // Create the in-process NetworkService object so that its getter is
+    // available on the IO thread.
+    GetNetworkService();
+  } else if (!network_service_in_process) {
+    // Start the network service process as soon as possible, since it is
+    // critical to start up performance.
+    browser_connection->GetConnector()->StartService(
+        mojom::kNetworkServiceName);
+  }
 }
 
 // static
diff --git a/content/browser/service_manager/service_manager_context.h b/content/browser/service_manager/service_manager_context.h
index 5845051..eebd74a 100644
--- a/content/browser/service_manager/service_manager_context.h
+++ b/content/browser/service_manager/service_manager_context.h
@@ -50,9 +50,6 @@
 
   static base::DeferredSequencedTaskRunner* GetAudioServiceRunner();
 
-  // Shutdowns the ServiceManager and the connections to the ServiceManager.
-  void ShutDown();
-
  private:
   class InProcessServiceManagerContext;
 
diff --git a/content/browser/startup_data_impl.h b/content/browser/startup_data_impl.h
index ddc91a0f..e3f06271 100644
--- a/content/browser/startup_data_impl.h
+++ b/content/browser/startup_data_impl.h
@@ -12,15 +12,13 @@
 
 namespace content {
 
-class ServiceManagerContext;
-
 // The browser implementation of StartupData.
 struct StartupDataImpl : public StartupData {
   StartupDataImpl();
   ~StartupDataImpl() override;
 
+  // TODO(hanxi): add ServiceManagerContext* here.
   std::unique_ptr<BrowserProcessSubThread> thread;
-  ServiceManagerContext* service_manager_context;
 };
 
 }  // namespace content
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom
index 757640bb..9fa1fed 100644
--- a/content/common/service_worker/embedded_worker.mojom
+++ b/content/common/service_worker/embedded_worker.mojom
@@ -15,6 +15,7 @@
 import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
+import "third_party/blink/public/mojom/script/script_type.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom";
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn
index 8dc74e9..69ec2a0 100644
--- a/content/public/common/BUILD.gn
+++ b/content/public/common/BUILD.gn
@@ -182,6 +182,8 @@
     "persistent_notification_status.h",
     "previews_state.h",
     "process_type.h",
+    "profiling.cc",
+    "profiling.h",
     "push_subscription_options.h",
     "referrer.cc",
     "referrer.h",
diff --git a/chrome/common/profiling.cc b/content/public/common/profiling.cc
similarity index 91%
rename from chrome/common/profiling.cc
rename to content/public/common/profiling.cc
index b662327..fe6201c 100644
--- a/chrome/common/profiling.cc
+++ b/content/public/common/profiling.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/common/profiling.h"
+#include "content/public/common/profiling.h"
 
 #include "base/at_exit.h"
 #include "base/base_switches.h"
@@ -16,9 +16,10 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread.h"
-#include "chrome/common/chrome_switches.h"
 #include "content/public/common/content_switches.h"
 
+namespace content {
+
 namespace {
 
 std::string GetProfileName() {
@@ -33,8 +34,8 @@
       profile_name = std::string("chrome-profile-{type}-{pid}");
     std::string process_type =
         command_line.GetSwitchValueASCII(switches::kProcessType);
-    std::string type = process_type.empty() ?
-        std::string("browser") : std::string(process_type);
+    std::string type = process_type.empty() ? std::string("browser")
+                                            : std::string(process_type);
     base::ReplaceSubstringsAfterOffset(&profile_name, 0, "{type}", type);
 
     return profile_name;
@@ -100,10 +101,10 @@
   DISALLOW_COPY_AND_ASSIGN(ProfilingThreadControl);
 };
 
-base::LazyInstance<ProfilingThreadControl>::Leaky
-    g_flush_thread_control = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<ProfilingThreadControl>::Leaky g_flush_thread_control =
+    LAZY_INSTANCE_INITIALIZER;
 
-} // namespace
+}  // namespace
 
 // static
 void Profiling::ProcessStarted() {
@@ -151,3 +152,5 @@
   else
     Start();
 }
+
+}  // namespace content
diff --git a/chrome/common/profiling.h b/content/public/common/profiling.h
similarity index 80%
rename from chrome/common/profiling.h
rename to content/public/common/profiling.h
index 6da67d97..8bfacba 100644
--- a/chrome/common/profiling.h
+++ b/content/public/common/profiling.h
@@ -2,19 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_COMMON_PROFILING_H_
-#define CHROME_COMMON_PROFILING_H_
+#ifndef CONTENT_PUBLIC_COMMON_PROFILING_H_
+#define CONTENT_PUBLIC_COMMON_PROFILING_H_
 
 #include "build/build_config.h"
 
 #include "base/debug/profiler.h"
 #include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
 
 // The Profiling class manages the interaction with a sampling based profiler.
 // Its function is controlled by the kProfilingAtStart, kProfilingFile, and
 // kProfilingFlush command line values.
 // All of the API should only be called from the main thread of the process.
-class Profiling {
+class CONTENT_EXPORT Profiling {
  public:
   // Called early in a process' life to allow profiling of startup time.
   // the presence of kProfilingAtStart is checked.
@@ -39,4 +42,6 @@
   DISALLOW_COPY_AND_ASSIGN(Profiling);
 };
 
-#endif  // CHROME_COMMON_PROFILING_H_
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_COMMON_PROFILING_H_
diff --git a/content/public/test/nested_message_pump_android.cc b/content/public/test/nested_message_pump_android.cc
index 48d4d17..4328e55 100644
--- a/content/public/test/nested_message_pump_android.cc
+++ b/content/public/test/nested_message_pump_android.cc
@@ -29,7 +29,9 @@
         run_depth(run_depth),
         should_quit(false),
         waitable_event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
-                       base::WaitableEvent::InitialState::NOT_SIGNALED) {}
+                       base::WaitableEvent::InitialState::NOT_SIGNALED) {
+    waitable_event.declare_only_used_while_idle();
+  }
 
   base::MessagePump::Delegate* delegate;
 
diff --git a/content/renderer/categorized_worker_pool.cc b/content/renderer/categorized_worker_pool.cc
index 23ff0b3..b764030 100644
--- a/content/renderer/categorized_worker_pool.cc
+++ b/content/renderer/categorized_worker_pool.cc
@@ -148,7 +148,12 @@
       has_ready_to_run_foreground_tasks_cv_(&lock_),
       has_ready_to_run_background_tasks_cv_(&lock_),
       has_namespaces_with_finished_running_tasks_cv_(&lock_),
-      shutdown_(false) {}
+      shutdown_(false) {
+  // Declare the two ConditionVariables which are used by worker threads to
+  // sleep-while-idle as such to avoid throwing off //base heuristics.
+  has_ready_to_run_foreground_tasks_cv_.declare_only_used_while_idle();
+  has_ready_to_run_background_tasks_cv_.declare_only_used_while_idle();
+}
 
 void CategorizedWorkerPool::Start(int num_threads) {
   DCHECK(threads_.empty());
diff --git a/content/renderer/media/stream/webmediaplayer_ms_compositor.cc b/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
index 18e9136d..afbc80e 100644
--- a/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
@@ -526,7 +526,13 @@
 
   scoped_refptr<media::VideoFrame> old_frame = std::move(current_frame_);
   current_frame_ = frame;
-  CheckForFrameChanges(old_frame, frame);
+
+  // Complete the checks after |current_frame_| is accessible to avoid
+  // deadlocks, see https://crbug.com/901744.
+  video_frame_compositor_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&WebMediaPlayerMSCompositor::CheckForFrameChanges, this,
+                     old_frame, frame));
 }
 
 void WebMediaPlayerMSCompositor::CheckForFrameChanges(
diff --git a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
index c11f55ae..f424353 100644
--- a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -429,12 +429,27 @@
                     blink::WebFrameSinkDestroyedCallback));
   MOCK_METHOD0(StartRendering, void());
   MOCK_METHOD0(StopRendering, void());
-  MOCK_METHOD1(Initialize, void(cc::VideoFrameProvider*));
+  MOCK_METHOD1(MockInitialize, void(cc::VideoFrameProvider*));
   MOCK_METHOD1(SetRotation, void(media::VideoRotation));
-  MOCK_METHOD1(SetIsOpaque, void(bool));
+  MOCK_METHOD1(MockSetIsOpaque, void(bool));
   MOCK_METHOD1(UpdateSubmissionState, void(bool));
   MOCK_METHOD1(SetForceSubmit, void(bool));
   MOCK_CONST_METHOD0(IsDrivingFrameUpdates, bool());
+
+  void Initialize(cc::VideoFrameProvider* provider) override {
+    provider_ = provider;
+    MockInitialize(provider);
+  }
+
+  // This method may try accessing frames, see deadlock case in
+  // https://crbug.com/901744.
+  void SetIsOpaque(bool opaque) override {
+    auto frame = provider_->GetCurrentFrame();
+    MockSetIsOpaque(opaque);
+  }
+
+ private:
+  cc::VideoFrameProvider* provider_;
 };
 
 // The class is used to generate a MockVideoProvider in
@@ -1168,7 +1183,7 @@
   provider->QueueFrames(timestamps, false);
   if (enable_surface_layer_for_video_) {
     EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
-    EXPECT_CALL(*submitter_ptr_, SetIsOpaque(false));
+    EXPECT_CALL(*submitter_ptr_, MockSetIsOpaque(false));
   }
   message_loop_controller_.RunAndWaitForStatus(
       media::PipelineStatus::PIPELINE_OK);
@@ -1182,7 +1197,7 @@
   provider->QueueFrames(timestamps, true);
   if (enable_surface_layer_for_video_) {
     EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(true));
-    EXPECT_CALL(*submitter_ptr_, SetIsOpaque(true));
+    EXPECT_CALL(*submitter_ptr_, MockSetIsOpaque(true));
   }
   message_loop_controller_.RunAndWaitForStatus(
       media::PipelineStatus::PIPELINE_OK);
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index e6f7e13..1e938d6 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -26,6 +26,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
 #include "content/app/mojo/mojo_init.h"
 #include "content/common/in_process_child_thread_params.h"
 #include "content/common/service_manager/child_connection.h"
@@ -299,9 +300,19 @@
   InputHandlerManagerDestroyedAfterCompositorThread
 #endif
 
+// TODO(crbug.com/902311): We should not disable
+// |NonResourceDispatchIPCTasksDontGoThroughScheduler| for Windows.
+#if defined(OS_WIN) && !defined(LEAK_SANITIZER)
+#define MAYBE_NonResourceDispatchIPCTasksDontGoThroughScheduler \
+  DISABLED_NonResourceDispatchIPCTasksDontGoThroughScheduler
+#else
+#define MAYBE_NonResourceDispatchIPCTasksDontGoThroughScheduler \
+  NonResourceDispatchIPCTasksDontGoThroughScheduler
+#endif
+
 // Disabled under LeakSanitizer due to memory leaks.
 TEST_F(RenderThreadImplBrowserTest,
-       WILL_LEAK(NonResourceDispatchIPCTasksDontGoThroughScheduler)) {
+       WILL_LEAK(MAYBE_NonResourceDispatchIPCTasksDontGoThroughScheduler)) {
   // NOTE other than not being a resource message, the actual message is
   // unimportant.
 
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 35cefd3d..5e08ea5c 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -737,6 +737,17 @@
 void ServiceWorkerContextClient::WillEvaluateScript() {
   DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
   start_timing_->script_evaluation_start_time = base::TimeTicks::Now();
+
+  // Temporary CHECK for https://crbug.com/881100
+  int64_t t0 =
+      start_timing_->start_worker_received_time.since_origin().InMicroseconds();
+  int64_t t1 = start_timing_->script_evaluation_start_time.since_origin()
+                   .InMicroseconds();
+  base::debug::Alias(&t0);
+  base::debug::Alias(&t1);
+  CHECK_LE(start_timing_->start_worker_received_time,
+           start_timing_->script_evaluation_start_time);
+
   (*instance_host_)->OnScriptEvaluationStart();
 }
 
@@ -744,6 +755,16 @@
   DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
   start_timing_->script_evaluation_end_time = base::TimeTicks::Now();
 
+  // Temporary CHECK for https://crbug.com/881100
+  int64_t t0 = start_timing_->script_evaluation_start_time.since_origin()
+                   .InMicroseconds();
+  int64_t t1 =
+      start_timing_->script_evaluation_end_time.since_origin().InMicroseconds();
+  base::debug::Alias(&t0);
+  base::debug::Alias(&t1);
+  CHECK_LE(start_timing_->script_evaluation_start_time,
+           start_timing_->script_evaluation_end_time);
+
   blink::mojom::ServiceWorkerStartStatus status =
       success ? blink::mojom::ServiceWorkerStartStatus::kNormalCompletion
               : blink::mojom::ServiceWorkerStartStatus::kAbruptCompletion;
@@ -1368,6 +1389,21 @@
         service_worker_version_id_, service_worker_scope_, script_url_);
   }
 
+  // Temporary CHECK for https://crbug.com/881100
+  int64_t t0 =
+      start_timing_->start_worker_received_time.since_origin().InMicroseconds();
+  int64_t t1 = start_timing_->script_evaluation_start_time.since_origin()
+                   .InMicroseconds();
+  int64_t t2 =
+      start_timing_->script_evaluation_end_time.since_origin().InMicroseconds();
+  base::debug::Alias(&t0);
+  base::debug::Alias(&t1);
+  base::debug::Alias(&t2);
+  CHECK_LE(start_timing_->start_worker_received_time,
+           start_timing_->script_evaluation_start_time);
+  CHECK_LE(start_timing_->script_evaluation_start_time,
+           start_timing_->script_evaluation_end_time);
+
   (*instance_host_)
       ->OnStarted(status, WorkerThread::GetCurrentId(),
                   std::move(start_timing_));
diff --git a/content/renderer/webgraphicscontext3d_provider_impl.cc b/content/renderer/webgraphicscontext3d_provider_impl.cc
index 42f8cb8b..22805b0 100644
--- a/content/renderer/webgraphicscontext3d_provider_impl.cc
+++ b/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -101,7 +101,9 @@
       std::make_unique<cc::GpuImageDecodeCache>(
           provider_.get(), use_transfer_cache, color_type, kMaxWorkingSetBytes,
           provider_->ContextCapabilities().max_texture_size,
-          cc::PaintImage::kDefaultGeneratorClientId));
+          cc::PaintImage::kDefaultGeneratorClientId,
+          blink::CanvasColorParams::CanvasColorSpaceToSkColorSpace(
+              color_space)));
   DCHECK(insertion_result.second);
   cache_iterator = insertion_result.first;
   return cache_iterator->second.get();
diff --git a/device/fido/fido_test_data.h b/device/fido/fido_test_data.h
index 8e5798d..287e5c9 100644
--- a/device/fido/fido_test_data.h
+++ b/device/fido/fido_test_data.h
@@ -1352,6 +1352,19 @@
     0xB2, 0x17, 0x6B, 0xBD, 0x30, 0x36, 0x59, 0xC9, 0xCD, 0x92,
 };
 
+constexpr uint8_t kTestGetAssertionResponseWithEmptyCredential[] = {
+    0x00, 0xA2, 0x02, 0x58, 0x25, 0x11, 0x94, 0x22, 0x8d, 0xa8, 0xfd, 0xbd,
+    0xee, 0xfd, 0x26, 0x1b, 0xd7, 0xb6, 0x59, 0x5c, 0xfd, 0x70, 0xa5, 0x0d,
+    0x70, 0xc6, 0x40, 0x7b, 0xcf, 0x01, 0x3d, 0xe9, 0x6d, 0x4e, 0xfb, 0x17,
+    0xde, 0x01, 0x00, 0x00, 0x00, 0x5F, 0x03, 0x58, 0x46, 0x30, 0x44, 0x02,
+    0x20, 0x62, 0xB8, 0xC4, 0x37, 0xB0, 0xB6, 0xFC, 0x89, 0x37, 0xF6, 0x45,
+    0xC0, 0x1E, 0x26, 0xCE, 0x0E, 0x26, 0x58, 0x38, 0xFE, 0xC4, 0xA8, 0x74,
+    0xC5, 0x5D, 0xDD, 0x6D, 0xEC, 0xF0, 0xA0, 0x83, 0xD3, 0x02, 0x20, 0x7C,
+    0xD4, 0x1C, 0xAF, 0x4F, 0xD8, 0x7F, 0x73, 0xBF, 0x01, 0x25, 0x06, 0x78,
+    0x11, 0x45, 0x2B, 0x5F, 0xB8, 0x17, 0xA3, 0xFA, 0x73, 0xB2, 0x17, 0x6B,
+    0xBD, 0x30, 0x36, 0x59, 0xC9, 0xCD, 0x92,
+};
+
 constexpr uint8_t kTestGetAssertionResponseWithIncorrectRpIdHash[] = {
     0x00, 0xA3, 0x01, 0xA2, 0x62, 0x69, 0x64, 0x58, 0x40, 0x9C, 0x06, 0x98,
     0x05, 0xA7, 0xE9, 0x0C, 0xED, 0xF9, 0x24, 0xAC, 0x5A, 0x29, 0x36, 0x95,
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc
index 738e805..e472c97 100644
--- a/device/fido/get_assertion_handler_unittest.cc
+++ b/device/fido/get_assertion_handler_unittest.cc
@@ -326,6 +326,32 @@
   EXPECT_FALSE(get_assertion_callback().was_called());
 }
 
+// Tests a scenario where the authenticator responds with an empty credential.
+// When GetAssertion request only has a single credential in the allow list,
+// this is a valid response. Check that credential is set by the client before
+// the response is returned to the relying party.
+TEST_F(FidoGetAssertionHandlerTest, ValidEmptyCredential) {
+  auto request_handler = CreateGetAssertionHandlerCtap();
+  discovery()->WaitForCallToStartAndSimulateSuccess();
+  // Resident Keys must be disabled, otherwise allow list check is skipped.
+  auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(
+      test_data::kTestGetInfoResponseWithoutResidentKeySupport);
+  device->ExpectCtap2CommandAndRespondWith(
+      CtapRequestCommand::kAuthenticatorGetAssertion,
+      test_data::kTestGetAssertionResponseWithEmptyCredential);
+  discovery()->AddDevice(std::move(device));
+
+  get_assertion_callback().WaitForCallback();
+  const auto& response = get_assertion_callback().value<0>();
+  EXPECT_TRUE(request_handler->is_complete());
+  EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
+  ASSERT_TRUE(response);
+  EXPECT_TRUE(response->credential());
+  EXPECT_THAT(
+      response->raw_credential_id(),
+      ::testing::ElementsAreArray(test_data::kTestGetAssertionCredentialId));
+}
+
 // Tests a scenario where authenticator responds without user entity in its
 // response but client is expecting a resident key credential.
 TEST_F(FidoGetAssertionHandlerTest, IncorrectUserEntity) {
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc
index d4102b2..4f387e0 100644
--- a/device/fido/get_assertion_request_handler.cc
+++ b/device/fido/get_assertion_request_handler.cc
@@ -85,6 +85,18 @@
                      });
 }
 
+// When the response from the authenticator does not contain a credential and
+// the allow list from the GetAssertion request only contains a single
+// credential id, manually set credential id in the returned response.
+void SetCredentialIdForResponseWithEmptyCredential(
+    const CtapGetAssertionRequest& request,
+    AuthenticatorGetAssertionResponse& response) {
+  if (request.allow_list() && request.allow_list()->size() == 1 &&
+      !response.credential()) {
+    response.SetCredential(request.allow_list()->at(0));
+  }
+}
+
 // Checks UserVerificationRequirement enum passed from the relying party is
 // compatible with the authenticator, and updates the request to the
 // "effective" user verification requirement.
@@ -220,6 +232,7 @@
     return;
   }
 
+  SetCredentialIdForResponseWithEmptyCredential(request_, *response);
   OnAuthenticatorResponse(authenticator, response_code, std::move(response));
 }
 
diff --git a/headless/lib/headless_content_main_delegate.cc b/headless/lib/headless_content_main_delegate.cc
index 1446bb3..551bd04 100644
--- a/headless/lib/headless_content_main_delegate.cc
+++ b/headless/lib/headless_content_main_delegate.cc
@@ -23,6 +23,7 @@
 #include "components/crash/core/common/crash_key.h"
 #include "content/public/browser/browser_main_runner.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/profiling.h"
 #include "headless/lib/browser/headless_browser_impl.h"
 #include "headless/lib/browser/headless_content_browser_client.h"
 #include "headless/lib/headless_crash_reporter_client.h"
@@ -48,6 +49,10 @@
 #include "headless/lib/renderer/headless_content_renderer_client.h"
 #endif
 
+#if defined(OS_POSIX)
+#include <signal.h>
+#endif
+
 namespace headless {
 namespace {
 // Keep in sync with content/common/content_constants_internal.h.
@@ -123,6 +128,8 @@
   // preempt this attempt.
   command_line->AppendSwitch(::switches::kDisableGpuCompositing);
 
+  content::Profiling::ProcessStarted();
+
   SetContentClient(&content_client_);
   return false;
 }
@@ -291,7 +298,29 @@
 #endif  // !defined(CHROME_MULTIPLE_DLL_CHILD)
 
 #if defined(OS_LINUX)
+void SIGTERMProfilingShutdown(int signal) {
+  content::Profiling::Stop();
+  struct sigaction sigact;
+  memset(&sigact, 0, sizeof(sigact));
+  sigact.sa_handler = SIG_DFL;
+  CHECK_EQ(sigaction(SIGTERM, &sigact, NULL), 0);
+  raise(signal);
+}
+
+void SetUpProfilingShutdownHandler() {
+  struct sigaction sigact;
+  sigact.sa_handler = SIGTERMProfilingShutdown;
+  sigact.sa_flags = SA_RESETHAND;
+  sigemptyset(&sigact.sa_mask);
+  CHECK_EQ(sigaction(SIGTERM, &sigact, NULL), 0);
+}
+
 void HeadlessContentMainDelegate::ZygoteForked() {
+  content::Profiling::ProcessStarted();
+  if (content::Profiling::BeingProfiled()) {
+    base::debug::RestartProfilingAfterFork();
+    SetUpProfilingShutdownHandler();
+  }
   const base::CommandLine& command_line(
       *base::CommandLine::ForCurrentProcess());
   const std::string process_type =
diff --git a/ios/chrome/browser/search_engines/resources/search_engine.js b/ios/chrome/browser/search_engines/resources/search_engine.js
index a3bd26f73..1f42b524 100644
--- a/ios/chrome/browser/search_engines/resources/search_engine.js
+++ b/ios/chrome/browser/search_engines/resources/search_engine.js
@@ -180,6 +180,12 @@
  *   searchableURL.
  */
 function generateSearchableUrl_(form) {
+  // Only consider <form> that navigates in current frame, because new
+  // TemplateURL will only be created from navigation in the same page:
+  // https://cs.chromium.org/chromium/src/chrome/browser/ui/search_engines/search_engine_tab_helper.cc?l=177&gsn=last_index
+  if (form.target && form.target != '_self')
+    return;
+
   // Only consider forms that GET data.
   if (form.method && form.method.toLowerCase() != 'get') {
     return;
diff --git a/ios/chrome/browser/search_engines/search_engine_tab_helper.h b/ios/chrome/browser/search_engines/search_engine_tab_helper.h
index 1002b3d..beb7c733 100644
--- a/ios/chrome/browser/search_engines/search_engine_tab_helper.h
+++ b/ios/chrome/browser/search_engines/search_engine_tab_helper.h
@@ -42,10 +42,15 @@
 
   explicit SearchEngineTabHelper(web::WebState* web_state);
 
-  // Creates a TemplateURL by downloading and parsing the OSDD
+  // Adds a TemplateURL by downloading and parsing the OSDD.
   void AddTemplateURLByOSDD(const GURL& page_url, const GURL& osdd_url);
 
+  // Adds a TemplateURL by |searchable_url|.
+  void AddTemplateURLBySearchableURL(const GURL& searchable_url);
+
   // WebStateObserver implementation.
+  void DidFinishNavigation(web::WebState* web_state,
+                           web::NavigationContext* navigation_context) override;
   void WebStateDestroyed(web::WebState* web_state) override;
 
   // Handles messages from JavaScript. Messages can be:
@@ -60,6 +65,14 @@
   // WebState this tab helper is attached to.
   web::WebState* web_state_ = nullptr;
 
+  // The searchable URL generated from <form> submission. This ivar is an empty
+  // GURL by default. If a web page has a searchable <form>, a searchable URL is
+  // generated by JavaScript when the <form> is submitted, and stored in this
+  // ivar. When the navigation triggered by the <form> submission finishes
+  // successfully, this ivar will be used to add a new TemplateURL and then it
+  // will be set to empty GURL again.
+  GURL searchable_url_;
+
   DISALLOW_COPY_AND_ASSIGN(SearchEngineTabHelper);
 };
 
diff --git a/ios/chrome/browser/search_engines/search_engine_tab_helper.mm b/ios/chrome/browser/search_engines/search_engine_tab_helper.mm
index b7acbd4..ac4c093f 100644
--- a/ios/chrome/browser/search_engines/search_engine_tab_helper.mm
+++ b/ios/chrome/browser/search_engines/search_engine_tab_helper.mm
@@ -7,11 +7,14 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_fetcher.h"
+#include "components/search_engines/template_url_service.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/search_engines/template_url_fetcher_factory.h"
+#include "ios/chrome/browser/search_engines/template_url_service_factory.h"
 #include "ios/web/public/favicon_status.h"
 #import "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
+#import "ios/web/public/web_state/navigation_context.h"
 #include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 
@@ -27,6 +30,8 @@
 const char kCommandOpenSearch[] = "searchEngine.openSearch";
 const char kOpenSearchPageUrlKey[] = "pageUrl";
 const char kOpenSearchOsddUrlKey[] = "osddUrl";
+const char kCommandSearchableUrl[] = "searchEngine.searchableUrl";
+const char kSearchableUrlUrlKey[] = "url";
 
 // Returns true if the |item|'s transition type is FORM_SUBMIT.
 bool IsFormSubmit(const web::NavigationItem* item) {
@@ -35,7 +40,7 @@
 }
 
 // Generates a keyword from |item|. This code is based on:
-// https://cs.chromium.org/chromium/src/chrome/browser/ui/search_engines/search_engine_tab_helper.cc?rcl=4e19b43513aa9590ae89d5c68523bc764f40067f&l=41i
+// https://cs.chromium.org/chromium/src/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
 base::string16 GenerateKeywordFromNavigationItem(
     const web::NavigationItem* item) {
   // Don't autogenerate keywords for pages that are the result of form
@@ -85,6 +90,22 @@
   web_state_ = nullptr;
 }
 
+// When the page is loaded, checks if |searchable_url_| has a value generated
+// from the <form> submission before the navigation. If true, and the navigation
+// is successful, adds a TemplateURL by |searchable_url_|. |searchable_url_|
+// will be set to empty in the end.
+void SearchEngineTabHelper::DidFinishNavigation(
+    web::WebState* web_state,
+    web::NavigationContext* navigation_context) {
+  if (!searchable_url_.is_empty()) {
+    if (!navigation_context->GetError() &&
+        !navigation_context->IsSameDocument()) {
+      AddTemplateURLBySearchableURL(searchable_url_);
+    }
+    searchable_url_ = GURL();
+  }
+}
+
 bool SearchEngineTabHelper::OnJsMessage(const base::DictionaryValue& message,
                                         const GURL& page_url,
                                         bool has_user_gesture,
@@ -104,13 +125,23 @@
       return false;
     AddTemplateURLByOSDD(GURL(document_url->GetString()),
                          GURL(osdd_url->GetString()));
+  } else if (cmd_str == kCommandSearchableUrl) {
+    const base::Value* url = message.FindKey(kSearchableUrlUrlKey);
+    if (!url || !url->is_string())
+      return false;
+    // Save |url| to |searchable_url_| when generated from <form> submission,
+    // and create the TemplateURL when the submission did lead to a successful
+    // navigation.
+    searchable_url_ = GURL(url->GetString());
+  } else {
+    return false;
   }
   return true;
 }
 
 // Creates a new TemplateURL by OSDD. The TemplateURL will be added to
 // TemplateURLService by TemplateURLFecther. This code is based on:
-// https://cs.chromium.org/chromium/src/chrome/browser/ui/search_engines/search_engine_tab_helper.cc?rcl=50f50d521b18ac53d05c4e159c02bcb609454b8e&l=96
+// https://cs.chromium.org/chromium/src/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
 void SearchEngineTabHelper::AddTemplateURLByOSDD(const GURL& page_url,
                                                  const GURL& osdd_url) {
   // Checks to see if we should generate a keyword based on the OSDD, and if
@@ -164,3 +195,73 @@
           browser_state->GetURLLoaderFactory(), MSG_ROUTING_NONE,
           /* content::ResourceType::RESOURCE_TYPE_SUB_RESOURCE */ 6);
 }
+
+// Creates a TemplateURL by |searchable_url| and adds it to TemplateURLService.
+// This code is based on:
+// https://cs.chromium.org/chromium/src/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
+void SearchEngineTabHelper::AddTemplateURLBySearchableURL(
+    const GURL& searchable_url) {
+  if (!searchable_url.is_valid()) {
+    return;
+  }
+
+  ios::ChromeBrowserState* browser_state =
+      ios::ChromeBrowserState::FromBrowserState(web_state_->GetBrowserState());
+  // Don't add TemplateURL under incognito mode.
+  if (browser_state->IsOffTheRecord())
+    return;
+
+  const web::NavigationManager* manager = web_state_->GetNavigationManager();
+  int last_index = manager->GetLastCommittedItemIndex();
+  // When there was no previous page, the last index will be 0. This is
+  // normally due to a form submit that opened in a new tab.
+  if (last_index <= 0)
+    return;
+  const web::NavigationItem* item = manager->GetItemAtIndex(last_index - 1);
+
+  base::string16 keyword(GenerateKeywordFromNavigationItem(item));
+  if (keyword.empty())
+    return;
+
+  TemplateURLService* url_service =
+      ios::TemplateURLServiceFactory::GetForBrowserState(browser_state);
+  if (!url_service)
+    return;
+
+  if (!url_service->loaded()) {
+    url_service->Load();
+    return;
+  }
+
+  const TemplateURL* current_url;
+  if (!url_service->CanAddAutogeneratedKeyword(keyword, searchable_url,
+                                               &current_url))
+    return;
+
+  if (current_url) {
+    if (current_url->originating_url().is_valid()) {
+      // The existing keyword was generated from an OpenSearch description
+      // document, don't regenerate.
+      return;
+    }
+    url_service->Remove(current_url);
+  }
+
+  TemplateURLData data;
+  data.SetShortName(keyword);
+  data.SetKeyword(keyword);
+  data.SetURL(searchable_url.spec());
+
+  const GURL& current_favicon =
+      manager->GetLastCommittedItem()->GetFavicon().url;
+  // If the favicon url isn't valid, it means there really isn't a favicon, or
+  // the favicon url wasn't obtained before the load started. This assumes the
+  // latter.
+  if (current_favicon.is_valid()) {
+    data.favicon_url = current_favicon;
+  } else if (item->GetReferrer().url.is_valid()) {
+    data.favicon_url = TemplateURL::GenerateFaviconURL(item->GetReferrer().url);
+  }
+  data.safe_for_autoreplace = true;
+  url_service->Add(std::make_unique<TemplateURL>(data));
+}
diff --git a/ios/chrome/browser/search_engines/search_engine_tab_helper_unittest.mm b/ios/chrome/browser/search_engines/search_engine_tab_helper_unittest.mm
index 59a6c61..35247f95 100644
--- a/ios/chrome/browser/search_engines/search_engine_tab_helper_unittest.mm
+++ b/ios/chrome/browser/search_engines/search_engine_tab_helper_unittest.mm
@@ -12,6 +12,7 @@
 #include "ios/chrome/browser/search_engines/template_url_service_factory.h"
 #include "ios/chrome/browser/web/chrome_web_test.h"
 #import "ios/web/public/test/web_test_with_web_state.h"
+#import "ios/web/public/test/web_view_interaction_test_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
@@ -23,10 +24,13 @@
 
 using base::test::ios::WaitUntilConditionOrTimeout;
 using base::test::ios::kWaitForJSCompletionTimeout;
+using web::test::SubmitWebViewFormWithId;
 
 namespace {
 const char kOpenSearchXmlFilePath[] =
     "/ios/testing/data/http_server_files/opensearch.xml";
+const char kPonyHtmlFilePath[] =
+    "/ios/testing/data/http_server_files/pony.html";
 
 // A BrowserStateKeyedServiceFactory::TestingFactory that creates a testing
 // TemplateURLService. The created TemplateURLService may contain some default
@@ -78,6 +82,15 @@
     return [result isEqual:@YES];
   }
 
+  // Sends a message that |searchable_url| is generated from <form> submission.
+  bool SendMessageOfSearchableUrl(const GURL& searchable_url) {
+    id result = ExecuteJavaScript([NSString
+        stringWithFormat:@"__gCrWeb.message.invokeOnHost({'command': "
+                         @"'searchEngine.searchableUrl', 'url' : '%s'}); true;",
+                         searchable_url.spec().c_str()]);
+    return [result isEqual:@YES];
+  }
+
   net::EmbeddedTestServer server_;
 
   DISALLOW_COPY_AND_ASSIGN(SearchEngineTabHelperTest);
@@ -86,7 +99,7 @@
 // Tests that SearchEngineTabHelper can add TemplateURL to TemplateURLService
 // when a OSDD <link> is found in web page.
 TEST_F(SearchEngineTabHelperTest, AddTemplateURLByOpenSearch) {
-  GURL page_url("https://chrooome.com");
+  GURL page_url("https://chromium.test");
   GURL osdd_url = server_.GetURL(kOpenSearchXmlFilePath);
 
   // Record the original TemplateURLs in TemplateURLService.
@@ -115,13 +128,58 @@
     }
   }
   ASSERT_TRUE(new_url);
-  EXPECT_EQ(base::UTF8ToUTF16("chrooome.com"), new_url->data().keyword());
+  EXPECT_EQ(base::UTF8ToUTF16("chromium.test"), new_url->data().keyword());
   EXPECT_EQ(base::UTF8ToUTF16("Chrooome"), new_url->data().short_name());
   EXPECT_EQ(
-      "https://chrooome.com/index.php?title=chrooome&search={searchTerms}",
+      "https://chromium.test/index.php?title=chrooome&search={searchTerms}",
       new_url->data().url());
 }
 
+// Tests that SearchEngineTabHelper can add TemplateURL to TemplateURLService
+// when a <form> submission generates a searchable URL and leads to a successful
+// navigation.
+TEST_F(SearchEngineTabHelperTest, AddTemplateURLBySearchableURL) {
+  GURL page_url("https://chromium.test");
+  GURL searchable_url(
+      "https://chromium.test/index.php?title=chrooome&search={searchTerms}");
+  // HTML of the search engine page, with a <form> navigates to pony.html as
+  // search result page.
+  NSString* html = [NSString
+      stringWithFormat:@"<html><form id='f' action='%s'></form></html>",
+                       server_.GetURL(kPonyHtmlFilePath).spec().c_str()];
+
+  // Record the original TemplateURLs in TemplateURLService.
+  std::vector<TemplateURL*> old_urls =
+      template_url_service()->GetTemplateURLs();
+
+  // Load an empty page, and send a message of openSearchUrl from Js.
+  LoadHtml(html, page_url);
+  SendMessageOfSearchableUrl(searchable_url);
+  SubmitWebViewFormWithId(web_state(), "f");
+
+  // Wait for TemplateURL added to TemplateURLService.
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
+    base::RunLoop().RunUntilIdle();
+    return template_url_service()->GetTemplateURLs().size() ==
+           old_urls.size() + 1;
+  }));
+
+  // TemplateURLService doesn't guarantee that newly added TemplateURL is
+  // appended, so we should check in a general way that only one TemplateURL is
+  // added and others remain untouched.
+  TemplateURL* new_url = nullptr;
+  for (TemplateURL* url : template_url_service()->GetTemplateURLs()) {
+    if (std::find(old_urls.begin(), old_urls.end(), url) == old_urls.end()) {
+      ASSERT_FALSE(new_url);
+      new_url = url;
+    }
+  }
+  ASSERT_TRUE(new_url);
+  EXPECT_EQ(base::UTF8ToUTF16("chromium.test"), new_url->data().keyword());
+  EXPECT_EQ(base::UTF8ToUTF16("chromium.test"), new_url->data().short_name());
+  EXPECT_EQ(searchable_url.spec(), new_url->data().url());
+}
+
 // Test fixture for SearchEngineTabHelper class in incognito mode.
 class SearchEngineTabHelperIncognitoTest : public SearchEngineTabHelperTest {
  protected:
@@ -140,7 +198,7 @@
 // mode.
 TEST_F(SearchEngineTabHelperIncognitoTest,
        NotAddTemplateURLByOpenSearchUnderIncognito) {
-  GURL page_url("https://chrooome.com");
+  GURL page_url("https://chromium.test");
   GURL osdd_url = server_.GetURL(kOpenSearchXmlFilePath);
 
   // Record the original TemplateURLs in TemplateURLService.
@@ -159,3 +217,35 @@
   }));
   EXPECT_EQ(old_urls, template_url_service()->GetTemplateURLs());
 }
+
+// Tests that SearchEngineTabHelper doesn't add TemplateURL to
+// TemplateURLService when a <form> submission generates a searchable URL and
+// leads to a successful navigation under incognito mode.
+TEST_F(SearchEngineTabHelperIncognitoTest,
+       NotAddTemplateURLBySearchableURLUnderIncognito) {
+  GURL page_url("https://chromium.test");
+  GURL searchable_url(
+      "https://chromium.test/index.php?title=chrooome&search={searchTerms}");
+  // HTML of the search engine page, with a <form> navigates to pony.html as
+  // search result page.
+  NSString* html = [NSString
+      stringWithFormat:@"<html><form id='f' action='%s'></form></html>",
+                       server_.GetURL(kPonyHtmlFilePath).spec().c_str()];
+
+  // Record the original TemplateURLs in TemplateURLService.
+  std::vector<TemplateURL*> old_urls =
+      template_url_service()->GetTemplateURLs();
+
+  // Load an empty page, and send a message of openSearchUrl from Js.
+  LoadHtml(html, page_url);
+  SendMessageOfSearchableUrl(searchable_url);
+  SubmitWebViewFormWithId(web_state(), "f");
+
+  // Wait for TemplateURL added to TemplateURLService.
+  ASSERT_FALSE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
+    base::RunLoop().RunUntilIdle();
+    return template_url_service()->GetTemplateURLs().size() ==
+           old_urls.size() + 1;
+  }));
+  EXPECT_EQ(old_urls, template_url_service()->GetTemplateURLs());
+}
diff --git a/ios/chrome/browser/ui/side_swipe/BUILD.gn b/ios/chrome/browser/ui/side_swipe/BUILD.gn
index ca6a89f9..240926fa 100644
--- a/ios/chrome/browser/ui/side_swipe/BUILD.gn
+++ b/ios/chrome/browser/ui/side_swipe/BUILD.gn
@@ -15,6 +15,8 @@
     "side_swipe_navigation_view.mm",
     "side_swipe_util.h",
     "side_swipe_util.mm",
+    "swipe_view.h",
+    "swipe_view.mm",
   ]
   deps = [
     "resources:side_swipe_navigation_back",
diff --git a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
index cc062666..d4fb9bf 100644
--- a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
+++ b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
@@ -15,6 +15,7 @@
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/background_generator.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_util.h"
+#import "ios/chrome/browser/ui/side_swipe/swipe_view.h"
 #import "ios/chrome/browser/ui/side_swipe_gesture_recognizer.h"
 #import "ios/chrome/browser/ui/tab_grid/grid/grid_constants.h"
 #import "ios/chrome/browser/ui/toolbar/public/side_swipe_toolbar_snapshot_providing.h"
@@ -47,122 +48,6 @@
 const CGFloat kResizeFactor = 4;
 }  // anonymous namespace
 
-@interface SwipeView : UIView
-
-@property(nonatomic, strong) UIImageView* topToolbarSnapshot;
-@property(nonatomic, strong) UIImageView* bottomToolbarSnapshot;
-
-@property(nonatomic, assign) CGFloat topMargin;
-@property(nonatomic, strong) NSLayoutConstraint* toolbarTopConstraint;
-@property(nonatomic, strong) NSLayoutConstraint* imageTopConstraint;
-
-@end
-
-@implementation SwipeView {
-  UIImageView* _image;
-}
-
-@synthesize topToolbarSnapshot = _topToolbarSnapshot;
-@synthesize bottomToolbarSnapshot = _bottomToolbarSnapshot;
-@synthesize topMargin = _topMargin;
-@synthesize toolbarTopConstraint = _toolbarTopConstraint;
-@synthesize imageTopConstraint = _imageTopConstraint;
-
-- (instancetype)initWithFrame:(CGRect)frame topMargin:(CGFloat)topMargin {
-  self = [super initWithFrame:frame];
-  if (self) {
-    _topMargin = topMargin;
-
-    _image = [[UIImageView alloc] initWithFrame:CGRectZero];
-    [_image setClipsToBounds:YES];
-    [_image setContentMode:UIViewContentModeScaleAspectFill];
-    [self addSubview:_image];
-
-    _topToolbarSnapshot = [[UIImageView alloc] initWithFrame:CGRectZero];
-    [self addSubview:_topToolbarSnapshot];
-
-    _bottomToolbarSnapshot = [[UIImageView alloc] initWithFrame:CGRectZero];
-    [self addSubview:_bottomToolbarSnapshot];
-
-    // All subviews are as wide as the parent
-    NSMutableArray* constraints = [NSMutableArray array];
-    for (UIView* view in self.subviews) {
-      [view setTranslatesAutoresizingMaskIntoConstraints:NO];
-      [constraints addObject:[view.leadingAnchor
-                                 constraintEqualToAnchor:self.leadingAnchor]];
-      [constraints addObject:[view.trailingAnchor
-                                 constraintEqualToAnchor:self.trailingAnchor]];
-    }
-
-    _toolbarTopConstraint = [[_topToolbarSnapshot topAnchor]
-        constraintEqualToAnchor:self.topAnchor];
-
-    if (!base::FeatureList::IsEnabled(
-            web::features::kBrowserContainerFullscreen)) {
-      _toolbarTopConstraint.constant = -StatusBarHeight();
-    }
-
-    _imageTopConstraint =
-        [_image.topAnchor constraintEqualToAnchor:self.topAnchor
-                                         constant:topMargin];
-    [constraints addObjectsFromArray:@[
-      _imageTopConstraint,
-      [[_image bottomAnchor] constraintEqualToAnchor:self.bottomAnchor],
-      _toolbarTopConstraint,
-      [_bottomToolbarSnapshot.bottomAnchor
-          constraintEqualToAnchor:self.bottomAnchor],
-    ]];
-
-    [NSLayoutConstraint activateConstraints:constraints];
-  }
-  return self;
-}
-
-- (void)layoutSubviews {
-  [super layoutSubviews];
-  [self updateImageBoundsAndZoom];
-}
-
-- (void)updateImageBoundsAndZoom {
-  UIImage* image = [_image image];
-  if (image) {
-    CGSize imageSize = image.size;
-    CGSize viewSize = [_image frame].size;
-    CGFloat zoomRatio = std::max(viewSize.height / imageSize.height,
-                                 viewSize.width / imageSize.width);
-    [_image layer].contentsRect =
-        CGRectMake(0.0, 0.0, viewSize.width / (zoomRatio * imageSize.width),
-                   viewSize.height / (zoomRatio * imageSize.height));
-  }
-}
-
-- (void)setTopMargin:(CGFloat)topMargin {
-  _topMargin = topMargin;
-  self.imageTopConstraint.constant = topMargin;
-}
-
-- (void)setImage:(UIImage*)image {
-  [_image setImage:image];
-  [self updateImageBoundsAndZoom];
-}
-
-- (void)setTopToolbarImage:(UIImage*)image {
-  [self.topToolbarSnapshot setImage:image];
-  if (!base::FeatureList::IsEnabled(
-          web::features::kBrowserContainerFullscreen)) {
-    // Update constraints as StatusBarHeight changes depending on orientation.
-    self.toolbarTopConstraint.constant = -StatusBarHeight();
-  }
-  [self.topToolbarSnapshot setNeedsLayout];
-}
-
-- (void)setBottomToolbarImage:(UIImage*)image {
-  [self.bottomToolbarSnapshot setImage:image];
-  [self.bottomToolbarSnapshot setNeedsLayout];
-}
-
-@end
-
 @interface CardSideSwipeView ()
 
 // Pan touches ended or were cancelled.
diff --git a/ios/chrome/browser/ui/side_swipe/swipe_view.h b/ios/chrome/browser/ui/side_swipe/swipe_view.h
new file mode 100644
index 0000000..599ebbb
--- /dev/null
+++ b/ios/chrome/browser/ui/side_swipe/swipe_view.h
@@ -0,0 +1,23 @@
+// 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 IOS_CHROME_BROWSER_UI_SIDE_SWIPE_SWIPE_VIEW_H_
+#define IOS_CHROME_BROWSER_UI_SIDE_SWIPE_SWIPE_VIEW_H_
+
+#import <UIKit/UIKit.h>
+
+@interface SwipeView : UIView
+
+// Space reserved at the top for the toolbar.
+@property(nonatomic, assign) CGFloat topMargin;
+
+- (instancetype)initWithFrame:(CGRect)frame topMargin:(CGFloat)topMargin;
+
+- (void)setTopToolbarImage:(UIImage*)image;
+- (void)setImage:(UIImage*)image;
+- (void)setBottomToolbarImage:(UIImage*)image;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SIDE_SWIPE_SWIPE_VIEW_H_
diff --git a/ios/chrome/browser/ui/side_swipe/swipe_view.mm b/ios/chrome/browser/ui/side_swipe/swipe_view.mm
new file mode 100644
index 0000000..855c438
--- /dev/null
+++ b/ios/chrome/browser/ui/side_swipe/swipe_view.mm
@@ -0,0 +1,128 @@
+// 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.
+
+#import "ios/chrome/browser/ui/side_swipe/swipe_view.h"
+
+#include "ios/chrome/browser/ui/util/ui_util.h"
+#include "ios/web/public/features.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface SwipeView ()
+
+@property(nonatomic, strong) UIImageView* topToolbarSnapshot;
+@property(nonatomic, strong) UIImageView* bottomToolbarSnapshot;
+
+@property(nonatomic, strong) NSLayoutConstraint* toolbarTopConstraint;
+@property(nonatomic, strong) NSLayoutConstraint* imageTopConstraint;
+
+@property(nonatomic, strong) UIImageView* imageView;
+
+@end
+
+@implementation SwipeView
+
+@synthesize topToolbarSnapshot = _topToolbarSnapshot;
+@synthesize bottomToolbarSnapshot = _bottomToolbarSnapshot;
+@synthesize topMargin = _topMargin;
+@synthesize toolbarTopConstraint = _toolbarTopConstraint;
+@synthesize imageTopConstraint = _imageTopConstraint;
+@synthesize imageView = _imageView;
+
+- (instancetype)initWithFrame:(CGRect)frame topMargin:(CGFloat)topMargin {
+  self = [super initWithFrame:frame];
+  if (self) {
+    _topMargin = topMargin;
+
+    _imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
+    [_imageView setClipsToBounds:YES];
+    [_imageView setContentMode:UIViewContentModeScaleAspectFill];
+    [self addSubview:_imageView];
+
+    _topToolbarSnapshot = [[UIImageView alloc] initWithFrame:CGRectZero];
+    [self addSubview:_topToolbarSnapshot];
+
+    _bottomToolbarSnapshot = [[UIImageView alloc] initWithFrame:CGRectZero];
+    [self addSubview:_bottomToolbarSnapshot];
+
+    // All subviews are as wide as the parent
+    NSMutableArray* constraints = [NSMutableArray array];
+    for (UIView* view in self.subviews) {
+      [view setTranslatesAutoresizingMaskIntoConstraints:NO];
+      [constraints addObject:[view.leadingAnchor
+                                 constraintEqualToAnchor:self.leadingAnchor]];
+      [constraints addObject:[view.trailingAnchor
+                                 constraintEqualToAnchor:self.trailingAnchor]];
+    }
+
+    _toolbarTopConstraint = [[_topToolbarSnapshot topAnchor]
+        constraintEqualToAnchor:self.topAnchor];
+
+    if (!base::FeatureList::IsEnabled(
+            web::features::kBrowserContainerFullscreen)) {
+      _toolbarTopConstraint.constant = -StatusBarHeight();
+    }
+
+    _imageTopConstraint =
+        [_imageView.topAnchor constraintEqualToAnchor:self.topAnchor
+                                             constant:topMargin];
+    [constraints addObjectsFromArray:@[
+      _imageTopConstraint,
+      [[_imageView bottomAnchor] constraintEqualToAnchor:self.bottomAnchor],
+      _toolbarTopConstraint,
+      [_bottomToolbarSnapshot.bottomAnchor
+          constraintEqualToAnchor:self.bottomAnchor],
+    ]];
+
+    [NSLayoutConstraint activateConstraints:constraints];
+  }
+  return self;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  [self updateImageBoundsAndZoom];
+}
+
+- (void)updateImageBoundsAndZoom {
+  UIImage* image = self.imageView.image;
+  if (image) {
+    CGSize imageSize = image.size;
+    CGSize viewSize = self.imageView.frame.size;
+    CGFloat zoomRatio = std::max(viewSize.height / imageSize.height,
+                                 viewSize.width / imageSize.width);
+    self.imageView.layer.contentsRect =
+        CGRectMake(0.0, 0.0, viewSize.width / (zoomRatio * imageSize.width),
+                   viewSize.height / (zoomRatio * imageSize.height));
+  }
+}
+
+- (void)setTopMargin:(CGFloat)topMargin {
+  _topMargin = topMargin;
+  self.imageTopConstraint.constant = topMargin;
+}
+
+- (void)setImage:(UIImage*)image {
+  self.imageView.image = image;
+  [self updateImageBoundsAndZoom];
+}
+
+- (void)setTopToolbarImage:(UIImage*)image {
+  [self.topToolbarSnapshot setImage:image];
+  if (!base::FeatureList::IsEnabled(
+          web::features::kBrowserContainerFullscreen)) {
+    // Update constraints as StatusBarHeight changes depending on orientation.
+    self.toolbarTopConstraint.constant = -StatusBarHeight();
+  }
+  [self.topToolbarSnapshot setNeedsLayout];
+}
+
+- (void)setBottomToolbarImage:(UIImage*)image {
+  [self.bottomToolbarSnapshot setImage:image];
+  [self.bottomToolbarSnapshot setNeedsLayout];
+}
+
+@end
diff --git a/ios/testing/data/http_server_files/opensearch.xml b/ios/testing/data/http_server_files/opensearch.xml
index d604c07..b36ed43 100644
--- a/ios/testing/data/http_server_files/opensearch.xml
+++ b/ios/testing/data/http_server_files/opensearch.xml
@@ -2,7 +2,6 @@
 <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
     <ShortName>Chrooome</ShortName>
     <Description>Chrooome</Description>
-    <Image height="16" width="16" type="image/x-icon">https://chrooome.com/favicon.ico</Image>
-    <Url type="text/html" method="get" template="https://chrooome.com/index.php?title=chrooome&amp;search={searchTerms}" />
-    <moz:SearchForm>https://en.cppreference.com/w/Special:Search</moz:SearchForm>
+    <Image height="16" width="16" type="image/x-icon">https://chromium.test/favicon.ico</Image>
+    <Url type="text/html" method="get" template="https://chromium.test/index.php?title=chrooome&amp;search={searchTerms}" />
 </OpenSearchDescription>
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index fe6c0b2b..2dcdd9c 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -3126,6 +3126,8 @@
 
   if (!web::GetWebClient()->IsSlimNavigationManagerEnabled()) {
     self.navigationManagerImpl->CommitPendingItem();
+    web::NavigationItem* lastCommittedItem = navManager->GetLastCommittedItem();
+    [self setDocumentURL:lastCommittedItem->GetURL() context:navigationContext];
   }
 
   if (provisionalLoad) {
@@ -4913,7 +4915,9 @@
   if (context && !IsPlaceholderUrl(context->GetUrl())) {
     [self updateSSLStatusForCurrentNavigationItem];
     [self updateHTML5HistoryState];
-    [self setNavigationItemTitle:[_webView title]];
+    if (!context->IsLoadingErrorPage()) {
+      [self setNavigationItemTitle:[_webView title]];
+    }
   }
 
   // Report cases where SSL cert is missing for a secure connection.
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index c0eeb7de..c15e8b5 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -804,6 +804,46 @@
   EXPECT_EQ(kAbsolute, trust_level);
 }
 
+// Tests |currentURLWithTrustLevel:| method.
+TEST_P(CRWWebControllerTest, CurrentUrlWithFailProvisionalNavigation) {
+  GURL url("http://chromium.test");
+  AddPendingItem(url, ui::PAGE_TRANSITION_TYPED);
+
+  [[[mock_web_view_ stub] andReturnBool:NO] hasOnlySecureContent];
+  [static_cast<WKWebView*>([[mock_web_view_ stub] andReturn:@""]) title];
+  SetWebViewURL(@"http://chromium.test");
+
+  // Stub out the injection process.
+  [[mock_web_view_ stub] evaluateJavaScript:OCMOCK_ANY
+                          completionHandler:OCMOCK_ANY];
+
+  // Simulate a page load to trigger a URL update.
+  NSError* error = [NSError errorWithDomain:NSURLErrorDomain
+                                       code:NSURLErrorUnsupportedURL
+                                   userInfo:nil];
+  NSObject* navigation = [[NSObject alloc] init];
+  [navigation_delegate_ webView:mock_web_view_
+      didStartProvisionalNavigation:static_cast<WKNavigation*>(navigation)];
+
+  NSObject* placeholder = [[NSObject alloc] init];
+  [static_cast<WKWebView*>([[mock_web_view_ stub] andReturn:placeholder])
+      loadRequest:OCMOCK_ANY];
+  // When navigating back slim navigation will immediately commit, so skip
+  // didFailProvisionalNavigation.
+  if (!GetWebClient()->IsSlimNavigationManagerEnabled()) {
+    [navigation_delegate_ webView:mock_web_view_
+        didFailProvisionalNavigation:static_cast<WKNavigation*>(navigation)
+                           withError:error];
+  } else {
+    [mock_wk_list_ setCurrentURL:@"http://chromium.test"];
+    [navigation_delegate_ webView:mock_web_view_
+              didCommitNavigation:static_cast<WKNavigation*>(navigation)];
+  }
+
+  URLVerificationTrustLevel trust_level = kNone;
+  EXPECT_EQ(url, [web_controller() currentURLWithTrustLevel:&trust_level]);
+  EXPECT_EQ(kAbsolute, trust_level);
+}
 INSTANTIATE_TEST_CASES(CRWWebControllerResponseTest);
 
 // Test fixture to test decidePolicyForNavigationAction:decisionHandler:
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm
index 8308d198..5559ee9d 100644
--- a/ios/web/web_state/web_state_observer_inttest.mm
+++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -53,6 +53,8 @@
 
 const char kExpectedMimeType[] = "text/html";
 
+const char kFailedTitle[] = "failed_title";
+
 // WebStateObserverTest is parameterized on this enum to test both
 // LegacyNavigationManagerImpl and WKBasedNavigationManagerImpl.
 enum NavigationManagerChoice {
@@ -775,7 +777,14 @@
   EXPECT_CALL(observer_,
               PageLoaded(web_state(), PageLoadCompletionStatus::FAILURE));
   test::LoadUrl(web_state(), url);
-  ASSERT_TRUE(test::WaitForPageToFinishLoading(web_state()));
+
+  // Ensure that title is not overridden by a placeholder navigation.
+  web::NavigationManager* manager = web_state()->GetNavigationManager();
+  web::NavigationItem* item = manager->GetPendingItem();
+  item->SetTitle(base::UTF8ToUTF16(kFailedTitle));
+  ASSERT_TRUE(test::WaitForWebViewContainingText(
+      web_state(), "The network connection was lost."));
+  DCHECK_EQ(item->GetTitle(), base::UTF8ToUTF16(kFailedTitle));
 }
 
 // Tests failed navigation because URL scheme is not supported.
diff --git a/net/url_request/url_fetcher_response_writer.cc b/net/url_request/url_fetcher_response_writer.cc
index 27e91a3..4ea8caf 100644
--- a/net/url_request/url_fetcher_response_writer.cc
+++ b/net/url_request/url_fetcher_response_writer.cc
@@ -102,7 +102,7 @@
 int URLFetcherFileWriter::Write(IOBuffer* buffer,
                                 int num_bytes,
                                 CompletionOnceCallback callback) {
-  DCHECK(file_stream_);
+  DCHECK(file_stream_) << "Call Initialize() first.";
   DCHECK(owns_file_);
   DCHECK(!callback_);
 
diff --git a/net/url_request/url_fetcher_response_writer.h b/net/url_request/url_fetcher_response_writer.h
index 1076a3ee..1415ba6 100644
--- a/net/url_request/url_fetcher_response_writer.h
+++ b/net/url_request/url_fetcher_response_writer.h
@@ -32,14 +32,17 @@
  public:
   virtual ~URLFetcherResponseWriter() {}
 
-  // Initializes this instance. If ERR_IO_PENDING is returned, |callback| will
-  // be run later with the result. Calling this method again after a
-  // Initialize() success results in discarding already written data.
+  // Initializes this instance. Returns an error code defined in
+  // //net/base/net_errors.h. If ERR_IO_PENDING is returned, |callback| will be
+  // run later with the result. If anything else is returned, |callback| will
+  // *not* be called. Calling this method again after a Initialize() success
+  // results in discarding already written data.
   virtual int Initialize(CompletionOnceCallback callback) = 0;
 
   // Writes |num_bytes| bytes in |buffer|, and returns the number of bytes
-  // written or an error code. If ERR_IO_PENDING is returned, |callback| will be
-  // run later with the result.
+  // written or an error code defined in //net/base/net_errors.h. If
+  // ERR_IO_PENDING is returned, |callback| will be run later with the result.
+  // If anything else is returned, |callback| will *not* be called.
   virtual int Write(IOBuffer* buffer,
                     int num_bytes,
                     CompletionOnceCallback callback) = 0;
@@ -49,8 +52,10 @@
   // errors (|net_error| not OK), this method may be called before the previous
   // operation completed. In this case, URLFetcherResponseWriter may skip
   // graceful shutdown and completion of the pending operation. After such a
-  // failure, the URLFetcherResponseWriter may be reused. If ERR_IO_PENDING is
-  // returned, |callback| will be run later with the result.
+  // failure, the URLFetcherResponseWriter may be reused. Returns an error code
+  // defined in //net/base/net_errors.h. If ERR_IO_PENDING is returned,
+  // |callback| will be run later with the result. If anything else is returned,
+  // |callback| will *not* be called.
   virtual int Finish(int net_error, CompletionOnceCallback callback) = 0;
 
   // Returns this instance's pointer as URLFetcherStringWriter when possible.
@@ -86,7 +91,9 @@
 class NET_EXPORT URLFetcherFileWriter : public URLFetcherResponseWriter {
  public:
   // |file_path| is used as the destination path. If |file_path| is empty,
-  // Initialize() will create a temporary file.
+  // Initialize() will create a temporary file. The destination file is deleted
+  // when a URLFetcherFileWriter instance is destructed unless DisownFile() is
+  // called.
   URLFetcherFileWriter(
       scoped_refptr<base::SequencedTaskRunner> file_task_runner,
       const base::FilePath& file_path);
diff --git a/remoting/protocol/webrtc_dummy_video_encoder.cc b/remoting/protocol/webrtc_dummy_video_encoder.cc
index ee31185..13356d21 100644
--- a/remoting/protocol/webrtc_dummy_video_encoder.cc
+++ b/remoting/protocol/webrtc_dummy_video_encoder.cc
@@ -115,15 +115,6 @@
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
-int32_t WebrtcDummyVideoEncoder::SetChannelParameters(uint32_t packet_loss,
-                                                      int64_t rtt) {
-  main_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&VideoChannelStateObserver::OnChannelParameters,
-                            video_channel_state_observer_, packet_loss,
-                            base::TimeDelta::FromMilliseconds(rtt)));
-  return WEBRTC_VIDEO_CODEC_OK;
-}
-
 int32_t WebrtcDummyVideoEncoder::SetRates(uint32_t bitrate,
                                           uint32_t framerate) {
   main_task_runner_->PostTask(
diff --git a/remoting/protocol/webrtc_dummy_video_encoder.h b/remoting/protocol/webrtc_dummy_video_encoder.h
index 8dffd63..75b5a0f 100644
--- a/remoting/protocol/webrtc_dummy_video_encoder.h
+++ b/remoting/protocol/webrtc_dummy_video_encoder.h
@@ -50,7 +50,6 @@
   int32_t Encode(const webrtc::VideoFrame& frame,
                  const webrtc::CodecSpecificInfo* codec_specific_info,
                  const std::vector<webrtc::FrameType>* frame_types) override;
-  int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override;
   int32_t SetRates(uint32_t bitrate, uint32_t framerate) override;
 
   webrtc::EncodedImageCallback::Result SendEncodedFrame(
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index b80b0c394..08e9d93 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -59,10 +59,10 @@
 crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ]
 crbug.com/728378 compositing/culling/tile-occlusion-boundaries.html [ Failure ]
 crbug.com/864398 compositing/iframes/floating-self-painting-frame.html [ Failure ]
-crbug.com/591099 compositing/masks/mask-with-removed-filters.html [ Failure ]
+crbug.com/591099 compositing/masks/mask-with-removed-filters.html [ Failure Pass ]
 crbug.com/591099 compositing/video-frame-size-change.html [ Pass ]
 crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ]
-crbug.com/591099 editing/selection/drag-in-iframe.html [ Failure Pass ]
+crbug.com/591099 editing/selection/drag-in-iframe.html [ Failure ]
 crbug.com/591099 editing/selection/paint-hyphen.html [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/floats/float-nowrap-3.html [ Pass ]
@@ -93,7 +93,7 @@
 crbug.com/40634 external/wpt/css/css-text/white-space/trailing-space-before-br-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ]
-crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Pass ]
+crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-transitions/properties-value-implicit-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-ui/text-overflow-010.html [ Pass ]
 crbug.com/893550 external/wpt/css/css-ui/text-overflow-015.html [ Failure ]
@@ -235,7 +235,7 @@
 crbug.com/591099 external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ]
 crbug.com/591099 external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ]
 crbug.com/591099 external/wpt/fetch/http-cache/basic-auth-cache-test.html [ Timeout ]
-crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ]
+crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ]
 crbug.com/591099 external/wpt/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html [ Timeout ]
 crbug.com/591099 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Pass ]
 crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_parent [ Timeout ]
@@ -246,7 +246,7 @@
 crbug.com/591099 external/wpt/picture-in-picture/leave-picture-in-picture.html [ Pass ]
 crbug.com/591099 external/wpt/picture-in-picture/picture-in-picture-window.html [ Pass ]
 crbug.com/591099 external/wpt/picture-in-picture/request-picture-in-picture-twice.html [ Pass ]
-crbug.com/591099 external/wpt/requestidlecallback/callback-iframe.html [ Pass ]
+crbug.com/591099 external/wpt/requestidlecallback/callback-iframe.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Pass ]
 crbug.com/591099 external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass ]
 crbug.com/591099 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Pass ]
@@ -258,8 +258,8 @@
 crbug.com/591099 fast/block/positioning/positioned-child-inside-relative-positioned-anonymous-block.html [ Failure ]
 crbug.com/591099 fast/borders/bidi-002.html [ Failure ]
 crbug.com/859497 fast/borders/bidi-009a.html [ Failure ]
-crbug.com/591099 fast/borders/border-radius-mask-canvas-border.html [ Failure ]
-crbug.com/591099 fast/borders/border-radius-mask-canvas-with-mask.html [ Failure ]
+crbug.com/591099 fast/borders/border-radius-mask-canvas-border.html [ Failure Pass ]
+crbug.com/591099 fast/borders/border-radius-mask-canvas-with-mask.html [ Failure Pass ]
 crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Pass ]
 crbug.com/807708 fast/css-intrinsic-dimensions/width-avoid-floats.html [ Failure ]
@@ -267,6 +267,8 @@
 crbug.com/835484 fast/css/focus-ring-recursive-continuations.html [ Failure ]
 crbug.com/835484 fast/css/outline-narrowLine.html [ Failure ]
 crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under.html [ Failure ]
+crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
+crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-list-translate.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ]
 crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
@@ -287,6 +289,7 @@
 crbug.com/591099 fast/text/descent-clip-in-scaled-page.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-in-relative-inline-right.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-in-relative-inline.html [ Failure ]
+crbug.com/899902 fast/text/ellipsis-with-self-painting-layer.html [ Pass ]
 crbug.com/796943 fast/text/international/shape-across-elements-simple.html [ Pass ]
 crbug.com/591099 fast/text/whitespace/018.html [ Failure ]
 crbug.com/591099 fast/writing-mode/auto-sizing-orthogonal-flows.html [ Failure ]
@@ -305,7 +308,7 @@
 crbug.com/591099 http/tests/devtools/network/network-datareceived.js [ Failure ]
 crbug.com/591099 http/tests/devtools/network/network-datasaver-warning.js [ Failure ]
 crbug.com/591099 http/tests/devtools/service-workers/service-worker-v8-cache.js [ Pass ]
-crbug.com/591099 http/tests/images/feature-policy-unoptimized-images-cached-image.html [ Failure ]
+crbug.com/591099 http/tests/images/feature-policy-unoptimized-images-cached-image.html [ Failure Pass ]
 crbug.com/591099 http/tests/images/restyle-decode-error.html [ Failure ]
 crbug.com/591099 http/tests/intersection-observer/v2/cross-origin-effects.html [ Failure ]
 crbug.com/591099 http/tests/intersection-observer/v2/cross-origin-occlusion.html [ Failure ]
@@ -320,17 +323,17 @@
 crbug.com/714962 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ]
 crbug.com/591099 inspector-protocol/timeline/page-frames.js [ Failure ]
 crbug.com/591099 intersection-observer/v2/text-shadow.html [ Failure ]
-crbug.com/591099 media/controls-after-reload.html [ Failure ]
-crbug.com/591099 media/controls-strict.html [ Failure ]
-crbug.com/591099 media/controls-styling-strict.html [ Failure ]
-crbug.com/591099 media/controls-styling.html [ Failure ]
-crbug.com/591099 media/controls-without-preload.html [ Failure ]
+crbug.com/591099 media/controls-after-reload.html [ Failure Pass ]
+crbug.com/591099 media/controls-strict.html [ Failure Pass ]
+crbug.com/591099 media/controls-styling-strict.html [ Failure Pass ]
+crbug.com/591099 media/controls-styling.html [ Failure Pass ]
+crbug.com/591099 media/controls-without-preload.html [ Failure Pass ]
 crbug.com/591099 media/controls/lazy-loaded-style.html [ Failure ]
-crbug.com/591099 media/controls/paint-controls-webkit-appearance-none-custom-bg.html [ Failure ]
-crbug.com/591099 media/controls/paint-controls-webkit-appearance-none.html [ Failure ]
-crbug.com/591099 media/video-controls-rendering.html [ Failure ]
-crbug.com/591099 media/video-display-toggle.html [ Failure ]
-crbug.com/591099 media/video-no-audio.html [ Failure ]
+crbug.com/591099 media/controls/paint-controls-webkit-appearance-none-custom-bg.html [ Failure Pass ]
+crbug.com/591099 media/controls/paint-controls-webkit-appearance-none.html [ Failure Pass ]
+crbug.com/591099 media/video-controls-rendering.html [ Failure Pass ]
+crbug.com/591099 media/video-display-toggle.html [ Failure Pass ]
+crbug.com/591099 media/video-no-audio.html [ Failure Pass ]
 crbug.com/591099 paint/float/float-under-inline-self-painting-change.html [ Failure ]
 crbug.com/835484 paint/inline/focus-ring-under-absolute-with-relative-continuation.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/clip-with-layout-delta.html [ Failure ]
@@ -356,14 +359,13 @@
 crbug.com/714962 paint/invalidation/position/relative-positioned-movement-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/position/relayout-fixed-position-after-scale.html [ Failure ]
 crbug.com/591099 paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html [ Failure ]
-crbug.com/591099 paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint.html [ Pass ]
 crbug.com/591099 paint/invalidation/svg/svg-background-partial-redraw.html [ Failure ]
 crbug.com/591099 paint/invalidation/svg/transform-focus-ring-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-extra-bottom-grow.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-two-pass-layout-overpaint.html [ Failure ]
 crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ]
 crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ]
-crbug.com/591099 rootscroller/rootscroller-during-fullscreen.html [ Pass Timeout ]
+crbug.com/591099 rootscroller/rootscroller-during-fullscreen.html [ Failure Pass Timeout ]
 crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ]
 crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Pass ]
 crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ]
@@ -378,8 +380,7 @@
 crbug.com/591099 tables/mozilla/bugs/bug2973.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug55527.html [ Failure ]
-crbug.com/591099 transforms/3d/general/perspective-units.html [ Pass ]
-crbug.com/591099 virtual/android/fullscreen/video-controls-timeline.html [ Failure ]
+crbug.com/591099 virtual/android/fullscreen/video-controls-timeline.html [ Failure Pass ]
 crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document-iframe.html [ Failure Pass ]
 crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Failure Pass ]
 crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ]
@@ -397,10 +398,14 @@
 crbug.com/591099 virtual/layout_ng/ [ Skip ]
 crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ]
 crbug.com/591099 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass ]
+crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
 crbug.com/591099 virtual/new-remote-playback-pipeline/ [ Skip ]
+crbug.com/591099 virtual/off-main-thread-worker-script-fetch/external/wpt/workers/constructors/Worker/AbstractWorker.onerror.html [ Pass ]
+crbug.com/591099 virtual/off-main-thread-worker-script-fetch/external/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html [ Pass ]
+crbug.com/591099 virtual/off-main-thread-worker-script-fetch/external/wpt/workers/semantics/multiple-workers/003.html [ Pass ]
 crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/redirect/redirect-count.any.html [ Pass ]
 crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ]
 crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ]
@@ -425,6 +430,7 @@
 crbug.com/591099 virtual/stable/ [ Skip ]
 crbug.com/591099 virtual/threaded/ [ Skip ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/mouse-cursor.html [ Failure ]
+crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/gesture/touch-gesture-scroll-input-field.html [ Pass ]
 crbug.com/591099 virtual/video-surface-layer/media/stable/video-object-fit-stable.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 940b0b1..4e5c291 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -543,6 +543,7 @@
 crbug.com/855279 fast/css/text-overflow-ellipsis-vertical-hittest.html [ Failure ]
 crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Failure ]
+crbug.com/899902 fast/text/ellipsis-with-self-painting-layer.html [ Failure ]
 crbug.com/796943 fast/text/international/shape-across-elements-simple.html [ Failure ]
 crbug.com/877946 external/wpt/css/CSS2/linebox/anonymous-inline-inherit-001.html [ Failure ]
 crbug.com/859233 external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html [ Failure ]
@@ -1823,6 +1824,9 @@
 crbug.com/867834 virtual/outofblink-cors/http/tests/security/isolatedWorld/cross-origin-xhr.html [ Crash ]
 
 # Timeout tests in dictionary order.
+# Using Skip because this is listed as a Slow test, so if Timeout is used it
+# will waste 30 or 90 seconds per run.
+crbug.com/870173 [ Mac ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/clients-matchall-order.https.html [ Skip ]
 
 # Failing tests in dictionary order.
 crbug.com/870173 virtual/outofblink-cors/http/tests/security/img-redirect-to-crossorigin-credentials.html [ Failure ]
@@ -2264,8 +2268,8 @@
 
 crbug.com/613887 http/tests/preload/meta-viewport-link-headers.html [ Failure Pass ]
 
-crbug.com/306222 fast/hidpi/image-srcset-relative-svg-canvas.html [ Skip ]
-crbug.com/306222 fast/hidpi/image-srcset-relative-svg-canvas-2x.html [ Skip ]
+crbug.com/306222 fast/hidpi/image-srcset-relative-svg-canvas.html [ Failure Pass ]
+crbug.com/306222 fast/hidpi/image-srcset-relative-svg-canvas-2x.html [ Failure Pass ]
 
 crbug.com/467477 fast/multicol/vertical-rl/nested-columns.html [ Failure ]
 
@@ -3063,7 +3067,6 @@
 crbug.com/626703 external/wpt/clear-site-data/executionContexts.sub.html [ Timeout ]
 crbug.com/626703 [ Win10 ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-column-row-gap-004.html [ Failure ]
 crbug.com/626703 [ Linux Mac Win7 ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-column-row-gap-004.html [ Failure ]
-crbug.com/626703 [ Mac10.12 Mac10.13 ] external/wpt/service-workers/service-worker/clients-matchall-order.https.html [ Timeout ]
 crbug.com/626703 [ Win7 ] external/wpt/css/css-lists/content-property/marker-text-matches-armenian.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/css-lists/content-property/marker-text-matches-upper-latin.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-lists/content-property/marker-text-matches-disc.html [ Failure ]
@@ -5325,10 +5328,10 @@
 crbug.com/893869 [ Linux Mac ] css3/masking/mask-repeat-space-padding.html [ Failure Pass ]
 
 # Sheriff 2018-10-12
-crbug.com/891155 [ Linux ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-drag.html [ Failure Pass ]
-crbug.com/891155 [ Linux ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-event-fired.html [ Failure Pass ]
-crbug.com/891155 [ Linux ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-drag.html [ Failure Pass ]
-crbug.com/891155 [ Linux ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-event-fired.html [ Failure Pass ]
+crbug.com/891155 [ Linux Win ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-drag.html [ Failure Pass ]
+crbug.com/891155 [ Linux Win ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-event-fired.html [ Failure Pass ]
+crbug.com/891155 [ Linux Win ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-drag.html [ Failure Pass ]
+crbug.com/891155 [ Linux Win ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-event-fired.html [ Failure Pass ]
 
 # Sheriff 2018-10-15
 crbug.com/895257 [ Mac ] external/wpt/css/css-fonts/variations/at-font-face-font-matching.html [ Failure Pass ]
@@ -5394,3 +5397,9 @@
 crbug.com/901317 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-registration-with-type.https.html [ Failure Pass ]
 crbug.com/901317 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-registration-with-type.https.html [ Failure Pass ]
 crbug.com/901317 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/update-registration-with-type.https.html [ Failure Pass ]
+
+#Sheriff 2018-11-06
+crbug.com/902632 [ Win Debug ] fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html [ Crash Pass ]
+crbug.com/902645 [ Retina ] transforms/3d/point-mapping/3d-point-mapping-3.html [ Failure Pass ]
+crbug.com/902645 [ Retina ] transforms/3d/point-mapping/3d-point-mapping-origins.html [ Failure Pass ]
+
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
index beddc1e..54b6fd2 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -178557,6 +178557,16 @@
      {}
     ]
    ],
+   "trusted-types/block-string-assignment-to-Element-outerHTML.tentative-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "trusted-types/block-string-assignment-to-HTMLElement-generic.tentative-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "trusted-types/support/helper.sub.js": [
     [
      {}
@@ -196760,27 +196770,27 @@
      {}
     ]
    ],
-   "content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html": [
+   "content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.sub.html": [
     [
-     "/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html",
+     "/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.sub.html",
      {}
     ]
    ],
-   "content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html": [
+   "content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.sub.html": [
     [
-     "/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html",
+     "/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.sub.html",
      {}
     ]
    ],
-   "content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html": [
+   "content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.sub.html": [
     [
-     "/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html",
+     "/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.sub.html",
      {}
     ]
    ],
-   "content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html": [
+   "content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.sub.html": [
     [
-     "/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html",
+     "/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.sub.html",
      {}
     ]
    ],
@@ -196940,9 +196950,9 @@
      {}
     ]
    ],
-   "content-security-policy/navigate-to/spv-only-sent-to-initiator.html": [
+   "content-security-policy/navigate-to/spv-only-sent-to-initiator.sub.html": [
     [
-     "/content-security-policy/navigate-to/spv-only-sent-to-initiator.html",
+     "/content-security-policy/navigate-to/spv-only-sent-to-initiator.sub.html",
      {}
     ]
    ],
@@ -267566,6 +267576,12 @@
      {}
     ]
    ],
+   "trusted-types/TrustedTypePolicyFactory-createPolicy-defaultTests.tentative.html": [
+    [
+     "/trusted-types/TrustedTypePolicyFactory-createPolicy-defaultTests.tentative.html",
+     {}
+    ]
+   ],
    "trusted-types/TrustedTypePolicyFactory-createPolicy-exposedTests.tentative.html": [
     [
      "/trusted-types/TrustedTypePolicyFactory-createPolicy-exposedTests.tentative.html",
@@ -293272,7 +293288,7 @@
    "testharness"
   ],
   "audio-output/META.yml": [
-   "ea6b29e42f38abeaa5eff6ed6c2fad18eed4e536",
+   "b6a7d4d06259117af8fb843f6a8d252bac01a8f3",
    "support"
   ],
   "audio-output/OWNERS": [
@@ -295951,20 +295967,20 @@
    "9cb770bcc1be7928b6dad61b29bf6f55c22eda0d",
    "support"
   ],
-  "content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html": [
-   "458373fbc01591c25a901379282a5370989b5084",
+  "content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.sub.html": [
+   "f58407ac6de2174b1d028d9a3ae7e793f4724c00",
    "testharness"
   ],
-  "content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html": [
-   "3ed4815bff6c363661ab94bdc1796067870aadab",
+  "content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.sub.html": [
+   "0ddc8820f94c70b6606970832eb90d089a0e8a10",
    "testharness"
   ],
-  "content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html": [
-   "f3f7896e932aafa137cf11b76c38246a101f4a00",
+  "content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.sub.html": [
+   "927ebb4d3619f8fb131600b89f00a19afd706116",
    "testharness"
   ],
-  "content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html": [
-   "08e0cbe3fb9b39f8b4945b422c5e459a2f862fb9",
+  "content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.sub.html": [
+   "56688fa418baad02bdb5b19008fdb865f6d6f6f6",
    "testharness"
   ],
   "content-security-policy/navigate-to/form-allowed.html": [
@@ -296079,7 +296095,7 @@
    "6784a56c8eb5e84d9434676d2c335173c7de1970",
    "support"
   ],
-  "content-security-policy/navigate-to/spv-only-sent-to-initiator.html": [
+  "content-security-policy/navigate-to/spv-only-sent-to-initiator.sub.html": [
    "a09057e71567efa082578541a624b9fe51e13737",
    "testharness"
   ],
@@ -402908,7 +402924,7 @@
    "testharness"
   ],
   "mediacapture-streams/META.yml": [
-   "9e8b0f46f9b02b3ab1ddb8786eb156d1afafd4ba",
+   "1ed650e97c451ef1266fd8435e2260d6bf617b67",
    "support"
   ],
   "mediacapture-streams/MediaDevices-IDL-all-expected.txt": [
@@ -413440,7 +413456,7 @@
    "testharness"
   ],
   "payment-request/payment-request-constructor.https.html": [
-   "b5997a0c9be55e2b3b135a4471aa2abc5e7440af",
+   "99c25d1723459bef569ca9e62ec29e0c889534f6",
    "testharness"
   ],
   "payment-request/payment-request-ctor-currency-code-checks.https.html": [
@@ -414500,7 +414516,7 @@
    "testharness"
   ],
   "presentation-api/controlling-ua/reconnectToMultiplePresentations_success-manual.https.html": [
-   "211e8a01058cdc4c1e4756edcd21cb6369875f25",
+   "ab1bd8089d191cd2971ae5b6b2f2c95b7c62c26d",
    "manual"
   ],
   "presentation-api/controlling-ua/reconnectToPresentation_notfound_error-manual.https.html": [
@@ -423552,7 +423568,7 @@
    "support"
   ],
   "screen-capture/META.yml": [
-   "6e5b23cd9672274d43c8d8bebe9bed66f7e651ee",
+   "47882d3275f1cc928555045b2def8fc90f6bcdb0",
    "support"
   ],
   "screen-capture/OWNERS": [
@@ -430851,6 +430867,10 @@
    "9daf20ec1869919603965942fa6a4c99925ac8e9",
    "testharness"
   ],
+  "trusted-types/TrustedTypePolicyFactory-createPolicy-defaultTests.tentative.html": [
+   "a6dd2d1317aa4df94e693e1ad7d0d0684ea0bbc2",
+   "testharness"
+  ],
   "trusted-types/TrustedTypePolicyFactory-createPolicy-exposedTests.tentative.html": [
    "af6e04941c3b6206602bc7f547a3b0c9ef555a11",
    "testharness"
@@ -430864,7 +430884,7 @@
    "testharness"
   ],
   "trusted-types/Window-TrustedTypes.tentative.html": [
-   "8e20e492e6a8484e386d1a08f854bd9b162bd6be",
+   "5bbb4356c21d249a21c8204aad6c9ba7a353cb4e",
    "testharness"
   ],
   "trusted-types/Window-open.tentative.html": [
@@ -430872,55 +430892,63 @@
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-DOMParser-parseFromString.tentative.html": [
-   "ec19ebc8db8a727db8f28a69dd82cab15a5d7af9",
+   "4446a58836695355efd0fbf3f9f5a0bd6c60c8a3",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.tentative.html": [
-   "99e187d45be6cb649e388995a2f775d5bbe6bcf4",
+   "2554ce635607ba06df3d975a0437b0862a30d799",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Document-write.tentative.html": [
-   "5e7039705a82886f369bb7c454b8ed08be25b2d6",
+   "0d9ff61c9b305e193f96cebe18810d597aa75158",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Element-insertAdjacentHTML.tentative.html": [
-   "4eee887a0053c3469d53d0e41ad89739502ca1a0",
+   "ae1ace69bf85853d0f1c3db333e4507ac1896073",
    "testharness"
   ],
+  "trusted-types/block-string-assignment-to-Element-outerHTML.tentative-expected.txt": [
+   "b30ab101c4c8950fcfb2375cd8c83ee575a4f61c",
+   "support"
+  ],
   "trusted-types/block-string-assignment-to-Element-outerHTML.tentative.html": [
-   "fde0c172f52cb27837077f8eddbd42d215b24956",
+   "945e3dd2a79b026ad35f379deece04c19eb89d8c",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Element-setAttribute.tentative.html": [
-   "26aaa5123e756219d3a47f07f2e5228ac1101407",
+   "646997de472ec98491d2d17fc65aeb77c999c03b",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Element-setAttributeNS.tentative.html": [
    "3ad27e219e998145610d79769a784034aef94aff",
    "testharness"
   ],
+  "trusted-types/block-string-assignment-to-HTMLElement-generic.tentative-expected.txt": [
+   "224d66f4cacf827eb36cd252603c2f6d3dee56e1",
+   "support"
+  ],
   "trusted-types/block-string-assignment-to-HTMLElement-generic.tentative.html": [
-   "ceac828d7bdea09bcf79b90c0a623e7d0c4f9735",
+   "2a7edab9db4aec7daa7c4e46769392f25676b07b",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Location-assign.tentative.html": [
-   "c0817d669a189d1b01859e1d821712b115297b0f",
+   "4ad4af9df5ae86b0bc2ab82d3b5ae062b88d70f6",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Location-href.tentative.html": [
-   "2a29e1e233ec16a747c279f0b319732868a6775a",
+   "fd0a4e5ea0e53c5b85f0bfb6d092c4cd63ceb790",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Location-replace.tentative.html": [
-   "8e534bf83827151cbeccfcc147f933e26fa0aefa",
+   "9b8cabe58359e664e1ad9d8c43f604f88c7b3784",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Range-createContextualFragment.tentative.html": [
-   "f44266a3074ee040e6a3e1b16868aa2bef44d110",
+   "4919b7fd4de8dcbe66daa87fdd1285dd96d4580d",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Window-open.tentative.html": [
-   "7b917dbf642302e0d21e5a688850d8f822f0c318",
+   "fd30b6edfbaf40c09cabe98d1bd8891446b16e65",
    "testharness"
   ],
   "trusted-types/idlharness.window.js": [
@@ -430928,7 +430956,7 @@
    "testharness"
   ],
   "trusted-types/support/helper.sub.js": [
-   "75874e5b3c2ed90f0ebfbfca2da701d027d2d832",
+   "9ad605975555df539e6444d3b8935197c7925aef",
    "support"
   ],
   "uievents/META.yml": [
@@ -434924,7 +434952,7 @@
    "support"
   ],
   "webrtc-identity/META.yml": [
-   "900769b9d4334bb38d6413beea6a28235d8c927c",
+   "940144cee1da5f2f0f2bdd27a8dfc8f5bfcc6a1d",
    "support"
   ],
   "webrtc-identity/RTCPeerConnection-constructor-expected.txt": [
@@ -434956,7 +434984,7 @@
    "support"
   ],
   "webrtc-stats/META.yml": [
-   "489264f23d6e8c096652620e6e7732a94644353f",
+   "10bcf856eb9258e0845f2fdcb6e08c43ebcdf78a",
    "support"
   ],
   "webrtc-stats/README.md": [
@@ -434972,7 +435000,7 @@
    "testharness"
   ],
   "webrtc/META.yml": [
-   "ea2846e97af01817f06343322efab3d941060f4c",
+   "2025a11f3810042bcef24acae751ce5ffd3a3ee8",
    "support"
   ],
   "webrtc/OWNERS": [
@@ -435684,7 +435712,7 @@
    "support"
   ],
   "webrtc/simplecall-no-ssrcs.https.html": [
-   "266b57663781115154f1ad8ddd2dd69143bc44b9",
+   "877791052824d9d5bf6b9718a4f4adc1d98c8742",
    "testharness"
   ],
   "webrtc/simplecall.https.html": [
@@ -441128,7 +441156,7 @@
    "testharness"
   ],
   "workers/modules/dedicated-worker-import-failure.html": [
-   "81d93322c77dd0d223ade30fed5c6b43ab8f05e0",
+   "439bea888b2bac65f5de50d47c12639fd49168a4",
    "testharness"
   ],
   "workers/modules/dedicated-worker-import-meta-expected.txt": [
@@ -441248,7 +441276,7 @@
    "support"
   ],
   "workers/modules/resources/new-worker-window.html": [
-   "5ae150725eb973ce1c2c7b54eb45669e057e8875",
+   "a7bd2eedef6ab6d639f28e063ccd50aefbbb0528",
    "support"
   ],
   "workers/modules/resources/post-message-on-load-worker.js": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/audio-output/META.yml b/third_party/WebKit/LayoutTests/external/wpt/audio-output/META.yml
index ea6b29e..b6a7d4d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/audio-output/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/audio-output/META.yml
@@ -1,3 +1,4 @@
 spec: https://w3c.github.io/mediacapture-output/
 suggested_reviewers:
   - guidou
+  - jan-ivar
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.sub.html
similarity index 89%
rename from third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html
rename to third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.sub.html
index 458373f..f58407a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.sub.html
@@ -12,5 +12,5 @@
     assert_equals(e.data.result, 'success');
   });
 </script>
-<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27%3B%20form-action%20%27self%27%3B&action=post_message_to_frame_owner.html&report_id=dummy">
+<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27%3B%20form-action%20%27self%27%3B&action=post_message_to_frame_owner.html&report_id={{uuid()}}">
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.sub.html
similarity index 89%
rename from third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html
rename to third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.sub.html
index 3ed4815..0ddc882 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.sub.html
@@ -12,5 +12,5 @@
     assert_equals(e.data.result, 'success');
   });
 </script>
-<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27%3B%20form-action%20%27self%27%3B&action=post_message_to_frame_owner.html&report_id=dummy">
+<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27%3B%20form-action%20%27self%27%3B&action=post_message_to_frame_owner.html&report_id={{uuid()}}">
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.sub.html
similarity index 90%
rename from third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html
rename to third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.sub.html
index f3f7896e..927ebb4d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.sub.html
@@ -13,5 +13,5 @@
     assert_equals(e.data.violatedDirective, 'form-action');
   });
 </script>
-<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27%3B%20form-action%20%27none%27%3B&action=post_message_to_frame_owner.html&report_id=dummy">
-</body>
\ No newline at end of file
+<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27%3B%20form-action%20%27none%27%3B&action=post_message_to_frame_owner.html&report_id={{uuid()}}"">
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.sub.html
similarity index 90%
rename from third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html
rename to third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.sub.html
index 08e0cbe..56688fa 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.sub.html
@@ -13,5 +13,5 @@
     assert_equals(e.data.violatedDirective, 'form-action');
   });
 </script>
-<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27%3B%20form-action%20%27none%27%3B&action=post_message_to_frame_owner.html&report_id=dummy">
+<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27%3B%20form-action%20%27none%27%3B&action=post_message_to_frame_owner.html&report_id={{uuid()}}">
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/spv-only-sent-to-initiator.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/spv-only-sent-to-initiator.sub.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/spv-only-sent-to-initiator.html
rename to third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/spv-only-sent-to-initiator.sub.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/META.yml b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/META.yml
index 9e8b0f4..1ed650e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/META.yml
@@ -5,3 +5,4 @@
   - dontcallmedom
   - eric-carlson
   - youennf
+  - jan-ivar
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-constructor.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-constructor.https.html
index b5997a0..99c25d17 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-constructor.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-constructor.https.html
@@ -283,9 +283,6 @@
       [
         {
           supportedMethods: "https://wpt.fyi/payment-request",
-          data: {
-            supportedTypes: ["debit"],
-          },
         },
       ],
       {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/reconnectToMultiplePresentations_success-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/reconnectToMultiplePresentations_success-manual.https.html
index 211e8a0..ab1bd80 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/reconnectToMultiplePresentations_success-manual.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/reconnectToMultiplePresentations_success-manual.https.html
@@ -94,13 +94,31 @@
     await eventWatcher2.wait_for('close');
     assert_equals(connection2.state, 'closed', 'The presentation connection is successfully closed.');
 
-    const c1 = await request1.reconnect(connection1.id);
-    assert_equals(c1, connection1, 'The promise is resolved with the existing presentation connection.');
+    const c11 = await request1.reconnect(connection1.id);
+    assert_equals(c11, connection1, 'The promise is resolved with the existing presentation connection.');
+
+    const c22 = await request2.reconnect(connection2.id);
+    assert_equals(c22, connection2, 'The promise is resolved with the existing presentation connection.');
+
+    await Promise.all([
+      eventWatcher1.wait_for('connect'),
+      eventWatcher2.wait_for('connect')
+    ]);
+
+    assert_equals(connection1.state, 'connected', 'The presentation connection is successfully reconnected.');
+    assert_equals(connection2.state, 'connected', 'The presentation connection is successfully reconnected.');
 
     // Reconnecting a presentation via a different presentation request with the same presentation
     // URLs will succeed
-    const c2 = await request1.reconnect(connection2.id);
-    assert_equals(c2, connection2, 'The promise is resolved with the existing presentation connection.');
+    connection2.close();
+    await eventWatcher2.wait_for('close');
+    const c12 = await request1.reconnect(connection2.id);
+    assert_equals(c12, connection2, 'The promise is resolved with the existing presentation connection.');
+
+    connection1.close();
+    await eventWatcher1.wait_for('close');
+    const c21 = await request2.reconnect(connection1.id);
+    assert_equals(c21, connection1, 'The promise is resolved with the existing presentation connection.');
 
     await Promise.all([
       eventWatcher1.wait_for('connect'),
diff --git a/third_party/WebKit/LayoutTests/external/wpt/quirks/reference/vertical-align-in-quirks-ref.html b/third_party/WebKit/LayoutTests/external/wpt/quirks/reference/vertical-align-in-quirks-ref.html
new file mode 100644
index 0000000..2395923
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/quirks/reference/vertical-align-in-quirks-ref.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<style>
+div {
+  font-size: 10px;
+  line-height: 50px;
+  border: 1px solid blue;
+}
+img {
+  width: 1em;
+  height: 2em;
+  background: orange;
+  border: 1px solid black;
+}
+.text-top {
+  vertical-align: text-top;
+}
+.text-bottom {
+  vertical-align: text-bottom;
+}
+.top {
+  vertical-align: top;
+}
+.bottom {
+  vertical-align: bottom;
+}
+</style>
+<body>
+  <div>
+    <img class="text-top" src="../../css/support/60x60-red.png">Y
+  </div>
+  <div>
+    <img class="text-bottom" src="../../css/support/60x60-red.png">Y
+  </div>
+  <div>
+    <img class="top" src="../../css/support/60x60-red.png">Y
+  </div>
+  <div>
+    <img class="bottom" src="../../css/support/60x60-red.png">Y
+  </div>
+  <div>
+    <img class="text-top" src="../../css/support/60x60-red.png"><span>Y</span>
+  </div>
+  <div>
+    <img class="text-bottom" src="../../css/support/60x60-red.png"><span>Y</span>
+  </div>
+  <div>
+    <img class="top" src="../../css/support/60x60-red.png"><span>Y</span>
+  </div>
+  <div>
+    <img class="bottom" src="../../css/support/60x60-red.png"><span>Y</span>
+  </div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/quirks/vertical-align-in-quirks.html b/third_party/WebKit/LayoutTests/external/wpt/quirks/vertical-align-in-quirks.html
new file mode 100644
index 0000000..1826d01
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/quirks/vertical-align-in-quirks.html
@@ -0,0 +1,56 @@
+<meta charset="utf-8">
+<title>CSS Text level 3 Test: letter spacing after bidi</title>
+<link rel="author" href="kojii@chromium.org">
+<link rel="match" href="reference/vertical-align-in-quirks-ref.html">
+<meta name="assert" content="Tests some vertical-align values match in quirks and standard modes.">
+<style>
+div {
+  font-size: 10px;
+  line-height: 50px;
+  border: 1px solid blue;
+}
+img {
+  width: 1em;
+  height: 2em;
+  background: orange;
+  border: 1px solid black;
+}
+.text-top {
+  vertical-align: text-top;
+}
+.text-bottom {
+  vertical-align: text-bottom;
+}
+.top {
+  vertical-align: top;
+}
+.bottom {
+  vertical-align: bottom;
+}
+</style>
+<body>
+  <div>
+    <img class="text-top" src="../css/support/60x60-red.png">Y
+  </div>
+  <div>
+    <img class="text-bottom" src="../css/support/60x60-red.png">Y
+  </div>
+  <div>
+    <img class="top" src="../css/support/60x60-red.png">Y
+  </div>
+  <div>
+    <img class="bottom" src="../css/support/60x60-red.png">Y
+  </div>
+  <div>
+    <img class="text-top" src="../css/support/60x60-red.png"><span>Y</span>
+  </div>
+  <div>
+    <img class="text-bottom" src="../css/support/60x60-red.png"><span>Y</span>
+  </div>
+  <div>
+    <img class="top" src="../css/support/60x60-red.png"><span>Y</span>
+  </div>
+  <div>
+    <img class="bottom" src="../css/support/60x60-red.png"><span>Y</span>
+  </div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/META.yml b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/META.yml
index 6e5b23c..47882d3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/META.yml
@@ -3,3 +3,4 @@
   - alvestrand
   - martinthomson
   - uysalere
+  - jan-ivar
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-include-uncontrolled.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-include-uncontrolled.https.html
index d3b5a96..9f34e570 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-include-uncontrolled.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-include-uncontrolled.https.html
@@ -4,46 +4,13 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
-const base_url = 'resources/blank.html'; // This is out-of-scope.
-const scope = base_url + '?clients-matchAll-includeUncontrolled';
-let frames = [];
-
-// Creates 3 iframes, 2 for in-scope and 1 for out-of-scope. Returns the frame
-// opened for scope + '#2'.
-async function create_iframes(scope) {
-  frames.push(await with_iframe(base_url));
-  frames.push(await with_iframe(scope + '#1'));
-  frames.push(await with_iframe(scope + '#2'));
-  return frames[2];
-}
-
-const expected_without_include_uncontrolled = [
-    // visibilityState, focused, url, type, frameType
-    ['visible', false, new URL(scope + '#1', location).toString(), 'window', 'nested'],
-    ['visible', true, new URL(scope + '#2', location).toString(), 'window', 'nested']
-];
-
-const expected_with_include_uncontrolled = [
-    // visibilityState, focused, url, type, frameType
-    ['visible', true, location.href, 'window', 'top-level'],
-    ['visible', false, new URL(scope + '#1', location).toString(), 'window', 'nested'],
-    ['visible', true, new URL(scope + '#2', location).toString(), 'window', 'nested'],
-    ['visible', false, new URL(base_url, location).toString(), 'window', 'nested']
-];
-
-function test_matchall(frame, expected, query_options) {
-  // Make sure we have focus for '#2' frame and its parent window.
-  frame.focus();
-  frame.contentWindow.focus();
+function test_matchall(service_worker, expected, query_options) {
   expected.sort((a, b) => a[2] > b[2] ? 1 : -1);
   return new Promise((resolve, reject) => {
     const channel = new MessageChannel();
     channel.port1.onmessage = e => {
-      // Ignore hidden clients which may be coming from background tabs, or
-      // clients unrelated to this test.
       const data = e.data.filter(info => {
-        return info[0] == 'visible' &&
-               info[2].indexOf('service-worker') > -1;
+        return info[2].indexOf('clients-matchall') > -1;
       });
       data.sort((a, b) => a[2] > b[2] ? 1 : -1);
       assert_equals(data.length, expected.length);
@@ -51,9 +18,8 @@
         assert_array_equals(data[i], expected[i]);
       resolve();
     };
-    frame.contentWindow.navigator.serviceWorker.controller.postMessage(
-        {port:channel.port2, options:query_options},
-        [channel.port2]);
+    service_worker.postMessage({port:channel.port2, options:query_options},
+                               [channel.port2]);
   });
 }
 
@@ -61,14 +27,91 @@
 // (We want to run the two tests sequentially in the same promise_test
 // so that we can use the same set of iframes without intefering each other.
 promise_test(async t => {
+  // |base_url| is out-of-scope.
+  const base_url = 'resources/blank.html?clients-matchall';
+  const scope = base_url + '-includeUncontrolled';
+
   const registration =
       await service_worker_unregister_and_register(
           t, 'resources/clients-matchall-worker.js', scope);
   t.add_cleanup(() => service_worker_unregister(t, scope));
-  await wait_for_state(t, registration.installing, 'activated');
-  const frame = await create_iframes(scope);
-  await test_matchall(frame, expected_without_include_uncontrolled);
-  await test_matchall(frame, expected_with_include_uncontrolled,
-                      {includeUncontrolled:true});
-}, 'Verify matchAll() respect includeUncontrolled');
+  const service_worker = registration.installing;
+  await wait_for_state(t, service_worker, 'activated');
+
+  // Creates 3 iframes, 2 for in-scope and 1 for out-of-scope.
+  let frames = [];
+  frames.push(await with_iframe(base_url));
+  frames.push(await with_iframe(scope + '#1'));
+  frames.push(await with_iframe(scope + '#2'));
+
+  // Make sure we have focus for '#2' frame and its parent window.
+  frames[2].focus();
+  frames[2].contentWindow.focus();
+
+  const expected_without_include_uncontrolled = [
+    // visibilityState, focused, url, type, frameType
+    ['visible', false, new URL(scope + '#1', location).toString(), 'window', 'nested'],
+    ['visible', true, new URL(scope + '#2', location).toString(), 'window', 'nested']
+  ];
+  const expected_with_include_uncontrolled = [
+    // visibilityState, focused, url, type, frameType
+    ['visible', true, location.href, 'window', 'top-level'],
+    ['visible', false, new URL(scope + '#1', location).toString(), 'window', 'nested'],
+    ['visible', true, new URL(scope + '#2', location).toString(), 'window', 'nested'],
+    ['visible', false, new URL(base_url, location).toString(), 'window', 'nested']
+  ];
+
+  await test_matchall(service_worker, expected_without_include_uncontrolled);
+  await test_matchall(service_worker, expected_with_include_uncontrolled,
+                      { includeUncontrolled: true });
+}, 'Verify matchAll() with windows respect includeUncontrolled');
+
+// TODO: Add tests for clients.matchAll for dedicated workers.
+
+async function create_shared_worker(script_url) {
+  const shared_worker = new SharedWorker(script_url);
+  const msgEvent = await new Promise(r => shared_worker.port.onmessage = r);
+  assert_equals(msgEvent.data, 'started');
+  return shared_worker;
+}
+
+// Run clients.matchAll for shared workers without and with
+// includeUncontrolled=true.
+promise_test(async t => {
+  const script_url = 'resources/clients-matchall-client-types-shared-worker.js';
+  const uncontrolled_script_url =
+      new URL(script_url + '?uncontrolled', location).toString();
+  const controlled_script_url =
+      new URL(script_url + '?controlled', location).toString();
+
+  // Start a shared worker that is not controlled by a service worker.
+  const uncontrolled_shared_worker =
+      await create_shared_worker(uncontrolled_script_url);
+
+  // Register a service worker.
+  const registration =
+      await service_worker_unregister_and_register(
+          t, 'resources/clients-matchall-worker.js', script_url);
+  t.add_cleanup(() => service_worker_unregister(t, script_url));
+  const service_worker = registration.installing;
+  await wait_for_state(t, service_worker, 'activated');
+
+  // Start another shared worker controlled by the service worker.
+  await create_shared_worker(controlled_script_url);
+
+  const expected_without_include_uncontrolled = [
+    // visibilityState, focused, url, type, frameType
+    [undefined, undefined, controlled_script_url, 'sharedworker', 'none'],
+  ];
+  const expected_with_include_uncontrolled = [
+    // visibilityState, focused, url, type, frameType
+    [undefined, undefined, controlled_script_url, 'sharedworker', 'none'],
+    [undefined, undefined, uncontrolled_script_url, 'sharedworker', 'none'],
+  ];
+
+  await test_matchall(service_worker, expected_without_include_uncontrolled,
+                      { type: 'sharedworker' });
+  await test_matchall(service_worker, expected_with_include_uncontrolled,
+                      { includeUncontrolled: true, type: 'sharedworker' });
+}, 'Verify matchAll() with shared workers respect includeUncontrolled');
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc-identity/META.yml b/third_party/WebKit/LayoutTests/external/wpt/webrtc-identity/META.yml
index 900769b..940144ce 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc-identity/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc-identity/META.yml
@@ -1,3 +1,4 @@
 spec: https://github.com/w3c/webrtc-identity
 suggested_reviewers:
   - martinthomson
+  - jan-ivar
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/META.yml b/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/META.yml
index 489264f..10bcf85 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/META.yml
@@ -2,3 +2,4 @@
 suggested_reviewers:
   - henbos
   - vr000m
+  - jan-ivar
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/META.yml b/third_party/WebKit/LayoutTests/external/wpt/webrtc/META.yml
index ea2846e..2025a11 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/META.yml
@@ -9,3 +9,4 @@
   - phoglund
   - youennf
   - rwaldron
+  - jan-ivar
diff --git a/third_party/WebKit/LayoutTests/fast/text/ellipsis-with-self-painting-layer-expected.html b/third_party/WebKit/LayoutTests/fast/text/ellipsis-with-self-painting-layer-expected.html
new file mode 100644
index 0000000..95536f6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/text/ellipsis-with-self-painting-layer-expected.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<style>
+div {
+  font-size: 10px;
+  border: 1px blue solid;
+  width: 10ch;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.padding > div {
+  padding-right: 4ch;
+}
+.inline-block {
+  background: red;
+  display: inline-block;
+  width: 4ch;
+  height: 1em;
+}
+.layer {
+  transform: translateY(0px);
+}
+</style>
+<body>
+  <div>123456789012</div>
+  <div>123456789012</div>
+  <div>123456789012</div>
+  <div>123456789012</div>
+  <div>123456789012</div>
+  <div>123456789012</div>
+  <section class="padding">
+    <div>123456789012</div>
+    <div>123456789012</div>
+    <div>123456789012</div>
+    <div>123456789012</div>
+    <div>123456789012</div>
+    <div>123456789012</div>
+  </section>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/text/ellipsis-with-self-painting-layer.html b/third_party/WebKit/LayoutTests/fast/text/ellipsis-with-self-painting-layer.html
new file mode 100644
index 0000000..981d3e93
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/text/ellipsis-with-self-painting-layer.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<style>
+div {
+  font-size: 10px;
+  border: 1px blue solid;
+  width: 10ch;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.padding > div {
+  padding-right: 4ch;
+}
+.inline-block {
+  background: red;
+  display: inline-block;
+  width: 4ch;
+  height: 1em;
+}
+.layer {
+  transform: translateY(0px);
+}
+</style>
+<body>
+  <div>123456789012</div>
+  <div>12345678
+    <span class="inline-block"></span>
+  </div>
+  <div>12345678
+    <span class="inline-block layer"></span>
+  </div>
+  <div>1234567890123
+    <span class="inline-block layer"></span>
+  </div>
+  <div>12345678
+    <span class="layer">0000</span>
+  </div>
+  <div>1234567890123
+    <span class="layer">0000</span>
+  </div>
+  <section class="padding">
+    <div>123456789012</div>
+    <div>12345678
+      <span class="inline-block"></span>
+    </div>
+    <div>12345678
+      <span class="inline-block layer"></span>
+    </div>
+    <div>1234567890123
+      <span class="inline-block layer"></span>
+    </div>
+    <div>12345678
+      <span class="layer">0000</span>
+    </div>
+    <div>1234567890123
+      <span class="layer">0000</span>
+    </div>
+  </section>
+</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-expected.txt
index 72b62a34..010fa72 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-expected.txt
@@ -27,3 +27,7 @@
 Running: testShouldNotJumpToBottomWhenPromptFillsEntireViewport
 Is at bottom: false, should stick: false
 
+Running: testShouldStickWhenEnteringCommandAndPromptIsOutOfView
+Sending key: Enter
+Is at bottom: true, should stick: true
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-onload-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-onload-expected.txt
new file mode 100644
index 0000000..68b35d0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-onload-expected.txt
@@ -0,0 +1,5 @@
+Verifies viewport stick-to-bottom behavior when Console is opened.
+
+Message count: 150
+Is at bottom: true, should stick: true
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-onload.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-onload.js
new file mode 100644
index 0000000..0d360e7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom-onload.js
@@ -0,0 +1,26 @@
+// 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.
+
+(async function() {
+  TestRunner.addResult(`Verifies viewport stick-to-bottom behavior when Console is opened.\n`);
+
+  // Log a ton of messages before opening console.
+  await TestRunner.evaluateInPagePromise(`
+      for (var i = 0; i < 150; ++i)
+        console.log("Message #" + i);
+
+      //# sourceURL=console-viewport-stick-to-bottom-onload.js
+    `);
+  await TestRunner.loadModule('console_test_runner');
+  await TestRunner.showPanel('console');
+  await ConsoleTestRunner.waitUntilConsoleEditorLoaded();
+
+  var viewport = Console.ConsoleView.instance()._viewport;
+  ConsoleTestRunner.waitForConsoleMessagesPromise(150);
+  await ConsoleTestRunner.waitForPendingViewportUpdates();
+
+  TestRunner.addResult(
+      'Is at bottom: ' + viewport.element.isScrolledToBottom() + ', should stick: ' + viewport.stickToBottom());
+  TestRunner.completeTest();
+})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom.js
index 459e105..1808493 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-viewport-stick-to-bottom.js
@@ -122,7 +122,23 @@
       consoleView._prompt.setText('Bar' + '\n'.repeat(viewportHeight));
 
       dumpAndContinue(next);
-    }
+    },
+
+    async function testShouldStickWhenEnteringCommandAndPromptIsOutOfView(next) {
+      consoleView._prompt.focus();
+      consoleView._prompt.setText('1');
+
+      // Set scrollTop such that prompt is not in visible area.
+      viewport.setStickToBottom(false);
+      viewport.element.scrollTop = 0;
+      await ConsoleTestRunner.waitForPendingViewportUpdates();
+
+      TestRunner.addResult(`Sending key: Enter`);
+      eventSender.keyDown('Enter');
+      await ConsoleTestRunner.waitForPendingViewportUpdates();
+
+      dumpAndContinue(next);
+    },
   ];
 
   function dumpAndContinue(callback) {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-page-metrics-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-page-metrics-expected.txt
new file mode 100644
index 0000000..01b14ee0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-page-metrics-expected.txt
@@ -0,0 +1,10 @@
+Test timeline page metrics.
+
+Entries:
+101.2 NaN FCP
+101.3 NaN FMP
+
+Markers:
+101.2 1.2000000000000028 First Contentful Paint
+101.3 1.2999999999999972 First Meaningful Paint
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-page-metrics.js b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-page-metrics.js
new file mode 100644
index 0000000..0bbdcb66
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-misc/timeline-page-metrics.js
@@ -0,0 +1,87 @@
+// 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.
+
+(async function() {
+  TestRunner.addResult(`Test timeline page metrics.\n`);
+  Runtime.experiments.enableForTest('timelinePaintTimingMarkers');
+  await TestRunner.loadModule('performance_test_runner');
+  await TestRunner.showPanel('timeline');
+
+  const rawTraceEvents = [
+    {
+      'args': {'name': 'CrBrowserMain'},
+      'cat': '__metadata',
+      'name': 'process_name',
+      'ph': 'M',
+      'pid': 17800,
+      'tid': 123,
+      'ts': 0
+    },
+    {'args':{'name':'Renderer'},'cat':'__metadata','name':'process_name','ph':'M','pid':17850,'tid':230,'ts':0},
+    {'args':{'name':'Renderer'},'cat':'__metadata','name':'process_name','ph':'M','pid':17851,'tid':231,'ts':0},
+    {'args':{'name':'Renderer'},'cat':'__metadata','name':'process_name','ph':'M','pid':17852,'tid':232,'ts':0},
+    {'args':{'name':'CrRendererMain'},'cat':'__metadata','name':'thread_name','ph':'M','pid':17850,'tid':230,'ts':0},
+    {'args':{'name':'CrRendererMain'},'cat':'__metadata','name':'thread_name','ph':'M','pid':17851,'tid':231,'ts':0},
+    {'args':{'name':'CrRendererMain'},'cat':'__metadata','name':'thread_name','ph':'M','pid':17852,'tid':232,'ts':0},
+    {
+      'args': {
+        "data": {
+          "frameTreeNodeId":550,
+          "persistentIds":true,
+          "frames": [
+            { "frame":"853DD8D6CA3B85CA78375EF189B779F6", "url":"https://www.example.com/", "name":"main",
+              "processId":17850 },
+            { "frame":"9B72B5F1A83B2DE0F8843B3D22878B81", "url":"https://www.example1.com/frame1.html", "name":"frame1",
+              "processId":17851, "parent":"853DD8D6CA3B85CA78375EF189B779F6"},
+            { "frame":"5D83B01045AD652BE04EA9A444221149", "url":"https://www.example2.com/frame2.html", "name":"frame2",
+              "processId":17852, "parent":"853DD8D6CA3B85CA78375EF189B779F6"}
+          ]
+        }
+      },
+      'cat': 'disabled-by-default-devtools.timeline',
+      'name': 'TracingStartedInBrowser',
+      'ph': 'I',
+      'pid': 17800,
+      'tid': 123,
+      'ts': 100000,
+      'tts': 606543
+    },
+
+    {"pid":17850,"tid":775,"ts":100500,"ph":"I","cat":"devtools.timeline","name":"FrameStartedLoading","args":{"frame":"853DD8D6CA3B85CA78375EF189B779F6"},"tts":606660},
+    {"pid":17850,"tid":775,"ts":101000,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstPaint","args":{"frame":"853DD8D6CA3B85CA78375EF189B779F6","data":{}},"tts":606700},
+    {"pid":17850,"tid":775,"ts":101200,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstContentfulPaint","args":{"frame":"853DD8D6CA3B85CA78375EF189B779F6","data":{}},"tts":606750},
+    {"pid":17850,"tid":775,"ts":101300,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaintCandidate","args":{"frame":"853DD8D6CA3B85CA78375EF189B779F6","data":{}},"tts":606800},
+    {"pid":17850,"tid":775,"ts":101300,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaint","args":{"frame":"853DD8D6CA3B85CA78375EF189B779F6","data":{}},"tts":606800},
+
+    {"pid":17851,"tid":775,"ts":100990,"ph":"I","cat":"devtools.timeline","name":"FrameStartedLoading","args":{"frame":"9B72B5F1A83B2DE0F8843B3D22878B81"},"tts":606660},
+    {"pid":17851,"tid":775,"ts":101100,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstPaint","args":{"frame":"9B72B5F1A83B2DE0F8843B3D22878B81","data":{}},"tts":606700},
+    {"pid":17851,"tid":775,"ts":101210,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstContentfulPaint","args":{"frame":"9B72B5F1A83B2DE0F8843B3D22878B81","data":{}},"tts":606750},
+    {"pid":17851,"tid":775,"ts":101300,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaintCandidate","args":{"frame":"9B72B5F1A83B2DE0F8843B3D22878B81","data":{}},"tts":606800},
+    {"pid":17851,"tid":775,"ts":101310,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaint","args":{"frame":"9B72B5F1A83B2DE0F8843B3D22878B81","data":{}},"tts":606800},
+
+    {"pid":17852,"tid":775,"ts":100880,"ph":"I","cat":"devtools.timeline","name":"FrameStartedLoading","args":{"frame":"5D83B01045AD652BE04EA9A444221149"},"tts":606660},
+    {"pid":17852,"tid":775,"ts":101200,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstPaint","args":{"frame":"5D83B01045AD652BE04EA9A444221149","data":{}},"tts":606700},
+    {"pid":17852,"tid":775,"ts":101300,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstContentfulPaint","args":{"frame":"5D83B01045AD652BE04EA9A444221149","data":{}},"tts":606750},
+    {"pid":17852,"tid":775,"ts":101400,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaintCandidate","args":{"frame":"5D83B01045AD652BE04EA9A444221149","data":{}},"tts":606800},
+    {"pid":17852,"tid":775,"ts":101500,"ph":"R","cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaint","args":{"frame":"5D83B01045AD652BE04EA9A444221149","data":{}},"tts":606800}
+  ];
+
+  const timeline = UI.panels.timeline;
+  timeline._setModel(PerformanceTestRunner.createPerformanceModelWithEvents(rawTraceEvents));
+  const flamechart = timeline._flameChart._mainFlameChart;
+
+  TestRunner.addResult(`Entries:`);
+  const data = flamechart._timelineData();
+  for (let i = 0; i < data.entryStartTimes.length; ++i) {
+    TestRunner.addResult(
+        `${data.entryStartTimes[i]} ${data.entryTotalTimes[i]} ${flamechart._dataProvider.entryTitle(i)}`);
+  }
+
+  TestRunner.addResult(`\nMarkers:`);
+  for (const marker of data.markers)
+    TestRunner.addResult(`${marker._startTime} ${marker._startOffset} ${marker._style.title}`);
+
+  TestRunner.completeTest();
+
+})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-time/timeline-usertiming.js b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-time/timeline-usertiming.js
index 1716d67..82666fe 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-time/timeline-usertiming.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-time/timeline-usertiming.js
@@ -103,13 +103,11 @@
 
   function dumpUserTimings() {
     var model = PerformanceTestRunner.timelineModel();
-    var asyncEvents;
     for (const track of model.tracks()) {
-      if (track.type === TimelineModel.TimelineModel.TrackType.Timings) {
-        for (const event of track.asyncEvents) {
-          if (event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming))
-            TestRunner.addResult(event.name);
-        }
+      if (track.type !== TimelineModel.TimelineModel.TrackType.Timings) continue;
+      for (const event of track.asyncEvents) {
+        if (event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming))
+          TestRunner.addResult(event.name);
       }
     }
   }
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 870b89a4..cb2c8ac 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -49,6 +49,7 @@
     "quota/quota_dispatcher_host.mojom",
     "quota/quota_types.mojom",
     "referrer.mojom",
+    "script/script_type.mojom",
     "service_worker/dispatch_fetch_event_params.mojom",
     "service_worker/navigation_preload_state.mojom",
     "service_worker/service_worker_client.mojom",
diff --git a/third_party/blink/public/mojom/script/OWNERS b/third_party/blink/public/mojom/script/OWNERS
new file mode 100644
index 0000000..e34e6a1
--- /dev/null
+++ b/third_party/blink/public/mojom/script/OWNERS
@@ -0,0 +1,7 @@
+file://third_party/blink/renderer/core/script/OWNERS
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+# TEAM: module-dev@chromium.org
+# COMPONENT: Blink>HTML>Script
diff --git a/third_party/blink/public/mojom/script/script_type.mojom b/third_party/blink/public/mojom/script/script_type.mojom
new file mode 100644
index 0000000..c067347c
--- /dev/null
+++ b/third_party/blink/public/mojom/script/script_type.mojom
@@ -0,0 +1,11 @@
+// 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 blink.mojom;
+
+// https://html.spec.whatwg.org/multipage/webappapis.html#definitions-2
+enum ScriptType {
+  kClassic,
+  kModule,
+};
diff --git a/third_party/blink/public/mojom/service_worker/service_worker_registration.mojom b/third_party/blink/public/mojom/service_worker/service_worker_registration.mojom
index d4c110e1..ec05b66 100644
--- a/third_party/blink/public/mojom/service_worker/service_worker_registration.mojom
+++ b/third_party/blink/public/mojom/service_worker/service_worker_registration.mojom
@@ -4,6 +4,7 @@
 
 module blink.mojom;
 
+import "third_party/blink/public/mojom/script/script_type.mojom";
 import "third_party/blink/public/mojom/service_worker/navigation_preload_state.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_object.mojom";
@@ -11,17 +12,6 @@
 
 const int64 kInvalidServiceWorkerRegistrationId = -1;
 
-// Represents ScriptType enum for ServiceWorkerRegistrationOptions:
-// https://w3c.github.io/ServiceWorker/#dom-registrationoptions-type
-// https://html.spec.whatwg.org/multipage/workers.html#workertype
-// TODO(asamidoi, nhiroki): Move this enum to blink/public/mojom/script or
-// somewhere else, and replace the duplicate enum in
-// third_party/blink/renderer/core/script/script.h.
-enum ScriptType {
-  kClassic,
-  kModule,
-};
-
 // Represents ServiceWorkerUpdateViaCache enum for ServiceWorkerRegistrationOptions:
 // https://w3c.github.io/ServiceWorker/#enumdef-serviceworkerupdateviacache
 enum ServiceWorkerUpdateViaCache {
diff --git a/third_party/blink/renderer/bindings/IDLUnionTypes.md b/third_party/blink/renderer/bindings/IDLUnionTypes.md
index b123c940..fa9558e 100644
--- a/third_party/blink/renderer/bindings/IDLUnionTypes.md
+++ b/third_party/blink/renderer/bindings/IDLUnionTypes.md
@@ -21,49 +21,42 @@
 
 The file name for a generated class is basically the same as its class
 name, but we use some aliases to avoid too-long file names
-(See http://crbug.com/611437 why we need to avoid long file names).
-Currently we use following alias(es).
-
-```
-CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContext -> RenderingContext
-```
+(See https://crbug.com/611437 why we need to avoid long file names).
 
 The paths for generated classes depend on the places union types are
-used. If a union type is used only by IDL files under modules/, the
-include path is `bindings/modules/v8/FooOrBar.h`. Otherwise, the
-include path is `bindings/core/v8/FooOrBar.h`. For example, given
+used. If a union type is used only in IDL files under modules/, the
+include path is `bindings/modules/v8/foo_or_bar.h`. Otherwise, the
+include path is `bindings/core/v8/foo_or_bar.h`. For example, given
 following definitions:
 
 ```webidl
-// core/fileapi/FileReader.idl
+// core/fileapi/file_reader.idl
 readonly attribute (DOMString or ArrayBuffer)? result;
 
-// dom/CommonDefinitions.idl
+// dom/common_definitions.idl
 typedef (ArrayBuffer or ArrayBufferView) BufferSource;
 
-// modules/encoding/TextDecoder.idl
+// modules/encoding/text_decoder.idl
 DOMString decode(optional BufferSource input, optional TextDecodeOptions options);
 
-// modules/fetch/Request.idl
+// modules/fetch/request.idl
 typedef (Request or USVString) RequestInfo;
 ```
 
 The include paths will be:
-- bindings/core/v8/StringOrArrayBuffer.h
-- bindings/core/v8/ArrayBufferOrArrayBufferView.h
-- bindings/modules/v8/RequestOrUSVString.h
+- bindings/core/v8/string_or_array_buffer.h
+- bindings/core/v8/array_buffer_or_array_buffer_view.h
+- bindings/modules/v8/request_or_usv_string.h
 
-Note that `ArrayBufferOrArrayBufferView` is located under core/ even
-it is used by `Request.idl` which is located under modules/.
+Note that `array_buffer_or_array_buffer_view.h` is located under core/ even
+it is used by `request.idl` which is located under modules/.
 
 **Special NOTE**: If you are going to use a union type under core/ and
 the union type is currently used only under modules/, you will need
 to update the include path for the union type under modules/.
 
-## Updating GN/GYP files
-TODO(bashi): Mitigate the pain of updating GN/GYP files.
-
-Due to the requirements of GN/GYP, we need to put generated file names
-in gni/gypi files. Please update
-`bindings/core/v8/generated.{gni,gypi}` and/or
-`bindings/modules/v8/generated.{gni,gypi}` accordingly.
+## Updating GN files
+Due to the requirements of GN, we need to put generated file names
+in GN files. Please update
+`bindings/core/v8/generated.gni` and/or
+`bindings/modules/v8/generated.gni` accordingly.
diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_dev_tools_host_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_dev_tools_host_custom.cc
index 2234657..f29e1cb 100644
--- a/third_party/blink/renderer/bindings/core/v8/custom/v8_dev_tools_host_custom.cc
+++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_dev_tools_host_custom.cc
@@ -155,7 +155,7 @@
   } else {
     v8::Local<v8::Object> window_wrapper =
         V8Window::findInstanceInPrototypeChain(
-            isolate->GetEnteredContext()->Global(), isolate);
+            isolate->GetEnteredOrMicrotaskContext()->Global(), isolate);
     if (window_wrapper.IsEmpty())
       return;
     DOMWindow* window = V8Window::ToImpl(window_wrapper);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
index 0707116f..2c76451 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -242,7 +242,7 @@
   DCHECK(IsMainThread());
   v8::Isolate* isolate = v8::Isolate::GetCurrent();
 
-  if (isolate->GetEnteredContext().IsEmpty())
+  if (isolate->GetEnteredOrMicrotaskContext().IsEmpty())
     return;
 
   // If called during context initialization, there will be no entered context.
diff --git a/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py b/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py
index c314fe6..ed93ca15 100755
--- a/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py
+++ b/third_party/blink/renderer/bindings/scripts/aggregate_generated_bindings.py
@@ -120,8 +120,7 @@
 def main():
     options, filenames = parse_options()
     component = options.component
-    idl_filenames = read_idl_files_list_from_file(filenames[0],
-                                                  is_gyp_format=False)
+    idl_filenames = read_idl_files_list_from_file(filenames[0])
     basenames = [idl_filename_to_basename(file_path)
                  for file_path in idl_filenames]
     file_contents = generate_content(component, basenames)
diff --git a/third_party/blink/renderer/bindings/scripts/compute_global_objects.py b/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
index ececf6113..1160e62 100755
--- a/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
+++ b/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
@@ -101,8 +101,8 @@
         for existing_interface_name_global_names
         in read_pickle_files(options.global_objects_component_files))
 
-    # Input IDL files are passed in a file, due to OS command line length
-    # limits. This is generated at GYP time, which is ok b/c files are static.
+    # File paths of input IDL files are passed in a file, which is generated at
+    # GN time. It is OK because the target IDL files themselves are static.
     idl_files = read_file_to_list(options.idl_files_list)
     interface_name_global_names.update(
             idl_files_to_interface_name_global_names(idl_files))
diff --git a/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py b/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
index 931b1d0..992d4db 100755
--- a/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
+++ b/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
@@ -347,7 +347,7 @@
     options, _ = parse_options()
 
     # IDL files are passed in a file, due to OS command line length limits
-    idl_files = read_idl_files_list_from_file(options.idl_files_list, is_gyp_format=False)
+    idl_files = read_idl_files_list_from_file(options.idl_files_list)
 
     # Compute information for individual files
     # Information is stored in global variables interfaces_info and
diff --git a/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py b/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py
index c54e0d3..62cee43c 100755
--- a/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py
+++ b/third_party/blink/renderer/bindings/scripts/generate_event_interfaces.py
@@ -87,8 +87,7 @@
             for name in EXPORTED_EXTENDED_ATTRIBUTES
             if name in extended_attributes]
 
-        return (posixpath.join(relative_dir_posix, interface_name),
-                extended_attributes_list)
+        return (relative_dir_posix, interface_name, extended_attributes_list)
 
     lines = [
         '{',
@@ -107,10 +106,11 @@
     interface_lines = [interface_line(event_idl_file)
                        for event_idl_file in event_idl_files]
     interface_lines.sort()
-    for name, attributes in interface_lines:
+    for relative_dir, name, attributes in interface_lines:
         lines.extend([
             '  {',
-            '    name: "%s",' % name
+            '    name: "%s",' % name,
+            '    interfaceHeaderDir: "%s",' % relative_dir
         ])
         for param, value in attributes:
             if param == 'RuntimeEnabled':
diff --git a/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py b/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
index c068fbd..376f82d 100755
--- a/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
+++ b/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
@@ -153,14 +153,14 @@
 def main():
     options, args = parse_options()
 
-    # Input IDL files are passed in a file, due to OS command line length
-    # limits. This is generated at GYP time, which is ok b/c files are static.
+    # File paths of input IDL files are passed in a file, which is generated at
+    # GN time. It is OK because the target IDL files are static.
     idl_files = read_file_to_list(options.idl_files_list)
 
     # Output IDL files (to generate) are passed at the command line, since
     # these are in the build directory, which is determined at build time, not
-    # GYP time.
-    # These are passed as pairs of GlobalObjectName, GlobalObject.idl
+    # GN time.
+    # These are passed as pairs of GlobalObjectName, global_object.idl
     interface_name_idl_filename = [(args[i], args[i + 1])
                                    for i in range(0, len(args), 2)]
 
diff --git a/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py b/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py
index dd1b8541..dd7e21c 100755
--- a/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py
+++ b/third_party/blink/renderer/bindings/scripts/generate_init_partial_interfaces.py
@@ -43,9 +43,6 @@
     parser = OptionParser(usage=usage)
     parser.add_option('--idl-files-list',
                       help='a text file containing the IDL file paths, so the command line doesn\'t exceed OS length limits.')
-    parser.add_option('--gyp-format-list', default=False, action='store_true',
-                      help='if specified, idl-files-list is newline separated. ' +
-                      'When unspecified, it\'s formatted as a Posix command line.')
     parser.add_option('--output')
 
     options, args = parser.parse_args()
@@ -86,7 +83,7 @@
 def main():
     options = parse_options()
 
-    idl_file_names = read_idl_files_list_from_file(options.idl_files_list, is_gyp_format=options.gyp_format_list)
+    idl_file_names = read_idl_files_list_from_file(options.idl_files_list)
 
     meta_data_list = extract_meta_data(idl_file_names)
     interface_names = ['V8%sPartial' % meta_data['basename']
diff --git a/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py b/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
index c55a0fe..f51f45d 100644
--- a/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
+++ b/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
@@ -220,7 +220,7 @@
         opts.info_dir, opts.target_component)
     generator = ExternalReferenceTableGenerator(opts, info_provider)
 
-    idl_files = utilities.read_idl_files_list_from_file(opts.idl_files_list, False)
+    idl_files = utilities.read_idl_files_list_from_file(opts.idl_files_list)
     for idl_file in idl_files:
         generator.process_idl_file(idl_file)
     output_code = generator.generate()
diff --git a/third_party/blink/renderer/bindings/scripts/generate_web_idl_collection.py b/third_party/blink/renderer/bindings/scripts/generate_web_idl_collection.py
index 4cd03f4..854a84b 100644
--- a/third_party/blink/renderer/bindings/scripts/generate_web_idl_collection.py
+++ b/third_party/blink/renderer/bindings/scripts/generate_web_idl_collection.py
@@ -32,7 +32,7 @@
 
 def main():
     options, _ = parse_options()
-    idl_file_names = utilities.read_idl_files_list_from_file(options.idl_list_file, False)
+    idl_file_names = utilities.read_idl_files_list_from_file(options.idl_list_file)
 
     parser = blink_idl_parser.BlinkIDLParser()
     collector = Collector(component=options.component, parser=parser)
diff --git a/third_party/blink/renderer/bindings/scripts/idl_compiler.py b/third_party/blink/renderer/bindings/scripts/idl_compiler.py
index 278954a..eef8935 100755
--- a/third_party/blink/renderer/bindings/scripts/idl_compiler.py
+++ b/third_party/blink/renderer/bindings/scripts/idl_compiler.py
@@ -178,8 +178,7 @@
     if options.generate_impl or options.read_idl_list_from_file:
         # |input_filename| should be a file which contains a list of IDL
         # dictionary paths.
-        input_filenames = read_idl_files_list_from_file(input_filename,
-                                                        is_gyp_format=True)
+        input_filenames = read_idl_files_list_from_file(input_filename)
     else:
         input_filenames = [input_filename]
 
diff --git a/third_party/blink/renderer/bindings/scripts/utilities.py b/third_party/blink/renderer/bindings/scripts/utilities.py
index 6e8482c..b25d117 100644
--- a/third_party/blink/renderer/bindings/scripts/utilities.py
+++ b/third_party/blink/renderer/bindings/scripts/utilities.py
@@ -281,19 +281,10 @@
     return idl_file_names
 
 
-def read_idl_files_list_from_file(filename, is_gyp_format):
-    """Similar to read_file_to_list, but also resolves cygpath.
-
-    If is_gyp_format is True, the file is treated as a newline-separated list
-    with no quoting or escaping. When False, the file is interpreted as a
-    Posix-style quoted and space-separated list."""
+def read_idl_files_list_from_file(filename):
+    """Similar to read_file_to_list, but also resolves cygpath."""
     with open(filename) as input_file:
-        if is_gyp_format:
-            file_names = sorted([os.path.realpath(line.rstrip('\n'))
-                                 for line in input_file])
-        else:
-            file_names = sorted(shlex.split(input_file))
-
+        file_names = sorted(shlex.split(input_file))
         idl_file_names = [file_name for file_name in file_names
                           if not file_name.startswith('/cygdrive')]
         cygdrive_names = [file_name for file_name in file_names
diff --git a/third_party/blink/renderer/build/scripts/make_event_factory.py b/third_party/blink/renderer/build/scripts/make_event_factory.py
index 18bd1b6..a941cc0a 100755
--- a/third_party/blink/renderer/build/scripts/make_event_factory.py
+++ b/third_party/blink/renderer/build/scripts/make_event_factory.py
@@ -91,6 +91,7 @@
 class EventFactoryWriter(json5_generator.Writer):
     default_parameters = {
         'ImplementedAs': {},
+        'interfaceHeaderDir': {},
         'RuntimeEnabled': {},
     }
     default_metadata = {
@@ -100,7 +101,7 @@
     }
     filters = {
         'cpp_name': name_utilities.cpp_name,
-        'script_name': name_utilities.script_name,
+        'name': lambda entry: entry['name'].original,
         'create_event_whitelist': create_event_whitelist,
         'create_event_measure_whitelist': create_event_measure_whitelist,
         'measure_name': measure_name,
@@ -121,14 +122,10 @@
         exit(1)
 
     def _headers_header_include_path(self, entry):
-        path = os.path.dirname(entry['name'].original)
+        path = entry['interfaceHeaderDir']
         if len(path):
             path += '/'
-        if entry['ImplementedAs']:
-            path += self.get_file_basename(entry['ImplementedAs'])
-        else:
-            path += self.get_file_basename(os.path.basename(entry['name'].original))
-        return path + '.h'
+        return path + self.get_file_basename(name_utilities.cpp_name(entry)) + '.h'
 
     def _headers_header_includes(self, entries):
         includes = dict()
diff --git a/third_party/blink/renderer/build/scripts/make_names.py b/third_party/blink/renderer/build/scripts/make_names.py
index 5ecc1fe2..dba17c6 100755
--- a/third_party/blink/renderer/build/scripts/make_names.py
+++ b/third_party/blink/renderer/build/scripts/make_names.py
@@ -30,7 +30,6 @@
 import os
 import sys
 
-from blinkbuild.name_style_converter import NameStyleConverter
 import hasher
 import json5_generator
 import template_expander
@@ -40,16 +39,15 @@
 def _symbol(entry):
     if entry['Symbol'] is not None:
         return entry['Symbol']
-    # TODO(tkent): Separate path information and interface name in
-    # event_interface_names.json5.
-    name = os.path.basename(entry['name'].original)
-    return 'k' + NameStyleConverter(name).to_upper_camel_case()
+    return 'k' + entry['name'].to_upper_camel_case()
 
 
 class MakeNamesWriter(json5_generator.Writer):
     default_parameters = {
         'Conditional': {},  # FIXME: Add support for Conditional.
         'ImplementedAs': {},
+        # This is not used in make_names,py, but used in make_event_factory.py.
+        'interfaceHeaderDir': {},
         'RuntimeEnabled': {},  # What should we do for runtime-enabled features?
         'Symbol': {},
     }
diff --git a/third_party/blink/renderer/build/scripts/name_utilities.py b/third_party/blink/renderer/build/scripts/name_utilities.py
index d6afcc0..2ef88dad 100644
--- a/third_party/blink/renderer/build/scripts/name_utilities.py
+++ b/third_party/blink/renderer/build/scripts/name_utilities.py
@@ -26,15 +26,9 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-import os.path
-
 from blinkbuild.name_style_converter import NameStyleConverter
 
 
-def script_name(entry):
-    return os.path.basename(entry['name'].original)
-
-
 def cpp_bool(value):
     if value is True:
         return 'true'
@@ -46,7 +40,7 @@
 
 
 def cpp_name(entry):
-    return entry['ImplementedAs'] or script_name(entry)
+    return entry['ImplementedAs'] or entry['name'].original
 
 
 def enum_for_css_keyword(keyword):
diff --git a/third_party/blink/renderer/build/scripts/templates/event_factory.cc.tmpl b/third_party/blink/renderer/build/scripts/templates/event_factory.cc.tmpl
index 1fe511b..498baf4 100644
--- a/third_party/blink/renderer/build/scripts/templates/event_factory.cc.tmpl
+++ b/third_party/blink/renderer/build/scripts/templates/event_factory.cc.tmpl
@@ -18,14 +18,14 @@
 namespace blink {
 
 Event* Event{{suffix}}Factory::Create(ExecutionContext* executionContext, const String& type) {
-  {% for event in events if event|script_name|create_event_whitelist or event|script_name|create_event_measure_whitelist %}
-  {% if event|script_name|create_event_whitelist or event|script_name|create_event_measure_whitelist %}
-  if (DeprecatedEqualIgnoringCase(type, "{{event|script_name}}"){% if event.RuntimeEnabled %} && RuntimeEnabledFeatures::{{event.RuntimeEnabled}}(){% endif %}) {
+  {% for event in events if event|name|create_event_whitelist or event|name|create_event_measure_whitelist %}
+  {% if event|name|create_event_whitelist or event|name|create_event_measure_whitelist %}
+  if (DeprecatedEqualIgnoringCase(type, "{{event|name}}"){% if event.RuntimeEnabled %} && RuntimeEnabledFeatures::{{event.RuntimeEnabled}}(){% endif %}) {
   {% else %}
-  if (type == "{{event|script_name}}"{% if event.RuntimeEnabled %} && RuntimeEnabledFeatures::{{event.RuntimeEnabled}}(){% endif %}) {
+  if (type == "{{event|name}}"{% if event.RuntimeEnabled %} && RuntimeEnabledFeatures::{{event.RuntimeEnabled}}(){% endif %}) {
   {% endif %}
-    {% if not event|script_name|create_event_whitelist %}
-    UseCounter::Count(executionContext, WebFeature::k{{event|script_name|measure_name}});
+    {% if not event|name|create_event_whitelist %}
+    UseCounter::Count(executionContext, WebFeature::k{{event|name|measure_name}});
     {% endif %}
     return {{event|cpp_name}}::Create();
   }
diff --git a/third_party/blink/renderer/core/css/css_initial_value.h b/third_party/blink/renderer/core/css/css_initial_value.h
index 7f127949..77a65cb 100644
--- a/third_party/blink/renderer/core/css/css_initial_value.h
+++ b/third_party/blink/renderer/core/css/css_initial_value.h
@@ -22,11 +22,12 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_INITIAL_VALUE_H_
 
 #include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/css_value.h"
 
 namespace blink {
 
-class CSSInitialValue : public CSSValue {
+class CORE_EXPORT CSSInitialValue : public CSSValue {
  public:
   static CSSInitialValue* Create();
 
diff --git a/third_party/blink/renderer/core/dom/events/README.md b/third_party/blink/renderer/core/dom/events/README.md
new file mode 100644
index 0000000..c002dab
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/events/README.md
@@ -0,0 +1,13 @@
+# DOM Events
+
+[Rendered](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/dom/events/README.md)
+
+Author: hayato@chromium.org
+
+The `renderer/core/dom/events` directory contains the implementation of [DOM Events].
+
+[DOM Events]: https://dom.spec.whatwg.org/#events
+
+Please avoid to put any kind of specific event's implementation in this directory, such as [UI Events].
+
+[UI Events]: https://w3c.github.io/uievents/
diff --git a/third_party/blink/renderer/core/dom/qualified_name.h b/third_party/blink/renderer/core/dom/qualified_name.h
index ea0348d..3c1b018 100644
--- a/third_party/blink/renderer/core/dom/qualified_name.h
+++ b/third_party/blink/renderer/core/dom/qualified_name.h
@@ -52,7 +52,7 @@
   USING_FAST_MALLOC(QualifiedName);
 
  public:
-  class QualifiedNameImpl : public RefCounted<QualifiedNameImpl> {
+  class CORE_EXPORT QualifiedNameImpl : public RefCounted<QualifiedNameImpl> {
    public:
     static scoped_refptr<QualifiedNameImpl> Create(
         const AtomicString& prefix,
diff --git a/third_party/blink/renderer/core/dom/space_split_string.h b/third_party/blink/renderer/core/dom/space_split_string.h
index 1e1afbf..6589128b 100644
--- a/third_party/blink/renderer/core/dom/space_split_string.h
+++ b/third_party/blink/renderer/core/dom/space_split_string.h
@@ -65,7 +65,7 @@
   const AtomicString& operator[](wtf_size_t i) const { return (*data_)[i]; }
 
  private:
-  class Data : public RefCounted<Data> {
+  class CORE_EXPORT Data : public RefCounted<Data> {
    public:
     static scoped_refptr<Data> Create(const AtomicString&);
     static scoped_refptr<Data> CreateUnique(const Data&);
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
index 98137c2..477b1fc0 100644
--- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -33,6 +33,7 @@
 #include <memory>
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_content_settings_client.h"
@@ -317,9 +318,9 @@
   auto worker_settings = std::make_unique<WorkerSettings>(
       shadow_page_->GetDocument()->GetFrame()->GetSettings());
 
-  // TODO(nhiroki); Set |script_type| to ScriptType::kModule for module fetch.
-  // (https://crbug.com/824646)
-  ScriptType script_type = ScriptType::kClassic;
+  // TODO(nhiroki); Set |script_type| to mojom::ScriptType::kModule for module
+  // fetch (https://crbug.com/824646).
+  mojom::ScriptType script_type = mojom::ScriptType::kClassic;
 
   const KURL script_response_url = main_script_loader_->ResponseURL();
   DCHECK(static_cast<KURL>(script_request_url_) == script_response_url ||
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
index 03604eb..3b0d304 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
@@ -130,8 +130,8 @@
     ExecutionContext* context) {
   ImageEncodeOptions* options = ImageEncodeOptions::Create();
   options->setType(ImageEncodingMimeTypeName(mime_type));
-  return new CanvasAsyncBlobCreator(image, options, function_type, callback,
-                                    start_time, context, nullptr);
+  return MakeGarbageCollected<CanvasAsyncBlobCreator>(
+      image, options, function_type, callback, start_time, context, nullptr);
 }
 
 CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::Create(
@@ -141,8 +141,8 @@
     TimeTicks start_time,
     ExecutionContext* context,
     ScriptPromiseResolver* resolver) {
-  return new CanvasAsyncBlobCreator(image, options, function_type, nullptr,
-                                    start_time, context, resolver);
+  return MakeGarbageCollected<CanvasAsyncBlobCreator>(
+      image, options, function_type, nullptr, start_time, context, resolver);
 }
 
 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
index e6fa475d..4e8d51ccb 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
@@ -68,6 +68,14 @@
                                         ScriptPromiseResolver*);
 
   void ScheduleAsyncBlobCreation(const double& quality);
+
+  CanvasAsyncBlobCreator(scoped_refptr<StaticBitmapImage>,
+                         const ImageEncodeOptions*,
+                         ToBlobFunctionType,
+                         V8BlobCallback*,
+                         TimeTicks start_time,
+                         ExecutionContext*,
+                         ScriptPromiseResolver*);
   virtual ~CanvasAsyncBlobCreator();
 
   // Methods are virtual for mocking in unit tests
@@ -85,13 +93,6 @@
   }
 
  protected:
-  CanvasAsyncBlobCreator(scoped_refptr<StaticBitmapImage>,
-                         const ImageEncodeOptions*,
-                         ToBlobFunctionType,
-                         V8BlobCallback*,
-                         TimeTicks start_time,
-                         ExecutionContext*,
-                         ScriptPromiseResolver*);
   static ImageEncodeOptions* GetImageEncodeOptionsForMimeType(
       ImageEncodingMimeType);
   // Methods are virtual for unit testing
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h b/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h
index fc7dd5c7b..76cd710 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h
@@ -28,9 +28,11 @@
 
  public:
   static CanvasFontCache* Create(Document& document) {
-    return new CanvasFontCache(document);
+    return MakeGarbageCollected<CanvasFontCache>(document);
   }
 
+  explicit CanvasFontCache(Document&);
+
   MutableCSSPropertyValueSet* ParseFont(const String&);
   void PruneAll();
   unsigned size();
@@ -53,7 +55,6 @@
   ~CanvasFontCache() override;
 
  private:
-  explicit CanvasFontCache(Document&);
   void Dispose();
   void SchedulePruningIfNeeded();
   typedef HeapHashMap<String, Member<MutableCSSPropertyValueSet>>
diff --git a/third_party/blink/renderer/core/html/canvas/image_data.cc b/third_party/blink/renderer/core/html/canvas/image_data.cc
index a5b1bd6..d39416e 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_data.cc
@@ -238,7 +238,9 @@
       AllocateAndValidateDataArray(4 * static_cast<unsigned>(size.Width()) *
                                        static_cast<unsigned>(size.Height()),
                                    storage_format);
-  return data_array ? new ImageData(size, data_array, color_settings) : nullptr;
+  return data_array
+             ? MakeGarbageCollected<ImageData>(size, data_array, color_settings)
+             : nullptr;
 }
 
 ImageDataColorSettings* CanvasColorParamsToImageDataColorSettings(
@@ -312,7 +314,8 @@
                                                0, 0, data_array.View(),
                                                color_settings))
     return nullptr;
-  return new ImageData(size, data_array.View(), color_settings);
+  return MakeGarbageCollected<ImageData>(size, data_array.View(),
+                                         color_settings);
 }
 
 static SkImageInfo GetImageInfo(scoped_refptr<StaticBitmapImage> image) {
@@ -376,7 +379,8 @@
 
   DOMArrayBufferView* byte_array = AllocateAndValidateDataArray(
       4 * width * height, kUint8ClampedArrayStorageFormat, &exception_state);
-  return byte_array ? new ImageData(IntSize(width, height), byte_array)
+  return byte_array ? MakeGarbageCollected<ImageData>(IntSize(width, height),
+                                                      byte_array)
                     : nullptr;
 }
 
@@ -389,7 +393,7 @@
     return nullptr;
 
   unsigned height = data.View()->length() / (width * 4);
-  return new ImageData(IntSize(width, height), data.View());
+  return MakeGarbageCollected<ImageData>(IntSize(width, height), data.View());
 }
 
 ImageData* ImageData::Create(NotShared<DOMUint8ClampedArray> data,
@@ -401,7 +405,7 @@
           data.View(), nullptr, &exception_state))
     return nullptr;
 
-  return new ImageData(IntSize(width, height), data.View());
+  return MakeGarbageCollected<ImageData>(IntSize(width, height), data.View());
 }
 
 ImageData* ImageData::CreateImageData(
@@ -422,7 +426,8 @@
   if (!buffer_view)
     return nullptr;
 
-  return new ImageData(IntSize(width, height), buffer_view, color_settings);
+  return MakeGarbageCollected<ImageData>(IntSize(width, height), buffer_view,
+                                         color_settings);
 }
 
 ImageData* ImageData::CreateImageData(ImageDataArray& data,
@@ -458,7 +463,8 @@
           buffer_view, color_settings, &exception_state))
     return nullptr;
 
-  return new ImageData(IntSize(width, height), buffer_view, color_settings);
+  return MakeGarbageCollected<ImageData>(IntSize(width, height), buffer_view,
+                                         color_settings);
 }
 
 // This function accepts size (0, 0) and always returns the ImageData in
@@ -476,7 +482,7 @@
   if (!byte_array)
     return nullptr;
 
-  return new ImageData(size, byte_array);
+  return MakeGarbageCollected<ImageData>(size, byte_array);
 }
 
 // This function is called from unit tests, and all the parameters are supposed
@@ -485,7 +491,7 @@
     const IntSize& size,
     DOMArrayBufferView* buffer_view,
     const ImageDataColorSettings* color_settings) {
-  return new ImageData(size, buffer_view, color_settings);
+  return MakeGarbageCollected<ImageData>(size, buffer_view, color_settings);
 }
 
 // Crops ImageData to the intersect of its size and the given rectangle. If the
@@ -531,7 +537,8 @@
       dst_index += dst_row_stride;
     }
   }
-  return new ImageData(dst_rect.Size(), buffer_view, color_settings_);
+  return MakeGarbageCollected<ImageData>(dst_rect.Size(), buffer_view,
+                                         color_settings_);
 }
 
 ScriptPromise ImageData::CreateImageBitmap(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/html/canvas/image_data.h b/third_party/blink/renderer/core/html/canvas/image_data.h
index 1f00590..e5adfd82 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data.h
+++ b/third_party/blink/renderer/core/html/canvas/image_data.h
@@ -108,6 +108,10 @@
                                   DOMArrayBufferView*,
                                   const ImageDataColorSettings* = nullptr);
 
+  ImageData(const IntSize&,
+            DOMArrayBufferView*,
+            const ImageDataColorSettings* = nullptr);
+
   ImageData* CropRect(const IntRect&, bool flip_y = false);
 
   ImageDataStorageFormat GetImageDataStorageFormat();
@@ -172,10 +176,6 @@
       ExceptionState* = nullptr);
 
  private:
-  ImageData(const IntSize&,
-            DOMArrayBufferView*,
-            const ImageDataColorSettings* = nullptr);
-
   IntSize size_;
   Member<ImageDataColorSettings> color_settings_;
   ImageDataArray data_union_;
diff --git a/third_party/blink/renderer/core/html/forms/image_input_type.cc b/third_party/blink/renderer/core/html/forms/image_input_type.cc
index 9d29c70d..cbdad34e 100644
--- a/third_party/blink/renderer/core/html/forms/image_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/image_input_type.cc
@@ -47,7 +47,7 @@
     : BaseButtonInputType(element), use_fallback_content_(false) {}
 
 InputType* ImageInputType::Create(HTMLInputElement& element) {
-  return new ImageInputType(element);
+  return MakeGarbageCollected<ImageInputType>(element);
 }
 
 const AtomicString& ImageInputType::FormControlType() const {
diff --git a/third_party/blink/renderer/core/html/forms/image_input_type.h b/third_party/blink/renderer/core/html/forms/image_input_type.h
index b7df559..0fc4ea613 100644
--- a/third_party/blink/renderer/core/html/forms/image_input_type.h
+++ b/third_party/blink/renderer/core/html/forms/image_input_type.h
@@ -41,11 +41,11 @@
 class ImageInputType final : public BaseButtonInputType {
  public:
   static InputType* Create(HTMLInputElement&);
+  ImageInputType(HTMLInputElement&);
   scoped_refptr<ComputedStyle> CustomStyleForLayoutObject(
       scoped_refptr<ComputedStyle>) override;
 
  private:
-  ImageInputType(HTMLInputElement&);
   const AtomicString& FormControlType() const override;
   bool IsFormDataAppendable() const override;
   void AppendToFormData(FormData&) const override;
diff --git a/third_party/blink/renderer/core/html/html_script_element.cc b/third_party/blink/renderer/core/html/html_script_element.cc
index f4e59ff..806a355 100644
--- a/third_party/blink/renderer/core/html/html_script_element.cc
+++ b/third_party/blink/renderer/core/html/html_script_element.cc
@@ -23,6 +23,7 @@
 
 #include "third_party/blink/renderer/core/html/html_script_element.h"
 
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
 #include "third_party/blink/renderer/core/dom/attribute.h"
@@ -95,7 +96,7 @@
 
 Node::InsertionNotificationRequest HTMLScriptElement::InsertedInto(
     ContainerNode& insertion_point) {
-  ScriptType script_type = ScriptType::kClassic;
+  mojom::ScriptType script_type = mojom::ScriptType::kClassic;
   if (insertion_point.isConnected() && HasSourceAttribute() &&
       !ScriptLoader::IsValidScriptTypeAndLanguage(
           TypeAttributeValue(), LanguageAttributeValue(),
diff --git a/third_party/blink/renderer/core/html/image_document.cc b/third_party/blink/renderer/core/html/image_document.cc
index 63921a2..c62ef5b 100644
--- a/third_party/blink/renderer/core/html/image_document.cc
+++ b/third_party/blink/renderer/core/html/image_document.cc
@@ -62,7 +62,7 @@
 class ImageEventListener : public EventListener {
  public:
   static ImageEventListener* Create(ImageDocument* document) {
-    return new ImageEventListener(document);
+    return MakeGarbageCollected<ImageEventListener>(document);
   }
   static const ImageEventListener* Cast(const EventListener* listener) {
     return listener->GetType() == kImageEventListenerType
@@ -70,6 +70,9 @@
                : nullptr;
   }
 
+  ImageEventListener(ImageDocument* document)
+      : EventListener(kImageEventListenerType), doc_(document) {}
+
   bool operator==(const EventListener& other) const override;
 
   void Trace(blink::Visitor* visitor) override {
@@ -78,9 +81,6 @@
   }
 
  private:
-  ImageEventListener(ImageDocument* document)
-      : EventListener(kImageEventListenerType), doc_(document) {}
-
   void handleEvent(ExecutionContext*, Event*) override;
 
   Member<ImageDocument> doc_;
@@ -89,17 +89,17 @@
 class ImageDocumentParser : public RawDataDocumentParser {
  public:
   static ImageDocumentParser* Create(ImageDocument* document) {
-    return new ImageDocumentParser(document);
+    return MakeGarbageCollected<ImageDocumentParser>(document);
   }
 
+  ImageDocumentParser(ImageDocument* document)
+      : RawDataDocumentParser(document) {}
+
   ImageDocument* GetDocument() const {
     return ToImageDocument(RawDataDocumentParser::GetDocument());
   }
 
  private:
-  ImageDocumentParser(ImageDocument* document)
-      : RawDataDocumentParser(document) {}
-
   void AppendBytes(const char*, size_t) override;
   void Finish() override;
 };
diff --git a/third_party/blink/renderer/core/html/image_document.h b/third_party/blink/renderer/core/html/image_document.h
index 36c0114..e8cf65d 100644
--- a/third_party/blink/renderer/core/html/image_document.h
+++ b/third_party/blink/renderer/core/html/image_document.h
@@ -37,9 +37,11 @@
 class CORE_EXPORT ImageDocument final : public HTMLDocument {
  public:
   static ImageDocument* Create(const DocumentInit& initializer) {
-    return new ImageDocument(initializer);
+    return MakeGarbageCollected<ImageDocument>(initializer);
   }
 
+  explicit ImageDocument(const DocumentInit&);
+
   ImageResourceContent* CachedImage();
 
   // TODO(hiroshige): Remove this.
@@ -58,8 +60,6 @@
   void Trace(blink::Visitor*) override;
 
  private:
-  explicit ImageDocument(const DocumentInit&);
-
   DocumentParser* CreateParser() override;
 
   void CreateDocumentStructure();
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index b2f38cd..9f3fb193 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -29,6 +29,7 @@
 
 #include <memory>
 #include "base/optional.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
 #include "third_party/blink/renderer/core/css/media_list.h"
 #include "third_party/blink/renderer/core/css/media_query_evaluator.h"
@@ -279,7 +280,7 @@
 
     if ((Match(tag_impl_, kScriptTag) && type_attribute_value_ == "module") ||
         IsLinkRelModulePreload()) {
-      request->SetScriptType(ScriptType::kModule);
+      request->SetScriptType(mojom::ScriptType::kModule);
     }
 
     request->SetCrossOrigin(cross_origin_);
@@ -594,7 +595,7 @@
     if (Match(tag_impl_, kInputTag) && !input_is_image_)
       return false;
     if (Match(tag_impl_, kScriptTag)) {
-      ScriptType script_type = ScriptType::kClassic;
+      mojom::ScriptType script_type = mojom::ScriptType::kClassic;
       if (!ScriptLoader::IsValidScriptTypeAndLanguage(
               type_attribute_value_, language_attribute_value_,
               ScriptLoader::kAllowLegacyTypeInTypeAttribute, script_type)) {
diff --git a/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc b/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc
index 21a28c7..c000bee 100644
--- a/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc
@@ -25,6 +25,7 @@
 
 #include "third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.h"
 
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
 #include "third_party/blink/renderer/core/html/parser/html_tokenizer.h"
 #include "third_party/blink/renderer/core/html/parser/html_tree_builder.h"
@@ -172,7 +173,7 @@
           language_attribute_value = item->Value();
         }
 
-        ScriptType script_type;
+        mojom::ScriptType script_type;
         if (ScriptLoader::IsValidScriptTypeAndLanguage(
                 type_attribute_value, language_attribute_value,
                 ScriptLoader::kAllowLegacyTypeInTypeAttribute, script_type)) {
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 5a4b09f6..6ac2b436 100644
--- a/third_party/blink/renderer/core/html/parser/preload_request.cc
+++ b/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -57,7 +57,7 @@
                                        kCrossOriginAttributeAnonymous);
   }
 
-  if (script_type_ == ScriptType::kModule) {
+  if (script_type_ == mojom::ScriptType::kModule) {
     DCHECK_EQ(resource_type_, ResourceType::kScript);
     params.SetCrossOriginAccessControl(
         document->GetSecurityOrigin(),
@@ -77,7 +77,7 @@
   if (request_type_ == kRequestTypeLinkRelPreload)
     params.SetLinkPreload(true);
 
-  if (script_type_ == ScriptType::kModule) {
+  if (script_type_ == mojom::ScriptType::kModule) {
     DCHECK_EQ(resource_type_, ResourceType::kScript);
     params.SetDecoderOptions(
         TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText());
diff --git a/third_party/blink/renderer/core/html/parser/preload_request.h b/third_party/blink/renderer/core/html/parser/preload_request.h
index 0bd0956..69759164 100644
--- a/third_party/blink/renderer/core/html/parser/preload_request.h
+++ b/third_party/blink/renderer/core/html/parser/preload_request.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/script/script.h"
@@ -101,7 +102,9 @@
   }
   ReferrerPolicy GetReferrerPolicy() const { return referrer_policy_; }
 
-  void SetScriptType(ScriptType script_type) { script_type_ = script_type; }
+  void SetScriptType(mojom::ScriptType script_type) {
+    script_type_ = script_type;
+  }
 
   // Only scripts and css stylesheets need to have integrity set on preloads.
   // This is because neither resource keeps raw data around to redo an
@@ -142,7 +145,7 @@
         resource_url_(resource_url),
         base_url_(base_url),
         resource_type_(resource_type),
-        script_type_(ScriptType::kClassic),
+        script_type_(mojom::ScriptType::kClassic),
         cross_origin_(kCrossOriginAttributeNotSet),
         importance_(mojom::FetchImportanceMode::kImportanceAuto),
         defer_(FetchParameters::kNoDefer),
@@ -163,7 +166,7 @@
   KURL base_url_;
   String charset_;
   ResourceType resource_type_;
-  ScriptType script_type_;
+  mojom::ScriptType script_type_;
   CrossOriginAttributeValue cross_origin_;
   mojom::FetchImportanceMode importance_;
   String nonce_;
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 2c0cf4c1..b875c21 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -842,48 +842,50 @@
                                  base::Optional<IntRect> crop_rect,
                                  Document* document,
                                  const ImageBitmapOptions* options) {
-  return new ImageBitmap(image, crop_rect, document, options);
+  return MakeGarbageCollected<ImageBitmap>(image, crop_rect, document, options);
 }
 
 ImageBitmap* ImageBitmap::Create(HTMLVideoElement* video,
                                  base::Optional<IntRect> crop_rect,
                                  Document* document,
                                  const ImageBitmapOptions* options) {
-  return new ImageBitmap(video, crop_rect, document, options);
+  return MakeGarbageCollected<ImageBitmap>(video, crop_rect, document, options);
 }
 
 ImageBitmap* ImageBitmap::Create(HTMLCanvasElement* canvas,
                                  base::Optional<IntRect> crop_rect,
                                  const ImageBitmapOptions* options) {
-  return new ImageBitmap(canvas, crop_rect, options);
+  return MakeGarbageCollected<ImageBitmap>(canvas, crop_rect, options);
 }
 
 ImageBitmap* ImageBitmap::Create(OffscreenCanvas* offscreen_canvas,
                                  base::Optional<IntRect> crop_rect,
                                  const ImageBitmapOptions* options) {
-  return new ImageBitmap(offscreen_canvas, crop_rect, options);
+  return MakeGarbageCollected<ImageBitmap>(offscreen_canvas, crop_rect,
+                                           options);
 }
 
 ImageBitmap* ImageBitmap::Create(ImageData* data,
                                  base::Optional<IntRect> crop_rect,
                                  const ImageBitmapOptions* options) {
-  return new ImageBitmap(data, crop_rect, options);
+  return MakeGarbageCollected<ImageBitmap>(data, crop_rect, options);
 }
 
 ImageBitmap* ImageBitmap::Create(ImageBitmap* bitmap,
                                  base::Optional<IntRect> crop_rect,
                                  const ImageBitmapOptions* options) {
-  return new ImageBitmap(bitmap, crop_rect, options);
+  return MakeGarbageCollected<ImageBitmap>(bitmap, crop_rect, options);
 }
 
 ImageBitmap* ImageBitmap::Create(scoped_refptr<StaticBitmapImage> image,
                                  base::Optional<IntRect> crop_rect,
                                  const ImageBitmapOptions* options) {
-  return new ImageBitmap(std::move(image), crop_rect, options);
+  return MakeGarbageCollected<ImageBitmap>(std::move(image), crop_rect,
+                                           options);
 }
 
 ImageBitmap* ImageBitmap::Create(scoped_refptr<StaticBitmapImage> image) {
-  return new ImageBitmap(std::move(image));
+  return MakeGarbageCollected<ImageBitmap>(std::move(image));
 }
 
 ImageBitmap* ImageBitmap::Create(const void* pixel_data,
@@ -892,9 +894,9 @@
                                  bool is_image_bitmap_premultiplied,
                                  bool is_image_bitmap_origin_clean,
                                  const CanvasColorParams& color_params) {
-  return new ImageBitmap(pixel_data, width, height,
-                         is_image_bitmap_premultiplied,
-                         is_image_bitmap_origin_clean, color_params);
+  return MakeGarbageCollected<ImageBitmap>(
+      pixel_data, width, height, is_image_bitmap_premultiplied,
+      is_image_bitmap_origin_clean, color_params);
 }
 
 void ImageBitmap::ResolvePromiseOnOriginalThread(
@@ -927,7 +929,7 @@
                     v8::Null(resolver->GetScriptState()->GetIsolate())));
     return;
   }
-  ImageBitmap* bitmap = new ImageBitmap(image);
+  ImageBitmap* bitmap = MakeGarbageCollected<ImageBitmap>(image);
   bitmap->BitmapImage()->SetOriginClean(origin_clean);
   resolver->Resolve(bitmap);
 }
@@ -981,7 +983,8 @@
   // a transparent black image, respecting the color_params but ignoring
   // poremultiply_alpha.
   if (src_rect.IsEmpty()) {
-    ImageBitmap* bitmap = new ImageBitmap(MakeBlankImage(parsed_options));
+    ImageBitmap* bitmap =
+        MakeGarbageCollected<ImageBitmap>(MakeBlankImage(parsed_options));
     if (bitmap->BitmapImage()) {
       bitmap->BitmapImage()->SetOriginClean(
           !image->WouldTaintOrigin(document->GetSecurityOrigin()));
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.h b/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
index 125be92..a2939fa 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
@@ -88,6 +88,33 @@
       const ImageBitmapOptions* = ImageBitmapOptions::Create());
   static sk_sp<SkImage> GetSkImageFromDecoder(std::unique_ptr<ImageDecoder>);
 
+  ImageBitmap(ImageElementBase*,
+              base::Optional<IntRect>,
+              Document*,
+              const ImageBitmapOptions*);
+  ImageBitmap(HTMLVideoElement*,
+              base::Optional<IntRect>,
+              Document*,
+              const ImageBitmapOptions*);
+  ImageBitmap(HTMLCanvasElement*,
+              base::Optional<IntRect>,
+              const ImageBitmapOptions*);
+  ImageBitmap(OffscreenCanvas*,
+              base::Optional<IntRect>,
+              const ImageBitmapOptions*);
+  ImageBitmap(ImageData*, base::Optional<IntRect>, const ImageBitmapOptions*);
+  ImageBitmap(ImageBitmap*, base::Optional<IntRect>, const ImageBitmapOptions*);
+  ImageBitmap(scoped_refptr<StaticBitmapImage>);
+  ImageBitmap(scoped_refptr<StaticBitmapImage>,
+              base::Optional<IntRect>,
+              const ImageBitmapOptions*);
+  ImageBitmap(const void* pixel_data,
+              uint32_t width,
+              uint32_t height,
+              bool is_image_bitmap_premultiplied,
+              bool is_image_bitmap_origin_clean,
+              const CanvasColorParams&);
+
   // Type and helper function required by CallbackPromiseAdapter:
   using WebType = sk_sp<SkImage>;
   static ImageBitmap* Take(ScriptPromiseResolver*, sk_sp<SkImage>);
@@ -145,32 +172,6 @@
   };
 
  private:
-  ImageBitmap(ImageElementBase*,
-              base::Optional<IntRect>,
-              Document*,
-              const ImageBitmapOptions*);
-  ImageBitmap(HTMLVideoElement*,
-              base::Optional<IntRect>,
-              Document*,
-              const ImageBitmapOptions*);
-  ImageBitmap(HTMLCanvasElement*,
-              base::Optional<IntRect>,
-              const ImageBitmapOptions*);
-  ImageBitmap(OffscreenCanvas*,
-              base::Optional<IntRect>,
-              const ImageBitmapOptions*);
-  ImageBitmap(ImageData*, base::Optional<IntRect>, const ImageBitmapOptions*);
-  ImageBitmap(ImageBitmap*, base::Optional<IntRect>, const ImageBitmapOptions*);
-  ImageBitmap(scoped_refptr<StaticBitmapImage>);
-  ImageBitmap(scoped_refptr<StaticBitmapImage>,
-              base::Optional<IntRect>,
-              const ImageBitmapOptions*);
-  ImageBitmap(const void* pixel_data,
-              uint32_t width,
-              uint32_t height,
-              bool is_image_bitmap_premultiplied,
-              bool is_image_bitmap_origin_clean,
-              const CanvasColorParams&);
   void UpdateImageBitmapMemoryUsage();
   static void ResolvePromiseOnOriginalThread(ScriptPromiseResolver*,
                                              sk_sp<SkImage>,
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
index e99e7ed..a28078f 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
@@ -225,7 +225,7 @@
   ImageBitmapFactories* supplement =
       Supplement<GlobalObject>::template From<ImageBitmapFactories>(object);
   if (!supplement) {
-    supplement = new ImageBitmapFactories;
+    supplement = MakeGarbageCollected<ImageBitmapFactories>();
     Supplement<GlobalObject>::ProvideTo(object, supplement);
   }
   return *supplement;
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h b/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
index 3ac0bbb..6b20fc6 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
@@ -109,9 +109,15 @@
                                      base::Optional<IntRect> crop_rect,
                                      const ImageBitmapOptions* options,
                                      ScriptState* script_state) {
-      return new ImageBitmapLoader(factory, crop_rect, script_state, options);
+      return MakeGarbageCollected<ImageBitmapLoader>(factory, crop_rect,
+                                                     script_state, options);
     }
 
+    ImageBitmapLoader(ImageBitmapFactories&,
+                      base::Optional<IntRect> crop_rect,
+                      ScriptState*,
+                      const ImageBitmapOptions*);
+
     void LoadBlobAsync(Blob*);
     ScriptPromise Promise() { return resolver_->Promise(); }
 
@@ -120,11 +126,6 @@
     ~ImageBitmapLoader() override = default;
 
    private:
-    ImageBitmapLoader(ImageBitmapFactories&,
-                      base::Optional<IntRect> crop_rect,
-                      ScriptState*,
-                      const ImageBitmapOptions*);
-
     enum ImageBitmapRejectionReason {
       kUndecodableImageBitmapRejectionReason,
       kAllocationFailureImageBitmapRejectionReason,
diff --git a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
index 7c053e5..679b7d6c 100644
--- a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
+++ b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.h"
 
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -42,7 +43,7 @@
       worker_clients, frame->Client()->CreateWorkerContentSettingsClient());
 
   auto creation_params = std::make_unique<GlobalScopeCreationParams>(
-      document->Url(), ScriptType::kModule, document->UserAgent(),
+      document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
       document->GetContentSecurityPolicy()->Headers(),
       document->GetReferrerPolicy(), document->GetSecurityOrigin(),
       document->IsSecureContext(), document->GetHttpsState(), worker_clients,
diff --git a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
index 53ed941..e8d970d7 100644
--- a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
+++ b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
@@ -207,7 +207,7 @@
   // exclusion space in the copy-chain is used for answering queries. Only when
   // we trigger a (rare) re-layout case will we need to rebuild the
   // derived_geometry_ data-structure.
-  struct DerivedGeometry {
+  struct CORE_EXPORT DerivedGeometry {
     USING_FAST_MALLOC(DerivedGeometry);
 
    public:
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
index c254b3a..2402cae8 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
@@ -80,6 +80,15 @@
   }
 }
 
+LayoutUnit NGInlineBoxState::TextTop(FontBaseline baseline_type) const {
+  if (!text_metrics.IsEmpty())
+    return text_top;
+  if (const SimpleFontData* font_data = style->GetFont().PrimaryFont())
+    return -font_data->GetFontMetrics().FixedAscent(baseline_type);
+  NOTREACHED();
+  return LayoutUnit();
+}
+
 bool NGInlineBoxState::CanAddTextOfStyle(
     const ComputedStyle& text_style) const {
   if (text_style.VerticalAlign() != EVerticalAlign::kBaseline)
@@ -552,8 +561,7 @@
         child.metrics = NGLineHeightMetrics::Zero();
       switch (child.vertical_align) {
         case EVerticalAlign::kTextTop:
-          DCHECK(!box->text_metrics.IsEmpty());
-          baseline_shift = child.metrics.ascent + box->text_top;
+          baseline_shift = child.metrics.ascent + box->TextTop(baseline_type);
           break;
         case EVerticalAlign::kTop:
           baseline_shift = child.metrics.ascent - max.ascent;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
index 5238efd..0328806 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
@@ -87,6 +87,9 @@
 
   void AccumulateUsedFonts(const ShapeResult*, FontBaseline);
 
+  // 'text-top' offset for 'vertical-align'.
+  LayoutUnit TextTop(FontBaseline baseline_type) const;
+
   // Create a box fragment for this box.
   void SetNeedsBoxFragment(const LayoutObject* inline_container);
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc
index 49df71cf..b19bf7c 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc
@@ -6,6 +6,7 @@
 
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/platform/fonts/font_baseline.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
 
@@ -115,6 +116,24 @@
 // Hide this child from being painted.
 void NGLineTruncator::HideChild(NGLineBoxFragmentBuilder::Child* child) {
   DCHECK(child->HasInFlowFragment());
+
+  // If this child has self painting layer, not producing fragments will not
+  // suppress painting because layers are painted separately. Move it out of the
+  // clipping area.
+  const NGPhysicalFragment* fragment = child->PhysicalFragment();
+  DCHECK(fragment);
+  if (const NGPhysicalBoxFragment* box_fragment =
+          ToNGPhysicalBoxFragmentOrNull(fragment)) {
+    if (box_fragment->HasSelfPaintingLayer()) {
+      // |avilable_width_| may not be enough when the contaning block has
+      // paddings, because clipping is at the content box but ellipsizing is at
+      // the padding box. Just move to the max because we don't know paddings,
+      // and max should do what we need.
+      child->offset.inline_offset = LayoutUnit::NearlyMax();
+      return;
+    }
+  }
+
   // TODO(kojii): Not producing fragments is the most clean and efficient way to
   // hide them, but we may want to revisit how to do this to reduce special
   // casing in other code.
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc
index a291509d2..c9176bf 100644
--- a/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -889,8 +889,8 @@
 
   UseCounter::Count(GetElement()->GetDocument(), WebFeature::kImageDecodeAPI);
 
-  auto* request =
-      new DecodeRequest(this, ScriptPromiseResolver::Create(script_state));
+  auto* request = MakeGarbageCollected<DecodeRequest>(
+      this, ScriptPromiseResolver::Create(script_state));
   Microtask::EnqueueMicrotask(
       WTF::Bind(&DecodeRequest::ProcessForTask, WrapWeakPersistent(request)));
   decode_requests_.push_back(request);
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
index d2b1e4ad..83fa598d 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
@@ -182,11 +182,11 @@
   reporting_proxy_ =
       std::make_unique<MainThreadWorkletReportingProxy>(&GetDocument());
   auto creation_params = std::make_unique<GlobalScopeCreationParams>(
-      GetDocument().Url(), ScriptType::kModule, GetDocument().UserAgent(),
-      Vector<CSPHeaderAndType>(), GetDocument().GetReferrerPolicy(),
-      GetDocument().GetSecurityOrigin(), GetDocument().IsSecureContext(),
-      GetDocument().GetHttpsState(), nullptr /* worker_clients */,
-      GetDocument().AddressSpace(),
+      GetDocument().Url(), mojom::ScriptType::kModule,
+      GetDocument().UserAgent(), Vector<CSPHeaderAndType>(),
+      GetDocument().GetReferrerPolicy(), GetDocument().GetSecurityOrigin(),
+      GetDocument().IsSecureContext(), GetDocument().GetHttpsState(),
+      nullptr /* worker_clients */, GetDocument().AddressSpace(),
       OriginTrialContext::GetTokens(&GetDocument()).get(),
       base::UnguessableToken::Create(), nullptr /* worker_settings */,
       kV8CacheOptionsDefault, new WorkletModuleResponsesMap);
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 6556296..69452f9 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource.cc
@@ -158,10 +158,10 @@
 
   Resource* Create(const ResourceRequest& request,
                    const ResourceLoaderOptions& options) const override {
-    return new ImageResource(request, options,
-                             ImageResourceContent::CreateNotStarted(),
-                             fetch_params_->GetImageRequestOptimization() ==
-                                 FetchParameters::kAllowPlaceholder);
+    return MakeGarbageCollected<ImageResource>(
+        request, options, ImageResourceContent::CreateNotStarted(),
+        fetch_params_->GetImageRequestOptimization() ==
+            FetchParameters::kAllowPlaceholder);
   }
 
  private:
@@ -212,8 +212,8 @@
 
 ImageResource* ImageResource::Create(const ResourceRequest& request) {
   ResourceLoaderOptions options;
-  return new ImageResource(request, options,
-                           ImageResourceContent::CreateNotStarted(), false);
+  return MakeGarbageCollected<ImageResource>(
+      request, options, ImageResourceContent::CreateNotStarted(), false);
 }
 
 ImageResource* ImageResource::CreateForTest(const KURL& url) {
@@ -232,8 +232,10 @@
           is_placeholder ? PlaceholderOption::kShowAndReloadPlaceholderAlways
                          : PlaceholderOption::kDoNotReloadPlaceholder) {
   DCHECK(GetContent());
-  RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this;
-  GetContent()->SetImageResourceInfo(new ImageResourceInfoImpl(this));
+  RESOURCE_LOADING_DVLOG(1)
+      << "MakeGarbageCollected<ImageResource>(ResourceRequest) " << this;
+  GetContent()->SetImageResourceInfo(
+      MakeGarbageCollected<ImageResourceInfoImpl>(this));
 }
 
 ImageResource::~ImageResource() {
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource.h b/third_party/blink/renderer/core/loader/resource/image_resource.h
index 572ecac..f24eef1 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource.h
+++ b/third_party/blink/renderer/core/loader/resource/image_resource.h
@@ -65,6 +65,10 @@
   static ImageResource* Create(const ResourceRequest&);
   static ImageResource* CreateForTest(const KURL&);
 
+  ImageResource(const ResourceRequest&,
+                const ResourceLoaderOptions&,
+                ImageResourceContent*,
+                bool is_placeholder);
   ~ImageResource() override;
 
   ImageResourceContent* GetContent();
@@ -120,11 +124,6 @@
   class ImageResourceInfoImpl;
   class ImageResourceFactory;
 
-  ImageResource(const ResourceRequest&,
-                const ResourceLoaderOptions&,
-                ImageResourceContent*,
-                bool is_placeholder);
-
   // Only for ImageResourceInfoImpl.
   void DecodeError(bool all_data_received);
   bool IsAccessAllowed(
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
index 776daad..e5764f1 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -112,7 +112,8 @@
 ImageResourceContent* ImageResourceContent::CreateLoaded(
     scoped_refptr<blink::Image> image) {
   DCHECK(image);
-  ImageResourceContent* content = new ImageResourceContent(std::move(image));
+  ImageResourceContent* content =
+      MakeGarbageCollected<ImageResourceContent>(std::move(image));
   content->content_status_ = ResourceStatus::kCached;
   return content;
 }
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
index e9fcd66..a94b30a 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_content.h
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
@@ -49,7 +49,7 @@
   // Used for loading.
   // Returned content will be associated immediately later with ImageResource.
   static ImageResourceContent* CreateNotStarted() {
-    return new ImageResourceContent(nullptr);
+    return MakeGarbageCollected<ImageResourceContent>(nullptr);
   }
 
   // Creates ImageResourceContent from an already loaded image.
@@ -57,6 +57,8 @@
 
   static ImageResourceContent* Fetch(FetchParameters&, ResourceFetcher*);
 
+  explicit ImageResourceContent(scoped_refptr<blink::Image> = nullptr);
+
   // Returns the NullImage() if the image is not available yet.
   blink::Image* GetImage() const;
   bool HasImage() const { return image_.get(); }
@@ -183,8 +185,6 @@
  private:
   using CanDeferInvalidation = ImageResourceObserver::CanDeferInvalidation;
 
-  explicit ImageResourceContent(scoped_refptr<blink::Image> = nullptr);
-
   // ImageObserver
   void DecodedSizeChangedTo(const blink::Image*, size_t new_size) override;
   bool ShouldPauseAnimation(const blink::Image*) override;
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.h b/third_party/blink/renderer/core/script/classic_pending_script.h
index 6655de5..45faa0a04 100644
--- a/third_party/blink/renderer/core/script/classic_pending_script.h
+++ b/third_party/blink/renderer/core/script/classic_pending_script.h
@@ -55,8 +55,8 @@
 
   void Trace(blink::Visitor*) override;
 
-  blink::ScriptType GetScriptType() const override {
-    return blink::ScriptType::kClassic;
+  mojom::ScriptType GetScriptType() const override {
+    return mojom::ScriptType::kClassic;
   }
 
   void WatchForLoad(PendingScriptClient*) override;
diff --git a/third_party/blink/renderer/core/script/classic_script.h b/third_party/blink/renderer/core/script/classic_script.h
index 873272c..0dd4b27 100644
--- a/third_party/blink/renderer/core/script/classic_script.h
+++ b/third_party/blink/renderer/core/script/classic_script.h
@@ -39,7 +39,9 @@
         script_source_code_(script_source_code),
         access_control_status_(access_control_status) {}
 
-  ScriptType GetScriptType() const override { return ScriptType::kClassic; }
+  mojom::ScriptType GetScriptType() const override {
+    return mojom::ScriptType::kClassic;
+  }
   void RunScript(LocalFrame*, const SecurityOrigin*) const override;
   String InlineSourceTextForCSP() const override {
     return script_source_code_.Source().ToString();
diff --git a/third_party/blink/renderer/core/script/module_pending_script.h b/third_party/blink/renderer/core/script/module_pending_script.h
index 916b0737..b9915712 100644
--- a/third_party/blink/renderer/core/script/module_pending_script.h
+++ b/third_party/blink/renderer/core/script/module_pending_script.h
@@ -71,7 +71,9 @@
                       bool is_external);
 
   // PendingScript
-  ScriptType GetScriptType() const override { return ScriptType::kModule; }
+  mojom::ScriptType GetScriptType() const override {
+    return mojom::ScriptType::kModule;
+  }
   Script* GetSource(const KURL& document_url) const override;
   bool IsReady() const override { return ready_; }
   bool IsExternal() const override { return is_external_; }
diff --git a/third_party/blink/renderer/core/script/module_script.h b/third_party/blink/renderer/core/script/module_script.h
index 43f90219..e44e3de 100644
--- a/third_party/blink/renderer/core/script/module_script.h
+++ b/third_party/blink/renderer/core/script/module_script.h
@@ -81,7 +81,9 @@
                                       const ScriptFetchOptions&,
                                       const TextPosition&);
 
-  ScriptType GetScriptType() const override { return ScriptType::kModule; }
+  mojom::ScriptType GetScriptType() const override {
+    return mojom::ScriptType::kModule;
+  }
   void RunScript(LocalFrame*, const SecurityOrigin*) const override;
   String InlineSourceTextForCSP() const override;
 
diff --git a/third_party/blink/renderer/core/script/pending_script.cc b/third_party/blink/renderer/core/script/pending_script.cc
index 5617cb0..318b4c3 100644
--- a/third_party/blink/renderer/core/script/pending_script.cc
+++ b/third_party/blink/renderer/core/script/pending_script.cc
@@ -139,7 +139,7 @@
   }
 
   if (OriginalContextDocument() != context_document) {
-    if (GetScriptType() == ScriptType::kModule) {
+    if (GetScriptType() == mojom::ScriptType::kModule) {
       // Do not execute module scripts if they are moved between documents.
       Dispose();
       return;
@@ -229,7 +229,7 @@
     // <spec step="3">If the script is from an external file, or the script's
     // type is "module", ...</spec>
     const bool needs_increment =
-        is_external || script->GetScriptType() == ScriptType::kModule ||
+        is_external || script->GetScriptType() == mojom::ScriptType::kModule ||
         is_imported_script;
     // <spec step="3">... then increment the ignore-destructive-writes counter
     // of the script element's node document. Let neutralized doc be that
@@ -256,7 +256,7 @@
     // <spec step="5.B.1">Set the script element's node document's currentScript
     // attribute to null.</spec>
     ScriptElementBase* current_script = nullptr;
-    if (script->GetScriptType() == ScriptType::kClassic)
+    if (script->GetScriptType() == mojom::ScriptType::kClassic)
       current_script = element;
     context_document->PushCurrentScript(current_script);
 
diff --git a/third_party/blink/renderer/core/script/pending_script.h b/third_party/blink/renderer/core/script/pending_script.h
index 02cf4944..0ab9815 100644
--- a/third_party/blink/renderer/core/script/pending_script.h
+++ b/third_party/blink/renderer/core/script/pending_script.h
@@ -27,6 +27,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_SCRIPT_H_
 
 #include "base/macros.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/script/script.h"
@@ -82,7 +83,7 @@
 
   ScriptElementBase* GetElement() const;
 
-  virtual ScriptType GetScriptType() const = 0;
+  virtual mojom::ScriptType GetScriptType() const = 0;
 
   virtual void Trace(blink::Visitor*);
   const char* NameInHeapSnapshot() const override { return "PendingScript"; }
@@ -107,7 +108,7 @@
 
   // Used for DCHECK()s.
   bool IsExternalOrModule() const {
-    return IsExternal() || GetScriptType() == ScriptType::kModule;
+    return IsExternal() || GetScriptType() == mojom::ScriptType::kModule;
   }
 
   void Dispose();
diff --git a/third_party/blink/renderer/core/script/script.h b/third_party/blink/renderer/core/script/script.h
index a807959..7ef29600 100644
--- a/third_party/blink/renderer/core/script/script.h
+++ b/third_party/blink/renderer/core/script/script.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_H_
 
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
@@ -16,10 +17,6 @@
 class LocalFrame;
 class SecurityOrigin;
 
-// TODO(asamidoi, nhiroki): Remove this enum in favor of
-// blink::mojom::ScriptType.
-enum class ScriptType { kClassic, kModule };
-
 // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script
 class CORE_EXPORT Script : public GarbageCollectedFinalized<Script> {
  public:
@@ -27,7 +24,7 @@
 
   virtual ~Script() {}
 
-  virtual ScriptType GetScriptType() const = 0;
+  virtual mojom::ScriptType GetScriptType() const = 0;
 
   // https://html.spec.whatwg.org/multipage/webappapis.html#run-a-classic-script
   // or
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc
index 07b010d..d1a1d4b 100644
--- a/third_party/blink/renderer/core/script/script_loader.cc
+++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -170,14 +170,14 @@
     const String& type,
     const String& language,
     LegacyTypeSupport support_legacy_types,
-    ScriptType& out_script_type) {
+    mojom::ScriptType& out_script_type) {
   if (IsValidClassicScriptTypeAndLanguage(type, language,
                                           support_legacy_types)) {
     // <spec step="7">... If the script block's type string is a JavaScript MIME
     // type essence match, the script's type is "classic". ...</spec>
     //
     // TODO(hiroshige): Annotate and/or cleanup this step.
-    out_script_type = ScriptType::kClassic;
+    out_script_type = mojom::ScriptType::kClassic;
     return true;
   }
 
@@ -185,7 +185,7 @@
     // <spec step="7">... If the script block's type string is an ASCII
     // case-insensitive match for the string "module", the script's type is
     // "module". ...</spec>
-    out_script_type = ScriptType::kModule;
+    out_script_type = mojom::ScriptType::kModule;
     return true;
   }
 
@@ -194,8 +194,9 @@
   return false;
 }
 
-bool ScriptLoader::BlockForNoModule(ScriptType script_type, bool nomodule) {
-  return nomodule && script_type == ScriptType::kClassic;
+bool ScriptLoader::BlockForNoModule(mojom::ScriptType script_type,
+                                    bool nomodule) {
+  return nomodule && script_type == mojom::ScriptType::kClassic;
 }
 
 // Corresponds to
@@ -221,7 +222,7 @@
 
 // https://github.com/WICG/feature-policy/issues/135
 bool ShouldBlockSyncScriptForFeaturePolicy(const ScriptElementBase* element,
-                                           ScriptType script_type,
+                                           mojom::ScriptType script_type,
                                            bool parser_inserted) {
   if (element->GetDocument().GetFeaturePolicy()->IsFeatureEnabled(
           mojom::FeaturePolicyFeature::kSyncScript)) {
@@ -229,7 +230,7 @@
   }
 
   // Module scripts never block parsing.
-  if (script_type == ScriptType::kModule || !parser_inserted)
+  if (script_type == mojom::ScriptType::kModule || !parser_inserted)
     return false;
 
   if (!element->HasSourceAttribute())
@@ -386,7 +387,7 @@
   ParserDisposition parser_state =
       IsParserInserted() ? kParserInserted : kNotParserInserted;
 
-  if (GetScriptType() == ScriptType::kModule)
+  if (GetScriptType() == mojom::ScriptType::kModule)
     UseCounter::Count(*context_document, WebFeature::kPrepareModuleScript);
 
   DCHECK(!prepared_pending_script_);
@@ -454,7 +455,7 @@
     }
 
     // <spec step="24.6">Switch on the script's type:</spec>
-    if (GetScriptType() == ScriptType::kClassic) {
+    if (GetScriptType() == mojom::ScriptType::kClassic) {
       // - "classic":
 
       // <spec step="15">If the script element has a charset attribute, then let
@@ -524,7 +525,7 @@
     // <spec step="25.2">Switch on the script's type:</spec>
     switch (GetScriptType()) {
       // <spec step="25.2.A">"classic"</spec>
-      case ScriptType::kClassic: {
+      case mojom::ScriptType::kClassic: {
         // <spec step="25.2.A.1">Let script be the result of creating a classic
         // script using source text, settings object, base URL, and
         // options.</spec>
@@ -551,7 +552,7 @@
       }
 
       // <spec step="25.2.B">"module"</spec>
-      case ScriptType::kModule: {
+      case mojom::ScriptType::kModule: {
         // <spec step="25.2.B.1">Let script be the result of creating a module
         // script using source text, settings object, base URL, and
         // options.</spec>
@@ -602,10 +603,10 @@
   // If the script's type is "module", and the element has been flagged as
   // "parser-inserted", and the element does not have an async attribute
   // ...</spec>
-  if ((GetScriptType() == ScriptType::kClassic &&
+  if ((GetScriptType() == mojom::ScriptType::kClassic &&
        element_->HasSourceAttribute() && element_->DeferAttributeValue() &&
        parser_inserted_ && !element_->AsyncAttributeValue()) ||
-      (GetScriptType() == ScriptType::kModule && parser_inserted_ &&
+      (GetScriptType() == mojom::ScriptType::kModule && parser_inserted_ &&
        !element_->AsyncAttributeValue())) {
     // This clause is implemented by the caller-side of prepareScript():
     // - HTMLParserScriptRunner::requestDeferredScript(), and
@@ -619,7 +620,7 @@
   // <spec step="26.B">If the script's type is "classic", and the element has a
   // src attribute, and the element has been flagged as "parser-inserted", and
   // the element does not have an async attribute ...</spec>
-  if (GetScriptType() == ScriptType::kClassic &&
+  if (GetScriptType() == mojom::ScriptType::kClassic &&
       element_->HasSourceAttribute() && parser_inserted_ &&
       !element_->AsyncAttributeValue()) {
     // This clause is implemented by the caller-side of prepareScript():
@@ -637,10 +638,10 @@
   // If the script's type is "module", and the element does not have an async
   // attribute, and the element does not have the "non-blocking" flag set
   // ...</spec>
-  if ((GetScriptType() == ScriptType::kClassic &&
+  if ((GetScriptType() == mojom::ScriptType::kClassic &&
        element_->HasSourceAttribute() && !element_->AsyncAttributeValue() &&
        !non_blocking_) ||
-      (GetScriptType() == ScriptType::kModule &&
+      (GetScriptType() == mojom::ScriptType::kModule &&
        !element_->AsyncAttributeValue() && !non_blocking_)) {
     // <spec step="26.C">... Add the element to the end of the list of scripts
     // that will execute in order as soon as possible associated with the node
@@ -664,9 +665,9 @@
   // src attribute
   //
   // If the script's type is "module" ...</spec>
-  if ((GetScriptType() == ScriptType::kClassic &&
+  if ((GetScriptType() == mojom::ScriptType::kClassic &&
        element_->HasSourceAttribute()) ||
-      GetScriptType() == ScriptType::kModule) {
+      GetScriptType() == mojom::ScriptType::kModule) {
     // <spec step="26.D">... The element must be added to the set of scripts
     // that will execute as soon as possible of the node document of the script
     // element at the time the prepare a script algorithm started. When the
@@ -688,7 +689,7 @@
 
   // The following clauses are executed only if the script's type is "classic"
   // and the element doesn't have a src attribute.
-  DCHECK_EQ(GetScriptType(), ScriptType::kClassic);
+  DCHECK_EQ(GetScriptType(), mojom::ScriptType::kClassic);
   DCHECK(!is_external_script_);
 
   // <spec step="26.E">If the element does not have a src attribute, and the
@@ -831,8 +832,8 @@
 
   // <spec step="14">If the script element has an event attribute and a for
   // attribute, and the script's type is "classic", then:</spec>
-  if (GetScriptType() != ScriptType::kClassic || event_attribute.IsNull() ||
-      for_attribute.IsNull())
+  if (GetScriptType() != mojom::ScriptType::kClassic ||
+      event_attribute.IsNull() || for_attribute.IsNull())
     return true;
 
   // <spec step="14.3">Strip leading and trailing ASCII whitespace from event
diff --git a/third_party/blink/renderer/core/script/script_loader.h b/third_party/blink/renderer/core/script/script_loader.h
index 0369a823..c805115 100644
--- a/third_party/blink/renderer/core/script/script_loader.h
+++ b/third_party/blink/renderer/core/script/script_loader.h
@@ -21,6 +21,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_LOADER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_LOADER_H_
 
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -72,9 +73,9 @@
       const String& type_attribute_value,
       const String& language_attribute_value,
       LegacyTypeSupport support_legacy_types,
-      ScriptType& out_script_type);
+      mojom::ScriptType& out_script_type);
 
-  static bool BlockForNoModule(ScriptType, bool nomodule);
+  static bool BlockForNoModule(mojom::ScriptType, bool nomodule);
 
   static network::mojom::FetchCredentialsMode ModuleScriptCredentialsMode(
       CrossOriginAttributeValue);
@@ -97,7 +98,7 @@
   bool IsParserInserted() const { return parser_inserted_; }
   bool AlreadyStarted() const { return already_started_; }
   bool IsNonBlocking() const { return non_blocking_; }
-  ScriptType GetScriptType() const { return script_type_; }
+  mojom::ScriptType GetScriptType() const { return script_type_; }
 
   // Helper functions used by our parent classes.
   void DidNotifySubtreeInsertionsToDocument();
@@ -169,7 +170,7 @@
   // <spec
   // href="https://html.spec.whatwg.org/multipage/scripting.html#concept-script-type">
   // ... It is determined when the script is prepared, ...</spec>
-  ScriptType script_type_ = ScriptType::kClassic;
+  mojom::ScriptType script_type_ = mojom::ScriptType::kClassic;
 
   // <spec
   // href="https://html.spec.whatwg.org/multipage/scripting.html#concept-script-external">
diff --git a/third_party/blink/renderer/core/script/script_runner_test.cc b/third_party/blink/renderer/core/script/script_runner_test.cc
index e25af54..05b41a5 100644
--- a/third_party/blink/renderer/core/script/script_runner_test.cc
+++ b/third_party/blink/renderer/core/script/script_runner_test.cc
@@ -35,7 +35,7 @@
 
   ~MockPendingScript() override {}
 
-  MOCK_CONST_METHOD0(GetScriptType, ScriptType());
+  MOCK_CONST_METHOD0(GetScriptType, mojom::ScriptType());
   MOCK_CONST_METHOD1(CheckMIMETypeBeforeRunScript, bool(Document*));
   MOCK_CONST_METHOD1(GetSource, Script*(const KURL&));
   MOCK_CONST_METHOD0(IsExternal, bool());
diff --git a/third_party/blink/renderer/core/script/xml_parser_script_runner.cc b/third_party/blink/renderer/core/script/xml_parser_script_runner.cc
index 84a33bd79..4b13772c 100644
--- a/third_party/blink/renderer/core/script/xml_parser_script_runner.cc
+++ b/third_party/blink/renderer/core/script/xml_parser_script_runner.cc
@@ -46,7 +46,7 @@
 
   pending_script->StopWatchingForLoad();
 
-  CHECK_EQ(pending_script->GetScriptType(), ScriptType::kClassic);
+  CHECK_EQ(pending_script->GetScriptType(), mojom::ScriptType::kClassic);
 
   // <spec label="Parsing" step="4">Execute the pending parsing-blocking
   // script.</spec>
@@ -76,7 +76,7 @@
   bool success = script_loader->PrepareScript(
       script_start_position, ScriptLoader::kAllowLegacyTypeInTypeAttribute);
 
-  if (script_loader->GetScriptType() != ScriptType::kClassic) {
+  if (script_loader->GetScriptType() != mojom::ScriptType::kClassic) {
     // XMLDocumentParser does not support a module script, and thus ignores it.
     success = false;
     document.AddConsoleMessage(
diff --git a/third_party/blink/renderer/core/style/content_data.cc b/third_party/blink/renderer/core/style/content_data.cc
index c88025ac..077259f 100644
--- a/third_party/blink/renderer/core/style/content_data.cc
+++ b/third_party/blink/renderer/core/style/content_data.cc
@@ -35,7 +35,7 @@
 namespace blink {
 
 ContentData* ContentData::Create(StyleImage* image) {
-  return new ImageContentData(image);
+  return MakeGarbageCollected<ImageContentData>(image);
 }
 
 ContentData* ContentData::Create(const String& text) {
diff --git a/third_party/blink/renderer/core/style/content_data.h b/third_party/blink/renderer/core/style/content_data.h
index 90c56f3..7d9fd3b 100644
--- a/third_party/blink/renderer/core/style/content_data.h
+++ b/third_party/blink/renderer/core/style/content_data.h
@@ -78,6 +78,8 @@
   friend class ContentData;
 
  public:
+  ImageContentData(StyleImage* image) : image_(image) { DCHECK(image_); }
+
   const StyleImage* GetImage() const { return image_.Get(); }
   StyleImage* GetImage() { return image_.Get(); }
   void SetImage(StyleImage* image) {
@@ -99,8 +101,6 @@
   void Trace(blink::Visitor*) override;
 
  private:
-  ImageContentData(StyleImage* image) : image_(image) { DCHECK(image_); }
-
   ContentData* CloneInternal() const override {
     StyleImage* image = const_cast<StyleImage*>(this->GetImage());
     return Create(image);
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc
index 4ec18c2..93b518a 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -8,6 +8,7 @@
 #include "services/network/public/mojom/fetch_api.mojom-blink.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/public/platform/dedicated_worker_factory.mojom-blink.h"
 #include "third_party/blink/public/platform/web_content_settings_client.h"
 #include "third_party/blink/public/platform/web_layer_tree_view.h"
@@ -322,9 +323,9 @@
     settings = WorkerSettings::Copy(worker_global_scope->GetWorkerSettings());
   }
 
-  ScriptType script_type = (options_->type() == "classic")
-                               ? ScriptType::kClassic
-                               : ScriptType::kModule;
+  mojom::ScriptType script_type = (options_->type() == "classic")
+                                      ? mojom::ScriptType::kClassic
+                                      : mojom::ScriptType::kModule;
   return std::make_unique<GlobalScopeCreationParams>(
       script_url, script_type, GetExecutionContext()->UserAgent(),
       GetExecutionContext()->GetContentSecurityPolicy()->Headers(),
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
index 93b0622..3cda139 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
@@ -133,7 +133,7 @@
         To<Document>(GetExecutionContext())->GetSettings());
     InitializeWorkerThread(
         std::make_unique<GlobalScopeCreationParams>(
-            script_url, ScriptType::kClassic, "fake user agent", headers,
+            script_url, mojom::ScriptType::kClassic, "fake user agent", headers,
             kReferrerPolicyDefault, security_origin_.get(),
             false /* starter_secure_context */,
             CalculateHttpsState(security_origin_.get()),
diff --git a/third_party/blink/renderer/core/workers/experimental/thread_pool.cc b/third_party/blink/renderer/core/workers/experimental/thread_pool.cc
index 7317304a..edd2ed31 100644
--- a/third_party/blink/renderer/core/workers/experimental/thread_pool.cc
+++ b/third_party/blink/renderer/core/workers/experimental/thread_pool.cc
@@ -109,7 +109,7 @@
       std::make_unique<WorkerSettings>(GetFrame()->GetSettings());
 
   proxy->StartWorker(std::make_unique<GlobalScopeCreationParams>(
-      context->Url(), ScriptType::kClassic, context->UserAgent(),
+      context->Url(), mojom::ScriptType::kClassic, context->UserAgent(),
       context->GetContentSecurityPolicy()->Headers(), kReferrerPolicyDefault,
       context->GetSecurityOrigin(), context->IsSecureContext(),
       context->GetHttpsState(), WorkerClients::Create(),
diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.cc b/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
index d49696c4..1aef5420 100644
--- a/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
+++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
@@ -11,8 +11,7 @@
 
 GlobalScopeCreationParams::GlobalScopeCreationParams(
     const KURL& script_url,
-    // TODO(asamidoi): Replace ScriptType to mojom::ScriptType
-    ScriptType script_type,
+    mojom::ScriptType script_type,
     const String& user_agent,
     const Vector<CSPHeaderAndType>& content_security_policy_parsed_headers,
     ReferrerPolicy referrer_policy,
diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.h b/third_party/blink/renderer/core/workers/global_scope_creation_params.h
index dc8b5a1..d3be49cb 100644
--- a/third_party/blink/renderer/core/workers/global_scope_creation_params.h
+++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.h
@@ -12,6 +12,7 @@
 #include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/mojom/net/ip_address_space.mojom-blink.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
@@ -39,8 +40,7 @@
  public:
   GlobalScopeCreationParams(
       const KURL& script_url,
-      // TODO(asamidoi): Replace ScriptType to mojom::ScriptType
-      ScriptType script_type,
+      mojom::ScriptType script_type,
       const String& user_agent,
       const Vector<CSPHeaderAndType>& content_security_policy_parsed_headers,
       ReferrerPolicy referrer_policy,
@@ -75,7 +75,7 @@
   // workers.
   KURL script_url;
 
-  ScriptType script_type;
+  mojom::ScriptType script_type;
   String user_agent;
 
   // |content_security_policy_parsed_headers| and
diff --git a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
index 6771bef6..dfec289 100644
--- a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
+++ b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
@@ -64,7 +64,7 @@
     reporting_proxy_ =
         std::make_unique<MainThreadWorkletReportingProxyForTest>(document);
     auto creation_params = std::make_unique<GlobalScopeCreationParams>(
-        document->Url(), ScriptType::kModule, document->UserAgent(),
+        document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
         document->GetContentSecurityPolicy()->Headers(),
         document->GetReferrerPolicy(), document->GetSecurityOrigin(),
         document->IsSecureContext(), document->GetHttpsState(),
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
index e516b397..f9247bd5 100644
--- a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
+++ b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h"
 
 #include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -56,7 +57,7 @@
 
   auto global_scope_creation_params =
       std::make_unique<GlobalScopeCreationParams>(
-          document->Url(), ScriptType::kModule, document->UserAgent(),
+          document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
           csp->Headers(), document->GetReferrerPolicy(),
           document->GetSecurityOrigin(), document->IsSecureContext(),
           document->GetHttpsState(), worker_clients, document->AddressSpace(),
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
index 603e645..c5e51f1c 100644
--- a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
+++ b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
@@ -203,7 +203,7 @@
     std::unique_ptr<WorkerSettings> worker_settings = nullptr;
     InitializeWorkerThread(
         std::make_unique<GlobalScopeCreationParams>(
-            document->Url(), ScriptType::kModule, document->UserAgent(),
+            document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
             document->GetContentSecurityPolicy()->Headers(),
             document->GetReferrerPolicy(), document->GetSecurityOrigin(),
             document->IsSecureContext(), document->GetHttpsState(),
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc
index 5528e048..2a6fb979 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -146,7 +146,7 @@
 
   // Step 1: "If worker global scope's type is "module", throw a TypeError
   // exception."
-  if (script_type_ == ScriptType::kModule) {
+  if (script_type_ == mojom::ScriptType::kModule) {
     exception_state.ThrowTypeError(
         "Module scripts don't support importScripts().");
     return;
@@ -621,7 +621,7 @@
 }
 
 bool WorkerGlobalScope::IsScriptFetchedOnMainThread() {
-  if (script_type_ == ScriptType::kModule)
+  if (script_type_ == mojom::ScriptType::kModule)
     return false;
   // It's now supported only for dedicated workers to load top-level classic
   // worker script off the main thread.
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h
index 317ce78..c5842fd 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.h
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -31,6 +31,7 @@
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -202,7 +203,7 @@
 
   void AddPausedCall(base::OnceClosure closure);
 
-  ScriptType GetScriptType() const { return script_type_; }
+  mojom::ScriptType GetScriptType() const { return script_type_; }
 
  private:
   void SetWorkerSettings(std::unique_ptr<WorkerSettings>);
@@ -248,7 +249,7 @@
   void TasksWereUnpaused() override;
 
   const KURL url_;
-  const ScriptType script_type_;
+  const mojom::ScriptType script_type_;
   const String user_agent_;
   const base::UnguessableToken parent_devtools_token_;
   const V8CacheOptions v8_cache_options_;
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test.cc b/third_party/blink/renderer/core/workers/worker_thread_test.cc
index 29120ae..fecaf6a 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread_test.cc
@@ -389,9 +389,9 @@
 
   auto global_scope_creation_params =
       std::make_unique<GlobalScopeCreationParams>(
-          KURL("http://fake.url/"), ScriptType::kClassic, "fake user agent",
-          headers, kReferrerPolicyDefault, security_origin_.get(),
-          false /* starter_secure_context */,
+          KURL("http://fake.url/"), mojom::ScriptType::kClassic,
+          "fake user agent", headers, kReferrerPolicyDefault,
+          security_origin_.get(), false /* starter_secure_context */,
           CalculateHttpsState(security_origin_.get()), WorkerClients::Create(),
           mojom::IPAddressSpace::kLocal, nullptr /* originTrialToken */,
           base::UnguessableToken::Create(),
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
index afbe3fc..934d862 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
+++ b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -91,7 +91,7 @@
     Vector<CSPHeaderAndType> headers{
         {"contentSecurityPolicy", kContentSecurityPolicyHeaderTypeReport}};
     auto creation_params = std::make_unique<GlobalScopeCreationParams>(
-        script_url, ScriptType::kClassic, "fake user agent", headers,
+        script_url, mojom::ScriptType::kClassic, "fake user agent", headers,
         kReferrerPolicyDefault, security_origin,
         false /* starter_secure_context */,
         CalculateHttpsState(security_origin), worker_clients,
diff --git a/third_party/blink/renderer/devtools/front_end/Runtime.js b/third_party/blink/renderer/devtools/front_end/Runtime.js
index 5e6e5f1..11093b8 100644
--- a/third_party/blink/renderer/devtools/front_end/Runtime.js
+++ b/third_party/blink/renderer/devtools/front_end/Runtime.js
@@ -309,7 +309,7 @@
    * @return {?string}
    */
   static queryParam(name) {
-    return Runtime._queryParamsObject[name] || null;
+    return Runtime._queryParamsObject.get(name);
   }
 
   /**
@@ -564,12 +564,8 @@
   }
 };
 
-/**
- * @type {!Object.<string, string>}
- */
-Runtime._queryParamsObject = {
-  __proto__: null
-};
+/** @type {!URLSearchParams} */
+Runtime._queryParamsObject = new URLSearchParams(Runtime.queryParamsString());
 
 Runtime._instanceSymbol = Symbol('instance');
 
@@ -1069,20 +1065,6 @@
   }
 };
 
-{
-  (function parseQueryParameters() {
-    const queryParams = Runtime.queryParamsString();
-    if (!queryParams)
-      return;
-    const params = queryParams.substring(1).split('&');
-    for (let i = 0; i < params.length; ++i) {
-      const pair = params[i].split('=');
-      const name = pair.shift();
-      Runtime._queryParamsObject[name] = pair.join('=');
-    }
-  })();
-}
-
 // This must be constructed after the query parameters have been parsed.
 Runtime.experiments = new Runtime.ExperimentsSupport();
 
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js b/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
index 08f4030a..ef80062 100644
--- a/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
+++ b/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
@@ -20,6 +20,10 @@
     this._innerPreviewElement = this._eagerPreviewElement.createChild('div', 'console-eager-inner-preview');
     this._eagerPreviewElement.appendChild(UI.Icon.create('smallicon-command-result', 'preview-result-icon'));
 
+    const editorContainerElement = this.element.createChild('div', 'console-prompt-editor-container');
+    if (this._isBelowPromptEnabled)
+      this.element.appendChild(this._eagerPreviewElement);
+
     this._eagerEvalSetting = Common.settings.moduleSetting('consoleEagerEval');
     this._eagerEvalSetting.addChangeListener(this._eagerSettingChanged.bind(this));
     this._eagerPreviewElement.classList.toggle('hidden', !this._eagerEvalSetting.get());
@@ -50,11 +54,9 @@
                                                      UI.GlassPane.AnchorBehavior.PreferBottom
       }));
       this._editor.widget().element.addEventListener('keydown', this._editorKeyDown.bind(this), true);
-      this._editor.widget().show(this.element);
+      this._editor.widget().show(editorContainerElement);
       this._editor.addEventListener(UI.TextEditor.Events.TextChanged, this._onTextChanged, this);
       this._editor.addEventListener(UI.TextEditor.Events.SuggestionChanged, this._onTextChanged, this);
-      if (this._isBelowPromptEnabled)
-        this.element.appendChild(this._eagerPreviewElement);
 
       this.setText(this._initialText);
       delete this._initialText;
@@ -239,6 +241,8 @@
 
     event.consume(true);
 
+    // Since we prevent default, manually emulate the native "scroll on key input" behavior.
+    this.element.scrollIntoView();
     this.clearAutocomplete();
 
     const str = this.text();
diff --git a/third_party/blink/renderer/devtools/front_end/console/consoleView.css b/third_party/blink/renderer/devtools/front_end/console/consoleView.css
index 58ba943..1bebaf91 100644
--- a/third_party/blink/renderer/devtools/front_end/console/consoleView.css
+++ b/third_party/blink/renderer/devtools/front_end/console/consoleView.css
@@ -88,7 +88,10 @@
     clear: right;
     position: relative;
     margin: 0 22px 0 20px;
-    min-height: 18px;  /* Sync with ConsoleViewMessage.js */
+}
+
+.console-prompt-editor-container {
+    min-height: 21px;
 }
 
 .console-message,
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js b/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js
index c79d75b1..ea46aab2 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js
+++ b/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js
@@ -116,7 +116,7 @@
         return event.name + ':' + event.args['step'];
       if (event._blackboxRoot)
         return Common.UIString('Blackboxed');
-      if (TimelineModel.TimelineModel.isMarkerEvent(event))
+      if (this._performanceModel.timelineModel().isMarkerEvent(event))
         return Timeline.TimelineUIUtils.markerShortTitle(event);
       const name = Timeline.TimelineUIUtils.eventStyle(event).title;
       const detailsText =
@@ -409,7 +409,7 @@
     const markerEventsFilter = Timeline.TimelineUIUtils.paintEventsFilter();
     for (let i = 0; i < events.length; ++i) {
       const e = events[i];
-      if (!isExtension && TimelineModel.TimelineModel.isMarkerEvent(e) && markerEventsFilter.accept(e)) {
+      if (!isExtension && this._performanceModel.timelineModel().isMarkerEvent(e) && markerEventsFilter.accept(e)) {
         this._markers.push(new Timeline.TimelineFlameChartMarker(
             e.startTime, e.startTime - this._model.minimumRecordTime(),
             Timeline.TimelineUIUtils.markerStyleForEvent(e)));
@@ -443,7 +443,7 @@
       const index = this._appendEvent(e, level);
       if (openEvents.length)
         this._entryParent[index] = openEvents.peekLast();
-      if (!isExtension && TimelineModel.TimelineModel.isMarkerEvent(e))
+      if (!isExtension && this._performanceModel.timelineModel().isMarkerEvent(e))
         this._timelineData.entryTotalTimes[this._entryData.length] = undefined;
 
       maxStackDepth = Math.max(maxStackDepth, openEvents.length + 1);
@@ -537,7 +537,7 @@
     const metricEvents = [];
     for (const track of this._model.tracks()) {
       for (const event of track.events) {
-        if (!TimelineModel.TimelineModel.isMarkerEvent(event) || !metricsEventFilter.accept(event))
+        if (!this._performanceModel.timelineModel().isMarkerEvent(event) || !metricsEventFilter.accept(event))
           continue;
         metricEvents.push(event);
       }
@@ -616,7 +616,7 @@
                 '%s (self %s)', Number.millisToString(totalTime, true), Number.millisToString(selfTime, true)) :
             Number.millisToString(totalTime, true);
       }
-      if (TimelineModel.TimelineModel.isMarkerEvent(event))
+      if (this._performanceModel.timelineModel().isMarkerEvent(event))
         title = Timeline.TimelineUIUtils.eventTitle(event);
       else
         title = this.entryTitle(entryIndex);
@@ -668,7 +668,7 @@
       const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
       if (this._model.isGenericTrace())
         return this._genericTraceEventColor(event);
-      if (TimelineModel.TimelineModel.isMarkerEvent(event))
+      if (this._performanceModel.timelineModel().isMarkerEvent(event))
         return Timeline.TimelineUIUtils.markerStyleForEvent(event).color;
       if (!SDK.TracingModel.isAsyncPhase(event.phase))
         return this._colorForEvent(event);
diff --git a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
index 9c7ca0b..fe08969 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
+++ b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
@@ -88,14 +88,15 @@
    * @param {!SDK.TracingModel.Event} event
    * @return {boolean}
    */
-  static isMarkerEvent(event) {
+  isMarkerEvent(event) {
     const recordTypes = TimelineModel.TimelineModel.RecordType;
     switch (event.name) {
       case recordTypes.TimeStamp:
+        return true;
       case recordTypes.MarkFirstPaint:
       case recordTypes.MarkFCP:
       case recordTypes.MarkFMP:
-        return true;
+        return event.args.frame === this._mainFrame.frameId;
       case recordTypes.MarkDOMContent:
       case recordTypes.MarkLoad:
         return !!event.args['data']['isMainFrame'];
@@ -539,7 +540,7 @@
             track.tasks.push(event);
           eventStack.push(event);
         }
-        if (TimelineModel.TimelineModel.isMarkerEvent(event))
+        if (this.isMarkerEvent(event))
           this._timeMarkerEvents.push(event);
 
         track.events.push(event);
@@ -684,7 +685,7 @@
     timelineData.frameId = pageFrameId || (this._mainFrame && this._mainFrame.frameId) || '';
     this._asyncEventTracker.processEvent(event);
 
-    if (TimelineModel.TimelineModel.isMarkerEvent(event))
+    if (this.isMarkerEvent(event))
       this._ensureNamedTrack(TimelineModel.TimelineModel.TrackType.Timings);
 
     switch (event.name) {
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
index db7e3881..f03c205 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
@@ -78,7 +78,7 @@
     Document* document = &GetDocument();
     thread->Start(
         std::make_unique<GlobalScopeCreationParams>(
-            document->Url(), ScriptType::kModule, document->UserAgent(),
+            document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
             Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
             document->GetSecurityOrigin(), document->IsSecureContext(),
             document->GetHttpsState(), clients, document->AddressSpace(),
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h
index 4defd92..4ddc3441 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h
@@ -42,15 +42,21 @@
 
  public:
   static CanvasGradient* Create(const FloatPoint& p0, const FloatPoint& p1) {
-    return new CanvasGradient(p0, p1);
+    return MakeGarbageCollected<CanvasGradient>(p0, p1);
   }
   static CanvasGradient* Create(const FloatPoint& p0,
                                 float r0,
                                 const FloatPoint& p1,
                                 float r1) {
-    return new CanvasGradient(p0, r0, p1, r1);
+    return MakeGarbageCollected<CanvasGradient>(p0, r0, p1, r1);
   }
 
+  CanvasGradient(const FloatPoint& p0, const FloatPoint& p1);
+  CanvasGradient(const FloatPoint& p0,
+                 float r0,
+                 const FloatPoint& p1,
+                 float r1);
+
   Gradient* GetGradient() const { return gradient_.get(); }
 
   void addColorStop(float value, const String& color, ExceptionState&);
@@ -58,12 +64,6 @@
   bool IsZeroSize() const { return is_zero_size_; }
 
  private:
-  CanvasGradient(const FloatPoint& p0, const FloatPoint& p1);
-  CanvasGradient(const FloatPoint& p0,
-                 float r0,
-                 const FloatPoint& p1,
-                 float r1);
-
   scoped_refptr<Gradient> gradient_;
   const bool is_zero_size_;
 };
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h
index f6c2828d..97b0dc0 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h
@@ -47,9 +47,12 @@
   static CanvasPattern* Create(scoped_refptr<Image> image,
                                Pattern::RepeatMode repeat,
                                bool origin_clean) {
-    return new CanvasPattern(std::move(image), repeat, origin_clean);
+    return MakeGarbageCollected<CanvasPattern>(std::move(image), repeat,
+                                               origin_clean);
   }
 
+  CanvasPattern(scoped_refptr<Image>, Pattern::RepeatMode, bool origin_clean);
+
   Pattern* GetPattern() const { return pattern_.get(); }
   const AffineTransform& GetTransform() const { return pattern_transform_; }
 
@@ -58,8 +61,6 @@
   void setTransform(DOMMatrix2DInit*, ExceptionState&);
 
  private:
-  CanvasPattern(scoped_refptr<Image>, Pattern::RepeatMode, bool origin_clean);
-
   scoped_refptr<Pattern> pattern_;
   AffineTransform pattern_transform_;
   bool origin_clean_;
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
index 471c0cd..14777dae 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
@@ -81,14 +81,16 @@
         CanvasRenderingContextHost* host,
         const CanvasContextCreationAttributesCore& attrs) override {
       DCHECK(!host->IsOffscreenCanvas());
-      return new CanvasRenderingContext2D(static_cast<HTMLCanvasElement*>(host),
-                                          attrs);
+      return MakeGarbageCollected<CanvasRenderingContext2D>(
+          static_cast<HTMLCanvasElement*>(host), attrs);
     }
     CanvasRenderingContext::ContextType GetContextType() const override {
       return CanvasRenderingContext::kContext2d;
     }
   };
 
+  CanvasRenderingContext2D(HTMLCanvasElement*,
+                           const CanvasContextCreationAttributesCore&);
   ~CanvasRenderingContext2D() override;
 
   HTMLCanvasElement* canvas() const {
@@ -213,8 +215,6 @@
  private:
   friend class CanvasRenderingContext2DAutoRestoreSkCanvas;
 
-  CanvasRenderingContext2D(HTMLCanvasElement*,
-                           const CanvasContextCreationAttributesCore&);
   void DispatchContextLostEvent(TimerBase*);
   void DispatchContextRestoredEvent(TimerBase*);
   void TryRestoreContextEvent(TimerBase*);
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h
index 292a085b..0a69b63 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h
@@ -31,15 +31,18 @@
 
  public:
   static CanvasRenderingContext2DState* Create() {
-    return new CanvasRenderingContext2DState;
+    return MakeGarbageCollected<CanvasRenderingContext2DState>();
   }
 
+  enum ClipListCopyMode { kCopyClipList, kDontCopyClipList };
+
+  CanvasRenderingContext2DState();
+  CanvasRenderingContext2DState(const CanvasRenderingContext2DState&,
+                                ClipListCopyMode);
   ~CanvasRenderingContext2DState() override;
 
   void Trace(blink::Visitor*) override;
 
-  enum ClipListCopyMode { kCopyClipList, kDontCopyClipList };
-
   enum PaintType {
     kFillPaintType,
     kStrokePaintType,
@@ -193,10 +196,6 @@
   const PaintFlags* GetFlags(PaintType, ShadowMode, ImageType = kNoImage) const;
 
  private:
-  CanvasRenderingContext2DState();
-  CanvasRenderingContext2DState(const CanvasRenderingContext2DState&,
-                                ClipListCopyMode);
-
   void UpdateLineDash() const;
   void UpdateStrokeStyle() const;
   void UpdateFillStyle() const;
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
index 4cb778b..4dcd674 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -147,7 +147,9 @@
 
   class WrapGradients final : public GarbageCollectedFinalized<WrapGradients> {
    public:
-    static WrapGradients* Create() { return new WrapGradients; }
+    static WrapGradients* Create() {
+      return MakeGarbageCollected<WrapGradients>();
+    }
 
     void Trace(blink::Visitor* visitor) {
       visitor->Trace(opaque_gradient_);
diff --git a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc
index f65cafdf..f4ce8d8 100644
--- a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc
+++ b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc
@@ -38,7 +38,7 @@
 CanvasRenderingContext* ImageBitmapRenderingContext::Factory::Create(
     CanvasRenderingContextHost* host,
     const CanvasContextCreationAttributesCore& attrs) {
-  return new ImageBitmapRenderingContext(host, attrs);
+  return MakeGarbageCollected<ImageBitmapRenderingContext>(host, attrs);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h
index 18cd0bf3..177b3221 100644
--- a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h
+++ b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h
@@ -34,6 +34,9 @@
     }
   };
 
+  ImageBitmapRenderingContext(CanvasRenderingContextHost*,
+                              const CanvasContextCreationAttributesCore&);
+
   // Script API
   void transferFromImageBitmap(ImageBitmap*, ExceptionState&);
 
@@ -45,10 +48,6 @@
   void SetCanvasGetContextResult(RenderingContext&) final;
 
   ~ImageBitmapRenderingContext() override;
-
- private:
-  ImageBitmapRenderingContext(CanvasRenderingContextHost*,
-                              const CanvasContextCreationAttributesCore&);
 };
 
 DEFINE_TYPE_CASTS(ImageBitmapRenderingContext,
diff --git a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc
index 7a3daced..19586d8 100644
--- a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc
@@ -18,8 +18,8 @@
     CanvasRenderingContextHost* host,
     const CanvasContextCreationAttributesCore& attrs)
     : CanvasRenderingContext(host, attrs),
-      image_layer_bridge_(
-          new ImageLayerBridge(attrs.alpha ? kNonOpaque : kOpaque)) {}
+      image_layer_bridge_(MakeGarbageCollected<ImageLayerBridge>(
+          attrs.alpha ? kNonOpaque : kOpaque)) {}
 
 ImageBitmapRenderingContextBase::~ImageBitmapRenderingContextBase() = default;
 
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
index d4c9ec4..14237a7 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h"
 
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -42,7 +43,7 @@
       worker_clients, frame->Client()->CreateWorkerContentSettingsClient());
 
   auto creation_params = std::make_unique<GlobalScopeCreationParams>(
-      document->Url(), ScriptType::kModule, document->UserAgent(),
+      document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
       document->GetContentSecurityPolicy()->Headers(),
       document->GetReferrerPolicy(), document->GetSecurityOrigin(),
       document->IsSecureContext(), document->GetHttpsState(), worker_clients,
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc
index 3e9f65ae..6296221ab 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc
@@ -61,7 +61,7 @@
     Document* document = &GetDocument();
     thread->Start(
         std::make_unique<GlobalScopeCreationParams>(
-            document->Url(), ScriptType::kModule, document->UserAgent(),
+            document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
             Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
             document->GetSecurityOrigin(), document->IsSecureContext(),
             document->GetHttpsState(), clients, document->AddressSpace(),
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
index 591ff61..5e63ebf 100644
--- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
+++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -395,14 +395,6 @@
   String source_code;
   std::unique_ptr<Vector<char>> cached_meta_data;
 
-  // TODO(https://crbug.com/824647): Use blink::mojom::ScriptType everywhere
-  // and deprecate blink::ScriptType.
-  // Remove this line after removed all blink::ScriptType.
-  ScriptType script_type =
-      (worker_start_data_.script_type == mojom::ScriptType::kModule)
-          ? ScriptType::kModule
-          : ScriptType::kClassic;
-
   // |main_script_loader_| isn't created if the InstalledScriptsManager had the
   // script.
   if (main_script_loader_) {
@@ -415,7 +407,7 @@
           kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy);
     }
     global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>(
-        worker_start_data_.script_url, script_type,
+        worker_start_data_.script_url, worker_start_data_.script_type,
         worker_start_data_.user_agent,
         content_security_policy ? content_security_policy->Headers()
                                 : Vector<CSPHeaderAndType>(),
@@ -434,7 +426,7 @@
     // We don't have to set ContentSecurityPolicy and ReferrerPolicy. They're
     // served by the installed scripts manager on the worker thread.
     global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>(
-        worker_start_data_.script_url, script_type,
+        worker_start_data_.script_url, worker_start_data_.script_type,
         worker_start_data_.user_agent, Vector<CSPHeaderAndType>(),
         kReferrerPolicyDefault, starter_origin, starter_secure_context,
         starter_https_state, worker_clients, worker_start_data_.address_space,
@@ -467,7 +459,7 @@
   // > Switching on job’s worker type, run these substeps with the following
   // > options:
   // https://w3c.github.io/ServiceWorker/#update-algorithm
-  if (script_type == ScriptType::kClassic) {
+  if (worker_start_data_.script_type == mojom::ScriptType::kClassic) {
     // > "classic": Fetch a classic worker script given job’s serialized script
     // > url, job’s client, "serviceworker", and the to-be-created environment
     // > settings object for this service worker.
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
index 460909f..b82bf3a8 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.cc
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -94,7 +94,7 @@
     return nullptr;
   }
 
-  return new ImageCapture(context, track);
+  return MakeGarbageCollected<ImageCapture>(context, track);
 }
 
 ImageCapture::~ImageCapture() {
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.h b/third_party/blink/renderer/modules/imagecapture/image_capture.h
index 40bbb4e..a88b868 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.h
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.h
@@ -40,6 +40,8 @@
   static ImageCapture* Create(ExecutionContext*,
                               MediaStreamTrack*,
                               ExceptionState&);
+
+  ImageCapture(ExecutionContext*, MediaStreamTrack*);
   ~ImageCapture() override;
 
   // EventTarget implementation.
@@ -80,8 +82,6 @@
   using PromiseResolverFunction =
       base::OnceCallback<void(ScriptPromiseResolver*)>;
 
-  ImageCapture(ExecutionContext*, MediaStreamTrack*);
-
   void OnMojoGetPhotoState(ScriptPromiseResolver*,
                            PromiseResolverFunction,
                            bool trigger_take_photo,
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.cc
index 1553070..6f53c0f 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.cc
@@ -18,8 +18,8 @@
     HTMLCanvasElement* element,
     ExecutionContext* context,
     std::unique_ptr<WebCanvasCaptureHandler> handler) {
-  return new CanvasCaptureMediaStreamTrack(component, element, context,
-                                           std::move(handler));
+  return MakeGarbageCollected<CanvasCaptureMediaStreamTrack>(
+      component, element, context, std::move(handler));
 }
 
 CanvasCaptureMediaStreamTrack* CanvasCaptureMediaStreamTrack::Create(
@@ -28,8 +28,8 @@
     ExecutionContext* context,
     std::unique_ptr<WebCanvasCaptureHandler> handler,
     double frame_rate) {
-  return new CanvasCaptureMediaStreamTrack(component, element, context,
-                                           std::move(handler), frame_rate);
+  return MakeGarbageCollected<CanvasCaptureMediaStreamTrack>(
+      component, element, context, std::move(handler), frame_rate);
 }
 
 HTMLCanvasElement* CanvasCaptureMediaStreamTrack::canvas() const {
@@ -44,7 +44,8 @@
     ScriptState* script_state) {
   MediaStreamComponent* cloned_component = Component()->Clone();
   CanvasCaptureMediaStreamTrack* cloned_track =
-      new CanvasCaptureMediaStreamTrack(*this, cloned_component);
+      MakeGarbageCollected<CanvasCaptureMediaStreamTrack>(*this,
+                                                          cloned_component);
   MediaStreamCenter::Instance().DidCreateMediaStreamTrack(cloned_component);
   return cloned_track;
 }
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.h b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.h
index 5166347..e2a24847 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.h
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.h
@@ -32,14 +32,6 @@
       std::unique_ptr<WebCanvasCaptureHandler>,
       double frame_rate);
 
-  HTMLCanvasElement* canvas() const;
-  void requestFrame();
-
-  CanvasCaptureMediaStreamTrack* clone(ScriptState*) override;
-
-  void Trace(blink::Visitor*) override;
-
- private:
   CanvasCaptureMediaStreamTrack(const CanvasCaptureMediaStreamTrack&,
                                 MediaStreamComponent*);
   CanvasCaptureMediaStreamTrack(MediaStreamComponent*,
@@ -52,6 +44,14 @@
                                 std::unique_ptr<WebCanvasCaptureHandler>,
                                 double frame_rate);
 
+  HTMLCanvasElement* canvas() const;
+  void requestFrame();
+
+  CanvasCaptureMediaStreamTrack* clone(ScriptState*) override;
+
+  void Trace(blink::Visitor*) override;
+
+ private:
   Member<HTMLCanvasElement> canvas_element_;
   Member<CanvasDrawListener> draw_listener_;
 };
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
index cc5be70..e662dc7 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
@@ -18,8 +18,8 @@
 using testing::Invoke;
 using testing::InvokeWithoutArgs;
 
-const uint32_t kWriteBufferSize = 1024;
-const uint32_t kDelegateReadBufferSize = 1024;
+const uint32_t kDefaultStreamWriteBufferSize = 1024;
+const uint32_t kDefaultStreamDelegateReadBufferSize = 1024;
 const quic::QuicStreamId kStreamId = 5;
 const std::string kSomeData = "howdy";
 
@@ -43,8 +43,8 @@
   ~P2PQuicStreamTest() override {}
 
   void InitializeStream(
-      uint32_t delegate_read_buffer_size = kDelegateReadBufferSize,
-      uint32_t write_buffer_size = kWriteBufferSize) {
+      uint32_t delegate_read_buffer_size = kDefaultStreamDelegateReadBufferSize,
+      uint32_t write_buffer_size = kDefaultStreamWriteBufferSize) {
     stream_ = new P2PQuicStreamImpl(
         kStreamId, &session_, delegate_read_buffer_size, write_buffer_size);
     stream_->SetDelegate(&delegate_);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
index 45c52ae..dd52eb1 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
@@ -27,8 +27,8 @@
 using ::testing::PolymorphicAction;
 
 const std::string kTriggerRemoteStreamPhrase = "open sesame";
-const uint32_t kWriteBufferSize = 100 * 1024;
-const uint32_t kDelegateReadBufferSize = 100 * 1024;
+const uint32_t kTransportWriteBufferSize = 100 * 1024;
+const uint32_t kTransportDelegateReadBufferSize = 100 * 1024;
 
 // A custom gmock Action that fires the given callback. This is used in
 // conjuction with the CallbackRunLoop in order to drive the TestTaskRunner
@@ -391,7 +391,8 @@
     client_certificates.push_back(client_cert);
     P2PQuicTransportConfig client_config(
         client_quic_transport_delegate.get(), client_packet_transport.get(),
-        client_certificates, kDelegateReadBufferSize, kWriteBufferSize);
+        client_certificates, kTransportDelegateReadBufferSize,
+        kTransportWriteBufferSize);
     client_config.is_server = false;
     client_config.can_respond_to_crypto_handshake =
         can_respond_to_crypto_handshake;
@@ -418,7 +419,8 @@
     server_certificates.push_back(server_cert);
     P2PQuicTransportConfig server_config(
         server_quic_transport_delegate.get(), server_packet_transport.get(),
-        server_certificates, kDelegateReadBufferSize, kWriteBufferSize);
+        server_certificates, kTransportDelegateReadBufferSize,
+        kTransportWriteBufferSize);
     server_config.is_server = true;
     server_config.can_respond_to_crypto_handshake =
         can_respond_to_crypto_handshake;
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
index c399bcfa..dd7834d 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -217,7 +217,7 @@
 
 void ServiceWorkerGlobalScope::CountWorkerScript(size_t script_size,
                                                  size_t cached_metadata_size) {
-  DCHECK_EQ(GetScriptType(), ScriptType::kClassic);
+  DCHECK_EQ(GetScriptType(), mojom::ScriptType::kClassic);
   DEFINE_THREAD_SAFE_STATIC_LOCAL(
       CustomCountHistogram, script_size_histogram,
       ("ServiceWorker.ScriptSize", 1000, 5000000, 50));
@@ -238,7 +238,7 @@
 void ServiceWorkerGlobalScope::CountImportedScript(
     size_t script_size,
     size_t cached_metadata_size) {
-  DCHECK_EQ(GetScriptType(), ScriptType::kClassic);
+  DCHECK_EQ(GetScriptType(), mojom::ScriptType::kClassic);
   CountScriptInternal(script_size, cached_metadata_size);
 }
 
@@ -249,7 +249,7 @@
   // Skip recording UMAs for module scripts because there're no ways to get the
   // number of static-imported scripts and the total size of the imported
   // scripts.
-  if (GetScriptType() == ScriptType::kModule) {
+  if (GetScriptType() == mojom::ScriptType::kModule) {
     return;
   }
 
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
index fec8754d..39ebb2f 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -68,7 +68,7 @@
     Document* document = &GetDocument();
     thread->Start(
         std::make_unique<GlobalScopeCreationParams>(
-            document->Url(), ScriptType::kModule, document->UserAgent(),
+            document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
             Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
             document->GetSecurityOrigin(), document->IsSecureContext(),
             document->GetHttpsState(), nullptr /* worker_clients */,
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
index f8887d5..5e44e21b 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
@@ -52,7 +52,7 @@
     Document* document = &GetDocument();
     thread->Start(
         std::make_unique<GlobalScopeCreationParams>(
-            document->Url(), ScriptType::kModule, document->UserAgent(),
+            document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
             Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
             document->GetSecurityOrigin(), document->IsSecureContext(),
             document->GetHttpsState(), nullptr /* worker_clients */,
diff --git a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
index dc41349..79bde8a 100644
--- a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
+++ b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
@@ -67,7 +67,7 @@
     Document* document = &GetDocument();
     thread->Start(
         std::make_unique<GlobalScopeCreationParams>(
-            document->Url(), ScriptType::kModule, document->UserAgent(),
+            document->Url(), mojom::ScriptType::kModule, document->UserAgent(),
             Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
             document->GetSecurityOrigin(), document->IsSecureContext(),
             document->GetHttpsState(), clients, document->AddressSpace(),
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
index 4f804da..c78b0db 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -1233,14 +1233,13 @@
   std::unique_ptr<Canvas2DLayerBridge> bridge =
       MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
                  color_params);
-  gfx::ColorSpace expected_color_space = gfx::ColorSpace::CreateSRGB();
   std::vector<cc::DrawImage> images = {
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
-                    SkMatrix::I(), 0u, expected_color_space),
+                    SkMatrix::I(), 0u),
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
-                    0u, expected_color_space)};
+                    0u)};
 
   bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
   bridge->Canvas()->drawImageRect(
@@ -1262,10 +1261,10 @@
   std::vector<cc::DrawImage> images = {
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
-                    SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()),
+                    SkMatrix::I(), 0u),
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
-                    0u, color_params.GetStorageGfxColorSpace())};
+                    0u)};
 
   bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
   bridge->Canvas()->drawImageRect(
@@ -1288,13 +1287,13 @@
   std::vector<cc::DrawImage> images = {
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
-                    SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()),
+                    SkMatrix::I(), 0u),
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
-                    0u, color_params.GetStorageGfxColorSpace()),
+                    0u),
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
-                    0u, color_params.GetStorageGfxColorSpace())};
+                    0u)};
 
   // First 2 images are budgeted, they should remain locked after the op.
   bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
@@ -1321,10 +1320,9 @@
                  color_params);
   bridge->DisableDeferral(DisableDeferralReason::kDisableDeferralReasonUnknown);
 
-  auto image =
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
-                    SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
-                    SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace());
+  auto image = cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
+                             SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
+                             SkMatrix::I(), 0u);
   bridge->Canvas()->drawImage(image.paint_image(), 0u, 0u, nullptr);
   EXPECT_EQ(image_decode_cache_.num_locked_images(), 1);
 
@@ -1345,10 +1343,10 @@
   std::vector<cc::DrawImage> images = {
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
-                    SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()),
+                    SkMatrix::I(), 0u),
       cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
-                    0u, color_params.GetStorageGfxColorSpace())};
+                    0u)};
   bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
 
   // Lose the context and ensure that the image provider is not used.
diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
index 6c70da7f..e8271b2 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
@@ -181,9 +181,14 @@
 }
 
 sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpace() const {
+  return CanvasColorSpaceToSkColorSpace(color_space_);
+}
+
+sk_sp<SkColorSpace> CanvasColorParams::CanvasColorSpaceToSkColorSpace(
+    CanvasColorSpace color_space) {
   SkColorSpace::Gamut gamut = SkColorSpace::kSRGB_Gamut;
   SkColorSpace::RenderTargetGamma gamma = SkColorSpace::kSRGB_RenderTargetGamma;
-  switch (color_space_) {
+  switch (color_space) {
     case kSRGBCanvasColorSpace:
       break;
     case kLinearRGBCanvasColorSpace:
diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.h b/third_party/blink/renderer/platform/graphics/canvas_color_params.h
index b326f23..eb5a1df 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_color_params.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.h
@@ -85,6 +85,8 @@
   // Return the color space of the underlying data for the canvas.
   gfx::ColorSpace GetStorageGfxColorSpace() const;
   sk_sp<SkColorSpace> GetSkColorSpace() const;
+  static sk_sp<SkColorSpace> CanvasColorSpaceToSkColorSpace(
+      CanvasColorSpace color_space);
   SkAlphaType GetSkAlphaType() const;
   const SkSurfaceProps* GetSkSurfaceProps() const;
 
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 418f607..44d13bd 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -516,7 +516,6 @@
  public:
   CanvasImageProvider(cc::ImageDecodeCache* cache_n32,
                       cc::ImageDecodeCache* cache_f16,
-                      const gfx::ColorSpace& target_color_space,
                       SkColorType target_color_type);
   ~CanvasImageProvider() override = default;
 
@@ -542,17 +541,15 @@
 CanvasResourceProvider::CanvasImageProvider::CanvasImageProvider(
     cc::ImageDecodeCache* cache_n32,
     cc::ImageDecodeCache* cache_f16,
-    const gfx::ColorSpace& target_color_space,
     SkColorType canvas_color_type)
     : playback_image_provider_n32_(cache_n32,
-                                   target_color_space,
                                    cc::PlaybackImageProvider::Settings()),
       weak_factory_(this) {
   // If the image provider may require to decode to half float instead of
   // uint8, create a f16 PlaybackImageProvider with the passed cache.
   if (canvas_color_type == kRGBA_F16_SkColorType) {
     DCHECK(cache_f16);
-    playback_image_provider_f16_.emplace(cache_f16, target_color_space,
+    playback_image_provider_f16_.emplace(cache_f16,
                                          cc::PlaybackImageProvider::Settings());
   }
 }
@@ -638,19 +635,13 @@
 
     DCHECK(!canvas_image_provider_);
 
-    gfx::ColorSpace target_color_space =
-        ColorParams().NeedsSkColorSpaceXformCanvas()
-            ? ColorParams().GetStorageGfxColorSpace()
-            : gfx::ColorSpace::CreateSRGB();
-
     // Create an ImageDecodeCache for half float images only if the canvas is
     // using half float back storage.
     cc::ImageDecodeCache* cache_f16 = nullptr;
     if (ColorParams().PixelFormat() == kF16CanvasPixelFormat)
       cache_f16 = ImageDecodeCacheF16();
     canvas_image_provider_ = std::make_unique<CanvasImageProvider>(
-        ImageDecodeCacheRGBA8(), cache_f16, target_color_space,
-        color_params_.GetSkColorType());
+        ImageDecodeCacheRGBA8(), cache_f16, color_params_.GetSkColorType());
 
     cc::SkiaPaintCanvas::ContextFlushes context_flushes;
     if (IsAccelerated() &&
@@ -786,21 +777,30 @@
 }
 
 cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCacheRGBA8() {
+  auto color_space = ColorParams().ColorSpace();
+  if (!ColorParams().NeedsSkColorSpaceXformCanvas()) {
+    color_space = kSRGBCanvasColorSpace;
+  }
+
   if (IsAccelerated() && context_provider_wrapper_) {
     return context_provider_wrapper_->ContextProvider()->ImageDecodeCache(
-        ColorParams().ColorSpace(), kRGBA8CanvasPixelFormat);
+        color_space, kRGBA8CanvasPixelFormat);
   }
-  return Image::SharedCCDecodeCache(ColorParams().ColorSpace(),
-                                    kRGBA8CanvasPixelFormat);
+
+  return Image::SharedCCDecodeCache(color_space, kRGBA8CanvasPixelFormat);
 }
 
 cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCacheF16() {
+  auto color_space = ColorParams().ColorSpace();
+  if (!ColorParams().NeedsSkColorSpaceXformCanvas()) {
+    color_space = kSRGBCanvasColorSpace;
+  }
+
   if (IsAccelerated() && context_provider_wrapper_) {
     return context_provider_wrapper_->ContextProvider()->ImageDecodeCache(
-        ColorParams().ColorSpace(), kF16CanvasPixelFormat);
+        color_space, kF16CanvasPixelFormat);
   }
-  return Image::SharedCCDecodeCache(ColorParams().ColorSpace(),
-                                    kF16CanvasPixelFormat);
+  return Image::SharedCCDecodeCache(color_space, kF16CanvasPixelFormat);
 }
 
 void CanvasResourceProvider::RecycleResource(
diff --git a/third_party/blink/renderer/platform/graphics/image.cc b/third_party/blink/renderer/platform/graphics/image.cc
index 3517817..4b07a4b2 100644
--- a/third_party/blink/renderer/platform/graphics/image.cc
+++ b/third_party/blink/renderer/platform/graphics/image.cc
@@ -71,7 +71,9 @@
     if (!decode_caches_[index]) {
       decode_caches_[index] = std::make_unique<cc::SoftwareImageDecodeCache>(
           CanvasColorParams::PixelFormatToSkColorType(pixel_format),
-          locked_memory_limit_bytes_, PaintImage::kDefaultGeneratorClientId);
+          locked_memory_limit_bytes_, PaintImage::kDefaultGeneratorClientId,
+          blink::CanvasColorParams::CanvasColorSpaceToSkColorSpace(
+              color_space));
     }
     return decode_caches_[index].get();
   }
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py b/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
index 691fd6c..e6782ee 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
@@ -231,7 +231,11 @@
             port.update_baseline(output_path, data)
         else:
             _log.info('Copying baseline to "%s"', port.relative_test_filename(output_path))
-            fs.copyfile(current_expected_path, output_path)
+            if fs.exists(current_expected_path):
+                fs.copyfile(current_expected_path, output_path)
+            else:
+                _log.error('Could not copy baseline to "%s" from "%s" because the source file does not exist',
+                           port.relative_test_filename(output_path), current_expected_path)
 
     def _handle_error(self, driver_output, reference_filename=None):
         """Returns test failures if some unusual errors happen in driver's run.
diff --git a/third_party/minizip/BUILD.gn b/third_party/minizip/BUILD.gn
index bc613515..f84bcd2 100644
--- a/third_party/minizip/BUILD.gn
+++ b/third_party/minizip/BUILD.gn
@@ -58,14 +58,13 @@
     "src/lib/brg/sha2.c",
     "src/lib/brg/sha2.h",
     "src/mz.h",
+    "src/mz_crypt.c",
     "src/mz_crypt.h",
     "src/mz_crypt_brg.c",
     "src/mz_os.c",
     "src/mz_os.h",
     "src/mz_strm.c",
     "src/mz_strm.h",
-    "src/mz_strm_crc32.c",
-    "src/mz_strm_crc32.h",
     "src/mz_strm_mem.c",
     "src/mz_strm_mem.h",
     "src/mz_strm_pkcrypt.c",
diff --git a/third_party/minizip/README.chromium b/third_party/minizip/README.chromium
index 5ff369e..e6602fe 100644
--- a/third_party/minizip/README.chromium
+++ b/third_party/minizip/README.chromium
@@ -1,8 +1,8 @@
 Name: nmoinvaz/minizip
 Short name: minizip
 URL: https://github.com/nmoinvaz/minizip
-Version: 2.7.0
-Revision: 43c01101bf09d473e3aff17fe665faa07ee742b7
+Version: 2.7.4
+Revision: c47090678d687742eddc60d07c5430279af416d8
 Security critical: yes
 License: Custom license
 License File: src/LICENSE
diff --git a/third_party/minizip/minizip_uncompress_corpus/encrypted_aes.zip b/third_party/minizip/minizip_uncompress_corpus/encrypted_aes.zip
new file mode 100644
index 0000000..aa2f073a
--- /dev/null
+++ b/third_party/minizip/minizip_uncompress_corpus/encrypted_aes.zip
Binary files differ
diff --git a/third_party/minizip/minizip_uncompress_corpus/encrypted_pkcrypt.zip b/third_party/minizip/minizip_uncompress_corpus/encrypted_pkcrypt.zip
new file mode 100644
index 0000000..924f933e9
--- /dev/null
+++ b/third_party/minizip/minizip_uncompress_corpus/encrypted_pkcrypt.zip
Binary files differ
diff --git a/third_party/minizip/minizip_uncompress_fuzzer.cc b/third_party/minizip/minizip_uncompress_fuzzer.cc
index 1b02b47..0688f9e6 100644
--- a/third_party/minizip/minizip_uncompress_fuzzer.cc
+++ b/third_party/minizip/minizip_uncompress_fuzzer.cc
@@ -11,6 +11,10 @@
 #include "third_party/minizip/src/mz_strm_mem.h"
 #include "third_party/minizip/src/mz_zip.h"
 
+namespace {
+const char kTestPassword[] = "test123";
+}
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   void* stream = mz_stream_mem_create(nullptr);
   mz_stream_mem_set_buffer(
@@ -24,13 +28,15 @@
   if (result == MZ_OK) {
     result = mz_zip_goto_first_entry(zip_file);
     while (result == MZ_OK) {
-      result = mz_zip_entry_read_open(zip_file, 0, nullptr);
+      mz_zip_file* file_info = nullptr;
+      result = mz_zip_entry_get_info(zip_file, &file_info);
       if (result != MZ_OK) {
         break;
       }
 
-      mz_zip_file* file_info = nullptr;
-      result = mz_zip_entry_get_info(zip_file, &file_info);
+      bool is_encrypted = (file_info->flag & MZ_ZIP_FLAG_ENCRYPTED);
+      result = mz_zip_entry_read_open(zip_file, 0,
+                                      is_encrypted ? kTestPassword : nullptr);
       if (result != MZ_OK) {
         break;
       }
diff --git a/third_party/webrtc_overrides/rtc_base/event.cc b/third_party/webrtc_overrides/rtc_base/event.cc
index 165d3124..014bc87 100644
--- a/third_party/webrtc_overrides/rtc_base/event.cc
+++ b/third_party/webrtc_overrides/rtc_base/event.cc
@@ -10,6 +10,8 @@
 
 using base::WaitableEvent;
 
+Event::Event() : Event(false, false) {}
+
 Event::Event(bool manual_reset, bool initially_signaled)
     : event_(manual_reset ? WaitableEvent::ResetPolicy::MANUAL
                           : WaitableEvent::ResetPolicy::AUTOMATIC,
diff --git a/third_party/webrtc_overrides/rtc_base/event.h b/third_party/webrtc_overrides/rtc_base/event.h
index 256b353..6cbba7f0 100644
--- a/third_party/webrtc_overrides/rtc_base/event.h
+++ b/third_party/webrtc_overrides/rtc_base/event.h
@@ -16,6 +16,7 @@
  public:
   static const int kForever = -1;
 
+  Event();
   Event(bool manual_reset, bool initially_signaled);
   ~Event();
 
@@ -28,7 +29,7 @@
 
  private:
   base::WaitableEvent event_;
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Event);
+  DISALLOW_COPY_AND_ASSIGN(Event);
 };
 
 // Pull ScopedAllowBaseSyncPrimitives into the rtc namespace.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 0e9562d..da03cd4 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -33836,6 +33836,14 @@
   <int value="3" label="Success page"/>
 </enum>
 
+<enum name="MultiDevice_Setup_HostStatus">
+  <int value="0" label="No eligible hosts"/>
+  <int value="1" label="Eligible host exists but no host set"/>
+  <int value="2" label="Host set locally but waiting for backend confirmation"/>
+  <int value="3" label="Host set but not yet verified"/>
+  <int value="4" label="Host verified"/>
+</enum>
+
 <enum name="MultiDeviceSetupNotification">
   <int value="0" label="New user, potential host exists"/>
   <int value="1" label="Existing user, host switched"/>
@@ -52323,6 +52331,7 @@
   <int value="2" label="FailedUnknownReason"/>
   <int value="3" label="GetWebApplicationInfoFailed"/>
   <int value="4" label="PreviouslyUninstalled"/>
+  <int value="5" label="WebContentsDestroyed"/>
 </enum>
 
 <enum name="WebAppInstallSource">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index f9e840aa5..d9b40e4 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -4040,7 +4040,17 @@
   <owner>khmel@google.com</owner>
   <summary>
     Arc Silent Auth Code status. This status is set during the ARC
-    reauthorization flow.
+    Device/Primary Account reauthorization flow.
+  </summary>
+</histogram>
+
+<histogram name="Arc.OptInSilentAuthCode.SecondaryAccount"
+    enum="ArcOptInSilentAuthCode">
+  <owner>khmel@google.com</owner>
+  <summary>
+    Arc Silent Auth Code status. This status is set during the minting of an
+    auth code for a Secondary Account. It can be set for Secondary Account
+    signin or reauthorization.
   </summary>
 </histogram>
 
@@ -4135,6 +4145,14 @@
   </summary>
 </histogram>
 
+<histogram name="Arc.Secondary.Signin.Result" enum="ArcProvisioningResult">
+  <owner>khmel@google.com</owner>
+  <summary>
+    The result (success or the type of failure) of ARC Secondary Account signin/
+    reauthorization.
+  </summary>
+</histogram>
+
 <histogram name="Arc.ShareFilesOnExit" enum="ArcShareFilesOnExit">
   <owner>weifangsun@google.com</owner>
   <owner>djacobo@google.com</owner>
@@ -51282,6 +51300,15 @@
   </summary>
 </histogram>
 
+<histogram name="MultiDevice.Setup.HostStatus"
+    enum="MultiDevice_Setup_HostStatus">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Breaks down percentages of host statuses. This metric is emitted to at the
+    creation of the user session, when the user logs in
+  </summary>
+</histogram>
+
 <histogram name="MultiDeviceSetup.OOBE.UserChoice"
     enum="MultiDeviceSetupOOBEUserChoice">
   <owner>hansberry@chromium.org</owner>
@@ -56167,9 +56194,9 @@
   </summary>
 </histogram>
 
-<histogram name="Net.FoundSystemTrustRootsAndroid" enum="Boolean"
-    expires_after="2018-08-30">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+<histogram name="Net.FoundSystemTrustRootsAndroid" enum="BooleanFound">
+  <owner>davidben@chromium.org</owner>
+  <owner>rsleevi@chromium.org</owner>
   <summary>
     Whether or not system installed trust anchors could be distinguished from
     user installed trust anchors. Recorded on first certificate verification on
@@ -124968,6 +124995,14 @@
   <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.Reshows"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="AutofillSaveCreditCardPromptRequestingExpirationDate"
+    separator=".">
+  <suffix name="RequestingExpirationDate"
+      label="Expiration date was explicitly requested in prompt"/>
+  <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.FirstShow"/>
+  <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.Reshows"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="AutofillSaveCreditCardPromptShow" separator=".">
   <suffix name="FirstShow"
       label="first time prompt is shown for a single credit card submit"/>
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index 728c073..aedd969f 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -363,6 +363,7 @@
     "junit/src/org/chromium/ui/AsyncViewStubTest.java",
     "junit/src/org/chromium/ui/AsyncViewProviderTest.java",
     "junit/src/org/chromium/ui/base/ClipboardTest.java",
+    "junit/src/org/chromium/ui/base/LocalizationUtilsTest.java",
     "junit/src/org/chromium/ui/base/SelectFileDialogTest.java",
     "junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java",
     "junit/src/org/chromium/ui/text/SpanApplierTest.java",
diff --git a/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java b/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java
index e1a87cb..d913975 100644
--- a/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java
+++ b/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java
@@ -139,5 +139,22 @@
         }
     }
 
+    /**
+     * Return true iff a locale string matches a specific language string.
+     *
+     * @param locale Chromium locale name (e.g. "fil", or "en-US").
+     * @param lang Chromium language name (e.g. "fi", or "en").
+     * @return true iff the locale name matches the languages. E.g. should
+     *         be false for ("fil", "fi") (Filipino locale + Finish language)
+     *         but true for ("en-US", "en") (USA locale + English language).
+     */
+    public static boolean chromiumLocaleMatchesLanguage(String locale, String lang) {
+        int pos = locale.indexOf('-');
+        if (pos > 0) {
+            return locale.substring(0, pos).equals(lang);
+        }
+        return locale.equals(lang);
+    }
+
     private static native int nativeGetFirstStrongCharacterDirection(String string);
 }
diff --git a/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java b/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java
index 38dc095..244e64ab 100644
--- a/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java
+++ b/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java
@@ -152,7 +152,7 @@
         // that allows a bit of growth, but is still in the right ballpark..
         ArrayList<String> activeLocales = new ArrayList<String>(6);
         for (String locale : BuildConfig.COMPRESSED_LOCALES) {
-            if (locale.startsWith(uiLanguage)) {
+            if (LocalizationUtils.chromiumLocaleMatchesLanguage(locale, uiLanguage)) {
                 activeLocales.add(locale);
             }
         }
diff --git a/ui/android/junit/src/org/chromium/ui/base/LocalizationUtilsTest.java b/ui/android/junit/src/org/chromium/ui/base/LocalizationUtilsTest.java
new file mode 100644
index 0000000..3cf5ab6
--- /dev/null
+++ b/ui/android/junit/src/org/chromium/ui/base/LocalizationUtilsTest.java
@@ -0,0 +1,53 @@
+// 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.
+
+package org.chromium.ui.base;
+
+import android.support.test.filters.SmallTest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/**
+ * Tests for LocalizationUtils class.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class LocalizationUtilsTest {
+    @Test
+    @SmallTest
+    public void testGetDefaultCompressedPakLocaleForLanguage() {
+        assertEquals("fr", LocalizationUtils.getDefaultCompressedPakLocaleForLanguage("fr"));
+        assertEquals("es", LocalizationUtils.getDefaultCompressedPakLocaleForLanguage("es"));
+        assertEquals("en-US", LocalizationUtils.getDefaultCompressedPakLocaleForLanguage("en"));
+        assertEquals("pt-PT", LocalizationUtils.getDefaultCompressedPakLocaleForLanguage("pt"));
+        assertEquals("zh-CN", LocalizationUtils.getDefaultCompressedPakLocaleForLanguage("zh"));
+    }
+
+    @Test
+    @SmallTest
+    public void testChromiumLocaleMatchesLanguage() {
+        assertTrue(LocalizationUtils.chromiumLocaleMatchesLanguage("en-US", "en"));
+        assertTrue(LocalizationUtils.chromiumLocaleMatchesLanguage("en-GB", "en"));
+        assertFalse(LocalizationUtils.chromiumLocaleMatchesLanguage("en-US", "es"));
+        assertTrue(LocalizationUtils.chromiumLocaleMatchesLanguage("es", "es"));
+        assertTrue(LocalizationUtils.chromiumLocaleMatchesLanguage("fi", "fi"));
+
+        // Filipino locale should *not* match Finish language.
+        // See http://crbug.com/901837
+        assertFalse(LocalizationUtils.chromiumLocaleMatchesLanguage("fil", "fi"));
+
+        // "tl" is the Android locale name for Filipines, due to historical
+        // reasons. The corresponding Chromium locale name is "fil".
+        // Check that the method only deals with Chromium locale names.
+        assertFalse(LocalizationUtils.chromiumLocaleMatchesLanguage("fil", "tl"));
+    }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/directory_contents.js b/ui/file_manager/file_manager/foreground/js/directory_contents.js
index 084d5938..6944b6a3 100644
--- a/ui/file_manager/file_manager/foreground/js/directory_contents.js
+++ b/ui/file_manager/file_manager/foreground/js/directory_contents.js
@@ -233,8 +233,7 @@
 DriveMetadataSearchContentScanner.prototype.scan = function(
     entriesCallback, successCallback, errorCallback) {
   chrome.fileManagerPrivate.searchDriveMetadata(
-      {query: '', types: this.searchType_, maxResults: 500},
-      function(results) {
+      {query: '', types: this.searchType_, maxResults: 100}, function(results) {
         if (this.cancelled_) {
           errorCallback(util.createDOMError(util.FileError.ABORT_ERR));
           return;